LCOV - code coverage report
Current view: top level - gcc/jit - jit-recording.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 92.1 % 3061 2819
Test Date: 2026-02-28 14:20:25 Functions: 94.4 % 428 404
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Internals of libgccjit: classes for recording calls made to the JIT API.
       2              :    Copyright (C) 2013-2026 Free Software Foundation, Inc.
       3              :    Contributed by David Malcolm <dmalcolm@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_SSTREAM
      23              : #include "system.h"
      24              : #include "coretypes.h"
      25              : #include "target.h"
      26              : #include "pretty-print.h"
      27              : #include "toplev.h"
      28              : 
      29              : 
      30              : #include "jit-builtins.h"
      31              : #include "jit-recording.h"
      32              : #include "jit-playback.h"
      33              : 
      34              : namespace gcc {
      35              : namespace jit {
      36              : 
      37              : // class dump
      38              : 
      39         1157 : dump::dump (recording::context &ctxt,
      40              :             const char *filename,
      41         1157 :             bool update_locations)
      42         1157 : : m_ctxt (ctxt),
      43         1157 :   m_filename (filename),
      44         1157 :   m_update_locations (update_locations),
      45         1157 :   m_line (0),
      46         1157 :   m_column (0)
      47              : {
      48         1157 :   m_file = fopen (filename, "w");
      49         1157 :   if (!m_file)
      50            0 :     ctxt.add_error (NULL,
      51              :                     "error opening dump file %s for writing: %s",
      52              :                     filename,
      53            0 :                     xstrerror (errno));
      54         1157 : }
      55              : 
      56         1157 : dump::~dump ()
      57              : {
      58         1157 :   if (m_file)
      59              :     {
      60         1157 :       int err = fclose (m_file);
      61         1157 :       if (err)
      62            0 :         m_ctxt.add_error (NULL,
      63              :                           "error closing dump file %s: %s",
      64              :                           m_filename,
      65            0 :                           xstrerror (errno));
      66              :     }
      67         1157 : }
      68              : 
      69              : /* Write the given message to the dump, using printf-formatting
      70              :    conventions, updating the line/column within the dump.
      71              : 
      72              :    Emit an error on the context if a failure occurs.  */
      73              : 
      74              : void
      75       174238 : dump::write (const char *fmt, ...)
      76              : {
      77       174238 :   int len;
      78       174238 :   va_list ap;
      79       174238 :   char *buf;
      80              : 
      81              :   /* If there was an error opening the file, we've already reported it.
      82              :      Don't attempt further work.  */
      83       174238 :   if (!m_file)
      84            0 :     return;
      85              : 
      86       174238 :   va_start (ap, fmt);
      87       174238 :   len = vasprintf (&buf, fmt, ap);
      88       174238 :   va_end (ap);
      89              : 
      90       174238 :   if (buf == NULL || len < 0)
      91              :     {
      92            0 :       m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
      93              :                         m_filename);
      94            0 :       return;
      95              :     }
      96              : 
      97       174238 :   if (fwrite (buf, strlen (buf), 1, m_file) != 1)
      98            0 :     m_ctxt.add_error (NULL, "error writing to dump file %s",
      99              :                       m_filename);
     100              : 
     101              :   /* Flush after each line, to ease debugging crashes.  */
     102       174238 :   fflush (m_file);
     103              : 
     104              :   /* Update line/column: */
     105     24878896 :   for (const char *ptr = buf; *ptr; ptr++)
     106              :     {
     107     24704658 :       if ('\n' == *ptr)
     108              :         {
     109       392791 :           m_line++;
     110       392791 :           m_column = 0;
     111              :         }
     112              :       else
     113     24311867 :         m_column++;
     114              :     }
     115              : 
     116       174238 :   free (buf);
     117              : }
     118              : 
     119              : /* Construct a gcc::jit::recording::location instance for the current
     120              :    location within the dump.  */
     121              : 
     122              : recording::location *
     123          186 : dump::make_location () const
     124              : {
     125          186 :   return m_ctxt.new_location (m_filename, m_line, m_column,
     126              :                               /* We need to flag such locations as *not*
     127              :                                  created by the user, so that
     128              :                                  reproducer::get_identifier can cope with
     129              :                                  them appearing *after* the memento that
     130              :                                  refers to them.  */
     131          186 :                               false);
     132              : }
     133              : 
     134              : /* A collection of allocations, all of which can be released together, to
     135              :    avoid needing to track and release them individually.  */
     136              : 
     137         1143 : class allocator
     138              : {
     139              :  public:
     140              :   ~allocator ();
     141              : 
     142              :   char *
     143              :   xstrdup_printf (const char *, ...)
     144              :     ATTRIBUTE_RETURNS_NONNULL
     145              :     GNU_PRINTF(2, 3);
     146              : 
     147              :   char *
     148              :   xstrdup_printf_va (const char *, va_list ap)
     149              :     ATTRIBUTE_RETURNS_NONNULL
     150              :     GNU_PRINTF(2, 0);
     151              : 
     152              :  private:
     153              :   auto_vec <void *> m_buffers;
     154              : };
     155              : 
     156              : /* allocator's destructor.  Call "free" on all of the allocations.  */
     157              : 
     158         1143 : allocator::~allocator ()
     159              : {
     160         1143 :   unsigned i;
     161         1143 :   void *buffer;
     162       162247 :   FOR_EACH_VEC_ELT (m_buffers, i, buffer)
     163       161104 :     free (buffer);
     164         1143 : }
     165              : 
     166              : /* Formatted printing, allocating to a buffer (or exiting the process if
     167              :    the allocation fails).
     168              : 
     169              :    The buffer exists until the allocator is cleaned up, and is freed at
     170              :    that point, so the caller doesn't need to track the result.  */
     171              : 
     172              : char *
     173       151636 : allocator::xstrdup_printf (const char *fmt, ...)
     174              : {
     175       151636 :   char *result;
     176       151636 :   va_list ap;
     177       151636 :   va_start (ap, fmt);
     178       151636 :   result = xstrdup_printf_va (fmt, ap);
     179       151636 :   va_end (ap);
     180       151636 :   return result;
     181              : }
     182              : 
     183              : /* Formatted printing, allocating to a buffer (or exiting the process if
     184              :    the allocation fails).
     185              : 
     186              :    The buffer exists until the allocator is cleaned up, and is freed at
     187              :    that point, so the caller doesn't need to track the result.  */
     188              : 
     189              : char *
     190       161104 : allocator::xstrdup_printf_va (const char *fmt, va_list ap)
     191              : {
     192       161104 :   char *result = xvasprintf (fmt, ap);
     193       161104 :   m_buffers.safe_push (result);
     194       161104 :   return result;
     195              : }
     196              : 
     197              : /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
     198              :    implementing gcc_jit_context_dump_reproducer_to_file.  */
     199              : 
     200              : class reproducer : public dump
     201              : {
     202              :  public:
     203              :   reproducer (recording::context &ctxt,
     204              :               const char *filename);
     205              : 
     206              :   void
     207              :   write_params (const vec <recording::context *> &contexts);
     208              : 
     209              :   void
     210              :   write_args (const vec <recording::context *> &contexts);
     211              : 
     212              :   const char *
     213              :   make_identifier (recording::memento *m, const char *prefix);
     214              : 
     215              :   const char *
     216              :   make_tmp_identifier (const char *prefix, recording::memento *m);
     217              : 
     218              :   const char *
     219              :   get_identifier (recording::context *ctxt);
     220              : 
     221              :   const char *
     222              :   get_identifier (recording::memento *m);
     223              : 
     224              :   const char *
     225              :   get_identifier_as_rvalue (recording::rvalue *m);
     226              : 
     227              :   const char *
     228              :   get_identifier_as_lvalue (recording::lvalue *m);
     229              : 
     230              :   const char *
     231              :   get_identifier_as_type (recording::type *m);
     232              : 
     233              :   char *
     234              :   xstrdup_printf (const char *, ...)
     235              :     ATTRIBUTE_RETURNS_NONNULL
     236              :     GNU_PRINTF(2, 3);
     237              : 
     238              :  private:
     239              :   const char * ensure_identifier_is_unique (const char *candidate, void *ptr);
     240              : 
     241              :  private:
     242              :   hash_map<recording::memento *, const char *> m_map_memento_to_identifier;
     243              : 
     244              :   struct hash_traits : public string_hash
     245              :   {
     246              :     static void remove (const char *) {}
     247              :   };
     248              :   hash_set<const char *, false, hash_traits> m_set_identifiers;
     249              :   allocator m_allocator;
     250              : };
     251              : 
     252              : /* gcc::jit::reproducer's constructor.  */
     253              : 
     254         1143 : reproducer::reproducer (recording::context &ctxt,
     255         1143 :                         const char *filename) :
     256              :   dump (ctxt, filename, 0),
     257         1143 :   m_map_memento_to_identifier (),
     258         1143 :   m_set_identifiers (),
     259         1143 :   m_allocator ()
     260              : {
     261         1143 : }
     262              : 
     263              : /* Write out a list of contexts as a set of parameters within a
     264              :    C function declaration.  */
     265              : 
     266              : void
     267         4572 : reproducer::write_params (const vec <recording::context *> &contexts)
     268              : {
     269         4572 :   unsigned i;
     270         4572 :   recording::context *ctxt;
     271         9208 :   FOR_EACH_VEC_ELT (contexts, i, ctxt)
     272              :     {
     273         4636 :       write ("gcc_jit_context *%s",
     274              :              get_identifier (ctxt));
     275         9272 :       if (i < contexts.length () - 1)
     276           64 :         write (",\n"
     277              :                "             ");
     278              :     }
     279         4572 : }
     280              : 
     281              : /* Write out a list of contexts as a set of arguments within a call
     282              :    to a C function.  */
     283              : 
     284              : void
     285         2286 : reproducer::write_args (const vec <recording::context *> &contexts)
     286              : {
     287         2286 :   unsigned i;
     288         2286 :   recording::context *ctxt;
     289         4604 :   FOR_EACH_VEC_ELT (contexts, i, ctxt)
     290              :     {
     291         2318 :       write ("%s",
     292              :              get_identifier (ctxt));
     293         4636 :       if (i < contexts.length () - 1)
     294           32 :         write (",\n"
     295              :                "               ");
     296              :     }
     297         2286 : }
     298              : 
     299              : /* Ensure that STR is a valid C identifier by overwriting
     300              :    any invalid chars in-place with underscores.
     301              : 
     302              :    This doesn't special-case the first character.  */
     303              : 
     304              : static void
     305        56840 : convert_to_identifier (char *str)
     306              : {
     307      1020284 :   for (char *p = str; *p; p++)
     308       963444 :     if (!ISALNUM (*p))
     309       194297 :       *p = '_';
     310        56840 : }
     311              : 
     312              : /* Given CANDIDATE, a possible C identifier for use in a reproducer,
     313              :    ensure that it is unique within the generated source file by
     314              :    appending PTR to it if necessary.  Return the resulting string.
     315              : 
     316              :    The reproducer will eventually clean up the buffer in its dtor.  */
     317              : 
     318              : const char *
     319        56959 : reproducer::ensure_identifier_is_unique (const char *candidate, void *ptr)
     320              : {
     321        56959 :   if (m_set_identifiers.contains (candidate))
     322        14906 :     candidate = m_allocator.xstrdup_printf ("%s_%p", candidate, ptr);
     323        56959 :   gcc_assert (!m_set_identifiers.contains (candidate));
     324        56959 :   m_set_identifiers.add (candidate);
     325        56959 :   return candidate;
     326              : }
     327              : 
     328              : /* Generate a C identifier for the given memento, associating the generated
     329              :    buffer with the memento (for future calls to get_identifier et al).
     330              : 
     331              :    The reproducer will eventually clean up the buffer in its dtor.  */
     332              : const char *
     333        56959 : reproducer::make_identifier (recording::memento *m, const char *prefix)
     334              : {
     335        56959 :   const char *result;
     336        56959 :   if (strlen (m->get_debug_string ()) < 100)
     337              :     {
     338        56840 :       char *buf = m_allocator.xstrdup_printf ("%s_%s",
     339              :                                               prefix,
     340              :                                               m->get_debug_string ());
     341        56840 :       convert_to_identifier (buf);
     342        56840 :       result = buf;
     343              :     }
     344              :   else
     345          119 :     result = m_allocator.xstrdup_printf ("%s_%p",
     346              :                                          prefix, (void *) m);
     347        56959 :   result = ensure_identifier_is_unique (result, m);
     348        56959 :   m_map_memento_to_identifier.put (m, result);
     349        56959 :   return result;
     350              : }
     351              : 
     352              : /* Generate a C identifier for a temporary variable.
     353              :    The reproducer will eventually clean up the buffer in its dtor.  */
     354              : 
     355              : const char *
     356         4011 : reproducer::make_tmp_identifier (const char *prefix, recording::memento *m)
     357              : {
     358         4011 :   return m_allocator.xstrdup_printf ("%s_%s",
     359         4011 :                                      prefix, get_identifier (m));
     360              : }
     361              : 
     362              : /* Generate a C identifier for the given context.
     363              :    The reproducer will eventually clean up the buffer in its dtor.  */
     364              : 
     365              : const char *
     366        75760 : reproducer::get_identifier (recording::context *ctxt)
     367              : {
     368        75760 :   return m_allocator.xstrdup_printf ("ctxt_%p",
     369        75760 :                                      (void *)ctxt);
     370              : }
     371              : 
     372              : /* Locate the C identifier for the given memento, which is assumed to
     373              :    have already been created via make_identifier.  */
     374              : 
     375              : const char *
     376       117599 : reproducer::get_identifier (recording::memento *m)
     377              : {
     378       117599 :   if (!m)
     379              :     return "NULL";
     380              : 
     381              :   /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
     382              :      and hence these locations appear in the context's memento list
     383              :      out-of-order: they appear in the context's memento list *after*
     384              :      the memento that refers to them.  For this case, it's simplest to
     385              :      pretend that they're NULL when writing out the code to recreate the
     386              :      memento that uses them.  */
     387        88484 :   if (recording::location *loc = m->dyn_cast_location ())
     388         6492 :     if (!loc->created_by_user ())
     389              :       return "NULL";
     390              : 
     391        88276 :   const char **slot = m_map_memento_to_identifier.get (m);
     392        88276 :   if (!slot)
     393              :     {
     394            0 :       get_context ().add_error (NULL,
     395              :                                 "unable to find identifier for %p: %s",
     396              :                                 (void *)m,
     397              :                                 m->get_debug_string ());
     398            0 :       gcc_unreachable ();
     399              :     }
     400        88276 :   return *slot;
     401              : }
     402              : 
     403              : /* Locate the C identifier for the given rvalue, wrapping it within
     404              :    a gcc_*_as_rvalue upcast if necessary.  */
     405              : 
     406              : const char *
     407        16967 : reproducer::get_identifier_as_rvalue (recording::rvalue *m)
     408              : {
     409        16967 :   if (!m)
     410              :     return "NULL";
     411        16857 :   return m->access_as_rvalue (*this);
     412              : }
     413              : 
     414              : /* Locate the C identifier for the given lvalue, wrapping it within
     415              :    a gcc_*_as_lvalue upcast if necessary.  */
     416              : 
     417              : const char *
     418         2928 : reproducer::get_identifier_as_lvalue (recording::lvalue *m)
     419              : {
     420         2928 :   if (!m)
     421              :     return "NULL";
     422         2928 :   return m->access_as_lvalue (*this);
     423              : }
     424              : 
     425              : /* Locate the C identifier for the given type, wrapping it within
     426              :    a gcc_*_as_type upcast if necessary.  */
     427              : 
     428              : const char *
     429        29918 : reproducer::get_identifier_as_type (recording::type *m)
     430              : {
     431        29918 :   if (!m)
     432              :     return "NULL";
     433        29918 :   return m->access_as_type (*this);
     434              : }
     435              : 
     436              : /* Formatted printing, allocating to a buffer (or exiting the process if
     437              :    the allocation fails).
     438              : 
     439              :    The buffer exists until the allocator is cleaned up, and is freed at
     440              :    that point, so the caller doesn't need to track the result.
     441              : 
     442              :    Note that we can't use ggc_printf since we're not within the compiler
     443              :    proper (when within gcc_jit_context_dump_reproducer_to_file).  */
     444              : 
     445              : char *
     446         9468 : reproducer::xstrdup_printf (const char *fmt, ...)
     447              : {
     448         9468 :   char *result;
     449         9468 :   va_list ap;
     450         9468 :   va_start (ap, fmt);
     451         9468 :   result = m_allocator.xstrdup_printf_va (fmt, ap);
     452         9468 :   va_end (ap);
     453         9468 :   return result;
     454              : }
     455              : 
     456              : /* A helper class for implementing make_debug_string, for building
     457              :    a temporary string from a vec of rvalues.  */
     458              : 
     459              : class comma_separated_string
     460              : {
     461              :  public:
     462              :   comma_separated_string (const auto_vec<recording::rvalue *> &rvalues,
     463              :                           enum recording::precedence prec);
     464              :   ~comma_separated_string ();
     465              : 
     466          711 :   const char *as_char_ptr () const { return m_buf; }
     467              : 
     468              :  private:
     469              :   char *m_buf;
     470              : };
     471              : 
     472              : /* comma_separated_string's ctor
     473              :    Build m_buf.  */
     474              : 
     475          711 : comma_separated_string::comma_separated_string
     476              :   (const auto_vec<recording::rvalue *> &rvalues,
     477          711 :    enum recording::precedence prec)
     478          711 : : m_buf (NULL)
     479              : {
     480              :   /* Calculate length of said buffer.  */
     481          711 :   size_t sz = 1; /* nil terminator */
     482         1947 :   for (unsigned i = 0; i< rvalues.length (); i++)
     483              :     {
     484         1236 :       sz += strlen (rvalues[i]->get_debug_string_parens (prec));
     485         1236 :       sz += 2; /* ", " separator */
     486              :     }
     487              : 
     488              :   /* Now allocate and populate the buffer.  */
     489          711 :   m_buf = new char[sz];
     490          711 :   size_t len = 0;
     491              : 
     492         2583 :   for (unsigned i = 0; i< rvalues.length (); i++)
     493              :     {
     494         1236 :       strcpy (m_buf + len, rvalues[i]->get_debug_string_parens (prec));
     495         1236 :       len += strlen (rvalues[i]->get_debug_string_parens (prec));
     496         3183 :       if (i + 1 < rvalues.length ())
     497              :         {
     498          600 :           strcpy (m_buf + len, ", ");
     499          600 :           len += 2;
     500              :         }
     501              :     }
     502          711 :   m_buf[len] = '\0';
     503          711 : }
     504              : 
     505              : /* comma_separated_string's dtor.  */
     506              : 
     507          711 : comma_separated_string::~comma_separated_string ()
     508              : {
     509          711 :   delete[] m_buf;
     510          711 : }
     511              : 
     512              : /**********************************************************************
     513              :  Recording.
     514              :  **********************************************************************/
     515              : 
     516              : /* Get the playback::location for the given recording::location,
     517              :    handling a NULL input with a NULL output.  */
     518              : 
     519              : playback::location *
     520        61821 : recording::playback_location (replayer *r, recording::location *loc)
     521              : {
     522        61821 :   if (loc)
     523         1418 :     return loc->playback_location (r);
     524              :   else
     525              :     return NULL;
     526              : }
     527              : 
     528              : /* Get a const char * for the given recording::string
     529              :    handling a NULL input with a NULL output.  */
     530              : 
     531              : const char *
     532        10899 : recording::playback_string (recording::string *str)
     533              : {
     534        10899 :   if (str)
     535         9937 :     return str->c_str ();
     536              :   else
     537              :     return NULL;
     538              : }
     539              : 
     540              : /* Get the playback::block for the given recording::block,
     541              :    handling a NULL input with a NULL output.  */
     542              : 
     543              : playback::block *
     544        13294 : recording::playback_block (recording::block *b)
     545              : {
     546        13294 :   if (b)
     547        13294 :     return b->playback_block ();
     548              :   else
     549              :     return NULL;
     550              : }
     551              : 
     552              : /* Methods of cc::jit::recording::context.  */
     553              : 
     554              : /* The constructor for gcc::jit::recording::context, used by
     555              :    gcc_jit_context_acquire and gcc_jit_context_new_child_context.  */
     556              : 
     557         2073 : recording::context::context (context *parent_ctxt)
     558              :   : log_user (NULL),
     559         2073 :     m_parent_ctxt (parent_ctxt),
     560         2073 :     m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this),
     561         2073 :     m_timer (NULL),
     562         2073 :     m_error_count (0),
     563         2073 :     m_first_error_str (NULL),
     564         2073 :     m_owns_first_error_str (false),
     565         2073 :     m_last_error_str (NULL),
     566         2073 :     m_owns_last_error_str (false),
     567         2073 :     m_mementos (),
     568         2073 :     m_compound_types (),
     569         2073 :     m_globals (),
     570         2073 :     m_functions (),
     571         2073 :     m_FILE_type (NULL),
     572         4146 :     m_builtins_manager(NULL)
     573              : {
     574         2073 :   if (parent_ctxt)
     575              :     {
     576              :       /* Inherit options from parent.  */
     577           36 :       for (unsigned i = 0; i < ARRAY_SIZE (m_str_options); i++)
     578              :         {
     579           24 :           const char *parent_opt = parent_ctxt->m_str_options[i];
     580           24 :           m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
     581              :         }
     582           12 :       memcpy (m_int_options,
     583              :               parent_ctxt->m_int_options,
     584              :               sizeof (m_int_options));
     585           12 :       memcpy (m_bool_options,
     586              :               parent_ctxt->m_bool_options,
     587              :               sizeof (m_bool_options));
     588           12 :       memcpy (m_inner_bool_options,
     589           12 :               parent_ctxt->m_inner_bool_options,
     590              :               sizeof (m_inner_bool_options));
     591           12 :       set_logger (parent_ctxt->get_logger ());
     592              :     }
     593              :   else
     594              :     {
     595         2061 :       memset (m_str_options, 0, sizeof (m_str_options));
     596         2061 :       memset (m_int_options, 0, sizeof (m_int_options));
     597         2061 :       memset (m_bool_options, 0, sizeof (m_bool_options));
     598         2061 :       memset (m_inner_bool_options, 0, sizeof (m_inner_bool_options));
     599         2061 :       m_inner_bool_options[INNER_BOOL_OPTION_PRINT_ERRORS_TO_STDERR] = true;
     600              :     }
     601              : 
     602         2073 :   memset (m_basic_types, 0, sizeof (m_basic_types));
     603         2073 : }
     604              : 
     605              : /* The destructor for gcc::jit::recording::context, implicitly used by
     606              :    gcc_jit_context_release.  */
     607              : 
     608         2041 : recording::context::~context ()
     609              : {
     610         2041 :   JIT_LOG_SCOPE (get_logger ());
     611         2041 :   int i;
     612         2041 :   memento *m;
     613      1683472 :   FOR_EACH_VEC_ELT (m_mementos, i, m)
     614              :     {
     615      1679390 :       delete m;
     616              :     }
     617              : 
     618         6123 :   for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
     619         4082 :     free (m_str_options[i]);
     620              : 
     621              :   char *optname;
     622         3428 :   FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
     623         1387 :     free (optname);
     624         2058 :   FOR_EACH_VEC_ELT (m_driver_options, i, optname)
     625           17 :     free (optname);
     626              : 
     627         2041 :   if (m_builtins_manager)
     628         1294 :     delete m_builtins_manager;
     629              : 
     630         2041 :   if (m_owns_first_error_str)
     631          606 :     free (m_first_error_str);
     632              : 
     633         2041 :   if (m_owns_last_error_str)
     634          606 :     if (m_last_error_str != m_first_error_str)
     635          330 :       free (m_last_error_str);
     636         2041 : }
     637              : 
     638              : /* Add the given mememto to the list of those tracked by this
     639              :    gcc::jit::recording::context, so that e.g. it can be deleted
     640              :    when this context is released.  */
     641              : 
     642              : void
     643      1681256 : recording::context::record (memento *m)
     644              : {
     645      1681256 :   gcc_assert (m);
     646              : 
     647      1681256 :   m_mementos.safe_push (m);
     648      1681271 : }
     649              : 
     650              : /* Replay this context (and any parents) into the given replayer.  */
     651              : 
     652              : void
     653         1346 : recording::context::replay_into (replayer *r)
     654              : {
     655         1346 :   JIT_LOG_SCOPE (get_logger ());
     656         1346 :   int i;
     657         1346 :   memento *m;
     658              : 
     659              :   /* If we have a parent context, we must replay it.  This will
     660              :      recursively walk backwards up the historical tree, then replay things
     661              :      forwards "in historical order", starting with the ultimate parent
     662              :      context, until we reach the "this" context.
     663              : 
     664              :      Note that we fully replay the parent, then fully replay the child,
     665              :      which means that inter-context references can only exist from child
     666              :      to parent, not the other way around.
     667              : 
     668              :      All of this replaying is suboptimal - it would be better to do the
     669              :      work for the parent context *once*, rather than replaying the parent
     670              :      every time we replay each child.  However, fixing this requires deep
     671              :      surgery to lifetime-management: we'd need every context family tree
     672              :      to have its own GC heap, and to initialize the GCC code to use that
     673              :      heap (with a mutex on such a heap).  */
     674         1346 :   if (m_parent_ctxt)
     675           20 :     m_parent_ctxt->replay_into (r);
     676              : 
     677         1346 :   if (r->errors_occurred ())
     678              :     return;
     679              : 
     680              :   /* Replay this context's saved operations into r.  */
     681       169117 :   FOR_EACH_VEC_ELT (m_mementos, i, m)
     682              :     {
     683              :       /* Disabled low-level debugging, here if we need it: print what
     684              :          we're replaying.
     685              :          Note that the calls to get_debug_string might lead to more
     686              :          mementos being created for the strings.
     687              :          This can also be used to exercise the debug_string
     688              :          machinery.  */
     689       167806 :       if (0)
     690              :         printf ("context %p replaying (%p): %s\n",
     691              :                 (void *)this, (void *)m, m->get_debug_string ());
     692              : 
     693       167806 :       m->replay_into (r);
     694              : 
     695       167806 :       if (r->errors_occurred ())
     696              :         return;
     697              :     }
     698         1346 : }
     699              : 
     700              : /* During a playback, we associate objects from the recording with
     701              :    their counterparts during this playback.
     702              : 
     703              :    For simplicity, we store this within the recording objects.
     704              : 
     705              :    The following method cleans away these associations, to ensure that
     706              :    we never have out-of-date associations lingering on subsequent
     707              :    playbacks (the objects pointed to are GC-managed, but the
     708              :    recording objects don't own refs to them).  */
     709              : 
     710              : void
     711         1346 : recording::context::disassociate_from_playback ()
     712              : {
     713         1346 :   JIT_LOG_SCOPE (get_logger ());
     714         1346 :   int i;
     715         1346 :   memento *m;
     716              : 
     717         1346 :   if (m_parent_ctxt)
     718           20 :     m_parent_ctxt->disassociate_from_playback ();
     719              : 
     720       171037 :   FOR_EACH_VEC_ELT (m_mementos, i, m)
     721              :     {
     722       169691 :       m->set_playback_obj (NULL);
     723              :     }
     724         1346 : }
     725              : 
     726              : /* Create a recording::string instance and add it to this context's list
     727              :    of mementos.
     728              : 
     729              :    This creates a fresh copy of the given 0-terminated buffer.  */
     730              : 
     731              : recording::string *
     732       140776 : recording::context::new_string (const char *text, bool escaped)
     733              : {
     734       140776 :   if (!text)
     735              :     return NULL;
     736              : 
     737       139248 :   recording::string *result = new string (this, text, escaped);
     738       139248 :   record (result);
     739       139248 :   return result;
     740              : }
     741              : 
     742              : /* Create a recording::location instance and add it to this context's
     743              :    list of mementos.
     744              : 
     745              :    Implements the post-error-checking part of
     746              :    gcc_jit_context_new_location.  */
     747              : 
     748              : recording::location *
     749         9908 : recording::context::new_location (const char *filename,
     750              :                                   int line,
     751              :                                   int column,
     752              :                                   bool created_by_user)
     753              : {
     754         9908 :   recording::location *result =
     755              :     new recording::location (this,
     756              :                              new_string (filename),
     757              :                              line, column,
     758         9908 :                              created_by_user);
     759         9908 :   record (result);
     760         9908 :   return result;
     761              : }
     762              : 
     763              : /* If we haven't seen this enum value yet, create a recording::type
     764              :    instance and add it to this context's list of mementos.
     765              : 
     766              :    If we have seen it before, reuse our cached value, so that repeated
     767              :    calls on the context give the same object.
     768              : 
     769              :    If we have a parent context, the cache is within the ultimate
     770              :    ancestor context.
     771              : 
     772              :    Implements the post-error-checking part of
     773              :    gcc_jit_context_get_type.  */
     774              : 
     775              : recording::type *
     776        37642 : recording::context::get_type (enum gcc_jit_types kind)
     777              : {
     778        37642 :   if (!m_basic_types[kind])
     779              :     {
     780        13174 :       if (m_parent_ctxt)
     781           24 :         m_basic_types[kind] = m_parent_ctxt->get_type (kind);
     782              :       else
     783              :         {
     784        13150 :           recording::type *result = new memento_of_get_type (this, kind);
     785        13150 :           record (result);
     786        13150 :           m_basic_types[kind] = result;
     787              :         }
     788              :     }
     789              : 
     790        37642 :   return m_basic_types[kind];
     791              : }
     792              : 
     793              : /* Get a recording::type instance for the given size and signedness.
     794              :    This is implemented in terms of recording::context::get_type
     795              :    above.
     796              : 
     797              :    Implements the post-error-checking part of
     798              :    gcc_jit_context_get_int_type.  */
     799              : 
     800              : recording::type *
     801         5181 : recording::context::get_int_type (int num_bytes, int is_signed)
     802              : {
     803              :   /* We can't use a switch here since some of the values are macros affected
     804              :      by options; e.g. i386.h has
     805              :        #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
     806              :      Compare with tree.cc's make_or_reuse_type.  Note that the _SIZE macros
     807              :      are in bits, rather than bytes.
     808              :   */
     809         5181 :   const int num_bits = num_bytes * 8;
     810         5181 :   if (num_bits == INT_TYPE_SIZE)
     811         3056 :     return get_type (is_signed
     812              :                      ? GCC_JIT_TYPE_INT
     813         1571 :                      : GCC_JIT_TYPE_UNSIGNED_INT);
     814         3610 :   if (num_bits == CHAR_TYPE_SIZE)
     815         3165 :     return get_type (is_signed
     816              :                      ? GCC_JIT_TYPE_SIGNED_CHAR
     817         1590 :                      : GCC_JIT_TYPE_UNSIGNED_CHAR);
     818         2020 :   if (num_bits == SHORT_TYPE_SIZE)
     819         1040 :     return get_type (is_signed
     820              :                      ? GCC_JIT_TYPE_SHORT
     821          520 :                      : GCC_JIT_TYPE_UNSIGNED_SHORT);
     822         1507 :   if (num_bits == LONG_TYPE_SIZE)
     823         2946 :     return get_type (is_signed
     824              :                      ? GCC_JIT_TYPE_LONG
     825         1493 :                      : GCC_JIT_TYPE_UNSIGNED_LONG);
     826            7 :   if (num_bits == LONG_LONG_TYPE_SIZE)
     827            9 :     return get_type (is_signed
     828              :                      ? GCC_JIT_TYPE_LONG_LONG
     829            7 :                      : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
     830            0 :   if (num_bits == 128)
     831            0 :     return get_type (is_signed
     832              :                      ? GCC_JIT_TYPE_INT128_T
     833            0 :                      : GCC_JIT_TYPE_UINT128_T);
     834              : 
     835              :   /* Some other size, not corresponding to the C int types.  */
     836              :   /* To be written: support arbitrary other sizes, sharing by
     837              :      memoizing at the recording::context level?  */
     838            0 :   gcc_unreachable ();
     839              : }
     840              : 
     841              : /* Create a recording::type instance and add it to this context's list
     842              :    of mementos.
     843              : 
     844              :    Implements the post-error-checking part of
     845              :    gcc_jit_context_new_array_type.  */
     846              : 
     847              : recording::type *
     848          390 : recording::context::new_array_type (recording::location *loc,
     849              :                                     recording::type *element_type,
     850              :                                     uint64_t num_elements)
     851              : {
     852          390 :   if (struct_ *s = element_type->dyn_cast_struct ())
     853            0 :     if (!s->get_fields ())
     854              :       {
     855            0 :         add_error (NULL,
     856              :                    "cannot create an array of type %s"
     857              :                    " until the fields have been set",
     858              :                    s->get_name ()->c_str ());
     859            0 :         return NULL;
     860              :       }
     861          390 :   recording::type *result =
     862          390 :     new recording::array_type (this, loc, element_type, num_elements);
     863          390 :   record (result);
     864          390 :   return result;
     865              : }
     866              : 
     867              : /* Create a recording::field instance and add it to this context's list
     868              :    of mementos.
     869              : 
     870              :    Implements the post-error-checking part of
     871              :    gcc_jit_context_new_field.  */
     872              : 
     873              : recording::field *
     874         4505 : recording::context::new_field (recording::location *loc,
     875              :                                recording::type *type,
     876              :                                const char *name)
     877              : {
     878         4505 :   recording::field *result =
     879         4505 :     new recording::field (this, loc, type, new_string (name));
     880         4505 :   record (result);
     881         4505 :   return result;
     882              : }
     883              : 
     884              : /* Create a recording::bitfield instance and add it to this context's list
     885              :    of mementos.
     886              : 
     887              :    Implements the post-error-checking part of
     888              :    gcc_jit_context_new_bitfield.  */
     889              : 
     890              : recording::field *
     891          110 : recording::context::new_bitfield (recording::location *loc,
     892              :                                   recording::type *type,
     893              :                                   int width,
     894              :                                   const char *name)
     895              : {
     896          110 :   recording::field *result =
     897          110 :     new recording::bitfield (this, loc, type, width, new_string (name));
     898          110 :   record (result);
     899          110 :   return result;
     900              : }
     901              : 
     902              : /* Create a recording::struct_ instance and add it to this context's
     903              :    list of mementos and list of compound types.
     904              : 
     905              :    Implements the post-error-checking part of
     906              :    gcc_jit_context_new_struct_type.  */
     907              : 
     908              : recording::struct_ *
     909         1001 : recording::context::new_struct_type (recording::location *loc,
     910              :                                      const char *name)
     911              : {
     912         1001 :   recording::struct_ *result = new struct_ (this, loc, new_string (name));
     913         1001 :   record (result);
     914         1001 :   m_compound_types.safe_push (result);
     915         1001 :   return result;
     916              : }
     917              : 
     918              : /* Create a recording::union_ instance and add it to this context's
     919              :    list of mementos and list of compound types.
     920              : 
     921              :    Implements the first post-error-checking part of
     922              :    gcc_jit_context_new_union_type.  */
     923              : 
     924              : recording::union_ *
     925           85 : recording::context::new_union_type (recording::location *loc,
     926              :                                     const char *name)
     927              : {
     928           85 :   recording::union_ *result = new union_ (this, loc, new_string (name));
     929           85 :   record (result);
     930           85 :   m_compound_types.safe_push (result);
     931           85 :   return result;
     932              : }
     933              : 
     934              : /* Create a recording::function_type instance and add it to this context's
     935              :    list of mementos.
     936              : 
     937              :    Used by new_function_ptr_type and by builtins_manager::make_fn_type.  */
     938              : 
     939              : recording::function_type *
     940         5539 : recording::context::new_function_type (recording::type *return_type,
     941              :                                        int num_params,
     942              :                                        recording::type **param_types,
     943              :                                        int is_variadic,
     944              :                                        bool is_target_builtin)
     945              : {
     946         5539 :   recording::function_type *fn_type
     947              :     = new function_type (this,
     948              :                          return_type,
     949              :                          num_params,
     950              :                          param_types,
     951              :                          is_variadic,
     952         5539 :                          is_target_builtin);
     953         5539 :   record (fn_type);
     954         5539 :   return fn_type;
     955              : }
     956              : 
     957              : /* Create a recording::type instance and add it to this context's list
     958              :    of mementos.
     959              : 
     960              :    Implements the post-error-checking part of
     961              :    gcc_jit_context_new_function_ptr_type.  */
     962              : 
     963              : recording::type *
     964           70 : recording::context::new_function_ptr_type (recording::location *, /* unused loc */
     965              :                                            recording::type *return_type,
     966              :                                            int num_params,
     967              :                                            recording::type **param_types,
     968              :                                            int is_variadic)
     969              : {
     970           70 :   recording::function_type *fn_type
     971           70 :     = new_function_type (return_type,
     972              :                          num_params,
     973              :                          param_types,
     974              :                          is_variadic,
     975              :                          false);
     976              : 
     977              :   /* Return a pointer-type to the function type.  */
     978           70 :   return fn_type->get_pointer ();
     979              : }
     980              : 
     981              : /* Create a recording::param instance and add it to this context's list
     982              :    of mementos.
     983              : 
     984              :    Implements the post-error-checking part of
     985              :    gcc_jit_context_new_param.  */
     986              : 
     987              : recording::param *
     988        20614 : recording::context::new_param (recording::location *loc,
     989              :                                recording::type *type,
     990              :                                const char *name)
     991              : {
     992        20614 :   recording::param *result = new recording::param (this, loc, type, new_string (name));
     993        20613 :   record (result);
     994        20614 :   return result;
     995              : }
     996              : 
     997              : /* Create a recording::function instance and add it to this context's list
     998              :    of mementos and list of functions.
     999              : 
    1000              :    Implements the post-error-checking part of
    1001              :    gcc_jit_context_new_function.  */
    1002              : 
    1003              : recording::function *
    1004         4385 : recording::context::new_function (recording::location *loc,
    1005              :                                   enum gcc_jit_function_kind kind,
    1006              :                                   recording::type *return_type,
    1007              :                                   const char *name,
    1008              :                                   int num_params,
    1009              :                                   recording::param **params,
    1010              :                                   int is_variadic,
    1011              :                                   enum built_in_function builtin_id)
    1012              : {
    1013         4385 :   recording::function *result =
    1014              :     new recording::function (this,
    1015              :                              loc, kind, return_type,
    1016              :                              new_string (name),
    1017              :                              num_params, params, is_variadic,
    1018         4385 :                              builtin_id, false);
    1019         4385 :   record (result);
    1020         4385 :   m_functions.safe_push (result);
    1021              : 
    1022         4385 :   return result;
    1023              : }
    1024              : 
    1025              : /* Locate the builtins_manager (if any) for this family of contexts,
    1026              :    creating it if it doesn't exist already.
    1027              : 
    1028              :    All of the recording contexts in a family share one builtins_manager:
    1029              :    if we have a child context, follow the parent links to get the
    1030              :    ultimate ancestor context, and look for it/store it there.  */
    1031              : 
    1032              : builtins_manager *
    1033        14701 : recording::context::get_builtins_manager ()
    1034              : {
    1035        14921 :   if (m_parent_ctxt)
    1036              :     return m_parent_ctxt->get_builtins_manager ();
    1037              : 
    1038        14701 :   if (!m_builtins_manager)
    1039         1326 :     m_builtins_manager = new builtins_manager (this);
    1040              : 
    1041        14701 :   return m_builtins_manager;
    1042              : }
    1043              : 
    1044              : /* Get a recording::function instance, which is lazily-created and added
    1045              :    to the context's lists of mementos.
    1046              : 
    1047              :    Implements the post-error-checking part of
    1048              :    gcc_jit_context_get_builtin_function.  */
    1049              : 
    1050              : recording::function *
    1051          255 : recording::context::get_builtin_function (const char *name)
    1052              : {
    1053          255 :   builtins_manager *bm = get_builtins_manager ();
    1054          255 :   return bm->get_builtin_function (name);
    1055              : }
    1056              : 
    1057              : /* Create a recording::function instance for a target-specific builtin.
    1058              : 
    1059              :    Implements the post-error-checking part of
    1060              :    gcc_jit_context_get_target_builtin_function.  */
    1061              : 
    1062              : recording::function *
    1063           10 : recording::context::get_target_builtin_function (const char *name)
    1064              : {
    1065           10 :   const char *asm_name = name;
    1066           20 :   if (target_function_types.count (name) == 0)
    1067              :   {
    1068            0 :     fprintf (stderr, "Cannot find target builtin %s\n", name);
    1069            0 :     return NULL;
    1070              :   }
    1071              : 
    1072           10 :   recording::function_type* func_type = target_function_types[name]
    1073           10 :     ->copy (this)->dyn_cast_function_type ();
    1074           10 :   const vec<type *>& param_types = func_type->get_param_types ();
    1075           10 :   recording::param **params = new recording::param *[param_types.length ()];
    1076              : 
    1077           10 :   int i;
    1078           10 :   recording::type *param_type;
    1079           20 :   FOR_EACH_VEC_ELT (param_types, i, param_type)
    1080              :     {
    1081           10 :       char buf[16];
    1082           10 :       snprintf (buf, 16, "arg%d", i);
    1083           10 :       params[i] = new_param (NULL,
    1084              :                              param_type,
    1085              :                              buf);
    1086              :   }
    1087              : 
    1088           10 :   recording::function *result =
    1089              :     new recording::function (this,
    1090              :           NULL,
    1091              :           GCC_JIT_FUNCTION_IMPORTED,
    1092              :           func_type->get_return_type (),
    1093              :           new_string (asm_name),
    1094           10 :           param_types.length (),
    1095              :           params,
    1096              :           func_type->is_variadic (),
    1097              :           BUILT_IN_NONE,
    1098           20 :           true);
    1099           10 :   record (result);
    1100              : 
    1101           10 :   return result;
    1102              : }
    1103              : 
    1104              : /* Create a recording::global instance and add it to this context's list
    1105              :    of mementos.
    1106              : 
    1107              :    Implements the post-error-checking part of
    1108              :    gcc_jit_context_new_global.  */
    1109              : 
    1110              : recording::lvalue *
    1111         2469 : recording::context::new_global (recording::location *loc,
    1112              :                                 enum gcc_jit_global_kind kind,
    1113              :                                 recording::type *type,
    1114              :                                 const char *name)
    1115              : {
    1116         2469 :   recording::global *result =
    1117         2469 :     new recording::global (this, loc, kind, type, new_string (name));
    1118         2469 :   record (result);
    1119         2469 :   m_globals.safe_push (result);
    1120              : 
    1121         2469 :   return result;
    1122              : }
    1123              : 
    1124              : void
    1125          860 : recording::context::new_global_init_rvalue (lvalue *variable,
    1126              :                                             rvalue *init)
    1127              : {
    1128          860 :   recording::global_init_rvalue *obj =
    1129          860 :     new recording::global_init_rvalue (this, variable, init);
    1130          860 :   record (obj);
    1131              : 
    1132          860 :   global *gbl = (global *) variable;
    1133          860 :   gbl->set_rvalue_init (init); /* Needed by the global for write dump.  */
    1134          860 : }
    1135              : 
    1136              : /* Create a recording::memento_of_typeinfo instance and add it
    1137              :    to this context's list of mementos.
    1138              : 
    1139              :    Implements the post-error-checking part of
    1140              :    gcc_jit_context_new_sizeof.  */
    1141              : 
    1142              : recording::rvalue *
    1143           15 : recording::context::new_sizeof (recording::type *type)
    1144              : {
    1145           15 :   recording::rvalue *result =
    1146           15 :     new memento_of_typeinfo (this, NULL, type, TYPE_INFO_SIZE_OF);
    1147           15 :   record (result);
    1148           15 :   return result;
    1149              : }
    1150              : 
    1151              : /* Create a recording::memento_of_typeinfo instance and add it
    1152              :    to this context's list of mementos.
    1153              : 
    1154              :    Implements the post-error-checking part of
    1155              :    gcc_jit_context_new_alignof.  */
    1156              : 
    1157              : recording::rvalue *
    1158           15 : recording::context::new_alignof (recording::type *type)
    1159              : {
    1160           15 :   recording::rvalue *result =
    1161           15 :     new memento_of_typeinfo (this, NULL, type, TYPE_INFO_ALIGN_OF);
    1162           15 :   record (result);
    1163           15 :   return result;
    1164              : }
    1165              : 
    1166              : /* Create a recording::memento_of_new_string_literal instance and add it
    1167              :    to this context's list of mementos.
    1168              : 
    1169              :    Implements the post-error-checking part of
    1170              :    gcc_jit_context_new_string_literal.  */
    1171              : 
    1172              : recording::rvalue *
    1173         1963 : recording::context::new_string_literal (const char *value)
    1174              : {
    1175         1963 :   recording::rvalue *result =
    1176         1963 :     new memento_of_new_string_literal (this, NULL, new_string (value));
    1177         1963 :   record (result);
    1178         1963 :   return result;
    1179              : }
    1180              : 
    1181              : /* Create a recording::memento_of_new_rvalue_from_vector instance and add it
    1182              :    to this context's list of mementos.
    1183              : 
    1184              :    Implements the post-error-checking part of
    1185              :    gcc_jit_context_new_rvalue_from_vector.  */
    1186              : 
    1187              : recording::rvalue *
    1188          120 : recording::context::new_rvalue_from_vector (location *loc,
    1189              :                                             vector_type *type,
    1190              :                                             rvalue **elements)
    1191              : {
    1192          120 :   recording::rvalue *result
    1193          120 :     = new memento_of_new_rvalue_from_vector (this, loc, type, elements);
    1194          120 :   record (result);
    1195          120 :   return result;
    1196              : }
    1197              : 
    1198              : recording::rvalue *
    1199           15 : recording::context::new_rvalue_vector_perm (location *loc,
    1200              :                           rvalue *elements1,
    1201              :                           rvalue *elements2,
    1202              :                           rvalue *mask)
    1203              : {
    1204           15 :   recording::rvalue *result
    1205              :     = new memento_of_new_rvalue_vector_perm (this, loc, elements1, elements2,
    1206           15 :                                              mask);
    1207           15 :   record (result);
    1208           15 :   return result;
    1209              : }
    1210              : 
    1211              : recording::rvalue *
    1212          675 : recording::context::new_ctor (recording::location *loc,
    1213              :                               recording::type *type,
    1214              :                               size_t num_values,
    1215              :                               field **fields,
    1216              :                               rvalue **values)
    1217              : {
    1218          675 :   recording::ctor *result = new ctor (this, loc, type);
    1219              : 
    1220              :   /* Short cut for zero init.  */
    1221          675 :   if (!num_values)
    1222              :     {
    1223           60 :       record (result);
    1224           60 :       return result;
    1225              :     }
    1226              : 
    1227          615 :   bool is_struct_or_union = type->is_struct () || type->is_union ();
    1228              : 
    1229              :   /* We need to copy fields and values into result's auto_vec:s.
    1230              :      Both for structs and unions and only values for arrays.  */
    1231          615 :   if (type->is_array () != NULL)
    1232              :     {
    1233          240 :       result->m_values.reserve (num_values, false);
    1234              : 
    1235         1020 :       for (size_t i = 0; i < num_values; i++)
    1236          780 :         result->m_values.quick_push (values[i]);
    1237              :     }
    1238          375 :   else if (is_struct_or_union && fields)
    1239              :     {
    1240              :       /* ctor values are paired with user specified fields.  */
    1241              : 
    1242          225 :       result->m_values.reserve (num_values, false);
    1243          225 :       result->m_fields.reserve (num_values, false);
    1244              : 
    1245          615 :       for (size_t i = 0; i < num_values; i++)
    1246              :         {
    1247          390 :           result->m_values.quick_push (values[i]);
    1248          390 :           result->m_fields.quick_push (fields[i]);
    1249              :         }
    1250              :     }
    1251          150 :   else if (is_struct_or_union && !fields)
    1252              :     {
    1253              :       /* ctor values are in definition order one by one,
    1254              :          so take the fields from the type object.  */
    1255              : 
    1256          150 :       result->m_values.reserve (num_values, false);
    1257          150 :       result->m_fields.reserve (num_values, false);
    1258              : 
    1259          150 :       compound_type *ct = reinterpret_cast<compound_type *>(type);
    1260          150 :       recording::fields *fields = ct->get_fields ();
    1261              : 
    1262              :       /* The entry point checks that num_values is not greater than
    1263              :          the amount of fields in 'fields'.  */
    1264          375 :       for (size_t i = 0; i < num_values; i++)
    1265              :         {
    1266          225 :           result->m_values.quick_push (values[i]);
    1267          225 :           result->m_fields.quick_push (fields->get_field (i));
    1268              :         }
    1269              :     }
    1270              :   else
    1271            0 :     gcc_unreachable ();
    1272              : 
    1273          615 :   record (result);
    1274          615 :   return result;
    1275              : }
    1276              : 
    1277              : /* Create a recording::unary_op instance and add it to this context's
    1278              :    list of mementos.
    1279              : 
    1280              :    Implements the post-error-checking part of
    1281              :    gcc_jit_context_new_unary_op.  */
    1282              : 
    1283              : recording::rvalue *
    1284          128 : recording::context::new_unary_op (recording::location *loc,
    1285              :                                   enum gcc_jit_unary_op op,
    1286              :                                   recording::type *result_type,
    1287              :                                   recording::rvalue *a)
    1288              : {
    1289          128 :   recording::rvalue *result =
    1290          128 :     new unary_op (this, loc, op, result_type, a);
    1291          128 :   record (result);
    1292          128 :   return result;
    1293              : }
    1294              : 
    1295              : /* Create a recording::binary_op instance and add it to this context's
    1296              :    list of mementos.
    1297              : 
    1298              :    Implements the post-error-checking part of
    1299              :    gcc_jit_context_new_binary_op.  */
    1300              : 
    1301              : recording::rvalue *
    1302         3333 : recording::context::new_binary_op (recording::location *loc,
    1303              :                                    enum gcc_jit_binary_op op,
    1304              :                                    recording::type *result_type,
    1305              :                                    recording::rvalue *a,
    1306              :                                    recording::rvalue *b)
    1307              : {
    1308         3333 :   recording::rvalue *result =
    1309         3333 :     new binary_op (this, loc, op, result_type, a, b);
    1310         3333 :   record (result);
    1311         3333 :   return result;
    1312              : }
    1313              : 
    1314              : /* Create a recording::comparison instance and add it to this context's
    1315              :    list of mementos.
    1316              : 
    1317              :    Implements the post-error-checking part of
    1318              :    gcc_jit_context_new_comparison.  */
    1319              : 
    1320              : recording::rvalue *
    1321         1509 : recording::context::new_comparison (recording::location *loc,
    1322              :                                     enum gcc_jit_comparison op,
    1323              :                                     recording::rvalue *a,
    1324              :                                     recording::rvalue *b)
    1325              : {
    1326         1509 :   recording::rvalue *result = new comparison (this, loc, op, a, b);
    1327         1509 :   record (result);
    1328         1509 :   return result;
    1329              : }
    1330              : 
    1331              : /* Create a recording::cast instance and add it to this context's list
    1332              :    of mementos.
    1333              : 
    1334              :    Implements the post-error-checking part of
    1335              :    gcc_jit_context_new_cast.  */
    1336              : 
    1337              : recording::rvalue *
    1338          379 : recording::context::new_cast (recording::location *loc,
    1339              :                               recording::rvalue *expr,
    1340              :                               recording::type *type_)
    1341              : {
    1342          379 :   recording::rvalue *result = new cast (this, loc, expr, type_);
    1343          379 :   record (result);
    1344          379 :   return result;
    1345              : }
    1346              : 
    1347              : /* Create a recording::bitcast instance and add it to this context's list
    1348              :    of mementos.
    1349              : 
    1350              :    Implements the post-error-checking part of
    1351              :    gcc_jit_context_new_bitcast.  */
    1352              : 
    1353              : recording::rvalue *
    1354           25 : recording::context::new_bitcast (location *loc,
    1355              :                                  rvalue *expr,
    1356              :                                  type *type_)
    1357              : {
    1358           25 :   recording::rvalue *result = new bitcast (this, loc, expr, type_);
    1359           25 :   record (result);
    1360           25 :   return result;
    1361              : }
    1362              : 
    1363              : /* Create a recording::call instance and add it to this context's list
    1364              :    of mementos.
    1365              : 
    1366              :    Implements the post-error-checking part of
    1367              :    gcc_jit_context_new_call.  */
    1368              : 
    1369              : recording::rvalue *
    1370          805 : recording::context::new_call (recording::location *loc,
    1371              :                               function *func,
    1372              :                               int numargs , recording::rvalue **args)
    1373              : {
    1374          805 :   recording::rvalue *result = new call (this, loc, func, numargs, args);
    1375          805 :   record (result);
    1376          805 :   return result;
    1377              : }
    1378              : 
    1379              : /* Create a recording::call_through_ptr instance and add it to this
    1380              :    context's list of mementos.
    1381              : 
    1382              :    Implements the post-error-checking part of
    1383              :    gcc_jit_context_new_call_through_ptr.  */
    1384              : 
    1385              : recording::rvalue *
    1386           15 : recording::context::new_call_through_ptr (recording::location *loc,
    1387              :                                           recording::rvalue *fn_ptr,
    1388              :                                           int numargs,
    1389              :                                           recording::rvalue **args)
    1390              :   {
    1391           15 :   recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
    1392           15 :   record (result);
    1393           15 :   return result;
    1394              : }
    1395              : 
    1396              : /* Create a recording::array_access instance and add it to this context's list
    1397              :    of mementos.
    1398              : 
    1399              :    Implements the post-error-checking part of
    1400              :    gcc_jit_context_new_array_access.  */
    1401              : 
    1402              : recording::lvalue *
    1403          474 : recording::context::new_array_access (recording::location *loc,
    1404              :                                       recording::rvalue *ptr,
    1405              :                                       recording::rvalue *index)
    1406              : {
    1407          474 :   recording::lvalue *result = new array_access (this, loc, ptr, index);
    1408          474 :   record (result);
    1409          474 :   return result;
    1410              : }
    1411              : 
    1412              : /* Create a recording::convert_vector instance and add it to this context's list
    1413              :    of mementos.
    1414              : 
    1415              :    Implements the post-error-checking part of
    1416              :    gcc_jit_context_convert_vector.  */
    1417              : 
    1418              : recording::rvalue *
    1419           15 : recording::context::new_convert_vector (recording::location *loc,
    1420              :                                     recording::rvalue *vector,
    1421              :                                     recording::type *type)
    1422              : {
    1423              :   // TODO: instead have an "internal function" memento?
    1424           15 :   recording::rvalue *result = new convert_vector (this, loc, vector, type);
    1425           15 :   record (result);
    1426           15 :   return result;
    1427              : }
    1428              : 
    1429              : /* Create a recording::vector_access instance and add it to this context's list
    1430              :    of mementos.
    1431              : 
    1432              :    Implements the post-error-checking part of
    1433              :    gcc_jit_context_new_vector_access.  */
    1434              : 
    1435              : recording::lvalue *
    1436           15 : recording::context::new_vector_access (recording::location *loc,
    1437              :                                       recording::rvalue *vector,
    1438              :                                       recording::rvalue *index)
    1439              : {
    1440           15 :   recording::lvalue *result = new vector_access (this, loc, vector, index);
    1441           15 :   record (result);
    1442           15 :   return result;
    1443              : }
    1444              : 
    1445              : /* Create a recording::case_ instance and add it to this context's list
    1446              :    of mementos.
    1447              : 
    1448              :    Implements the post-error-checking part of
    1449              :    gcc_jit_context_new_case.  */
    1450              : 
    1451              : recording::case_ *
    1452           95 : recording::context::new_case (recording::rvalue *min_value,
    1453              :                               recording::rvalue *max_value,
    1454              :                               recording::block *block)
    1455              : {
    1456           95 :   recording::case_ *result = new case_ (this, min_value, max_value, block);
    1457           95 :   record (result);
    1458           95 :   return result;
    1459              : }
    1460              : 
    1461              : /* Set the given string option for this context, or add an error if
    1462              :    it's not recognized.
    1463              : 
    1464              :    Implements the post-error-checking part of
    1465              :    gcc_jit_context_set_str_option.  */
    1466              : 
    1467              : void
    1468         1757 : recording::context::set_str_option (enum gcc_jit_str_option opt,
    1469              :                                     const char *value)
    1470              : {
    1471         1757 :   if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
    1472              :     {
    1473            0 :       add_error (NULL,
    1474              :                  "unrecognized (enum gcc_jit_str_option) value: %i", opt);
    1475            0 :       return;
    1476              :     }
    1477         1757 :   free (m_str_options[opt]);
    1478         1757 :   m_str_options[opt] = value ? xstrdup (value) : NULL;
    1479         1757 :   log_str_option (opt);
    1480              : }
    1481              : 
    1482              : const char*
    1483        11322 : recording::context::get_str_option (enum gcc_jit_str_option opt)
    1484              : {
    1485        11322 :   if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
    1486              :     {
    1487            0 :       add_error (NULL,
    1488              :                  "unrecognized (enum gcc_jit_str_option) value: %i", opt);
    1489            0 :       return NULL;
    1490              :     }
    1491        11322 :   return m_str_options[opt];
    1492              : }
    1493              : 
    1494              : void
    1495            5 : recording::context::set_output_ident (const char *ident)
    1496              : {
    1497            5 :   recording::output_ident *memento = new output_ident (this, ident);
    1498            5 :   record (memento);
    1499            5 : }
    1500              : 
    1501              : bool
    1502            0 : recording::context::get_abort_on_unsupported_target_builtin ()
    1503              : {
    1504            0 :   return m_abort_on_unsupported_target_builtin;
    1505              : }
    1506              : 
    1507              : void
    1508            0 : recording::context::set_abort_on_unsupported_target_builtin ()
    1509              : {
    1510            0 :   m_abort_on_unsupported_target_builtin = true;
    1511            0 : }
    1512              : 
    1513              : /* Set the given integer option for this context, or add an error if
    1514              :    it's not recognized.
    1515              : 
    1516              :    Implements the post-error-checking part of
    1517              :    gcc_jit_context_set_int_option.  */
    1518              : 
    1519              : void
    1520         1802 : recording::context::set_int_option (enum gcc_jit_int_option opt,
    1521              :                                     int value)
    1522              : {
    1523         1802 :   if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
    1524              :     {
    1525            0 :       add_error (NULL,
    1526              :                  "unrecognized (enum gcc_jit_int_option) value: %i", opt);
    1527            0 :       return;
    1528              :     }
    1529         1802 :   m_int_options[opt] = value;
    1530         1802 :   log_int_option (opt);
    1531              : }
    1532              : 
    1533              : /* Set the given boolean option for this context, or add an error if
    1534              :    it's not recognized.
    1535              : 
    1536              :    Implements the post-error-checking part of
    1537              :    gcc_jit_context_set_bool_option.  */
    1538              : 
    1539              : void
    1540         7569 : recording::context::set_bool_option (enum gcc_jit_bool_option opt,
    1541              :                                      int value)
    1542              : {
    1543         7569 :   if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
    1544              :     {
    1545            0 :       add_error (NULL,
    1546              :                  "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
    1547            0 :       return;
    1548              :     }
    1549         7569 :   m_bool_options[opt] = value ? true : false;
    1550         7569 :   log_bool_option (opt);
    1551              : }
    1552              : 
    1553              : void
    1554           10 : recording::context::set_inner_bool_option (enum inner_bool_option inner_opt,
    1555              :                                            int value)
    1556              : {
    1557           10 :   gcc_assert (inner_opt >= 0 && inner_opt < NUM_INNER_BOOL_OPTIONS);
    1558           10 :   m_inner_bool_options[inner_opt] = value ? true : false;
    1559           10 :   log_inner_bool_option (inner_opt);
    1560           10 : }
    1561              : 
    1562              : 
    1563              : /* Add the given optname to this context's list of extra options.
    1564              : 
    1565              :    Implements the post-error-checking part of
    1566              :    gcc_jit_context_add_command_line_option.  */
    1567              : 
    1568              : void
    1569         1387 : recording::context::add_command_line_option (const char *optname)
    1570              : {
    1571         1387 :   m_command_line_options.safe_push (xstrdup (optname));
    1572         1387 : }
    1573              : 
    1574              : /* Add any user-provided extra options, starting with any from
    1575              :    parent contexts.
    1576              :    Called by playback::context::make_fake_args.  */
    1577              : 
    1578              : void
    1579         1351 : recording::context::append_command_line_options (vec <char *> *argvec)
    1580              : {
    1581         1351 :   if (m_parent_ctxt)
    1582           20 :     m_parent_ctxt->append_command_line_options (argvec);
    1583              : 
    1584              :   int i;
    1585              :   char *optname;
    1586         2208 :   FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
    1587          857 :     argvec->safe_push (xstrdup (optname));
    1588         1351 : }
    1589              : 
    1590              : /* Add the given optname to this context's list of extra driver options.  */
    1591              : 
    1592              : void
    1593           47 : recording::context::add_driver_option (const char *optname)
    1594              : {
    1595           47 :   m_driver_options.safe_push (xstrdup (optname));
    1596           47 : }
    1597              : 
    1598              : /* Add any user-provided driver options, starting with any from
    1599              :    parent contexts.
    1600              :    Called by playback::context::invoke_driver.  */
    1601              : 
    1602              : void
    1603         1159 : recording::context::append_driver_options (auto_string_vec *argvec)
    1604              : {
    1605         1159 :   if (m_parent_ctxt)
    1606           20 :     m_parent_ctxt->append_driver_options (argvec);
    1607              : 
    1608              :   int i;
    1609              :   char *optname;
    1610              : 
    1611         1174 :   FOR_EACH_VEC_ELT (m_driver_options, i, optname)
    1612           15 :     argvec->safe_push (xstrdup (optname));
    1613         1159 : }
    1614              : 
    1615              : /* Add the given dumpname/out_ptr pair to this context's list of requested
    1616              :    dumps.
    1617              : 
    1618              :    Implements the post-error-checking part of
    1619              :    gcc_jit_context_enable_dump.  */
    1620              : 
    1621              : void
    1622           50 : recording::context::enable_dump (const char *dumpname,
    1623              :                                  char **out_ptr)
    1624              : {
    1625           50 :   requested_dump d;
    1626           50 :   gcc_assert (dumpname);
    1627           50 :   gcc_assert (out_ptr);
    1628              : 
    1629           50 :   d.m_dumpname = dumpname;
    1630           50 :   d.m_out_ptr = out_ptr;
    1631           50 :   *out_ptr = NULL;
    1632           50 :   m_requested_dumps.safe_push (d);
    1633           50 : }
    1634              : 
    1635              : /* Validate this context, and if it passes, compile it to memory
    1636              :    (within a mutex).
    1637              : 
    1638              :    Implements the post-error-checking part of
    1639              :    gcc_jit_context_compile.  */
    1640              : 
    1641              : result *
    1642         1714 : recording::context::compile ()
    1643              : {
    1644         1714 :   if (m_populated_target_info)
    1645              :   {
    1646            1 :     add_error (NULL,
    1647              :       "cannot compile after calling gcc_jit_context_get_target_info");
    1648            1 :     return NULL;
    1649              :   }
    1650              : 
    1651         1713 :   JIT_LOG_SCOPE (get_logger ());
    1652              : 
    1653         1713 :   log_all_options ();
    1654              : 
    1655         1713 :   validate ();
    1656              : 
    1657         1713 :   if (errors_occurred ())
    1658              :     return NULL;
    1659              : 
    1660              :   /* Set up a compile_to_memory playback context.  */
    1661         1173 :   ::gcc::jit::playback::compile_to_memory replayer (this);
    1662              : 
    1663              :   /* Use it.  */
    1664         1173 :   replayer.compile ();
    1665              : 
    1666              :   /* Get the jit::result (or NULL) from the
    1667              :      compile_to_memory playback context.  */
    1668         1173 :   return replayer.get_result_obj ();
    1669         1713 : }
    1670              : 
    1671              : /* Validate this context, and if it passes, compile it to a file
    1672              :    (within a mutex).
    1673              : 
    1674              :    Implements the post-error-checking part of
    1675              :    gcc_jit_context_compile_to_file.  */
    1676              : 
    1677              : void
    1678          126 : recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
    1679              :                                      const char *output_path)
    1680              : {
    1681          126 :   if (m_populated_target_info)
    1682              :   {
    1683            0 :     add_error (NULL,
    1684              :       "cannot compile after calling gcc_jit_context_get_target_info");
    1685            0 :     return;
    1686              :   }
    1687              : 
    1688          126 :   JIT_LOG_SCOPE (get_logger ());
    1689              : 
    1690          126 :   log_all_options ();
    1691              : 
    1692          126 :   validate ();
    1693              : 
    1694          126 :   if (errors_occurred ())
    1695            0 :     return;
    1696              : 
    1697              :   /* Set up a compile_to_file playback context.  */
    1698          126 :   ::gcc::jit::playback::compile_to_file replayer (this,
    1699              :                                                   output_kind,
    1700          126 :                                                   output_path);
    1701              : 
    1702              :   /* Use it.  */
    1703          126 :   replayer.compile ();
    1704          126 : }
    1705              : 
    1706              : void
    1707           32 : recording::context::populate_target_info ()
    1708              : {
    1709           32 :   JIT_LOG_SCOPE (get_logger ());
    1710              : 
    1711           32 :   log_all_options ();
    1712              : 
    1713           32 :   if (errors_occurred ())
    1714            0 :     return;
    1715              : 
    1716           32 :   add_driver_option ("-fsyntax-only");
    1717           32 :   m_populated_target_info = true;
    1718              : 
    1719              :   /* Set up a populate_target_info playback context.  */
    1720           32 :   ::gcc::jit::playback::populate_target_info replayer (this);
    1721              : 
    1722              :   /* Use it.  */
    1723           32 :   replayer.compile ();
    1724              : 
    1725           32 :   m_target_info = replayer.move_target_info ();
    1726           32 : }
    1727              : 
    1728              : /* Format the given error using printf's conventions, print
    1729              :    it to stderr, and add it to the context.  */
    1730              : 
    1731              : void
    1732           25 : recording::context::add_diagnostic (location *loc,
    1733              :   diagnostics::kind diagnostic_kind, const char *fmt, ...)
    1734              : {
    1735           25 :   va_list ap;
    1736           25 :   va_start (ap, fmt);
    1737           25 :   add_error_va (loc, diagnostic_kind, fmt, ap);
    1738           25 :   va_end (ap);
    1739           25 : }
    1740              : 
    1741              : void
    1742          464 : recording::context::add_error (location *loc, const char *fmt, ...)
    1743              : {
    1744          464 :   va_list ap;
    1745          464 :   va_start (ap, fmt);
    1746          464 :   add_error_va (loc, diagnostics::kind::error, fmt, ap);
    1747          464 :   va_end (ap);
    1748          464 : }
    1749              : 
    1750              : /* Format the given error using printf's conventions, print
    1751              :    it to stderr, and add it to the context.  */
    1752              : 
    1753              : void
    1754         5377 : recording::context::add_error_va (location *loc,
    1755              :   diagnostics::kind diagnostic_kind, const char *fmt, va_list ap)
    1756              : {
    1757         5377 :   int len;
    1758         5377 :   char *malloced_msg;
    1759         5377 :   const char *errmsg;
    1760         5377 :   bool has_ownership;
    1761              : 
    1762         5377 :   JIT_LOG_SCOPE (get_logger ());
    1763              : 
    1764         5377 :   len = vasprintf (&malloced_msg, fmt, ap);
    1765         5377 :   if (malloced_msg == NULL || len < 0)
    1766              :     {
    1767              :       errmsg = "out of memory generating error message";
    1768              :       has_ownership = false;
    1769              :     }
    1770              :   else
    1771              :     {
    1772         5377 :       errmsg = malloced_msg;
    1773         5377 :       has_ownership = true;
    1774              :     }
    1775         5377 :   if (get_logger ())
    1776         5376 :     get_logger ()->log ("%s %i: %s",
    1777              :                         diagnostics::get_text_for_kind (diagnostic_kind),
    1778              :                         m_error_count, errmsg);
    1779              : 
    1780         5377 :   const char *ctxt_progname =
    1781         5377 :     get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
    1782         5377 :   if (!ctxt_progname)
    1783            6 :     ctxt_progname = "libgccjit.so";
    1784              : 
    1785         5377 :   bool print_errors_to_stderr =
    1786         5377 :       get_inner_bool_option (INNER_BOOL_OPTION_PRINT_ERRORS_TO_STDERR);
    1787         5377 :   if (print_errors_to_stderr)
    1788              :   {
    1789         5377 :     if (loc)
    1790         1765 :       fprintf (stderr, "%s: %s: %s: %s\n",
    1791              :                ctxt_progname,
    1792              :                loc->get_debug_string (),
    1793              :                diagnostics::get_text_for_kind (diagnostic_kind),
    1794              :                errmsg);
    1795              :     else
    1796         3612 :       fprintf (stderr, "%s: %s: %s\n",
    1797              :                ctxt_progname,
    1798              :                diagnostics::get_text_for_kind (diagnostic_kind),
    1799              :                errmsg);
    1800              :   }
    1801              : 
    1802         5377 :   if (!m_error_count)
    1803              :     {
    1804          611 :       m_first_error_str = const_cast <char *> (errmsg);
    1805          611 :       m_owns_first_error_str = has_ownership;
    1806              :     }
    1807              : 
    1808         5377 :   if (m_owns_last_error_str)
    1809         4771 :     if (m_last_error_str != m_first_error_str)
    1810         4441 :       free (m_last_error_str);
    1811         5377 :   m_last_error_str = const_cast <char *> (errmsg);
    1812         5377 :   m_owns_last_error_str = has_ownership;
    1813              : 
    1814         5377 :   if (diagnostic_kind == diagnostics::kind::error)
    1815         5367 :     m_error_count++;
    1816         5377 : }
    1817              : 
    1818              : /* Get the message for the first error that occurred on this context, or
    1819              :    NULL if no errors have occurred on it.
    1820              : 
    1821              :    Implements the post-error-checking part of
    1822              :    gcc_jit_context_get_first_error.  */
    1823              : 
    1824              : const char *
    1825          530 : recording::context::get_first_error () const
    1826              : {
    1827          530 :   return m_first_error_str;
    1828              : }
    1829              : 
    1830              : /* Get the message for the last error that occurred on this context, or
    1831              :    NULL if no errors have occurred on it.
    1832              : 
    1833              :    Implements the post-error-checking part of
    1834              :    gcc_jit_context_get_last_error.  */
    1835              : 
    1836              : const char *
    1837           86 : recording::context::get_last_error () const
    1838              : {
    1839           86 :   return m_last_error_str;
    1840              : }
    1841              : 
    1842              : /* Lazily generate and record a recording::type representing an opaque
    1843              :    struct named "FILE".
    1844              : 
    1845              :    For use if client code tries to dereference the result of
    1846              :    get_type (GCC_JIT_TYPE_FILE_PTR).  */
    1847              : 
    1848              : recording::type *
    1849           19 : recording::context::get_opaque_FILE_type ()
    1850              : {
    1851           19 :   if (!m_FILE_type)
    1852           19 :     m_FILE_type = new_struct_type (NULL, "FILE");
    1853           19 :   return m_FILE_type;
    1854              : }
    1855              : 
    1856              : /* Dump a C-like representation of the given context to the given path.
    1857              :    If UPDATE_LOCATIONS is true, update the locations within the
    1858              :    context's mementos to point to the dumpfile.
    1859              : 
    1860              :    Implements the post-error-checking part of
    1861              :    gcc_jit_context_dump_to_file.  */
    1862              : 
    1863              : void
    1864           14 : recording::context::dump_to_file (const char *path, bool update_locations)
    1865              : {
    1866           14 :   int i;
    1867           14 :   dump d (*this, path, update_locations);
    1868              : 
    1869              :   /* Forward declaration of structs and unions.  */
    1870           14 :   compound_type *st;
    1871           30 :   FOR_EACH_VEC_ELT (m_compound_types, i, st)
    1872              :     {
    1873            2 :       d.write ("%s;\n\n", st->get_debug_string ());
    1874              :     }
    1875              : 
    1876              :   /* Content of structs, where set.  */
    1877           16 :   FOR_EACH_VEC_ELT (m_compound_types, i, st)
    1878            2 :     if (st->get_fields ())
    1879              :       {
    1880            2 :         st->get_fields ()->write_to_dump (d);
    1881            2 :         d.write ("\n");
    1882              :       }
    1883              : 
    1884              :   /* Globals.  */
    1885              :   global *g;
    1886           14 :   FOR_EACH_VEC_ELT (m_globals, i, g)
    1887              :     {
    1888            0 :       g->write_to_dump (d);
    1889              :     }
    1890           14 :   if (!m_globals.is_empty ())
    1891            0 :     d.write ("\n");
    1892              : 
    1893              :   function *fn;
    1894           28 :   FOR_EACH_VEC_ELT (m_functions, i, fn)
    1895              :     {
    1896           14 :       fn->write_to_dump (d);
    1897              :     }
    1898              : 
    1899              :   top_level_asm *tla;
    1900           14 :   FOR_EACH_VEC_ELT (m_top_level_asms, i, tla)
    1901            0 :     tla->write_to_dump (d);
    1902           14 : }
    1903              : 
    1904              : static const char * const
    1905              :  str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
    1906              :   "GCC_JIT_STR_OPTION_PROGNAME",
    1907              :   "GCC_JIT_STR_OPTION_SPECIAL_CHARS_IN_FUNC_NAMES",
    1908              : };
    1909              : 
    1910              : static const char * const
    1911              :  int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
    1912              :   "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
    1913              : };
    1914              : 
    1915              : static const char * const
    1916              :  bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
    1917              :   "GCC_JIT_BOOL_OPTION_DEBUGINFO",
    1918              :   "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
    1919              :   "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
    1920              :   "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
    1921              :   "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
    1922              :   "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
    1923              :   "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
    1924              :   "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES",
    1925              : };
    1926              : 
    1927              : static const char * const
    1928              :  inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = {
    1929              :   "gcc_jit_context_set_bool_allow_unreachable_blocks",
    1930              :   "gcc_jit_context_set_bool_use_external_driver",
    1931              :   "gcc_jit_context_set_bool_print_errors_to_stderr",
    1932              : };
    1933              : 
    1934              : /* Write the current value of all options to the log file (if any).  */
    1935              : 
    1936              : void
    1937         1871 : recording::context::log_all_options () const
    1938              : {
    1939         1871 :   int opt_idx;
    1940              : 
    1941         1871 :   if (!get_logger ())
    1942              :     return;
    1943              : 
    1944         3441 :   for (opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
    1945         2294 :     log_str_option ((enum gcc_jit_str_option)opt_idx);
    1946              : 
    1947         2294 :   for (opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
    1948         1147 :     log_int_option ((enum gcc_jit_int_option)opt_idx);
    1949              : 
    1950        10323 :   for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
    1951         9176 :     log_bool_option ((enum gcc_jit_bool_option)opt_idx);
    1952         4588 :   for (opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
    1953         3441 :     log_inner_bool_option ((enum inner_bool_option)opt_idx);
    1954              : }
    1955              : 
    1956              : /* Write the current value of the given string option to the
    1957              :    log file (if any).  */
    1958              : 
    1959              : void
    1960         4051 : recording::context::log_str_option (enum gcc_jit_str_option opt) const
    1961              : {
    1962         4051 :   gcc_assert (opt < GCC_JIT_NUM_STR_OPTIONS);
    1963         4051 :   if (get_logger ())
    1964              :     {
    1965         3371 :       if (m_str_options[opt])
    1966         2149 :         log ("%s: \"%s\"",
    1967         2149 :              str_option_reproducer_strings[opt],
    1968              :              m_str_options[opt]);
    1969              :       else
    1970         1222 :         log ("%s: NULL",
    1971         1222 :              str_option_reproducer_strings[opt]);
    1972              :     }
    1973         4051 : }
    1974              : 
    1975              : /* Write the current value of the given int option to the
    1976              :    log file (if any).  */
    1977              : 
    1978              : void
    1979         2949 : recording::context::log_int_option (enum gcc_jit_int_option opt) const
    1980              : {
    1981         2949 :   gcc_assert (opt < GCC_JIT_NUM_INT_OPTIONS);
    1982         2949 :   if (get_logger ())
    1983         2264 :     log ("%s: %i",
    1984              :          int_option_reproducer_strings[opt],
    1985         2264 :          m_int_options[opt]);
    1986         2949 : }
    1987              : 
    1988              : /* Write the current value of the given bool option to the
    1989              :    log file (if any).  */
    1990              : 
    1991              : void
    1992        16745 : recording::context::log_bool_option (enum gcc_jit_bool_option opt) const
    1993              : {
    1994        16745 :   gcc_assert (opt < GCC_JIT_NUM_BOOL_OPTIONS);
    1995        16745 :   if (get_logger ())
    1996        29032 :     log ("%s: %s",
    1997        14516 :          bool_option_reproducer_strings[opt],
    1998        14516 :          m_bool_options[opt] ? "true" : "false");
    1999        16745 : }
    2000              : 
    2001              : /* Write the current value of the given "inner" bool option to the
    2002              :    log file (if any).  */
    2003              : 
    2004              : void
    2005         3451 : recording::context::log_inner_bool_option (enum inner_bool_option opt) const
    2006              : {
    2007         3451 :   gcc_assert (opt < NUM_INNER_BOOL_OPTIONS);
    2008         3451 :   if (get_logger ())
    2009         6902 :     log ("%s: %s",
    2010         3451 :          inner_bool_option_reproducer_strings[opt],
    2011         3451 :          m_inner_bool_options[opt] ? "true" : "false");
    2012         3451 : }
    2013              : 
    2014              : /* Write C source code to PATH that attempts to replay the API
    2015              :    calls made to this context (and its parents), for use in
    2016              :    minimizing test cases for libgccjit.
    2017              : 
    2018              :    Implements the post-error-checking part of
    2019              :    gcc_jit_context_dump_reproducer_to_file.  */
    2020              : 
    2021              : void
    2022         1143 : recording::context::dump_reproducer_to_file (const char *path)
    2023              : {
    2024         1143 :   JIT_LOG_SCOPE (get_logger ());
    2025         1143 :   reproducer r (*this, path);
    2026              : 
    2027              :   /* Generate the "ancestry" of this context, as a list.  */
    2028         1143 :   auto_vec <context *> ascending_contexts;
    2029         2302 :   for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
    2030         1159 :     ascending_contexts.safe_push (ctxt);
    2031              : 
    2032              :   /* Reverse the list, giving a list of contexts from
    2033              :      top-most parent context down through to youngest child context.
    2034              :      We will use this list as the parameters of the functions in
    2035              :      our generated file.  */
    2036         1143 :   unsigned num_ctxts = ascending_contexts.length ();
    2037         1143 :   auto_vec <context *> contexts (num_ctxts);
    2038         2302 :   for (unsigned i = 0; i < num_ctxts; i++)
    2039         1159 :     contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
    2040              : 
    2041              :   /* contexts[0] should be the top-level context.  */
    2042         1143 :   gcc_assert (contexts[0]);
    2043         1143 :   gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
    2044              : 
    2045              :   /* The final element in contexts should be "this".  */
    2046         1143 :   gcc_assert (contexts[contexts.length () - 1] == this);
    2047         1143 :   gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
    2048              :               == contexts[0]);
    2049              : 
    2050         1143 :   r.write ("/* This code was autogenerated by"
    2051              :            " gcc_jit_context_dump_reproducer_to_file.\n\n");
    2052         1143 :   print_version (r.get_file (), "  ", false);
    2053         1143 :   r.write ("*/\n");
    2054         1143 :   r.write ("#include <libgccjit.h>\n\n");
    2055         1143 :   r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
    2056         1143 :   r.write ("static void\nset_options (");
    2057         1143 :   r.write_params (contexts);
    2058         1143 :   r.write (");\n\n");
    2059         1143 :   r.write ("static void\ncreate_code (");
    2060         1143 :   r.write_params (contexts);
    2061         1143 :   r.write (");\n\n");
    2062         1143 :   r.write ("int\nmain (int argc, const char **argv)\n");
    2063         1143 :   r.write ("{\n");
    2064         2302 :   for (unsigned i = 0; i < num_ctxts; i++)
    2065         2318 :     r.write ("  gcc_jit_context *%s;\n",
    2066         1159 :              r.get_identifier (contexts[i]));
    2067         1143 :   r.write ("  gcc_jit_result *result;\n"
    2068              :            "\n");
    2069              : 
    2070              :   /* Create the contexts.
    2071              :      The top-level context is acquired from a clean slate, the others as
    2072              :      children of the prior context.  */
    2073         1143 :   r.write ("  %s = gcc_jit_context_acquire ();\n",
    2074         1143 :            r.get_identifier (contexts[0]));
    2075         1159 :   for (unsigned i = 1; i < num_ctxts; i++)
    2076           32 :     r.write ("  %s = gcc_jit_context_new_child_context (%s);\n",
    2077           16 :              r.get_identifier (contexts[i]),
    2078           16 :              r.get_identifier (contexts[i - 1]));
    2079         1143 :   r.write ("  set_options (");
    2080         1143 :   r.write_args (contexts);
    2081         1143 :   r.write (");\n");
    2082         1143 :   r.write ("  create_code (");
    2083         1143 :   r.write_args (contexts);
    2084         1143 :   r.write (");\n");
    2085              : 
    2086         1143 :   r.write ("  result = gcc_jit_context_compile (%s);\n",
    2087              :            r.get_identifier (this));
    2088              : 
    2089         2302 :   for (unsigned i = num_ctxts; i > 0; i--)
    2090         1159 :     r.write ("  gcc_jit_context_release (%s);\n",
    2091         1159 :              r.get_identifier (contexts[i - 1]));
    2092              : 
    2093         1143 :   r.write ("  gcc_jit_result_release (result);\n"
    2094              :            "  return 0;\n"
    2095              :            "}\n\n");
    2096              : 
    2097              :   /* Define (char *) variables for use in calls to
    2098              :      gcc_jit_context_enable_dump.  */
    2099         2302 :   for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
    2100              :     {
    2101         1179 :       if (m_requested_dumps.length ())
    2102              :         {
    2103           20 :           r.write ("/* Requested dumps for %s.  */\n",
    2104           20 :                    r.get_identifier (contexts[ctxt_idx]));
    2105           55 :           for (unsigned i = 0; i < m_requested_dumps.length (); i++)
    2106           70 :             r.write ("static char *dump_%p;\n",
    2107           35 :                      (void *)&m_requested_dumps[i]);
    2108           20 :           r.write ("\n");
    2109              :         }
    2110              :     }
    2111              : 
    2112              :   /* Write out values of options.  */
    2113         1143 :   r.write ("static void\nset_options (");
    2114         1143 :   r.write_params (contexts);
    2115         1143 :   r.write (")\n{\n");
    2116         2302 :   for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
    2117              :     {
    2118         1159 :       if (ctxt_idx > 0)
    2119           16 :         r.write ("\n");
    2120              : 
    2121         2318 :       r.write ("  /* Set options for %s.  */\n",
    2122         1159 :                r.get_identifier (contexts[ctxt_idx]));
    2123              : 
    2124         1159 :       r.write ("  /* String options.  */\n");
    2125         3477 :       for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
    2126              :         {
    2127         2318 :           r.write ("  gcc_jit_context_set_str_option (%s,\n"
    2128              :                    "                                  %s,\n",
    2129         2318 :                    r.get_identifier (contexts[ctxt_idx]),
    2130         2318 :                    str_option_reproducer_strings[opt_idx]);
    2131         2318 :           if (m_str_options[opt_idx])
    2132         1089 :             r.write ("                                  \"%s\");\n",
    2133              :                      m_str_options[opt_idx]);
    2134              :           else
    2135         1229 :             r.write ("                                  NULL);\n");
    2136              :         }
    2137         1159 :       r.write ("  /* Int options.  */\n");
    2138         2318 :       for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
    2139         1159 :         r.write ("  gcc_jit_context_set_int_option (%s,\n"
    2140              :                  "                                  %s,\n"
    2141              :                  "                                  %i);\n",
    2142         1159 :                  r.get_identifier (contexts[ctxt_idx]),
    2143         1159 :                  int_option_reproducer_strings[opt_idx],
    2144              :                  m_int_options[opt_idx]);
    2145         1159 :       r.write ("  /* Boolean options.  */\n");
    2146        10431 :       for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
    2147         9272 :         r.write ("  gcc_jit_context_set_bool_option (%s,\n"
    2148              :                  "                                  %s,\n"
    2149              :                  "                                  %i);\n",
    2150         9272 :                  r.get_identifier (contexts[ctxt_idx]),
    2151         9272 :                  bool_option_reproducer_strings[opt_idx],
    2152         9272 :                  m_bool_options[opt_idx]);
    2153         4636 :       for (int opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
    2154        10431 :         r.write ("  %s (%s, %i);\n",
    2155         3477 :                  inner_bool_option_reproducer_strings[opt_idx],
    2156         3477 :                  r.get_identifier (contexts[ctxt_idx]),
    2157         3477 :                  m_inner_bool_options[opt_idx]);
    2158              : 
    2159         1159 :       if (!m_command_line_options.is_empty ())
    2160              :         {
    2161         1070 :           int i;
    2162         1070 :           char *optname;
    2163         1070 :           r.write ("  /* User-provided command-line options.  */\n");
    2164         3245 :           FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
    2165         2210 :             r.write ("  gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
    2166         1105 :                      r.get_identifier (contexts[ctxt_idx]),
    2167              :                      optname);
    2168              :         }
    2169              : 
    2170         1159 :       if (!m_driver_options.is_empty ())
    2171              :         {
    2172           10 :           int i;
    2173           10 :           char *optname;
    2174           10 :           r.write ("  /* User-provided driver options.  */\n");
    2175           35 :           FOR_EACH_VEC_ELT (m_driver_options, i, optname)
    2176           30 :             r.write ("  gcc_jit_context_add_driver_option (%s, \"%s\");\n",
    2177           15 :                      r.get_identifier (contexts[ctxt_idx]),
    2178              :                      optname);
    2179              :         }
    2180              : 
    2181         1159 :       if (m_requested_dumps.length ())
    2182              :         {
    2183           20 :           r.write ("  /* Requested dumps.  */\n");
    2184              :           /* Dumpfiles that were requested via gcc_jit_context_enable_dump.  */
    2185         1194 :           for (unsigned i = 0; i < m_requested_dumps.length (); i++)
    2186              :             {
    2187           35 :               r.write ("  gcc_jit_context_enable_dump (%s,\n"
    2188              :                        "                               \"%s\",\n"
    2189              :                        "                               &dump_%p);\n",
    2190           35 :                        r.get_identifier (contexts[ctxt_idx]),
    2191           35 :                        m_requested_dumps[i].m_dumpname,
    2192           35 :                        (void *)&m_requested_dumps[i]);
    2193              :             }
    2194              :         }
    2195              :     }
    2196         1143 :   r.write ("}\n\n");
    2197              : 
    2198         1143 :   r.write ("static void\ncreate_code (");
    2199         1143 :   r.write_params (contexts);
    2200         1143 :   r.write (")\n"
    2201              :            "{\n");
    2202         2302 :   for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
    2203              :     {
    2204         1159 :       memento *m;
    2205         1159 :       int i;
    2206         1159 :       if (ctxt_idx > 0)
    2207           16 :         r.write ("\n\n");
    2208              : 
    2209         1159 :       r.write ("  /* Replay of API calls for %s.  */\n",
    2210         1159 :                r.get_identifier (contexts[ctxt_idx]));
    2211       174733 :       FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
    2212       171336 :         m->write_reproducer (r);
    2213              :     }
    2214         1143 :   r.write ("}\n");
    2215         1143 : }
    2216              : 
    2217              : /* Copy the requested dumps within this context and all ancestors into
    2218              :    OUT. */
    2219              : 
    2220              : void
    2221         1351 : recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
    2222              : {
    2223         1351 :   if (m_parent_ctxt)
    2224           20 :     m_parent_ctxt->get_all_requested_dumps (out);
    2225              : 
    2226         1381 :   out->reserve (m_requested_dumps.length ());
    2227         1351 :   out->splice (m_requested_dumps);
    2228         1351 : }
    2229              : 
    2230              : /* Create a recording::top_level_asm instance and add it to this
    2231              :    context's list of mementos and to m_top_level_asms.
    2232              : 
    2233              :    Implements the post-error-checking part of
    2234              :    gcc_jit_context_add_top_level_asm.  */
    2235              : 
    2236              : void
    2237           10 : recording::context::add_top_level_asm (recording::location *loc,
    2238              :                                        const char *asm_stmts)
    2239              : {
    2240           10 :   recording::top_level_asm *asm_obj
    2241           10 :     = new recording::top_level_asm (this, loc, new_string (asm_stmts));
    2242           10 :   record (asm_obj);
    2243           10 :   m_top_level_asms.safe_push (asm_obj);
    2244           10 : }
    2245              : 
    2246              : /* This is a pre-compilation check for the context (and any parents).
    2247              : 
    2248              :    Detect errors within the context, adding errors if any are found.  */
    2249              : 
    2250              : void
    2251         1859 : recording::context::validate ()
    2252              : {
    2253         1859 :   JIT_LOG_SCOPE (get_logger ());
    2254              : 
    2255         1859 :   if (m_parent_ctxt)
    2256           20 :     m_parent_ctxt->validate ();
    2257              : 
    2258              :   int i;
    2259              :   function *fn;
    2260         6262 :   FOR_EACH_VEC_ELT (m_functions, i, fn)
    2261         4403 :     fn->validate ();
    2262         1859 : }
    2263              : 
    2264              : /* The implementation of class gcc::jit::recording::memento.  */
    2265              : 
    2266              : /* Get a (const char *) debug description of the given memento, by
    2267              :    calling the pure-virtual make_debug_string hook, caching the
    2268              :    result.
    2269              : 
    2270              :    It is intended that this should only be called in debugging and
    2271              :    error-handling paths, so this doesn't need to be particularly
    2272              :    optimized.  */
    2273              : 
    2274              : const char *
    2275       188985 : recording::memento::get_debug_string ()
    2276              : {
    2277       188985 :   if (!m_debug_string)
    2278        92673 :     m_debug_string = make_debug_string ();
    2279       188985 :   return m_debug_string->c_str ();
    2280              : }
    2281              : 
    2282              : /* Default implementation of recording::memento::write_to_dump, writing
    2283              :    an indented form of the memento's debug string to the dump.  */
    2284              : 
    2285              : void
    2286          156 : recording::memento::write_to_dump (dump &d)
    2287              : {
    2288          156 :   d.write ("  %s\n", get_debug_string ());
    2289          156 : }
    2290              : 
    2291              : /* The implementation of class gcc::jit::recording::string.  */
    2292              : 
    2293              : /* Constructor for gcc::jit::recording::string::string, allocating a
    2294              :    copy of the given text using new char[].  */
    2295              : 
    2296       139248 : recording::string::string (context *ctxt, const char *text, bool escaped)
    2297              : : memento (ctxt),
    2298       139248 :   m_escaped (escaped)
    2299              : {
    2300       139248 :   m_len = strlen (text);
    2301       139248 :   m_buffer = new char[m_len + 1];
    2302       139248 :   strcpy (m_buffer, text);
    2303       139248 : }
    2304              : 
    2305              : /* Destructor for gcc::jit::recording::string::string.  */
    2306              : 
    2307       277108 : recording::string::~string ()
    2308              : {
    2309       138554 :   delete[] m_buffer;
    2310       277108 : }
    2311              : 
    2312              : /* Function for making gcc::jit::recording::string instances on a
    2313              :    context via printf-style formatting.
    2314              : 
    2315              :    It is intended that this should only be called in debugging and
    2316              :    error-handling paths, so this doesn't need to be particularly
    2317              :    optimized, hence the double-copy of the string is acceptable.  */
    2318              : 
    2319              : recording::string *
    2320        29961 : recording::string::from_printf (context *ctxt, const char *fmt, ...)
    2321              : {
    2322        29961 :   int len;
    2323        29961 :   va_list ap;
    2324        29961 :   char *buf;
    2325        29961 :   recording::string *result;
    2326              : 
    2327        29961 :   va_start (ap, fmt);
    2328        29961 :   len = vasprintf (&buf, fmt, ap);
    2329        29961 :   va_end (ap);
    2330              : 
    2331        29961 :   if (buf == NULL || len < 0)
    2332              :     {
    2333            0 :       ctxt->add_error (NULL, "malloc failure");
    2334            0 :       return NULL;
    2335              :     }
    2336              : 
    2337        29961 :   result = ctxt->new_string (buf);
    2338        29961 :   free (buf);
    2339        29961 :   return result;
    2340              : }
    2341              : 
    2342              : /* Implementation of recording::memento::make_debug_string for strings,
    2343              :    wrapping the given string in quotes and escaping as necessary.  */
    2344              : 
    2345              : recording::string *
    2346        34750 : recording::string::make_debug_string ()
    2347              : {
    2348              :   /* Avoid infinite recursion into strings when logging all mementos:
    2349              :      don't re-escape strings:  */
    2350        34750 :   if (m_escaped)
    2351              :     return this;
    2352              : 
    2353              :   /* Wrap in quotes and do escaping etc */
    2354              : 
    2355        34750 :   size_t sz = (1 /* opening quote */
    2356        34750 :                + (m_len * 2) /* each char might get escaped */
    2357              :                + 1 /* closing quote */
    2358        34750 :                + 1); /* nil termintator */
    2359        34750 :   char *tmp = new char[sz];
    2360        34750 :   size_t len = 0;
    2361              : 
    2362              : #define APPEND(CH)  do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
    2363        34750 :   APPEND('"'); /* opening quote */
    2364      2928754 :   for (size_t i = 0; i < m_len ; i++)
    2365              :     {
    2366      2894004 :       char ch = m_buffer[i];
    2367      2894004 :       switch (ch)
    2368              :         {
    2369      2893604 :         default:
    2370      2893604 :           APPEND(ch);
    2371      2893604 :           break;
    2372          165 :         case '\t':
    2373          165 :           APPEND('\\');
    2374          165 :           APPEND('t');
    2375          165 :           break;
    2376          220 :         case '\n':
    2377          220 :           APPEND('\\');
    2378          220 :           APPEND('n');
    2379          220 :           break;
    2380           15 :         case '\\':
    2381           15 :         case '"':
    2382           15 :           APPEND('\\');
    2383           15 :           APPEND(ch);
    2384           15 :           break;
    2385              :         }
    2386              :     }
    2387        34750 :   APPEND('"'); /* closing quote */
    2388              : #undef APPEND
    2389        34750 :   tmp[len] = '\0'; /* nil termintator */
    2390              : 
    2391        34750 :   string *result = m_ctxt->new_string (tmp, true);
    2392              : 
    2393        34750 :   delete[] tmp;
    2394        34750 :   return result;
    2395              : }
    2396              : 
    2397              : /* Implementation of recording::memento::write_reproducer for strings. */
    2398              : 
    2399              : void
    2400       105658 : recording::string::write_reproducer (reproducer &)
    2401              : {
    2402              :   /* Empty.  */
    2403       105658 : }
    2404              : 
    2405              : /* The implementation of class gcc::jit::recording::output_ident.  */
    2406              : 
    2407              : /* Constructor for gcc::jit::recording::output_ident, allocating a
    2408              :    copy of the given text using new char[].  */
    2409              : 
    2410            5 : recording::output_ident::output_ident (context *ctxt, const char *ident)
    2411            5 : : memento (ctxt)
    2412              : {
    2413            5 :   m_ident = ident ? xstrdup (ident) : NULL;
    2414            5 : }
    2415              : 
    2416              : /* Destructor for gcc::jit::recording::output_ident.  */
    2417              : 
    2418           10 : recording::output_ident::~output_ident ()
    2419              : {
    2420            5 :   free (m_ident);
    2421           10 : }
    2422              : 
    2423              : /* Implementation of pure virtual hook recording::memento::replay_into
    2424              :    for recording::output_ident.  */
    2425              : 
    2426              : void
    2427            5 : recording::output_ident::replay_into (replayer *r)
    2428              : {
    2429            5 :   r->set_output_ident (m_ident);
    2430            5 : }
    2431              : 
    2432              : /* Implementation of recording::memento::make_debug_string for output_ident.  */
    2433              : 
    2434              : recording::string *
    2435            0 : recording::output_ident::make_debug_string ()
    2436              : {
    2437            0 :   return m_ctxt->new_string (m_ident);
    2438              : }
    2439              : 
    2440              : /* Implementation of recording::memento::write_reproducer for output_ident.  */
    2441              : 
    2442              : void
    2443            5 : recording::output_ident::write_reproducer (reproducer &r)
    2444              : {
    2445            5 :   r.write ("  gcc_jit_context_set_output_ident (%s, \"%s\");",
    2446              :            r.get_identifier (get_context ()),
    2447              :            m_ident);
    2448            5 : }
    2449              : 
    2450              : 
    2451              : /* The implementation of class gcc::jit::recording::location.  */
    2452              : 
    2453              : /* Implementation of recording::memento::replay_into for locations.
    2454              : 
    2455              :    Create a new playback::location and store it into the
    2456              :    recording::location's m_playback_obj field.  */
    2457              : 
    2458              : void
    2459          965 : recording::location::replay_into (replayer *r)
    2460              : {
    2461         1930 :   m_playback_obj = r->new_location (this,
    2462          965 :                                     m_filename->c_str (),
    2463              :                                     m_line,
    2464              :                                     m_column);
    2465          965 : }
    2466              : 
    2467              : /* Implementation of recording::memento::make_debug_string for locations,
    2468              :    turning them into the usual form:
    2469              :      FILENAME:LINE:COLUMN
    2470              :    like we do when emitting diagnostics.  */
    2471              : 
    2472              : recording::string *
    2473         9554 : recording::location::make_debug_string ()
    2474              : {
    2475         9554 :   return string::from_printf (m_ctxt,
    2476              :                               "%s:%i:%i",
    2477         9554 :                               m_filename->c_str (), m_line, m_column);
    2478              : }
    2479              : 
    2480              : /* Implementation of recording::memento::write_reproducer for locations. */
    2481              : 
    2482              : void
    2483         9571 : recording::location::write_reproducer (reproducer &r)
    2484              : {
    2485         9571 :   const char *id = r.make_identifier (this, "loc");
    2486         9571 :   r.write ("  gcc_jit_location *%s =\n"
    2487              :            "    gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
    2488              :            "    %s, /* const char *filename */\n"
    2489              :            "    %i, /* int line */\n"
    2490              :            "    %i);/* int column */\n",
    2491              :            id,
    2492              :            r.get_identifier (get_context ()),
    2493         9571 :            m_filename->get_debug_string (),
    2494              :            m_line, m_column);
    2495         9571 : }
    2496              : 
    2497              : /* The implementation of class gcc::jit::recording::type.  */
    2498              : 
    2499              : /* Given a type T, get the type T*.
    2500              : 
    2501              :    If this doesn't already exist, generate a new memento_of_get_pointer
    2502              :    instance and add it to this type's context's list of mementos.
    2503              : 
    2504              :    Otherwise, use the cached type.
    2505              : 
    2506              :    Implements the post-error-checking part of
    2507              :    gcc_jit_type_get_pointer.  */
    2508              : 
    2509              : recording::type *
    2510        48857 : recording::type::get_pointer ()
    2511              : {
    2512        48857 :   if (!m_pointer_to_this_type)
    2513              :     {
    2514        43810 :       m_pointer_to_this_type = new memento_of_get_pointer (this);
    2515        43810 :       m_ctxt->record (m_pointer_to_this_type);
    2516              :     }
    2517        48857 :   return m_pointer_to_this_type;
    2518              : }
    2519              : 
    2520              : /* Given a type T, get the type const T.
    2521              : 
    2522              :    Implements the post-error-checking part of
    2523              :    gcc_jit_type_get_const.  */
    2524              : 
    2525              : recording::type *
    2526          816 : recording::type::get_const ()
    2527              : {
    2528          816 :   recording::type *result = new memento_of_get_const (this);
    2529          816 :   m_ctxt->record (result);
    2530          816 :   return result;
    2531              : }
    2532              : 
    2533              : /* Given a type T, get the type restrict T.
    2534              : 
    2535              :    Implements the post-error-checking part of
    2536              :    gcc_jit_type_get_restrict.  */
    2537              : 
    2538              : recording::type *
    2539           10 : recording::type::get_restrict ()
    2540              : {
    2541           10 :   recording::type *result = new memento_of_get_restrict (this);
    2542           10 :   m_ctxt->record (result);
    2543           10 :   return result;
    2544              : }
    2545              : 
    2546              : /* Given a type T, get the type volatile T.
    2547              : 
    2548              :    Implements the post-error-checking part of
    2549              :    gcc_jit_type_get_volatile.  */
    2550              : 
    2551              : recording::type *
    2552          291 : recording::type::get_volatile ()
    2553              : {
    2554          291 :   recording::type *result = new memento_of_get_volatile (this);
    2555          291 :   m_ctxt->record (result);
    2556          291 :   return result;
    2557              : }
    2558              : 
    2559              : /* Given a type, get an aligned version of the type.
    2560              : 
    2561              :    Implements the post-error-checking part of
    2562              :    gcc_jit_type_get_aligned.  */
    2563              : 
    2564              : recording::type *
    2565          384 : recording::type::get_aligned (size_t alignment_in_bytes)
    2566              : {
    2567          384 :   recording::type *result
    2568          384 :     = new memento_of_get_aligned (this, alignment_in_bytes);
    2569          384 :   m_ctxt->record (result);
    2570          384 :   return result;
    2571              : }
    2572              : 
    2573              : /* Given a type, get a vector version of the type.
    2574              : 
    2575              :    Implements the post-error-checking part of
    2576              :    gcc_jit_type_get_vector.  */
    2577              : 
    2578              : recording::type *
    2579      1374401 : recording::type::get_vector (size_t num_units)
    2580              : {
    2581      1374401 :   recording::type *result
    2582      1374401 :     = new vector_type (this, num_units);
    2583      1374401 :   m_ctxt->record (result);
    2584      1374401 :   return result;
    2585              : }
    2586              : 
    2587              : const char *
    2588        28190 : recording::type::access_as_type (reproducer &r)
    2589              : {
    2590        28190 :   return r.get_identifier (this);
    2591              : }
    2592              : 
    2593              : /* Override of default implementation of
    2594              :    recording::type::get_size.
    2595              : 
    2596              :    Return the size in bytes.  This is in use for global
    2597              :    initialization.  */
    2598              : 
    2599              : size_t
    2600        19805 : recording::memento_of_get_type::get_size ()
    2601              : {
    2602        19805 :   int size;
    2603        19805 :   machine_mode m;
    2604        19805 :   switch (m_kind)
    2605              :     {
    2606              :     case GCC_JIT_TYPE_VOID:
    2607              :       return 0;
    2608         2381 :     case GCC_JIT_TYPE_BOOL:
    2609         2381 :     case GCC_JIT_TYPE_CHAR:
    2610         2381 :     case GCC_JIT_TYPE_SIGNED_CHAR:
    2611         2381 :     case GCC_JIT_TYPE_UNSIGNED_CHAR:
    2612         2381 :       return 1;
    2613              :     case GCC_JIT_TYPE_SHORT:
    2614              :     case GCC_JIT_TYPE_UNSIGNED_SHORT:
    2615              :       size = SHORT_TYPE_SIZE;
    2616              :       break;
    2617              :     case GCC_JIT_TYPE_INT:
    2618              :     case GCC_JIT_TYPE_UNSIGNED_INT:
    2619        15560 :       size = INT_TYPE_SIZE;
    2620              :       break;
    2621          600 :     case GCC_JIT_TYPE_LONG:
    2622          600 :     case GCC_JIT_TYPE_UNSIGNED_LONG:
    2623          600 :       size = LONG_TYPE_SIZE;
    2624              :       break;
    2625              :     case GCC_JIT_TYPE_LONG_LONG:
    2626              :     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
    2627         1163 :       size = LONG_LONG_TYPE_SIZE;
    2628              :       break;
    2629           60 :     case GCC_JIT_TYPE_UINT8_T:
    2630           60 :     case GCC_JIT_TYPE_INT8_T:
    2631           60 :       size = 8;
    2632           60 :       break;
    2633              :     case GCC_JIT_TYPE_UINT16_T:
    2634              :     case GCC_JIT_TYPE_INT16_T:
    2635              :       size = 16;
    2636              :       break;
    2637              :     case GCC_JIT_TYPE_UINT32_T:
    2638              :     case GCC_JIT_TYPE_INT32_T:
    2639        15560 :       size = 32;
    2640              :       break;
    2641              :     case GCC_JIT_TYPE_UINT64_T:
    2642              :     case GCC_JIT_TYPE_INT64_T:
    2643         1163 :       size = 64;
    2644              :       break;
    2645              :     case GCC_JIT_TYPE_UINT128_T:
    2646              :     case GCC_JIT_TYPE_INT128_T:
    2647           75 :       size = 128;
    2648              :       break;
    2649           60 :     case GCC_JIT_TYPE_FLOAT:
    2650           60 :       m = targetm.c.mode_for_floating_type (TI_FLOAT_TYPE);
    2651           60 :       size = GET_MODE_PRECISION (m).to_constant ();
    2652           60 :       break;
    2653              : #ifdef HAVE_BFmode
    2654            0 :     case GCC_JIT_TYPE_BFLOAT16:
    2655            0 :       return GET_MODE_UNIT_SIZE (BFmode);
    2656              : #endif
    2657           15 :     case GCC_JIT_TYPE_DOUBLE:
    2658           15 :       m = targetm.c.mode_for_floating_type (TI_DOUBLE_TYPE);
    2659           15 :       size = GET_MODE_PRECISION (m).to_constant ();
    2660           15 :       break;
    2661            0 :     case GCC_JIT_TYPE_LONG_DOUBLE:
    2662            0 :       m = targetm.c.mode_for_floating_type (TI_LONG_DOUBLE_TYPE);
    2663            0 :       size = GET_MODE_PRECISION (m).to_constant ();
    2664            0 :       break;
    2665              :     case GCC_JIT_TYPE_FLOAT16:
    2666              :       size = 16;
    2667              :       break;
    2668              :     case GCC_JIT_TYPE_FLOAT32:
    2669        15560 :       size = 32;
    2670              :       break;
    2671              :     case GCC_JIT_TYPE_FLOAT64:
    2672         1163 :       size = 64;
    2673              :       break;
    2674              :     case GCC_JIT_TYPE_FLOAT128:
    2675           75 :       size = 128;
    2676              :       break;
    2677              :     case GCC_JIT_TYPE_SIZE_T:
    2678         1163 :       size = MAX_BITS_PER_WORD;
    2679              :       break;
    2680            0 :     default:
    2681              :       /* As this function is called by
    2682              :          'gcc_jit_global_set_initializer' and
    2683              :          'recording::global::write_reproducer' possible types are only
    2684              :          integrals and are covered by the previous cases.  */
    2685            0 :       gcc_unreachable ();
    2686              :     }
    2687              : 
    2688        17424 :   return size / BITS_PER_UNIT;
    2689              : }
    2690              : 
    2691              : /* Implementation of pure virtual hook recording::type::dereference for
    2692              :    recording::memento_of_get_type.  */
    2693              : 
    2694              : recording::type *
    2695          992 : recording::memento_of_get_type::dereference ()
    2696              : {
    2697          992 :   switch (m_kind)
    2698              :     {
    2699            0 :     default: gcc_unreachable ();
    2700              : 
    2701              :     case GCC_JIT_TYPE_VOID:
    2702              :       return NULL;
    2703              : 
    2704          141 :     case GCC_JIT_TYPE_VOID_PTR:
    2705          141 :       return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
    2706              : 
    2707              :     case GCC_JIT_TYPE_BOOL:
    2708              :     case GCC_JIT_TYPE_CHAR:
    2709              :     case GCC_JIT_TYPE_SIGNED_CHAR:
    2710              :     case GCC_JIT_TYPE_UNSIGNED_CHAR:
    2711              :     case GCC_JIT_TYPE_SHORT:
    2712              :     case GCC_JIT_TYPE_UNSIGNED_SHORT:
    2713              :     case GCC_JIT_TYPE_INT:
    2714              :     case GCC_JIT_TYPE_UNSIGNED_INT:
    2715              :     case GCC_JIT_TYPE_LONG:
    2716              :     case GCC_JIT_TYPE_UNSIGNED_LONG:
    2717              :     case GCC_JIT_TYPE_LONG_LONG:
    2718              :     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
    2719              :     case GCC_JIT_TYPE_UINT8_T:
    2720              :     case GCC_JIT_TYPE_UINT16_T:
    2721              :     case GCC_JIT_TYPE_UINT32_T:
    2722              :     case GCC_JIT_TYPE_UINT64_T:
    2723              :     case GCC_JIT_TYPE_UINT128_T:
    2724              :     case GCC_JIT_TYPE_INT8_T:
    2725              :     case GCC_JIT_TYPE_INT16_T:
    2726              :     case GCC_JIT_TYPE_INT32_T:
    2727              :     case GCC_JIT_TYPE_INT64_T:
    2728              :     case GCC_JIT_TYPE_INT128_T:
    2729              :     case GCC_JIT_TYPE_FLOAT:
    2730              :     case GCC_JIT_TYPE_BFLOAT16:
    2731              :     case GCC_JIT_TYPE_DOUBLE:
    2732              :     case GCC_JIT_TYPE_LONG_DOUBLE:
    2733              :     case GCC_JIT_TYPE_FLOAT16:
    2734              :     case GCC_JIT_TYPE_FLOAT32:
    2735              :     case GCC_JIT_TYPE_FLOAT64:
    2736              :     case GCC_JIT_TYPE_FLOAT128:
    2737              :     case GCC_JIT_TYPE_COMPLEX_FLOAT:
    2738              :     case GCC_JIT_TYPE_COMPLEX_DOUBLE:
    2739              :     case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
    2740              :       /* Not a pointer: */
    2741              :       return NULL;
    2742              : 
    2743          120 :     case GCC_JIT_TYPE_CONST_CHAR_PTR:
    2744          120 :       return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
    2745              : 
    2746              :     case GCC_JIT_TYPE_SIZE_T:
    2747              :       /* Not a pointer: */
    2748              :       return NULL;
    2749              : 
    2750           19 :     case GCC_JIT_TYPE_FILE_PTR:
    2751              :       /* Give the client code back an opaque "struct FILE".  */
    2752           19 :       return m_ctxt->get_opaque_FILE_type ();
    2753              :     }
    2754              : }
    2755              : 
    2756              : /* Implementation of pure virtual hook recording::type::is_int for
    2757              :    recording::memento_of_get_type.  */
    2758              : 
    2759              : bool
    2760        38581 : recording::memento_of_get_type::is_int () const
    2761              : {
    2762        38581 :   switch (m_kind)
    2763              :     {
    2764            0 :     default: gcc_unreachable ();
    2765              : 
    2766              :     case GCC_JIT_TYPE_VOID:
    2767              :       return false;
    2768              : 
    2769              :     case GCC_JIT_TYPE_VOID_PTR:
    2770              :       return false;
    2771              : 
    2772              :     case GCC_JIT_TYPE_BOOL:
    2773              :       return false;
    2774              : 
    2775              :     case GCC_JIT_TYPE_CHAR:
    2776              :     case GCC_JIT_TYPE_SIGNED_CHAR:
    2777              :     case GCC_JIT_TYPE_UNSIGNED_CHAR:
    2778              :     case GCC_JIT_TYPE_SHORT:
    2779              :     case GCC_JIT_TYPE_UNSIGNED_SHORT:
    2780              :     case GCC_JIT_TYPE_INT:
    2781              :     case GCC_JIT_TYPE_UNSIGNED_INT:
    2782              :     case GCC_JIT_TYPE_LONG:
    2783              :     case GCC_JIT_TYPE_UNSIGNED_LONG:
    2784              :     case GCC_JIT_TYPE_LONG_LONG:
    2785              :     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
    2786              :     case GCC_JIT_TYPE_UINT8_T:
    2787              :     case GCC_JIT_TYPE_UINT16_T:
    2788              :     case GCC_JIT_TYPE_UINT32_T:
    2789              :     case GCC_JIT_TYPE_UINT64_T:
    2790              :     case GCC_JIT_TYPE_UINT128_T:
    2791              :     case GCC_JIT_TYPE_INT8_T:
    2792              :     case GCC_JIT_TYPE_INT16_T:
    2793              :     case GCC_JIT_TYPE_INT32_T:
    2794              :     case GCC_JIT_TYPE_INT64_T:
    2795              :     case GCC_JIT_TYPE_INT128_T:
    2796              :       return true;
    2797              : 
    2798              :     case GCC_JIT_TYPE_FLOAT:
    2799              :     case GCC_JIT_TYPE_BFLOAT16:
    2800              :     case GCC_JIT_TYPE_DOUBLE:
    2801              :     case GCC_JIT_TYPE_LONG_DOUBLE:
    2802              :     case GCC_JIT_TYPE_FLOAT16:
    2803              :     case GCC_JIT_TYPE_FLOAT32:
    2804              :     case GCC_JIT_TYPE_FLOAT64:
    2805              :     case GCC_JIT_TYPE_FLOAT128:
    2806              :       return false;
    2807              : 
    2808              :     case GCC_JIT_TYPE_CONST_CHAR_PTR:
    2809              :       return false;
    2810              : 
    2811              :     case GCC_JIT_TYPE_SIZE_T:
    2812              :       return true;
    2813              : 
    2814              :     case GCC_JIT_TYPE_FILE_PTR:
    2815              :       return false;
    2816              : 
    2817              :     case GCC_JIT_TYPE_COMPLEX_FLOAT:
    2818              :     case GCC_JIT_TYPE_COMPLEX_DOUBLE:
    2819              :     case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
    2820              :       return false;
    2821              :     }
    2822              : }
    2823              : 
    2824              : /* Implementation of pure virtual hook recording::type::is_signed for
    2825              :    recording::memento_of_get_type.  */
    2826              : 
    2827              : bool
    2828        18938 : recording::memento_of_get_type::is_signed () const
    2829              : {
    2830        18938 :   switch (m_kind)
    2831              :     {
    2832            0 :     default: gcc_unreachable ();
    2833              : 
    2834              :     case GCC_JIT_TYPE_SIGNED_CHAR:
    2835              :     case GCC_JIT_TYPE_CHAR:
    2836              :     case GCC_JIT_TYPE_SHORT:
    2837              :     case GCC_JIT_TYPE_INT:
    2838              :     case GCC_JIT_TYPE_LONG:
    2839              :     case GCC_JIT_TYPE_LONG_LONG:
    2840              :     case GCC_JIT_TYPE_INT8_T:
    2841              :     case GCC_JIT_TYPE_INT16_T:
    2842              :     case GCC_JIT_TYPE_INT32_T:
    2843              :     case GCC_JIT_TYPE_INT64_T:
    2844              :     case GCC_JIT_TYPE_INT128_T:
    2845              :       return true;
    2846              : 
    2847         1798 :     case GCC_JIT_TYPE_VOID:
    2848         1798 :     case GCC_JIT_TYPE_VOID_PTR:
    2849         1798 :     case GCC_JIT_TYPE_BOOL:
    2850         1798 :     case GCC_JIT_TYPE_UNSIGNED_CHAR:
    2851         1798 :     case GCC_JIT_TYPE_UNSIGNED_SHORT:
    2852         1798 :     case GCC_JIT_TYPE_UNSIGNED_INT:
    2853         1798 :     case GCC_JIT_TYPE_UNSIGNED_LONG:
    2854         1798 :     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
    2855         1798 :     case GCC_JIT_TYPE_UINT8_T:
    2856         1798 :     case GCC_JIT_TYPE_UINT16_T:
    2857         1798 :     case GCC_JIT_TYPE_UINT32_T:
    2858         1798 :     case GCC_JIT_TYPE_UINT64_T:
    2859         1798 :     case GCC_JIT_TYPE_UINT128_T:
    2860              : 
    2861         1798 :     case GCC_JIT_TYPE_FLOAT:
    2862         1798 :     case GCC_JIT_TYPE_BFLOAT16:
    2863         1798 :     case GCC_JIT_TYPE_DOUBLE:
    2864         1798 :     case GCC_JIT_TYPE_LONG_DOUBLE:
    2865         1798 :     case GCC_JIT_TYPE_FLOAT16:
    2866         1798 :     case GCC_JIT_TYPE_FLOAT32:
    2867         1798 :     case GCC_JIT_TYPE_FLOAT64:
    2868         1798 :     case GCC_JIT_TYPE_FLOAT128:
    2869              : 
    2870         1798 :     case GCC_JIT_TYPE_CONST_CHAR_PTR:
    2871              : 
    2872         1798 :     case GCC_JIT_TYPE_SIZE_T:
    2873              : 
    2874         1798 :     case GCC_JIT_TYPE_FILE_PTR:
    2875              : 
    2876         1798 :     case GCC_JIT_TYPE_COMPLEX_FLOAT:
    2877         1798 :     case GCC_JIT_TYPE_COMPLEX_DOUBLE:
    2878         1798 :     case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
    2879         1798 :       return false;
    2880              :     }
    2881              : }
    2882              : 
    2883              : /* Implementation of pure virtual hook recording::type::is_float for
    2884              :    recording::memento_of_get_type.  */
    2885              : 
    2886              : bool
    2887         3221 : recording::memento_of_get_type::is_float () const
    2888              : {
    2889         3221 :   switch (m_kind)
    2890              :     {
    2891            0 :     default: gcc_unreachable ();
    2892              : 
    2893              :     case GCC_JIT_TYPE_VOID:
    2894              :       return false;
    2895              : 
    2896              :     case GCC_JIT_TYPE_VOID_PTR:
    2897              :       return false;
    2898              : 
    2899              :     case GCC_JIT_TYPE_BOOL:
    2900              :       return false;
    2901              : 
    2902              :     case GCC_JIT_TYPE_CHAR:
    2903              :     case GCC_JIT_TYPE_SIGNED_CHAR:
    2904              :     case GCC_JIT_TYPE_UNSIGNED_CHAR:
    2905              :     case GCC_JIT_TYPE_SHORT:
    2906              :     case GCC_JIT_TYPE_UNSIGNED_SHORT:
    2907              :     case GCC_JIT_TYPE_INT:
    2908              :     case GCC_JIT_TYPE_UNSIGNED_INT:
    2909              :     case GCC_JIT_TYPE_LONG:
    2910              :     case GCC_JIT_TYPE_UNSIGNED_LONG:
    2911              :     case GCC_JIT_TYPE_LONG_LONG:
    2912              :     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
    2913              :     case GCC_JIT_TYPE_UINT8_T:
    2914              :     case GCC_JIT_TYPE_UINT16_T:
    2915              :     case GCC_JIT_TYPE_UINT32_T:
    2916              :     case GCC_JIT_TYPE_UINT64_T:
    2917              :     case GCC_JIT_TYPE_UINT128_T:
    2918              :     case GCC_JIT_TYPE_INT8_T:
    2919              :     case GCC_JIT_TYPE_INT16_T:
    2920              :     case GCC_JIT_TYPE_INT32_T:
    2921              :     case GCC_JIT_TYPE_INT64_T:
    2922              :     case GCC_JIT_TYPE_INT128_T:
    2923              :       return false;
    2924              : 
    2925              :     case GCC_JIT_TYPE_FLOAT:
    2926              :     case GCC_JIT_TYPE_BFLOAT16:
    2927              :     case GCC_JIT_TYPE_DOUBLE:
    2928              :     case GCC_JIT_TYPE_LONG_DOUBLE:
    2929              :     case GCC_JIT_TYPE_FLOAT16:
    2930              :     case GCC_JIT_TYPE_FLOAT32:
    2931              :     case GCC_JIT_TYPE_FLOAT64:
    2932              :     case GCC_JIT_TYPE_FLOAT128:
    2933              :       return true;
    2934              : 
    2935              :     case GCC_JIT_TYPE_CONST_CHAR_PTR:
    2936              :       return false;
    2937              : 
    2938              :     case GCC_JIT_TYPE_SIZE_T:
    2939              :       return false;
    2940              : 
    2941              :     case GCC_JIT_TYPE_FILE_PTR:
    2942              :       return false;
    2943              : 
    2944              :     case GCC_JIT_TYPE_COMPLEX_FLOAT:
    2945              :     case GCC_JIT_TYPE_COMPLEX_DOUBLE:
    2946              :     case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
    2947              :       return true;
    2948              :     }
    2949              : }
    2950              : 
    2951              : /* Implementation of pure virtual hook recording::type::is_bool for
    2952              :    recording::memento_of_get_type.  */
    2953              : 
    2954              : bool
    2955         1150 : recording::memento_of_get_type::is_bool () const
    2956              : {
    2957         1150 :   switch (m_kind)
    2958              :     {
    2959            0 :     default: gcc_unreachable ();
    2960              : 
    2961              :     case GCC_JIT_TYPE_VOID:
    2962              :       return false;
    2963              : 
    2964              :     case GCC_JIT_TYPE_VOID_PTR:
    2965              :       return false;
    2966              : 
    2967          303 :     case GCC_JIT_TYPE_BOOL:
    2968          303 :       return true;
    2969              : 
    2970              :     case GCC_JIT_TYPE_CHAR:
    2971              :     case GCC_JIT_TYPE_SIGNED_CHAR:
    2972              :     case GCC_JIT_TYPE_UNSIGNED_CHAR:
    2973              :     case GCC_JIT_TYPE_SHORT:
    2974              :     case GCC_JIT_TYPE_UNSIGNED_SHORT:
    2975              :     case GCC_JIT_TYPE_INT:
    2976              :     case GCC_JIT_TYPE_UNSIGNED_INT:
    2977              :     case GCC_JIT_TYPE_LONG:
    2978              :     case GCC_JIT_TYPE_UNSIGNED_LONG:
    2979              :     case GCC_JIT_TYPE_LONG_LONG:
    2980              :     case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
    2981              :     case GCC_JIT_TYPE_UINT8_T:
    2982              :     case GCC_JIT_TYPE_UINT16_T:
    2983              :     case GCC_JIT_TYPE_UINT32_T:
    2984              :     case GCC_JIT_TYPE_UINT64_T:
    2985              :     case GCC_JIT_TYPE_UINT128_T:
    2986              :     case GCC_JIT_TYPE_INT8_T:
    2987              :     case GCC_JIT_TYPE_INT16_T:
    2988              :     case GCC_JIT_TYPE_INT32_T:
    2989              :     case GCC_JIT_TYPE_INT64_T:
    2990              :     case GCC_JIT_TYPE_INT128_T:
    2991              :       return false;
    2992              : 
    2993              :     case GCC_JIT_TYPE_FLOAT:
    2994              :     case GCC_JIT_TYPE_BFLOAT16:
    2995              :     case GCC_JIT_TYPE_DOUBLE:
    2996              :     case GCC_JIT_TYPE_LONG_DOUBLE:
    2997              :     case GCC_JIT_TYPE_FLOAT16:
    2998              :     case GCC_JIT_TYPE_FLOAT32:
    2999              :     case GCC_JIT_TYPE_FLOAT64:
    3000              :     case GCC_JIT_TYPE_FLOAT128:
    3001              :       return false;
    3002              : 
    3003              :     case GCC_JIT_TYPE_CONST_CHAR_PTR:
    3004              :       return false;
    3005              : 
    3006              :     case GCC_JIT_TYPE_SIZE_T:
    3007              :       return false;
    3008              : 
    3009              :     case GCC_JIT_TYPE_FILE_PTR:
    3010              :       return false;
    3011              : 
    3012              :     case GCC_JIT_TYPE_COMPLEX_FLOAT:
    3013              :     case GCC_JIT_TYPE_COMPLEX_DOUBLE:
    3014              :     case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
    3015              :       return false;
    3016              :     }
    3017              : }
    3018              : 
    3019              : /* Implementation of pure virtual hook recording::memento::replay_into
    3020              :    for recording::memento_of_get_type.  */
    3021              : 
    3022              : void
    3023         8289 : recording::memento_of_get_type::replay_into (replayer *r)
    3024              : {
    3025         8289 :   set_playback_obj (r->get_type (m_kind));
    3026         8289 : }
    3027              : 
    3028              : /* The implementation of class gcc::jit::recording::memento_of_get_type.  */
    3029              : 
    3030              : /* Descriptive strings for each of enum gcc_jit_types.  */
    3031              : 
    3032              : static const char * const get_type_strings[] = {
    3033              :   "void",    /* GCC_JIT_TYPE_VOID */
    3034              :   "void *",  /* GCC_JIT_TYPE_VOID_PTR */
    3035              : 
    3036              :   "bool",  /* GCC_JIT_TYPE_BOOL */
    3037              : 
    3038              :   "char",           /* GCC_JIT_TYPE_CHAR */
    3039              :   "signed char",    /* GCC_JIT_TYPE_SIGNED_CHAR */
    3040              :   "unsigned char",  /* GCC_JIT_TYPE_UNSIGNED_CHAR */
    3041              : 
    3042              :   "short",           /* GCC_JIT_TYPE_SHORT */
    3043              :   "unsigned short",  /* GCC_JIT_TYPE_UNSIGNED_SHORT */
    3044              : 
    3045              :   "int",           /* GCC_JIT_TYPE_INT */
    3046              :   "unsigned int",  /* GCC_JIT_TYPE_UNSIGNED_INT */
    3047              : 
    3048              :   "long",           /* GCC_JIT_TYPE_LONG  */
    3049              :   "unsigned long",  /* GCC_JIT_TYPE_UNSIGNED_LONG, */
    3050              : 
    3051              :   "long long",           /* GCC_JIT_TYPE_LONG_LONG */
    3052              :   "unsigned long long",  /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
    3053              : 
    3054              :   "float",        /* GCC_JIT_TYPE_FLOAT */
    3055              :   "double",       /* GCC_JIT_TYPE_DOUBLE */
    3056              :   "long double",  /* GCC_JIT_TYPE_LONG_DOUBLE */
    3057              : 
    3058              :   "const char *",  /* GCC_JIT_TYPE_CONST_CHAR_PTR */
    3059              : 
    3060              :   "size_t",  /* GCC_JIT_TYPE_SIZE_T */
    3061              : 
    3062              :   "FILE *",  /* GCC_JIT_TYPE_FILE_PTR */
    3063              : 
    3064              :   "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
    3065              :   "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
    3066              :   "complex long double",  /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
    3067              : 
    3068              :   "__uint8_t",    /* GCC_JIT_TYPE_UINT8_T */
    3069              :   "__uint16_t",   /* GCC_JIT_TYPE_UINT16_T */
    3070              :   "__uint32_t",   /* GCC_JIT_TYPE_UINT32_T */
    3071              :   "__uint64_t",   /* GCC_JIT_TYPE_UINT64_T */
    3072              :   "__uint128_t",  /* GCC_JIT_TYPE_UINT128_T */
    3073              :   "__int8_t",     /* GCC_JIT_TYPE_INT8_T */
    3074              :   "__int16_t",    /* GCC_JIT_TYPE_INT16_T */
    3075              :   "__int32_t",    /* GCC_JIT_TYPE_INT32_T */
    3076              :   "__int64_t",    /* GCC_JIT_TYPE_INT64_T */
    3077              :   "__int128_t",   /* GCC_JIT_TYPE_INT128_T */
    3078              :   "bfloat16",     /* GCC_JIT_TYPE_BFLOAT16 */
    3079              :   "_Float16",     /* GCC_JIT_TYPE_FLOAT16 */
    3080              :   "_Float32",     /* GCC_JIT_TYPE_FLOAT32 */
    3081              :   "_Float64",     /* GCC_JIT_TYPE_FLOAT64 */
    3082              :   "__float128",   /* GCC_JIT_TYPE_FLOAT128 */
    3083              : };
    3084              : 
    3085              : /* Implementation of recording::memento::make_debug_string for
    3086              :    results of get_type, using a simple table of type names.  */
    3087              : 
    3088              : recording::string *
    3089         5836 : recording::memento_of_get_type::make_debug_string ()
    3090              : {
    3091         5836 :   return m_ctxt->new_string (get_type_strings[m_kind]);
    3092              : }
    3093              : 
    3094              : static const char * const get_type_enum_strings[] = {
    3095              :   "GCC_JIT_TYPE_VOID",
    3096              :   "GCC_JIT_TYPE_VOID_PTR",
    3097              :   "GCC_JIT_TYPE_BOOL",
    3098              :   "GCC_JIT_TYPE_CHAR",
    3099              :   "GCC_JIT_TYPE_SIGNED_CHAR",
    3100              :   "GCC_JIT_TYPE_UNSIGNED_CHAR",
    3101              :   "GCC_JIT_TYPE_SHORT",
    3102              :   "GCC_JIT_TYPE_UNSIGNED_SHORT",
    3103              :   "GCC_JIT_TYPE_INT",
    3104              :   "GCC_JIT_TYPE_UNSIGNED_INT",
    3105              :   "GCC_JIT_TYPE_LONG",
    3106              :   "GCC_JIT_TYPE_UNSIGNED_LONG",
    3107              :   "GCC_JIT_TYPE_LONG_LONG",
    3108              :   "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
    3109              :   "GCC_JIT_TYPE_FLOAT",
    3110              :   "GCC_JIT_TYPE_DOUBLE",
    3111              :   "GCC_JIT_TYPE_LONG_DOUBLE",
    3112              :   "GCC_JIT_TYPE_CONST_CHAR_PTR",
    3113              :   "GCC_JIT_TYPE_SIZE_T",
    3114              :   "GCC_JIT_TYPE_FILE_PTR",
    3115              :   "GCC_JIT_TYPE_COMPLEX_FLOAT",
    3116              :   "GCC_JIT_TYPE_COMPLEX_DOUBLE",
    3117              :   "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE",
    3118              :   "GCC_JIT_TYPE_UINT8_T",
    3119              :   "GCC_JIT_TYPE_UINT16_T",
    3120              :   "GCC_JIT_TYPE_UINT32_T",
    3121              :   "GCC_JIT_TYPE_UINT64_T",
    3122              :   "GCC_JIT_TYPE_UINT128_T",
    3123              :   "GCC_JIT_TYPE_INT8_T",
    3124              :   "GCC_JIT_TYPE_INT16_T",
    3125              :   "GCC_JIT_TYPE_INT32_T",
    3126              :   "GCC_JIT_TYPE_INT64_T",
    3127              :   "GCC_JIT_TYPE_INT128_T",
    3128              :   "GCC_JIT_TYPE_BFLOAT16",
    3129              :   "GCC_JIT_TYPE_FLOAT16",
    3130              :   "GCC_JIT_TYPE_FLOAT32",
    3131              :   "GCC_JIT_TYPE_FLOAT64",
    3132              :   "GCC_JIT_TYPE_FLOAT128",
    3133              : };
    3134              : 
    3135              : void
    3136         5818 : recording::memento_of_get_type::write_reproducer (reproducer &r)
    3137              : {
    3138         5818 :   const char *id = r.make_identifier (this, "type");
    3139         5818 :   r.write ("  gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
    3140              :            id,
    3141              :            r.get_identifier (get_context ()),
    3142         5818 :            get_type_enum_strings[m_kind]);
    3143         5818 : }
    3144              : 
    3145              : /* The implementation of class gcc::jit::recording::memento_of_get_pointer.  */
    3146              : 
    3147              : /* Override of default implementation of
    3148              :    recording::type::get_size for get_pointer.  */
    3149              : 
    3150              : size_t
    3151           10 : recording::memento_of_get_pointer::get_size ()
    3152              : {
    3153           10 :   return POINTER_SIZE / BITS_PER_UNIT;
    3154              : }
    3155              : 
    3156              : /* Override of default implementation of
    3157              :    recording::type::accepts_writes_from for get_pointer.
    3158              : 
    3159              :    Require a pointer type, and allowing writes to
    3160              :    (const T *) from a (T*), but not the other way around.  */
    3161              : 
    3162              : bool
    3163          522 : recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
    3164              : {
    3165              :   /* Must be a pointer type: */
    3166          522 :   type *rtype_points_to = rtype->is_pointer ();
    3167          522 :   if (!rtype_points_to)
    3168              :     return false;
    3169              : 
    3170              :   /* It's OK to assign to a (const T *) from a (T *).  */
    3171          457 :   if (m_other_type->unqualified ()->accepts_writes_from (rtype_points_to))
    3172              :   {
    3173              :     return true;
    3174              :   }
    3175              : 
    3176              :   /* It's OK to assign to a (volatile const T *) from a (volatile const T *). */
    3177           46 :   return m_other_type->is_same_type_as (rtype_points_to);
    3178              : }
    3179              : 
    3180              : /* Implementation of pure virtual hook recording::memento::replay_into
    3181              :    for recording::memento_of_get_pointer.  */
    3182              : 
    3183              : void
    3184         1306 : recording::memento_of_get_pointer::replay_into (replayer *)
    3185              : {
    3186         1306 :   set_playback_obj (m_other_type->playback_type ()->get_pointer ());
    3187         1306 : }
    3188              : 
    3189              : /* Implementation of recording::memento::make_debug_string for
    3190              :    results of get_pointer, adding " *" to the underlying type,
    3191              :    with special-casing to handle function pointer types.  */
    3192              : 
    3193              : recording::string *
    3194         1203 : recording::memento_of_get_pointer::make_debug_string ()
    3195              : {
    3196              :   /* Special-case function pointer types, to put the "*" in parens between
    3197              :      the return type and the params (for one level of dereferencing, at
    3198              :      least).  */
    3199         1203 :   if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
    3200           60 :     return fn_type->make_debug_string_with_ptr ();
    3201              : 
    3202         1143 :   return string::from_printf (m_ctxt,
    3203         2286 :                               "%s *", m_other_type->get_debug_string ());
    3204              : }
    3205              : 
    3206              : /* Implementation of recording::memento::write_reproducer for get_pointer.  */
    3207              : 
    3208              : void
    3209         1200 : recording::memento_of_get_pointer::write_reproducer (reproducer &r)
    3210              : {
    3211              :   /* We need to special-case function pointer types; see the notes in
    3212              :      recording::function_type::write_deferred_reproducer.  */
    3213         1200 :   if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
    3214              :     {
    3215           55 :       fn_type->write_deferred_reproducer (r, this);
    3216           55 :       return;
    3217              :     }
    3218              : 
    3219         1145 :   const char *id = r.make_identifier (this, "type");
    3220         1145 :   r.write ("  gcc_jit_type *%s =\n"
    3221              :            "    gcc_jit_type_get_pointer (%s);\n",
    3222              :            id,
    3223              :            r.get_identifier_as_type (m_other_type));
    3224              : }
    3225              : 
    3226              : /* The implementation of class gcc::jit::recording::memento_of_get_const.  */
    3227              : 
    3228              : /* Implementation of pure virtual hook recording::memento::replay_into
    3229              :    for recording::memento_of_get_const.  */
    3230              : 
    3231              : void
    3232          585 : recording::memento_of_get_const::replay_into (replayer *)
    3233              : {
    3234          585 :   set_playback_obj (m_other_type->playback_type ()->get_const ());
    3235          585 : }
    3236              : 
    3237              : /* Implementation of recording::memento::make_debug_string for
    3238              :    results of get_const, prepending "const ".  */
    3239              : 
    3240              : recording::string *
    3241          661 : recording::memento_of_get_const::make_debug_string ()
    3242              : {
    3243          661 :   return string::from_printf (m_ctxt,
    3244          661 :                               "const %s", m_other_type->get_debug_string ());
    3245              : }
    3246              : 
    3247              : /* Implementation of recording::memento::write_reproducer for const types. */
    3248              : 
    3249              : void
    3250          661 : recording::memento_of_get_const::write_reproducer (reproducer &r)
    3251              : {
    3252          661 :   const char *id = r.make_identifier (this, "type");
    3253          661 :   r.write ("  gcc_jit_type *%s =\n"
    3254              :            "    gcc_jit_type_get_const (%s);\n",
    3255              :            id,
    3256              :            r.get_identifier_as_type (m_other_type));
    3257          661 : }
    3258              : 
    3259              : /* The implementation of class gcc::jit::recording::memento_of_get_volatile.  */
    3260              : 
    3261              : /* Implementation of pure virtual hook recording::memento::replay_into
    3262              :    for recording::memento_of_get_volatile.  */
    3263              : 
    3264              : void
    3265          115 : recording::memento_of_get_volatile::replay_into (replayer *)
    3266              : {
    3267          115 :   set_playback_obj (m_other_type->playback_type ()->get_volatile ());
    3268          115 : }
    3269              : 
    3270              : /* Implementation of recording::memento::make_debug_string for
    3271              :    results of get_volatile, prepending "volatile ".  */
    3272              : 
    3273              : recording::string *
    3274          236 : recording::memento_of_get_volatile::make_debug_string ()
    3275              : {
    3276          236 :   return string::from_printf (m_ctxt,
    3277          236 :                               "volatile %s", m_other_type->get_debug_string ());
    3278              : }
    3279              : 
    3280              : /* Implementation of recording::memento::write_reproducer for volatile
    3281              :    types. */
    3282              : 
    3283              : void
    3284          236 : recording::memento_of_get_volatile::write_reproducer (reproducer &r)
    3285              : {
    3286          236 :   const char *id = r.make_identifier (this, "type");
    3287          236 :   r.write ("  gcc_jit_type *%s =\n"
    3288              :            "    gcc_jit_type_get_volatile (%s);\n",
    3289              :            id,
    3290              :            r.get_identifier_as_type (m_other_type));
    3291          236 : }
    3292              : 
    3293              : /* The implementation of class gcc::jit::recording::memento_of_get_restrict.  */
    3294              : 
    3295              : /* Implementation of pure virtual hook recording::memento::replay_into
    3296              :    for recording::memento_of_get_restrict.  */
    3297              : 
    3298              : void
    3299           10 : recording::memento_of_get_restrict::replay_into (replayer *)
    3300              : {
    3301           10 :   set_playback_obj (m_other_type->playback_type ()->get_restrict ());
    3302           10 : }
    3303              : 
    3304              : /* Implementation of recording::memento::make_debug_string for
    3305              :    results of get_restrict, prepending "restrict ".  */
    3306              : 
    3307              : recording::string *
    3308           10 : recording::memento_of_get_restrict::make_debug_string ()
    3309              : {
    3310           10 :   return string::from_printf (m_ctxt,
    3311           10 :                               "restrict %s", m_other_type->get_debug_string ());
    3312              : }
    3313              : 
    3314              : /* Implementation of recording::memento::write_reproducer for restrict
    3315              :    types.  */
    3316              : 
    3317              : void
    3318           10 : recording::memento_of_get_restrict::write_reproducer (reproducer &r)
    3319              : {
    3320           10 :   const char *id = r.make_identifier (this, "type");
    3321           10 :   r.write ("  gcc_jit_type *%s =\n"
    3322              :            "    gcc_jit_type_get_restrict (%s);\n",
    3323              :            id,
    3324              :            r.get_identifier_as_type (m_other_type));
    3325           10 : }
    3326              : 
    3327              : /* The implementation of class gcc::jit::recording::memento_of_get_aligned.  */
    3328              : 
    3329              : /* Implementation of pure virtual hook recording::memento::replay_into
    3330              :    for recording::memento_of_get_aligned.  */
    3331              : 
    3332              : void
    3333          160 : recording::memento_of_get_aligned::replay_into (replayer *)
    3334              : {
    3335          160 :   set_playback_obj
    3336          160 :     (m_other_type->playback_type ()->get_aligned (m_alignment_in_bytes));
    3337          160 : }
    3338              : 
    3339              : /* Implementation of recording::memento::make_debug_string for
    3340              :    results of get_aligned.  */
    3341              : 
    3342              : recording::string *
    3343          299 : recording::memento_of_get_aligned::make_debug_string ()
    3344              : {
    3345          299 :   return string::from_printf (m_ctxt,
    3346              :                               "%s  __attribute__((aligned(%zi)))",
    3347          299 :                               m_other_type->get_debug_string (),
    3348          299 :                               m_alignment_in_bytes);
    3349              : }
    3350              : 
    3351              : /* Implementation of recording::memento::write_reproducer for aligned
    3352              :    types. */
    3353              : 
    3354              : void
    3355          299 : recording::memento_of_get_aligned::write_reproducer (reproducer &r)
    3356              : {
    3357          299 :   const char *id = r.make_identifier (this, "type");
    3358          299 :   r.write ("  gcc_jit_type *%s =\n"
    3359              :            "    gcc_jit_type_get_aligned (%s, %zi);\n",
    3360              :            id,
    3361              :            r.get_identifier_as_type (m_other_type),
    3362              :            m_alignment_in_bytes);
    3363          299 : }
    3364              : 
    3365              : /* The implementation of class gcc::jit::recording::vector_type.  */
    3366              : 
    3367              : /* Implementation of pure virtual hook recording::memento::replay_into
    3368              :    for recording::vector_type.  */
    3369              : 
    3370              : void
    3371          375 : recording::vector_type::replay_into (replayer *)
    3372              : {
    3373          375 :   set_playback_obj
    3374          375 :     (m_other_type->playback_type ()->get_vector (m_num_units));
    3375          375 : }
    3376              : 
    3377              : /* Implementation of recording::memento::make_debug_string for
    3378              :    results of get_vector.  */
    3379              : 
    3380              : recording::string *
    3381          441 : recording::vector_type::make_debug_string ()
    3382              : {
    3383          441 :   return string::from_printf
    3384          441 :     (m_ctxt,
    3385              :      "%s  __attribute__((vector_size(sizeof (%s) * %zi)))",
    3386          441 :      m_other_type->get_debug_string (),
    3387          441 :      m_other_type->get_debug_string (),
    3388          441 :      m_num_units);
    3389              : }
    3390              : 
    3391              : /* Implementation of recording::memento::write_reproducer for vector types. */
    3392              : 
    3393              : void
    3394          441 : recording::vector_type::write_reproducer (reproducer &r)
    3395              : {
    3396          441 :   const char *id = r.make_identifier (this, "type");
    3397          441 :   r.write ("  gcc_jit_type *%s =\n"
    3398              :            "    gcc_jit_type_get_vector (%s, %zi);\n",
    3399              :            id,
    3400              :            r.get_identifier_as_type (m_other_type),
    3401              :            m_num_units);
    3402          441 : }
    3403              : 
    3404              : /* The implementation of class gcc::jit::recording::array_type */
    3405              : 
    3406              : /* Implementation of pure virtual hook recording::type::dereference for
    3407              :    recording::array_type.  */
    3408              : 
    3409              : recording::type *
    3410          688 : recording::array_type::dereference ()
    3411              : {
    3412          688 :   return m_element_type;
    3413              : }
    3414              : 
    3415              : /* Implementation of pure virtual hook recording::memento::replay_into
    3416              :    for recording::array_type.  */
    3417              : 
    3418              : void
    3419          330 : recording::array_type::replay_into (replayer *r)
    3420              : {
    3421          330 :   set_playback_obj (r->new_array_type (playback_location (r, m_loc),
    3422          330 :                                        m_element_type->playback_type (),
    3423              :                                        m_num_elements));
    3424          330 : }
    3425              : 
    3426              : /* Implementation of recording::memento::make_debug_string for
    3427              :    results of new_array_type.  */
    3428              : 
    3429              : recording::string *
    3430          245 : recording::array_type::make_debug_string ()
    3431              : {
    3432          245 :   return string::from_printf (m_ctxt,
    3433              :                               "%s[%" PRIu64 "]",
    3434          245 :                               m_element_type->get_debug_string (),
    3435          245 :                               m_num_elements);
    3436              : }
    3437              : 
    3438              : /* Implementation of recording::memento::write_reproducer for array
    3439              :    types. */
    3440              : 
    3441              : void
    3442          245 : recording::array_type::write_reproducer (reproducer &r)
    3443              : {
    3444          245 :   const char *id = r.make_identifier (this, "array_type");
    3445          490 :   r.write ("  gcc_jit_type *%s =\n"
    3446              :            "    gcc_jit_context_new_array_type_u64 (%s,\n"
    3447              :            "                                        %s, /* gcc_jit_location *loc */\n"
    3448              :            "                                        %s, /* gcc_jit_type *element_type */\n"
    3449              :            "                                        %" PRIu64 "); /* int num_elements */\n",
    3450              :            id,
    3451              :            r.get_identifier (get_context ()),
    3452          245 :            r.get_identifier (m_loc),
    3453              :            r.get_identifier_as_type (m_element_type),
    3454              :            m_num_elements);
    3455          245 : }
    3456              : 
    3457              : /* The implementation of class gcc::jit::recording::function_type */
    3458              : 
    3459              : /* Constructor for gcc::jit::recording::function_type.  */
    3460              : 
    3461       487329 : recording::function_type::function_type (context *ctxt,
    3462              :                                          type *return_type,
    3463              :                                          int num_params,
    3464              :                                          type **param_types,
    3465              :                                          int is_variadic,
    3466       487329 :                                          bool is_target_builtin)
    3467              : : type (ctxt),
    3468       487329 :   m_return_type (return_type),
    3469       487329 :   m_param_types (),
    3470       487329 :   m_is_variadic (is_variadic),
    3471       487329 :   m_is_target_builtin (is_target_builtin)
    3472              : {
    3473      1955122 :   for (int i = 0; i< num_params; i++)
    3474      1467793 :     m_param_types.safe_push (param_types[i]);
    3475       487329 : }
    3476              : 
    3477              : /* Implementation of pure virtual hook recording::type::dereference for
    3478              :    recording::function_type.  */
    3479              : 
    3480              : recording::type *
    3481            0 : recording::function_type::dereference ()
    3482              : {
    3483            0 :   return NULL;
    3484              : }
    3485              : 
    3486              : /* Implementation of virtual hook recording::type::is_same_type_as for
    3487              :    recording::function_type.
    3488              : 
    3489              :    We override this to avoid requiring identity of function pointer types,
    3490              :    so that if client code has obtained the same signature in
    3491              :    different ways (e.g. via gcc_jit_context_new_function_ptr_type
    3492              :    vs gcc_jit_function_get_address), the different function_type
    3493              :    instances are treated as compatible.
    3494              : 
    3495              :    We can't use type::accepts_writes_from for this as we need a stronger
    3496              :    notion of "sameness": if we have a fn_ptr type that has args that are
    3497              :    themselves fn_ptr types, then those args still need to match exactly.
    3498              : 
    3499              :    Alternatively, we could consolidate attempts to create identical
    3500              :    function_type instances so that pointer equality works, but that runs
    3501              :    into issues about the lifetimes of the cache (w.r.t. nested contexts).  */
    3502              : 
    3503              : bool
    3504           45 : recording::function_type::is_same_type_as (type *other)
    3505              : {
    3506           45 :   gcc_assert (other);
    3507              : 
    3508           45 :   function_type *other_fn_type = other->dyn_cast_function_type ();
    3509           45 :   if (!other_fn_type)
    3510              :     return false;
    3511              : 
    3512              :   /* Everything must match.  */
    3513              : 
    3514           45 :   if (!m_return_type->is_same_type_as (other_fn_type->m_return_type))
    3515              :     return false;
    3516              : 
    3517          135 :   if (m_param_types.length () != other_fn_type->m_param_types.length ())
    3518              :     return false;
    3519              : 
    3520              :   unsigned i;
    3521              :   type *param_type;
    3522          100 :   FOR_EACH_VEC_ELT (m_param_types, i, param_type)
    3523           65 :     if (!param_type->is_same_type_as (other_fn_type->m_param_types[i]))
    3524              :       return false;
    3525              : 
    3526           35 :   if (m_is_variadic != other_fn_type->m_is_variadic)
    3527              :     return false;
    3528              : 
    3529              :   /* Passed all tests.  */
    3530              :   return true;
    3531              : }
    3532              : 
    3533              : /* Implementation of pure virtual hook recording::memento::replay_into
    3534              :    for recording::function_type.  */
    3535              : 
    3536              : void
    3537         5379 : recording::function_type::replay_into (replayer *r)
    3538              : {
    3539              :   /* Convert m_param_types to a vec of playback type.  */
    3540         5379 :   auto_vec <playback::type *> param_types;
    3541         5379 :   int i;
    3542         5379 :   recording::type *type;
    3543         5379 :   param_types.create (m_param_types.length ());
    3544        15076 :   FOR_EACH_VEC_ELT (m_param_types, i, type)
    3545         4318 :     param_types.safe_push (type->playback_type ());
    3546              : 
    3547         5379 :   set_playback_obj (r->new_function_type (m_return_type->playback_type (),
    3548              :                                           &param_types,
    3549              :                                           m_is_variadic));
    3550         5379 : }
    3551              : 
    3552              : /* Special-casing for make_debug_string for get_pointer results for
    3553              :    handling (one level) of pointers to functions.  */
    3554              : 
    3555              : recording::string *
    3556           60 : recording::function_type::make_debug_string_with_ptr ()
    3557              : {
    3558           60 :   return make_debug_string_with ("(*) ");
    3559              : }
    3560              : 
    3561              : /* Implementation of recording::memento::make_debug_string for
    3562              :    results of new_function_type.  */
    3563              : 
    3564              : recording::string *
    3565           55 : recording::function_type::make_debug_string ()
    3566              : {
    3567           55 :   return make_debug_string_with ("");
    3568              : }
    3569              : 
    3570              : /* Build a debug string representation of the form:
    3571              : 
    3572              :      RESULT_TYPE INSERT (PARAM_TYPES)
    3573              : 
    3574              :    for use when handling 0 and 1 level of indirection to this
    3575              :    function type.  */
    3576              : 
    3577              : recording::string *
    3578          115 : recording::function_type::make_debug_string_with (const char *insert)
    3579              : {
    3580              :   /* First, build a buffer for the arguments.  */
    3581              :   /* Calculate length of said buffer.  */
    3582          115 :   size_t sz = 1; /* nil terminator */
    3583          310 :   for (unsigned i = 0; i< m_param_types.length (); i++)
    3584              :     {
    3585          195 :       sz += strlen (m_param_types[i]->get_debug_string ());
    3586          195 :       sz += 2; /* ", " separator */
    3587              :     }
    3588          115 :   if (m_is_variadic)
    3589            0 :     sz += 5; /* ", ..." separator and ellipsis */
    3590              : 
    3591              :   /* Now allocate and populate the buffer.  */
    3592          115 :   char *argbuf = new char[sz];
    3593          115 :   size_t len = 0;
    3594              : 
    3595          415 :   for (unsigned i = 0; i< m_param_types.length (); i++)
    3596              :     {
    3597          195 :       strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
    3598          195 :       len += strlen (m_param_types[i]->get_debug_string ());
    3599          505 :       if (i + 1 < m_param_types.length ())
    3600              :         {
    3601           90 :           strcpy (argbuf + len, ", ");
    3602           90 :           len += 2;
    3603              :         }
    3604              :     }
    3605          115 :   if (m_is_variadic)
    3606              :     {
    3607            0 :       if (m_param_types.length ())
    3608              :         {
    3609            0 :           strcpy (argbuf + len, ", ");
    3610            0 :           len += 2;
    3611              :         }
    3612            0 :       strcpy (argbuf + len, "...");
    3613            0 :       len += 3;
    3614              :     }
    3615          115 :   argbuf[len] = '\0';
    3616              : 
    3617              :   /* ...and use it to get the string for the call as a whole.  */
    3618          115 :   string *result = string::from_printf (m_ctxt,
    3619              :                                         "%s %s(%s)",
    3620          115 :                                         m_return_type->get_debug_string (),
    3621              :                                         insert,
    3622              :                                         argbuf);
    3623              : 
    3624          115 :   delete[] argbuf;
    3625              : 
    3626          115 :   return result;
    3627              : }
    3628              : 
    3629              : /* Implementation of recording::memento::write_reproducer for function
    3630              :    types.  */
    3631              : 
    3632              : void
    3633          207 : recording::function_type::write_reproducer (reproducer &)
    3634              : {
    3635              :   /* see notes below.  */
    3636          207 : }
    3637              : 
    3638              : /* There's a get_pointer within context::new_function_ptr_type:
    3639              :    the type received by client code isn't the memento for the
    3640              :    function_type, but instead the result of get_pointer on it.
    3641              : 
    3642              :    Hence we can't directly write a reproducer that gives function_type.
    3643              :    Instead we special-case things within get_pointer, detecting this
    3644              :    case, calling the following function.  */
    3645              : 
    3646              : void
    3647           55 : recording::function_type::write_deferred_reproducer (reproducer &r,
    3648              :                                                      memento *ptr_type)
    3649              : {
    3650           55 :   gcc_assert (ptr_type);
    3651           55 :   r.make_identifier (this, "function_type");
    3652           55 :   const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
    3653           55 :   const char *param_types_id = r.make_tmp_identifier ("params_for", this);
    3654           55 :   r.write ("  gcc_jit_type *%s[%i] = {\n",
    3655              :            param_types_id,
    3656              :            m_param_types.length ());
    3657           55 :   int i;
    3658           55 :   type *param_type;
    3659          200 :   FOR_EACH_VEC_ELT (m_param_types, i, param_type)
    3660           90 :     r.write ("    %s,\n", r.get_identifier_as_type (param_type));
    3661           55 :   r.write ("  };\n");
    3662          105 :   r.write ("  gcc_jit_type *%s =\n"
    3663              :            "    gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
    3664              :            "                                           %s, /* gcc_jit_location *loc */\n"
    3665              :            "                                           %s, /* gcc_jit_type *return_type */\n"
    3666              :            "                                           %i, /* int num_params */\n"
    3667              :            "                                           %s, /* gcc_jit_type **param_types */\n"
    3668              :            "                                           %i); /* int is_variadic */\n",
    3669              :            ptr_id,
    3670              :            r.get_identifier (get_context ()),
    3671              :            "NULL", /* location is not stored */
    3672              :            r.get_identifier_as_type (m_return_type),
    3673              :            m_param_types.length (),
    3674              :            param_types_id,
    3675              :            m_is_variadic);
    3676           55 : }
    3677              : 
    3678              : /* The implementation of class gcc::jit::recording::field.  */
    3679              : 
    3680              : /* Implementation of pure virtual hook recording::memento::replay_into
    3681              :    for recording::field.  */
    3682              : 
    3683              : void
    3684         1718 : recording::field::replay_into (replayer *r)
    3685              : {
    3686         1718 :   set_playback_obj (r->new_field (playback_location (r, m_loc),
    3687         1718 :                                   m_type->playback_type (),
    3688              :                                   playback_string (m_name)));
    3689         1718 : }
    3690              : 
    3691              : /* Override the default implementation of
    3692              :    recording::memento::write_to_dump.  Dump each field
    3693              :    by dumping a line of the form:
    3694              :       TYPE NAME;
    3695              :    so that we can build up a struct/union field by field.  */
    3696              : 
    3697              : void
    3698            8 : recording::field::write_to_dump (dump &d)
    3699              : {
    3700            8 :   d.write ("  %s %s;\n",
    3701            8 :            m_type->get_debug_string (),
    3702            8 :            m_name->c_str ());
    3703            8 : }
    3704              : 
    3705              : /* Implementation of recording::memento::make_debug_string for
    3706              :    results of new_field.  */
    3707              : 
    3708              : recording::string *
    3709         3990 : recording::field::make_debug_string ()
    3710              : {
    3711         3990 :   return m_name;
    3712              : }
    3713              : 
    3714              : /* Implementation of recording::memento::write_reproducer for fields.  */
    3715              : 
    3716              : void
    3717         3989 : recording::field::write_reproducer (reproducer &r)
    3718              : {
    3719         3989 :   const char *id = r.make_identifier (this, "field");
    3720         7978 :   r.write("  gcc_jit_field *%s =\n"
    3721              :           "    gcc_jit_context_new_field (%s,\n"
    3722              :           "                               %s, /* gcc_jit_location *loc */\n"
    3723              :           "                               %s, /* gcc_jit_type *type, */\n"
    3724              :           "                               %s); /* const char *name */\n",
    3725              :           id,
    3726              :           r.get_identifier (get_context ()),
    3727         3989 :           r.get_identifier (m_loc),
    3728              :           r.get_identifier_as_type (m_type),
    3729         3989 :           m_name->get_debug_string ());
    3730         3989 : }
    3731              : 
    3732              : /* The implementation of class gcc::jit::recording::bitfield.  */
    3733              : 
    3734              : /* Implementation of pure virtual hook recording::memento::replay_into
    3735              :    for recording::bitfield.  */
    3736              : 
    3737              : void
    3738           95 : recording::bitfield::replay_into (replayer *r)
    3739              : {
    3740          190 :   set_playback_obj (r->new_bitfield (playback_location (r, m_loc),
    3741           95 :                                      m_type->playback_type (),
    3742              :                                      m_width,
    3743              :                                      playback_string (m_name)));
    3744           95 : }
    3745              : 
    3746              : /* Override the default implementation of
    3747              :    recording::memento::write_to_dump.  Dump each bit field
    3748              :    by dumping a line of the form:
    3749              :       TYPE NAME:WIDTH;
    3750              :    so that we can build up a struct/union field by field.  */
    3751              : 
    3752              : void
    3753            0 : recording::bitfield::write_to_dump (dump &d)
    3754              : {
    3755            0 :   d.write ("  %s %s:%d;\n",
    3756            0 :            m_type->get_debug_string (),
    3757            0 :            m_name->c_str (),
    3758              :            m_width);
    3759            0 : }
    3760              : 
    3761              : /* Implementation of recording::memento::make_debug_string for
    3762              :    results of new_bitfield.  */
    3763              : 
    3764              : recording::string *
    3765           85 : recording::bitfield::make_debug_string ()
    3766              : {
    3767           85 :   return string::from_printf (m_ctxt,
    3768              :                               "%s:%d",
    3769           85 :                               m_name->c_str (), m_width);
    3770              : }
    3771              : 
    3772              : /* Implementation of recording::memento::write_reproducer for bitfields.  */
    3773              : 
    3774              : void
    3775           85 : recording::bitfield::write_reproducer (reproducer &r)
    3776              : {
    3777           85 :   const char *id = r.make_identifier (this, "bitfield");
    3778          170 :   r.write ("  gcc_jit_field *%s =\n"
    3779              :            "    gcc_jit_context_new_bitfield (%s,\n"
    3780              :            "                               %s, /* gcc_jit_location *loc */\n"
    3781              :            "                               %s, /* gcc_jit_type *type, */\n"
    3782              :            "                               %d, /* int width, */\n"
    3783              :            "                               %s); /* const char *name */\n",
    3784              :            id,
    3785              :            r.get_identifier (get_context ()),
    3786           85 :            r.get_identifier (m_loc),
    3787              :            r.get_identifier_as_type (m_type),
    3788              :            m_width,
    3789           85 :            m_name->get_debug_string ());
    3790           85 : }
    3791              : 
    3792              : /* The implementation of class gcc::jit::recording::compound_type */
    3793              : 
    3794              : /* The constructor for gcc::jit::recording::compound_type.  */
    3795              : 
    3796         1086 : recording::compound_type::compound_type (context *ctxt,
    3797              :                                          location *loc,
    3798         1086 :                                          string *name)
    3799              : : type (ctxt),
    3800         1086 :   m_loc (loc),
    3801         1086 :   m_name (name),
    3802         1086 :   m_fields (NULL)
    3803              : {
    3804         1086 : }
    3805              : 
    3806              : /* Set the fields of a compound type.
    3807              : 
    3808              :    Implements the post-error-checking part of
    3809              :    gcc_jit_struct_set_fields, and is also used by
    3810              :    gcc_jit_context_new_union_type.  */
    3811              : 
    3812              : void
    3813         1037 : recording::compound_type::set_fields (location *loc,
    3814              :                                       int num_fields,
    3815              :                                       field **field_array)
    3816              : {
    3817         1037 :   m_loc = loc;
    3818         1037 :   gcc_assert (m_fields == NULL);
    3819              : 
    3820         1037 :   m_fields = new fields (this, num_fields, field_array);
    3821         1037 :   m_ctxt->record (m_fields);
    3822         1037 : }
    3823              : 
    3824              : /* Implementation of pure virtual hook recording::type::dereference for
    3825              :    recording::compound_type.  */
    3826              : 
    3827              : recording::type *
    3828            0 : recording::compound_type::dereference ()
    3829              : {
    3830            0 :   return NULL; /* not a pointer */
    3831              : }
    3832              : 
    3833              : /* The implementation of class gcc::jit::recording::struct_.  */
    3834              : 
    3835              : /* The constructor for gcc::jit::recording::struct_.  */
    3836              : 
    3837         1001 : recording::struct_::struct_ (context *ctxt,
    3838              :                              location *loc,
    3839         1001 :                              string *name)
    3840         1001 : : compound_type (ctxt, loc, name)
    3841              : {
    3842         1001 : }
    3843              : 
    3844              : /* Implementation of pure virtual hook recording::memento::replay_into
    3845              :    for recording::struct_.  */
    3846              : 
    3847              : void
    3848          527 : recording::struct_::replay_into (replayer *r)
    3849              : {
    3850         1054 :   set_playback_obj (
    3851          527 :     r->new_compound_type (playback_location (r, get_loc ()),
    3852              :                           get_name ()->c_str (),
    3853              :                           true /* is_struct */));
    3854          527 : }
    3855              : 
    3856              : const char *
    3857         1728 : recording::struct_::access_as_type (reproducer &r)
    3858              : {
    3859         1728 :   return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
    3860         1728 :                            r.get_identifier (this));
    3861              : }
    3862              : 
    3863              : /* Implementation of recording::memento::make_debug_string for
    3864              :    structs.  */
    3865              : 
    3866              : recording::string *
    3867          841 : recording::struct_::make_debug_string ()
    3868              : {
    3869          841 :   return string::from_printf (m_ctxt,
    3870          841 :                               "struct %s", get_name ()->c_str ());
    3871              : }
    3872              : 
    3873              : void
    3874          842 : recording::struct_::write_reproducer (reproducer &r)
    3875              : {
    3876          842 :   const char *id = r.make_identifier (this, "struct");
    3877          842 :   r.write ("  gcc_jit_struct *%s =\n"
    3878              :            "    gcc_jit_context_new_opaque_struct (%s,\n"
    3879              :            "                                       %s, /* gcc_jit_location *loc */\n"
    3880              :            "                                       %s); /* const char *name */\n",
    3881              :            id,
    3882              :            r.get_identifier (get_context ()),
    3883          842 :            r.get_identifier (get_loc ()),
    3884          842 :            get_name ()->get_debug_string ());
    3885          842 : }
    3886              : 
    3887              : /* The implementation of class gcc::jit::recording::union_.  */
    3888              : 
    3889              : /* The constructor for gcc::jit::recording::union_.  */
    3890              : 
    3891           85 : recording::union_::union_ (context *ctxt,
    3892              :                            location *loc,
    3893           85 :                            string *name)
    3894           85 : : compound_type (ctxt, loc, name)
    3895              : {
    3896           85 : }
    3897              : 
    3898              : /* Implementation of pure virtual hook recording::memento::replay_into
    3899              :    for recording::union_.  */
    3900              : 
    3901              : void
    3902           75 : recording::union_::replay_into (replayer *r)
    3903              : {
    3904          150 :   set_playback_obj (
    3905           75 :     r->new_compound_type (playback_location (r, get_loc ()),
    3906              :                           get_name ()->c_str (),
    3907              :                           false /* is_struct */));
    3908           75 : }
    3909              : 
    3910              : /* Implementation of recording::memento::make_debug_string for
    3911              :    unions.  */
    3912              : 
    3913              : recording::string *
    3914           60 : recording::union_::make_debug_string ()
    3915              : {
    3916           60 :   return string::from_printf (m_ctxt,
    3917           60 :                               "union %s", get_name ()->c_str ());
    3918              : }
    3919              : 
    3920              : /* Implementation of recording::memento::write_reproducer for unions.  */
    3921              : 
    3922              : void
    3923           60 : recording::union_::write_reproducer (reproducer &r)
    3924              : {
    3925           60 :   const char *id = r.make_identifier (this, "union");
    3926              : 
    3927           60 :   const char *fields_id = r.make_tmp_identifier ("fields_for", this);
    3928           60 :   r.write ("  gcc_jit_field *%s[%i] = {\n",
    3929              :            fields_id,
    3930              :            get_fields ()->length ());
    3931          390 :   for (int i = 0; i < get_fields ()->length (); i++)
    3932          135 :     r.write ("    %s,\n", r.get_identifier (get_fields ()->get_field (i)));
    3933           60 :   r.write ("  };\n");
    3934              : 
    3935          120 :   r.write ("  gcc_jit_type *%s =\n"
    3936              :            "    gcc_jit_context_new_union_type (%s,\n"
    3937              :            "                                    %s, /* gcc_jit_location *loc */\n"
    3938              :            "                                    %s, /* const char *name */\n"
    3939              :            "                                    %i, /* int num_fields */\n"
    3940              :            "                                    %s); /* gcc_jit_field **fields */\n",
    3941              :            id,
    3942              :            r.get_identifier (get_context ()),
    3943           60 :            r.get_identifier (get_loc ()),
    3944           60 :            get_name ()->get_debug_string (),
    3945              :            get_fields ()->length (),
    3946              :            fields_id);
    3947           60 : }
    3948              : 
    3949              : /* The implementation of class gcc::jit::recording::fields.  */
    3950              : 
    3951              : /* The constructor for gcc::jit::recording::fields.  */
    3952              : 
    3953         1037 : recording::fields::fields (compound_type *struct_or_union,
    3954              :                            int num_fields,
    3955         1037 :                            field **fields)
    3956              : : memento (struct_or_union->m_ctxt),
    3957         1037 :   m_struct_or_union (struct_or_union),
    3958         1037 :   m_fields ()
    3959              : {
    3960         4681 :   for (int i = 0; i < num_fields; i++)
    3961              :     {
    3962         3644 :       gcc_assert (fields[i]->get_container () == NULL);
    3963         3644 :       fields[i]->set_container (m_struct_or_union);
    3964         3644 :       m_fields.safe_push (fields[i]);
    3965              :     }
    3966         1037 : }
    3967              : 
    3968              : /* Implementation of pure virtual hook recording::memento::replay_into
    3969              :    for recording::fields.  */
    3970              : 
    3971              : void
    3972          572 : recording::fields::replay_into (replayer *)
    3973              : {
    3974          572 :   auto_vec<playback::field *> playback_fields;
    3975          572 :   playback_fields.create (m_fields.length ());
    3976         2375 :   for (unsigned i = 0; i < m_fields.length (); i++)
    3977         1803 :     playback_fields.safe_push (m_fields[i]->playback_field ());
    3978          572 :   m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
    3979          572 : }
    3980              : 
    3981              : /* Override the default implementation of
    3982              :    recording::memento::write_to_dump by writing a union/struct
    3983              :    declaration of this form:
    3984              : 
    3985              :       struct/union NAME {
    3986              :         TYPE_1 NAME_1;
    3987              :         TYPE_2 NAME_2;
    3988              :         ....
    3989              :         TYPE_N NAME_N;
    3990              :       };
    3991              : 
    3992              :     to the dump.  */
    3993              : 
    3994              : void
    3995            2 : recording::fields::write_to_dump (dump &d)
    3996              : {
    3997            2 :   int i;
    3998            2 :   field *f;
    3999              : 
    4000            2 :   d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
    4001           12 :   FOR_EACH_VEC_ELT (m_fields, i, f)
    4002            8 :     f->write_to_dump (d);
    4003            2 :   d.write ("};\n");
    4004            2 : }
    4005              : 
    4006              : /* Implementation of recording::memento::write_reproducer for the fields
    4007              :    subclass.  */
    4008              : 
    4009              : void
    4010          863 : recording::fields::write_reproducer (reproducer &r)
    4011              : {
    4012          863 :   if (m_struct_or_union)
    4013          863 :     if (m_struct_or_union->dyn_cast_struct () == NULL)
    4014              :       /* We have a union; the fields have already been written by
    4015              :          union::write_reproducer.  */
    4016          863 :       return;
    4017              : 
    4018          803 :   const char *fields_id = r.make_identifier (this, "fields");
    4019          803 :   r.write ("  gcc_jit_field *%s[%i] = {\n",
    4020              :            fields_id,
    4021              :            m_fields.length ());
    4022          803 :   int i;
    4023          803 :   field *field;
    4024         4574 :   FOR_EACH_VEC_ELT (m_fields, i, field)
    4025         2968 :     r.write ("    %s,\n", r.get_identifier (field));
    4026          803 :   r.write ("  };\n");
    4027              : 
    4028         2351 :   r.write ("  gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
    4029              :            "                             %s, /* gcc_jit_location *loc */\n"
    4030              :            "                             %i, /* int num_fields */\n"
    4031              :            "                             %s); /* gcc_jit_field **fields */\n",
    4032          803 :            r.get_identifier (m_struct_or_union),
    4033              :            r.get_identifier ((memento *)NULL),
    4034              :            m_fields.length (),
    4035              :            fields_id);
    4036              : }
    4037              : 
    4038              : /* Implementation of recording::memento::make_debug_string for
    4039              :    field tables.  */
    4040              : 
    4041              : recording::string *
    4042          797 : recording::fields::make_debug_string ()
    4043              : {
    4044          797 :   return string::from_printf (m_ctxt,
    4045          797 :                               "fields");
    4046              : }
    4047              : 
    4048              : /* The implementation of class gcc::jit::recording::rvalue.  */
    4049              : 
    4050              : /* Create a recording::access_field_rvalue instance and add it to
    4051              :    the rvalue's context's list of mementos.
    4052              : 
    4053              :    Implements the post-error-checking part of
    4054              :    gcc_jit_rvalue_access_field.  */
    4055              : 
    4056              : recording::rvalue *
    4057          139 : recording::rvalue::access_field (recording::location *loc,
    4058              :                                  field *field)
    4059              : {
    4060          139 :   recording::rvalue *result =
    4061          139 :     new access_field_rvalue (m_ctxt, loc, this, field);
    4062          139 :   m_ctxt->record (result);
    4063          139 :   return result;
    4064              : }
    4065              : 
    4066              : /* Create a recording::dereference_field_rvalue instance and add it to
    4067              :    the rvalue's context's list of mementos.
    4068              : 
    4069              :    Implements the post-error-checking part of
    4070              :    gcc_jit_rvalue_dereference_field.  */
    4071              : 
    4072              : recording::lvalue *
    4073         1516 : recording::rvalue::dereference_field (recording::location *loc,
    4074              :                                       field *field)
    4075              : {
    4076         1516 :   recording::lvalue *result =
    4077         1516 :     new dereference_field_rvalue (m_ctxt, loc, this, field);
    4078         1516 :   m_ctxt->record (result);
    4079         1516 :   return result;
    4080              : }
    4081              : 
    4082              : /* Create a recording::dereference_rvalue instance and add it to the
    4083              :    rvalue's context's list of mementos.
    4084              : 
    4085              :    Implements the post-error-checking part of
    4086              :    gcc_jit_rvalue_dereference.  */
    4087              : 
    4088              : recording::lvalue *
    4089          684 : recording::rvalue::dereference (recording::location *loc)
    4090              : {
    4091          684 :   recording::lvalue *result =
    4092          684 :     new dereference_rvalue (m_ctxt, loc, this);
    4093          684 :   m_ctxt->record (result);
    4094          684 :   return result;
    4095              : }
    4096              : 
    4097              : /* An rvalue visitor, for validating that every rvalue within an expression
    4098              :    trees within "STMT" has the correct scope (e.g. no access to locals
    4099              :    of a different function).  */
    4100              : 
    4101        16436 : class rvalue_usage_validator : public recording::rvalue_visitor
    4102              : {
    4103              :  public:
    4104              :   rvalue_usage_validator (const char *api_funcname,
    4105              :                           recording::context *ctxt,
    4106              :                           recording::statement *stmt);
    4107              : 
    4108              :   void
    4109              :   visit (recording::rvalue *rvalue) final override;
    4110              : 
    4111              :  private:
    4112              :   const char *m_api_funcname;
    4113              :   recording::context *m_ctxt;
    4114              :   recording::statement *m_stmt;
    4115              : };
    4116              : 
    4117              : /* The trivial constructor for rvalue_usage_validator.  */
    4118              : 
    4119        16436 : rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
    4120              :                                                 recording::context *ctxt,
    4121        16436 :                                                 recording::statement *stmt)
    4122        16436 :   : m_api_funcname (api_funcname),
    4123        16436 :     m_ctxt (ctxt),
    4124        16436 :     m_stmt (stmt)
    4125              : {
    4126        16436 : }
    4127              : 
    4128              : /* Verify that the given rvalue is in the correct scope.  */
    4129              : 
    4130              : void
    4131        27104 : rvalue_usage_validator::visit (recording::rvalue *rvalue)
    4132              : {
    4133        27104 :   gcc_assert (m_stmt->get_block ());
    4134        27104 :   recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
    4135              : 
    4136              :   /* Most rvalues don't have a scope (only locals and params).  */
    4137        27104 :   if (rvalue->get_scope ())
    4138              :     {
    4139        11715 :       if (rvalue->get_scope () != stmt_scope)
    4140           10 :         m_ctxt->add_error
    4141           10 :           (rvalue->get_loc (),
    4142              :            "%s:"
    4143              :            " rvalue %s (type: %s)"
    4144              :            " has scope limited to function %s"
    4145              :            " but was used within function %s"
    4146              :            " (in statement: %s)",
    4147              :            m_api_funcname,
    4148              :            rvalue->get_debug_string (),
    4149           10 :            rvalue->get_type ()->get_debug_string (),
    4150           10 :            rvalue->get_scope ()->get_debug_string (),
    4151              :            stmt_scope->get_debug_string (),
    4152              :            m_stmt->get_debug_string ());
    4153              :     }
    4154              :   else
    4155              :     {
    4156        15389 :       if (rvalue->dyn_cast_param ())
    4157            5 :         m_ctxt->add_error
    4158            5 :           (rvalue->get_loc (),
    4159              :            "%s:"
    4160              :            " param %s (type: %s)"
    4161              :            " was used within function %s"
    4162              :            " (in statement: %s)"
    4163              :            " but is not associated with any function",
    4164              :            m_api_funcname,
    4165              :            rvalue->get_debug_string (),
    4166            5 :            rvalue->get_type ()->get_debug_string (),
    4167              :            stmt_scope->get_debug_string (),
    4168            5 :            m_stmt->get_debug_string ());
    4169              :     }
    4170        27104 : }
    4171              : 
    4172              : /* Verify that it's valid to use this rvalue (and all expressions
    4173              :    in the tree below it) within the given statement.
    4174              : 
    4175              :    For example, we must reject attempts to use a local from one
    4176              :    function within a different function here, or we'll get
    4177              :    an ICE deep inside toplev::main.  */
    4178              : 
    4179              : void
    4180        16436 : recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
    4181              : {
    4182        16436 :   rvalue_usage_validator v (api_funcname,
    4183              :                             s->get_context (),
    4184        16436 :                             s);
    4185              : 
    4186              :   /* Verify that it's OK to use this rvalue within s.  */
    4187        16436 :   v.visit (this);
    4188              : 
    4189              :   /* Traverse the expression tree below "this", verifying all rvalues
    4190              :      within it.  */
    4191        16436 :   visit_children (&v);
    4192        16436 : }
    4193              : 
    4194              : /* Set the scope of this rvalue to be the given function.  This can only
    4195              :    be done once on a given rvalue.  */
    4196              : 
    4197              : void
    4198        23305 : recording::rvalue::set_scope (function *scope)
    4199              : {
    4200        23305 :   gcc_assert (scope);
    4201        23305 :   gcc_assert (m_scope == NULL);
    4202        23305 :   m_scope = scope;
    4203        23305 : }
    4204              : 
    4205              : 
    4206              : /* Implementation of recording::rvalue::access_as_rvalue for rvalues
    4207              :    themselves.
    4208              :    Instances of rvalue don't need an upcast call.  */
    4209              : 
    4210              : const char *
    4211         9191 : recording::rvalue::access_as_rvalue (reproducer &r)
    4212              : {
    4213         9191 :   return r.get_identifier (this);
    4214              : }
    4215              : 
    4216              : /* Return a debug string for the given rvalue, wrapping it in parentheses
    4217              :    if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
    4218              :    stronger precedence that this rvalue's precedence.
    4219              : 
    4220              :    For example, given:
    4221              : 
    4222              :            MULT
    4223              :           /    \
    4224              :        PLUS     MINUS
    4225              :       /    \   /     \
    4226              :      A      B C       D
    4227              : 
    4228              :    we want to emit:
    4229              : 
    4230              :      (A + B) * (C - D)
    4231              : 
    4232              :    since MULT has strong precedence than PLUS and MINUS, whereas for:
    4233              : 
    4234              :            PLUS
    4235              :           /    \
    4236              :        MULT     DIVIDE
    4237              :       /    \   /      \
    4238              :      A      B C        D
    4239              : 
    4240              :    we can simply emit:
    4241              : 
    4242              :      A * B + C / D
    4243              : 
    4244              :    since PLUS has weaker precedence than MULT and DIVIDE.  */
    4245              : 
    4246              : const char *
    4247        12114 : recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
    4248              : {
    4249        12114 :   enum precedence this_prec = get_precedence ();
    4250              : 
    4251              :   /* If this_prec has stronger precedence than outer_prec, we don't
    4252              :      need to wrap this in parens within the outer debug string.
    4253              :      Stronger precedences occur earlier than weaker within the enum,
    4254              :      so this is a less than test.  Equal precedences don't need
    4255              :      parentheses.  */
    4256        12114 :   if (this_prec <= outer_prec)
    4257        10854 :     return get_debug_string();
    4258              : 
    4259              :   /* Otherwise, we need parentheses.  */
    4260              : 
    4261              :   /* Lazily-build and cache m_parenthesized_string.  */
    4262         1260 :   if (!m_parenthesized_string)
    4263              :     {
    4264          634 :       const char *debug_string = get_debug_string ();
    4265          634 :       m_parenthesized_string = string::from_printf (get_context (),
    4266              :                                                     "(%s)",
    4267              :                                                     debug_string);
    4268              :     }
    4269         1260 :   gcc_assert (m_parenthesized_string);
    4270         1260 :   return m_parenthesized_string->c_str ();
    4271              : }
    4272              : 
    4273              : 
    4274              : /* The implementation of class gcc::jit::recording::lvalue.  */
    4275              : 
    4276              : /* Create a recording::new_access_field_of_lvalue instance and add it to
    4277              :    the lvalue's context's list of mementos.
    4278              : 
    4279              :    Implements the post-error-checking part of
    4280              :    gcc_jit_lvalue_access_field.  */
    4281              : 
    4282              : recording::lvalue *
    4283          219 : recording::lvalue::access_field (recording::location *loc,
    4284              :                                  field *field)
    4285              : {
    4286          219 :   recording::lvalue *result =
    4287          219 :     new access_field_of_lvalue (m_ctxt, loc, this, field);
    4288          219 :   m_ctxt->record (result);
    4289          219 :   return result;
    4290              : }
    4291              : 
    4292              : /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
    4293              :    Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
    4294              :    upcast call.  */
    4295              : 
    4296              : const char *
    4297         3412 : recording::lvalue::access_as_rvalue (reproducer &r)
    4298              : {
    4299         3412 :   return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
    4300         3412 :                            r.get_identifier (this));
    4301              : }
    4302              : 
    4303              : /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
    4304              :    Instances of lvalue don't need to be upcast.  */
    4305              : 
    4306              : const char *
    4307         2854 : recording::lvalue::access_as_lvalue (reproducer &r)
    4308              : {
    4309         2854 :   return r.get_identifier (this);
    4310              : }
    4311              : 
    4312              : /* Create a recording::get_address_of_lvalue instance and add it to
    4313              :    the lvalue's context's list of mementos.
    4314              : 
    4315              :    Implements the post-error-checking part of
    4316              :    gcc_jit_lvalue_get_address.  */
    4317              : 
    4318              : recording::rvalue *
    4319          508 : recording::lvalue::get_address (recording::location *loc)
    4320              : {
    4321          508 :   recording::rvalue *result =
    4322          508 :     new get_address_of_lvalue (m_ctxt, loc, this);
    4323          508 :   m_ctxt->record (result);
    4324          508 :   return result;
    4325              : }
    4326              : 
    4327              : void
    4328           15 : recording::lvalue::set_tls_model (enum gcc_jit_tls_model model)
    4329              : {
    4330           15 :     m_tls_model = model;
    4331           15 : }
    4332              : 
    4333            5 : void recording::lvalue::set_link_section (const char *name)
    4334              : {
    4335            5 :   m_link_section = new_string (name);
    4336            5 : }
    4337              : 
    4338           20 : void recording::lvalue::set_register_name (const char *reg_name)
    4339              : {
    4340           20 :   m_reg_name = new_string (reg_name);
    4341           20 : }
    4342              : 
    4343           10 : void recording::lvalue::set_alignment (unsigned bytes)
    4344              : {
    4345           10 :   m_alignment = bytes;
    4346           10 : }
    4347              : 
    4348            5 : void recording::lvalue::add_string_attribute (
    4349              :         gcc_jit_variable_attribute attribute,
    4350              :         const char* value)
    4351              : {
    4352            5 :   m_string_attributes.push_back (std::make_pair (attribute, std::string (value)));
    4353            5 : }
    4354              : 
    4355              : /* The implementation of class gcc::jit::recording::param.  */
    4356              : 
    4357              : /* Implementation of pure virtual hook recording::memento::replay_into
    4358              :    for recording::param.  */
    4359              : 
    4360              : void
    4361        16518 : recording::param::replay_into (replayer *r)
    4362              : {
    4363        16518 :   set_playback_obj (r->new_param (playback_location (r, m_loc),
    4364        16518 :                                   m_type->playback_type (),
    4365        16518 :                                   m_name->c_str ()));
    4366        16518 : }
    4367              : 
    4368              : /* Implementation of recording::rvalue::access_as_rvalue for params.
    4369              :    Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
    4370              :    upcast call.  */
    4371              : 
    4372              : const char *
    4373         4254 : recording::param::access_as_rvalue (reproducer &r)
    4374              : {
    4375         4254 :   return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
    4376         4254 :                            r.get_identifier (this));
    4377              : }
    4378              : 
    4379              : /* Implementation of recording::lvalue::access_as_lvalue for params.
    4380              :    Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
    4381              :    upcast call.  */
    4382              : 
    4383              : const char *
    4384           74 : recording::param::access_as_lvalue (reproducer &r)
    4385              : {
    4386           74 :   return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
    4387           74 :                            r.get_identifier (this));
    4388              : }
    4389              : 
    4390              : /* Implementation of recording::memento::write_reproducer for params. */
    4391              : 
    4392              : void
    4393         7222 : recording::param::write_reproducer (reproducer &r)
    4394              : {
    4395         7222 :   const char *id = r.make_identifier (this, "param");
    4396        14444 :   r.write ("  gcc_jit_param *%s =\n"
    4397              :            "    gcc_jit_context_new_param (%s,\n"
    4398              :            "                               %s, /* gcc_jit_location *loc */\n"
    4399              :            "                               %s, /*gcc_jit_type *type */\n"
    4400              :            "                               %s); /* const char *name */\n",
    4401              :            id,
    4402              :     r.get_identifier (get_context ()),
    4403         7222 :            r.get_identifier (m_loc),
    4404              :            r.get_identifier_as_type (m_type),
    4405         7222 :            m_name->get_debug_string ());
    4406         7222 : }
    4407              : 
    4408              : /* The implementation of class gcc::jit::recording::function.  */
    4409              : 
    4410              : /* gcc::jit::recording::function's constructor.  */
    4411              : 
    4412        17795 : recording::function::function (context *ctxt,
    4413              :                                recording::location *loc,
    4414              :                                enum gcc_jit_function_kind kind,
    4415              :                                type *return_type,
    4416              :                                recording::string *name,
    4417              :                                int num_params,
    4418              :                                recording::param **params,
    4419              :                                int is_variadic,
    4420              :                                enum built_in_function builtin_id,
    4421        17795 :                                bool is_target_builtin)
    4422              : : memento (ctxt),
    4423        17795 :   m_loc (loc),
    4424        17795 :   m_kind (kind),
    4425        17795 :   m_return_type (return_type),
    4426        17795 :   m_name (name),
    4427        17795 :   m_params (),
    4428        17795 :   m_is_variadic (is_variadic),
    4429        17795 :   m_builtin_id (builtin_id),
    4430        17795 :   m_locals (),
    4431        17795 :   m_blocks (),
    4432        17795 :   m_fn_ptr_type (NULL),
    4433        17795 :   m_attributes (),
    4434        17795 :   m_string_attributes (),
    4435        17795 :   m_int_array_attributes (),
    4436        17795 :   m_is_target_builtin (is_target_builtin)
    4437              : {
    4438        37125 :   for (int i = 0; i< num_params; i++)
    4439              :     {
    4440        19330 :       param *param = params[i];
    4441        19330 :       gcc_assert (param);
    4442              : 
    4443              :       /* Associate each param with this function.
    4444              : 
    4445              :          Verify that the param doesn't already have a function.  */
    4446        19330 :       if (param->get_scope ())
    4447              :         {
    4448              :           /* We've already rejected attempts to reuse a param between
    4449              :              different functions (within gcc_jit_context_new_function), so
    4450              :              if the param *does* already have a function, it must be being
    4451              :              reused within the params array for this function.  We must
    4452              :              produce an error for this reuse (blocking the compile), since
    4453              :              otherwise we'd have an ICE later on.  */
    4454            5 :           gcc_assert (this == param->get_scope ());
    4455            5 :           ctxt->add_error
    4456            5 :             (loc,
    4457              :              "gcc_jit_context_new_function:"
    4458              :              " parameter %s (type: %s)"
    4459              :              " is used more than once when creating function %s",
    4460              :              param->get_debug_string (),
    4461            5 :              param->get_type ()->get_debug_string (),
    4462              :              name->c_str ());
    4463              :         }
    4464              :       else
    4465              :         {
    4466              :           /* The normal, non-error case: associate this function with the
    4467              :              param.  */
    4468        19325 :           param->set_scope (this);
    4469              :         }
    4470              : 
    4471        19330 :       m_params.safe_push (param);
    4472              :     }
    4473        17795 : }
    4474              : 
    4475              : /* Implementation of pure virtual hook recording::memento::replay_into
    4476              :    for recording::function.  */
    4477              : 
    4478              : void
    4479        16667 : recording::function::replay_into (replayer *r)
    4480              : {
    4481              :   /* Convert m_params to a vec of playback param.  */
    4482        16667 :   auto_vec <playback::param *> params;
    4483        16667 :   int i;
    4484        16667 :   recording::param *param;
    4485        16667 :   params.create (m_params.length ());
    4486        49852 :   FOR_EACH_VEC_ELT (m_params, i, param)
    4487        16518 :     params.safe_push (param->playback_param ());
    4488              : 
    4489        16667 :   set_playback_obj (r->new_function (playback_location (r, m_loc),
    4490              :                                      m_kind,
    4491        16667 :                                      m_return_type->playback_type (),
    4492        16667 :                                      m_name->c_str (),
    4493              :                                      &params,
    4494              :                                      m_is_variadic,
    4495              :                                      m_builtin_id,
    4496        16667 :                                      m_attributes,
    4497        16667 :                                      m_string_attributes,
    4498        16667 :                                      m_int_array_attributes,
    4499        16667 :                                      m_is_target_builtin));
    4500        16667 : }
    4501              : 
    4502              : /* Create a recording::local instance and add it to
    4503              :    the functions's context's list of mementos, and to the function's
    4504              :    list of locals.
    4505              : 
    4506              :    Implements the post-error-checking part of
    4507              :    gcc_jit_function_new_local.  */
    4508              : 
    4509              : recording::lvalue *
    4510         3975 : recording::function::new_local (recording::location *loc,
    4511              :                                 type *type,
    4512              :                                 const char *name)
    4513              : {
    4514         3975 :   local *result = new local (this, loc, type, new_string (name));
    4515         3975 :   m_ctxt->record (result);
    4516         3975 :   m_locals.safe_push (result);
    4517         3975 :   return result;
    4518              : }
    4519              : 
    4520              : /* Create a recording::local instance and add it to
    4521              :    the functions's context's list of mementos, and to the function's
    4522              :    list of locals.
    4523              : 
    4524              :    Implements the post-error-checking part of
    4525              :    gcc_jit_function_new_temp.  */
    4526              : 
    4527              : recording::lvalue *
    4528            5 : recording::function::new_temp (recording::location *loc,
    4529              :                                type *type)
    4530              : {
    4531            5 :   local *result = new local (this, loc, type, NULL);
    4532            5 :   m_ctxt->record (result);
    4533            5 :   m_locals.safe_push (result);
    4534            5 :   return result;
    4535              : }
    4536              : 
    4537              : /* Create a recording::block instance and add it to
    4538              :    the functions's context's list of mementos, and to the function's
    4539              :    list of blocks.
    4540              : 
    4541              :    Implements the post-error-checking part of
    4542              :    gcc_jit_function_new_block.  */
    4543              : 
    4544              : recording::block*
    4545         6474 : recording::function::new_block (const char *name)
    4546              : {
    4547         6474 :   gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
    4548              : 
    4549         6474 :   recording::block *result =
    4550         9056 :     new recording::block (this, m_blocks.length (), new_string (name));
    4551         6474 :   m_ctxt->record (result);
    4552         6474 :   m_blocks.safe_push (result);
    4553         6474 :   return result;
    4554              : }
    4555              : 
    4556              : /* Override the default implementation of
    4557              :    recording::memento::write_to_dump by dumping a C-like
    4558              :    representation of the function; either like a prototype
    4559              :    for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
    4560              :    all other kinds of function.  */
    4561              : 
    4562              : void
    4563           14 : recording::function::write_to_dump (dump &d)
    4564              : {
    4565           14 :   for (auto attr: m_attributes)
    4566              :   {
    4567            0 :     const char* attribute = fn_attribute_to_string (attr);
    4568            0 :     if (attribute)
    4569            0 :       d.write ("__attribute(%s)__\n", attribute);
    4570              :   }
    4571           14 :   for (auto attr: m_string_attributes)
    4572              :   {
    4573            0 :     gcc_jit_fn_attribute& name = std::get<0>(attr);
    4574            0 :     std::string& value = std::get<1>(attr);
    4575            0 :     const char* attribute = fn_attribute_to_string (name);
    4576              : 
    4577            0 :     if (attribute)
    4578            0 :       d.write ("__attribute(%s(\"%s\"))__\n", attribute, value.c_str());
    4579            0 :   }
    4580           14 :   for (auto attr: m_int_array_attributes)
    4581              :   {
    4582            0 :     gcc_jit_fn_attribute& name = std::get<0>(attr);
    4583            0 :     std::vector<int>& values = std::get<1>(attr);
    4584            0 :     const char* attribute = fn_attribute_to_string (name);
    4585            0 :     if (attribute)
    4586              :     {
    4587            0 :       d.write ("__attribute(%s(", attribute);
    4588            0 :       for (size_t i = 0; i < values.size(); ++i)
    4589              :       {
    4590            0 :         if (i > 0)
    4591            0 :           d.write (", %d", values[i]);
    4592              :         else
    4593            0 :           d.write ("%d", values[i]);
    4594              :       }
    4595            0 :       d.write ("))__\n");
    4596              :     }
    4597            0 :   }
    4598              : 
    4599           14 :   switch (m_kind)
    4600              :     {
    4601            0 :     default: gcc_unreachable ();
    4602           14 :     case GCC_JIT_FUNCTION_EXPORTED:
    4603           14 :     case GCC_JIT_FUNCTION_IMPORTED:
    4604           14 :       d.write ("extern ");
    4605           14 :       break;
    4606            0 :     case GCC_JIT_FUNCTION_INTERNAL:
    4607            0 :       d.write ("static ");
    4608            0 :       break;
    4609            0 :     case GCC_JIT_FUNCTION_ALWAYS_INLINE:
    4610            0 :       d.write ("static inline ");
    4611            0 :       break;
    4612              :      }
    4613           14 :   d.write ("%s\n", m_return_type->get_debug_string ());
    4614              : 
    4615           14 :   if (d.update_locations ())
    4616           14 :     m_loc = d.make_location ();
    4617              : 
    4618           14 :   d.write ("%s (", get_debug_string ());
    4619              : 
    4620           14 :   int i;
    4621           14 :   recording::param *param;
    4622           74 :   FOR_EACH_VEC_ELT (m_params, i, param)
    4623              :     {
    4624           46 :       if (i > 0)
    4625           32 :         d.write (", ");
    4626           46 :       d.write ("%s %s",
    4627           46 :                param->get_type ()->get_debug_string (),
    4628              :                param->get_debug_string ());
    4629              :     }
    4630           14 :   d.write (")");
    4631           14 :   if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
    4632              :     {
    4633            2 :       d.write ("; /* (imported) */\n\n");
    4634              :     }
    4635              :   else
    4636              :     {
    4637           12 :       int i;
    4638           12 :       local *var = NULL;
    4639           12 :       block *b;
    4640           12 :       d.write ("\n{\n");
    4641              : 
    4642              :       /* Write locals: */
    4643           40 :       FOR_EACH_VEC_ELT (m_locals, i, var)
    4644           16 :         var->write_to_dump (d);
    4645           12 :       if (m_locals.length ())
    4646            8 :         d.write ("\n");
    4647              : 
    4648              :       /* Write each block: */
    4649           56 :       FOR_EACH_VEC_ELT (m_blocks, i, b)
    4650              :         {
    4651           44 :           if (i > 0)
    4652           32 :             d.write ("\n");
    4653           44 :           b->write_to_dump (d);
    4654              :         }
    4655              : 
    4656           12 :       d.write ("}\n\n");
    4657              :     }
    4658           14 : }
    4659              : 
    4660              : /* Pre-compilation validation of a function, for those things we can't
    4661              :    check until the context is (supposedly) fully-populated.  */
    4662              : 
    4663              : void
    4664         4403 : recording::function::validate ()
    4665              : {
    4666              :   /* Complain about empty functions with non-void return type.  */
    4667         4403 :   if (m_kind != GCC_JIT_FUNCTION_IMPORTED
    4668         4403 :       && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
    4669         3227 :     if (m_blocks.length () == 0)
    4670            5 :       m_ctxt->add_error (m_loc,
    4671              :                          "function %s returns non-void (type: %s)"
    4672              :                          " but has no blocks",
    4673              :                          get_debug_string (),
    4674            5 :                          m_return_type->get_debug_string ());
    4675              : 
    4676              :   /* Check that all blocks are terminated.  */
    4677              :   int num_invalid_blocks = 0;
    4678              :   {
    4679              :     int i;
    4680              :     block *b;
    4681              : 
    4682        10885 :     FOR_EACH_VEC_ELT (m_blocks, i, b)
    4683         6482 :       if (!b->validate ())
    4684          423 :         num_invalid_blocks++;
    4685              :   }
    4686              : 
    4687              :   /* Check that all blocks are reachable.  */
    4688         4403 :   if (!m_ctxt->get_inner_bool_option
    4689         4403 :         (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
    4690         4403 :       && m_blocks.length () > 0 && num_invalid_blocks == 0)
    4691              :     {
    4692              :       /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
    4693              :          flag, starting at the initial block.  */
    4694         3477 :       auto_vec<block *> worklist (m_blocks.length ());
    4695         3477 :       worklist.safe_push (m_blocks[0]);
    4696        22417 :       while (worklist.length () > 0)
    4697              :         {
    4698         5993 :           block *b = worklist.pop ();
    4699         5993 :           b->m_is_reachable = true;
    4700              : 
    4701              :           /* Add successor blocks that aren't yet marked to the worklist.  */
    4702              :           /* We checked that each block has a terminating statement above .  */
    4703         5993 :           vec <block *> successors = b->get_successor_blocks ();
    4704         5993 :           int i;
    4705         5993 :           block *succ;
    4706        15086 :           FOR_EACH_VEC_ELT (successors, i, succ)
    4707         3100 :             if (!succ->m_is_reachable)
    4708         2516 :               worklist.safe_push (succ);
    4709         5993 :           successors.release ();
    4710              :         }
    4711              : 
    4712              :       /* Now complain about any blocks that haven't been marked.  */
    4713              :       {
    4714              :         int i;
    4715              :         block *b;
    4716        12948 :         FOR_EACH_VEC_ELT (m_blocks, i, b)
    4717         5994 :           if (!b->m_is_reachable)
    4718            5 :             m_ctxt->add_error (b->get_loc (),
    4719              :                                "unreachable block: %s",
    4720              :                                b->get_debug_string ());
    4721              :       }
    4722         3477 :     }
    4723         4403 : }
    4724              : 
    4725              : /* Implements the post-error-checking part of
    4726              :    gcc_jit_function_dump_to_dot.  */
    4727              : 
    4728              : void
    4729            0 : recording::function::dump_to_dot (const char *path)
    4730              : {
    4731            0 :   FILE *fp  = fopen (path, "w");
    4732            0 :   if (!fp)
    4733            0 :     return;
    4734              : 
    4735            0 :   pretty_printer the_pp;
    4736            0 :   the_pp.set_output_stream (fp);
    4737              : 
    4738            0 :   pretty_printer *pp = &the_pp;
    4739              : 
    4740            0 :   pp_printf (pp, "digraph %s", get_debug_string ());
    4741            0 :   pp_string (pp, " {\n");
    4742              : 
    4743              :   /* Blocks: */
    4744            0 :   {
    4745            0 :     int i;
    4746            0 :     block *b;
    4747            0 :     FOR_EACH_VEC_ELT (m_blocks, i, b)
    4748            0 :       b->dump_to_dot (pp);
    4749              :   }
    4750              : 
    4751              :   /* Edges: */
    4752              :   {
    4753              :     int i;
    4754              :     block *b;
    4755            0 :     FOR_EACH_VEC_ELT (m_blocks, i, b)
    4756            0 :       b->dump_edges_to_dot (pp);
    4757              :   }
    4758              : 
    4759            0 :   pp_string (pp, "}\n");
    4760            0 :   pp_flush (pp);
    4761            0 :   fclose (fp);
    4762            0 : }
    4763              : 
    4764              : /* Implements the post-error-checking part of
    4765              :    gcc_jit_function_get_address.  */
    4766              : 
    4767              : recording::rvalue *
    4768           15 : recording::function::get_address (recording::location *loc)
    4769              : {
    4770              :   /* Lazily create and cache the function pointer type.  */
    4771           15 :   if (!m_fn_ptr_type)
    4772              :     {
    4773              :       /* Make a recording::function_type for this function.  */
    4774           30 :       auto_vec <recording::type *> param_types (m_params.length ());
    4775           15 :       unsigned i;
    4776           15 :       recording::param *param;
    4777           45 :       FOR_EACH_VEC_ELT (m_params, i, param)
    4778           15 :         param_types.safe_push (param->get_type ());
    4779           15 :       recording::function_type *fn_type
    4780           60 :         = m_ctxt->new_function_type (m_return_type,
    4781           30 :                                      m_params.length (),
    4782              :                                      param_types.address (),
    4783              :                                      m_is_variadic,
    4784           15 :                                      m_is_target_builtin);
    4785           15 :       m_fn_ptr_type = fn_type->get_pointer ();
    4786           15 :     }
    4787           15 :   gcc_assert (m_fn_ptr_type);
    4788              : 
    4789           15 :   rvalue *result = new function_pointer (get_context (), loc, this, m_fn_ptr_type);
    4790           15 :   m_ctxt->record (result);
    4791           15 :   return result;
    4792              : }
    4793              : 
    4794              : void
    4795           45 : recording::function::add_attribute (gcc_jit_fn_attribute attribute)
    4796              : {
    4797           45 :   m_attributes.push_back (attribute);
    4798           45 : }
    4799              : 
    4800              : void
    4801            5 : recording::function::add_string_attribute (gcc_jit_fn_attribute attribute,
    4802              :                                            const char* value)
    4803              : {
    4804           10 :   m_string_attributes.push_back (
    4805           10 :         std::make_pair (attribute, std::string (value)));
    4806            5 : }
    4807              : 
    4808              : void
    4809            5 : recording::function::add_integer_array_attribute (
    4810              :         gcc_jit_fn_attribute attribute,
    4811              :         const int* value,
    4812              :         size_t length)
    4813              : {
    4814            5 :   m_int_array_attributes.push_back (std::make_pair (
    4815              :     attribute,
    4816            5 :     std::vector<int> (value, value + length)));
    4817            5 : }
    4818              : 
    4819              : /* Implementation of recording::memento::make_debug_string for
    4820              :    functions.  */
    4821              : 
    4822              : recording::string *
    4823         3310 : recording::function::make_debug_string ()
    4824              : {
    4825         3310 :   return m_name;
    4826              : }
    4827              : 
    4828              : /* A table of enum gcc_jit_function_kind values expressed in string
    4829              :    form.  */
    4830              : 
    4831              : static const char * const names_of_function_kinds[] = {
    4832              :   "GCC_JIT_FUNCTION_EXPORTED",
    4833              :   "GCC_JIT_FUNCTION_INTERNAL",
    4834              :   "GCC_JIT_FUNCTION_IMPORTED",
    4835              :   "GCC_JIT_FUNCTION_ALWAYS_INLINE"
    4836              : };
    4837              : 
    4838              : /* Implementation of recording::memento::write_reproducer for functions. */
    4839              : 
    4840              : static const char * const fn_attribute_reproducer_strings[] =
    4841              : {
    4842              :   "GCC_JIT_FN_ATTRIBUTE_ALIAS",
    4843              :   "GCC_JIT_FN_ATTRIBUTE_ALWAYS_INLINE",
    4844              :   "GCC_JIT_FN_ATTRIBUTE_INLINE",
    4845              :   "GCC_JIT_FN_ATTRIBUTE_NOINLINE",
    4846              :   "GCC_JIT_FN_ATTRIBUTE_TARGET",
    4847              :   "GCC_JIT_FN_ATTRIBUTE_USED",
    4848              :   "GCC_JIT_FN_ATTRIBUTE_VISIBILITY",
    4849              :   "GCC_JIT_FN_ATTRIBUTE_COLD",
    4850              :   "GCC_JIT_FN_ATTRIBUTE_RETURNS_TWICE",
    4851              :   "GCC_JIT_FN_ATTRIBUTE_PURE",
    4852              :   "GCC_JIT_FN_ATTRIBUTE_CONST",
    4853              :   "GCC_JIT_FN_ATTRIBUTE_WEAK",
    4854              :   "GCC_JIT_FN_ATTRIBUTE_NONNULL",
    4855              :   "GCC_JIT_FN_ATTRIBUTE_ARM_CMSE_NONSECURE_CALL",
    4856              :   "GCC_JIT_FN_ATTRIBUTE_ARM_CMSE_NONSECURE_ENTRY",
    4857              :   "GCC_JIT_FN_ATTRIBUTE_ARM_PCS",
    4858              :   "GCC_JIT_FN_ATTRIBUTE_AVR_INTERRUPT",
    4859              :   "GCC_JIT_FN_ATTRIBUTE_AVR_NOBLOCK",
    4860              :   "GCC_JIT_FN_ATTRIBUTE_AVR_SIGNAL",
    4861              :   "GCC_JIT_FN_ATTRIBUTE_GCN_AMDGPU_HSA_KERNEL",
    4862              :   "GCC_JIT_FN_ATTRIBUTE_MSP430_INTERRUPT",
    4863              :   "GCC_JIT_FN_ATTRIBUTE_NVPTX_KERNEL",
    4864              :   "GCC_JIT_FN_ATTRIBUTE_RISCV_INTERRUPT",
    4865              :   "GCC_JIT_FN_ATTRIBUTE_X86_FAST_CALL",
    4866              :   "GCC_JIT_FN_ATTRIBUTE_X86_INTERRUPT",
    4867              :   "GCC_JIT_FN_ATTRIBUTE_X86_MS_ABI",
    4868              :   "GCC_JIT_FN_ATTRIBUTE_X86_STDCALL",
    4869              :   "GCC_JIT_FN_ATTRIBUTE_X86_SYSV_ABI",
    4870              :   "GCC_JIT_FN_ATTRIBUTE_X86_THIS_CALL",
    4871              : };
    4872              : 
    4873              : std::string
    4874            5 : get_vector_int_debug (std::vector<int> &values)
    4875              : {
    4876            5 :   std::stringstream s;
    4877              : 
    4878            5 :   s << "{";
    4879           10 :   for(auto it = values.begin(); it != values.end(); ++it)
    4880              :     {
    4881            5 :       if (it != values.begin() )
    4882            0 :          s << ", ";
    4883            5 :       s << *it;
    4884              :     }
    4885            5 :   s << "}";
    4886            5 :   return s.str();
    4887            5 : }
    4888              : 
    4889              : void
    4890         3365 : recording::function::write_reproducer (reproducer &r)
    4891              : {
    4892         3365 :   const char *id = r.make_identifier (this, "func");
    4893              : 
    4894         3365 :   if (m_builtin_id)
    4895              :     {
    4896          220 :       r.write ("  gcc_jit_function *%s =\n"
    4897              :                "    gcc_jit_context_get_builtin_function (%s,\n"
    4898              :                "                                          %s);\n",
    4899              :                id,
    4900              :                r.get_identifier (get_context ()),
    4901          220 :                m_name->get_debug_string ());
    4902          220 :       return;
    4903              :     }
    4904         3145 :   const char *params_id = r.make_tmp_identifier ("params_for", this);
    4905         3145 :   r.write ("  gcc_jit_param *%s[%i] = {\n",
    4906              :            params_id,
    4907              :            m_params.length ());
    4908         3145 :   int i;
    4909         3145 :   param *param;
    4910        11911 :   FOR_EACH_VEC_ELT (m_params, i, param)
    4911         5621 :     r.write ("    %s,\n", r.get_identifier (param));
    4912         3145 :   r.write ("  };\n");
    4913         9435 :   r.write ("  gcc_jit_function *%s =\n"
    4914              :            "    gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
    4915              :            "                                  %s, /* gcc_jit_location *loc */\n"
    4916              :            "                                  %s, /* enum gcc_jit_function_kind kind */\n"
    4917              :            "                                  %s, /* gcc_jit_type *return_type */\n"
    4918              :            "                                  %s, /* const char *name */\n"
    4919              :            "                                  %i, /* int num_params */\n"
    4920              :            "                                  %s, /* gcc_jit_param **params */\n"
    4921              :            "                                  %i); /* int is_variadic */\n",
    4922              :            id,
    4923              :            r.get_identifier (get_context ()),
    4924         3145 :            r.get_identifier (m_loc),
    4925         3145 :            names_of_function_kinds[m_kind],
    4926              :            r.get_identifier_as_type (m_return_type),
    4927         3145 :            m_name->get_debug_string (),
    4928              :            m_params.length (),
    4929              :            params_id,
    4930              :            m_is_variadic);
    4931         3190 :   for (auto attribute : m_attributes)
    4932           45 :     r.write("  gcc_jit_function_add_attribute (%s, %s);\n",
    4933              :             id,
    4934           45 :             fn_attribute_reproducer_strings[attribute]);
    4935         3150 :   for (auto attribute : m_string_attributes)
    4936            5 :     r.write("  gcc_jit_function_add_string_attribute (%s, %s, \"%s\");\n",
    4937              :             id,
    4938            5 :             fn_attribute_reproducer_strings[std::get<0>(attribute)],
    4939           10 :             std::get<1>(attribute).c_str());
    4940         3150 :   for (auto attribute : m_int_array_attributes) {
    4941            5 :     r.write("  gcc_jit_function_add_integer_array_attribute (%s,\n"
    4942              :             "                                                %s,\n"
    4943              :             "                                                (int[])%s,\n"
    4944              :             "                                                %lu);\n",
    4945              :             id,
    4946            5 :             fn_attribute_reproducer_strings[std::get<0>(attribute)],
    4947           10 :             get_vector_int_debug (std::get<1>(attribute)).c_str(),
    4948            5 :             std::get<1>(attribute).size ());
    4949            5 :   }
    4950              : }
    4951              : 
    4952              : 
    4953              : /* The implementation of class gcc::jit::recording::block.  */
    4954              : 
    4955              : /* Create a recording::eval instance and add it to
    4956              :    the block's context's list of mementos, and to the block's
    4957              :    list of statements.
    4958              : 
    4959              :    Implements the heart of gcc_jit_block_add_eval.  */
    4960              : 
    4961              : recording::statement *
    4962         2022 : recording::block::add_eval (recording::location *loc,
    4963              :                             recording::rvalue *rvalue)
    4964              : {
    4965         2022 :   statement *result = new eval (this, loc, rvalue);
    4966         2022 :   m_ctxt->record (result);
    4967         2022 :   m_statements.safe_push (result);
    4968         2022 :   return result;
    4969              : }
    4970              : 
    4971              : /* Create a recording::assignment instance and add it to
    4972              :    the block's context's list of mementos, and to the block's
    4973              :    list of statements.
    4974              : 
    4975              :    Implements the heart of gcc_jit_block_add_assignment.  */
    4976              : 
    4977              : recording::statement *
    4978         4639 : recording::block::add_assignment (recording::location *loc,
    4979              :                                   recording::lvalue *lvalue,
    4980              :                                   recording::rvalue *rvalue)
    4981              : {
    4982         4639 :   statement *result = new assignment (this, loc, lvalue, rvalue);
    4983         4639 :   m_ctxt->record (result);
    4984         4639 :   m_statements.safe_push (result);
    4985         4639 :   return result;
    4986              : }
    4987              : 
    4988              : /* Create a recording::assignment_op instance and add it to
    4989              :    the block's context's list of mementos, and to the block's
    4990              :    list of statements.
    4991              : 
    4992              :    Implements the heart of gcc_jit_block_add_assignment_op.  */
    4993              : 
    4994              : recording::statement *
    4995          484 : recording::block::add_assignment_op (recording::location *loc,
    4996              :                                      recording::lvalue *lvalue,
    4997              :                                      enum gcc_jit_binary_op op,
    4998              :                                      recording::rvalue *rvalue)
    4999              : {
    5000          484 :   statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
    5001          484 :   m_ctxt->record (result);
    5002          484 :   m_statements.safe_push (result);
    5003          484 :   return result;
    5004              : }
    5005              : 
    5006              : /* Create a recording::comment instance and add it to
    5007              :    the block's context's list of mementos, and to the block's
    5008              :    list of statements.
    5009              : 
    5010              :    Implements the heart of gcc_jit_block_add_comment.  */
    5011              : 
    5012              : recording::statement *
    5013          450 : recording::block::add_comment (recording::location *loc,
    5014              :                                const char *text)
    5015              : {
    5016          450 :   statement *result = new comment (this, loc, new_string (text));
    5017          450 :   m_ctxt->record (result);
    5018          450 :   m_statements.safe_push (result);
    5019          450 :   return result;
    5020              : }
    5021              : 
    5022              : /* Create a recording::extended_asm_simple instance and add it to
    5023              :    the block's context's list of mementos, and to the block's
    5024              :    list of statements.
    5025              : 
    5026              :    Implements the heart of gcc_jit_block_add_extended_asm.  */
    5027              : 
    5028              : recording::extended_asm *
    5029           50 : recording::block::add_extended_asm (location *loc,
    5030              :                                     const char *asm_template)
    5031              : {
    5032           50 :   extended_asm *result
    5033           50 :     = new extended_asm_simple (this, loc, new_string (asm_template));
    5034           50 :   m_ctxt->record (result);
    5035           50 :   m_statements.safe_push (result);
    5036           50 :   return result;
    5037              : }
    5038              : 
    5039              : /* Create a recording::end_with_conditional instance and add it to
    5040              :    the block's context's list of mementos, and to the block's
    5041              :    list of statements.
    5042              : 
    5043              :    Implements the heart of gcc_jit_block_end_with_conditional.  */
    5044              : 
    5045              : recording::statement *
    5046          879 : recording::block::end_with_conditional (recording::location *loc,
    5047              :                                         recording::rvalue *boolval,
    5048              :                                         recording::block *on_true,
    5049              :                                         recording::block *on_false)
    5050              : {
    5051          879 :   statement *result = new conditional (this, loc, boolval, on_true, on_false);
    5052          879 :   m_ctxt->record (result);
    5053          879 :   m_statements.safe_push (result);
    5054          879 :   m_has_been_terminated = true;
    5055          879 :   return result;
    5056              : }
    5057              : 
    5058              : /* Create a recording::end_with_jump instance and add it to
    5059              :    the block's context's list of mementos, and to the block's
    5060              :    list of statements.
    5061              : 
    5062              :    Implements the heart of gcc_jit_block_end_with_jump.  */
    5063              : 
    5064              : recording::statement *
    5065         1202 : recording::block::end_with_jump (recording::location *loc,
    5066              :                                  recording::block *target)
    5067              : {
    5068         1202 :   statement *result = new jump (this, loc, target);
    5069         1202 :   m_ctxt->record (result);
    5070         1202 :   m_statements.safe_push (result);
    5071         1202 :   m_has_been_terminated = true;
    5072         1202 :   return result;
    5073              : }
    5074              : 
    5075              : /* Create a recording::end_with_return instance and add it to
    5076              :    the block's context's list of mementos, and to the block's
    5077              :    list of statements.
    5078              : 
    5079              :    Implements the post-error-checking parts of
    5080              :    gcc_jit_block_end_with_return and
    5081              :    gcc_jit_block_end_with_void_return.  */
    5082              : 
    5083              : recording::statement *
    5084         3930 : recording::block::end_with_return (recording::location *loc,
    5085              :                                    recording::rvalue *rvalue)
    5086              : {
    5087              :   /* This is used by both gcc_jit_function_add_return and
    5088              :      gcc_jit_function_add_void_return; rvalue will be non-NULL for
    5089              :      the former and NULL for the latter.  */
    5090         3930 :   statement *result = new return_ (this, loc, rvalue);
    5091         3930 :   m_ctxt->record (result);
    5092         3930 :   m_statements.safe_push (result);
    5093         3930 :   m_has_been_terminated = true;
    5094         3930 :   return result;
    5095              : }
    5096              : 
    5097              : /* Create a recording::switch_ instance and add it to
    5098              :    the block's context's list of mementos, and to the block's
    5099              :    list of statements.
    5100              : 
    5101              :    Implements the heart of gcc_jit_block_end_with_switch.  */
    5102              : 
    5103              : recording::statement *
    5104           20 : recording::block::end_with_switch (recording::location *loc,
    5105              :                                    recording::rvalue *expr,
    5106              :                                    recording::block *default_block,
    5107              :                                    int num_cases,
    5108              :                                    recording::case_ **cases)
    5109              : {
    5110           20 :   statement *result = new switch_ (this, loc,
    5111              :                                    expr,
    5112              :                                    default_block,
    5113              :                                    num_cases,
    5114           20 :                                    cases);
    5115           20 :   m_ctxt->record (result);
    5116           20 :   m_statements.safe_push (result);
    5117           20 :   m_has_been_terminated = true;
    5118           20 :   return result;
    5119              : }
    5120              : 
    5121              : /* Create a recording::extended_asm_goto instance and add it to
    5122              :    the block's context's list of mementos, and to the block's
    5123              :    list of statements.
    5124              : 
    5125              :    Implements the heart of gcc_jit_block_end_with_extended_asm_goto.  */
    5126              : 
    5127              : 
    5128              : recording::extended_asm *
    5129           20 : recording::block::end_with_extended_asm_goto (location *loc,
    5130              :                                               const char *asm_template,
    5131              :                                               int num_goto_blocks,
    5132              :                                               block **goto_blocks,
    5133              :                                               block *fallthrough_block)
    5134              : {
    5135           20 :   extended_asm *result
    5136              :     = new extended_asm_goto (this, loc, new_string (asm_template),
    5137              :                              num_goto_blocks, goto_blocks,
    5138           20 :                              fallthrough_block);
    5139           20 :   m_ctxt->record (result);
    5140           20 :   m_statements.safe_push (result);
    5141           20 :   m_has_been_terminated = true;
    5142           20 :   return result;
    5143              : }
    5144              : 
    5145              : /* Override the default implementation of
    5146              :    recording::memento::write_to_dump for blocks by writing
    5147              :    an unindented block name as a label, followed by the indented
    5148              :    statements:
    5149              : 
    5150              :     BLOCK_NAME:
    5151              :       STATEMENT_1;
    5152              :       STATEMENT_2;
    5153              :       ...
    5154              :       STATEMENT_N;  */
    5155              : 
    5156              : void
    5157           44 : recording::block::write_to_dump (dump &d)
    5158              : {
    5159           44 :   d.write ("%s:\n", get_debug_string ());
    5160              : 
    5161           44 :   int i;
    5162           44 :   statement *s;
    5163          244 :   FOR_EACH_VEC_ELT (m_statements, i, s)
    5164          156 :     s->write_to_dump (d);
    5165           44 : }
    5166              : 
    5167              : /* Validate a block by ensuring that it has been terminated.  */
    5168              : 
    5169              : bool
    5170         6482 : recording::block::validate ()
    5171              : {
    5172              :   /* Check for termination.  */
    5173         6482 :   if (!has_been_terminated ())
    5174              :     {
    5175          423 :       statement *stmt = get_last_statement ();
    5176          423 :       location *loc = stmt ? stmt->get_loc () : NULL;
    5177          423 :       m_func->get_context ()->add_error (loc,
    5178              :                                          "unterminated block in %s: %s",
    5179          423 :                                          m_func->get_debug_string (),
    5180              :                                          get_debug_string ());
    5181          423 :       return false;
    5182              :     }
    5183              : 
    5184              :   return true;
    5185              : }
    5186              : 
    5187              : /* Get the source-location of a block by using that of the first
    5188              :    statement within it, if any.  */
    5189              : 
    5190              : recording::location *
    5191            5 : recording::block::get_loc () const
    5192              : {
    5193            5 :   recording::statement *stmt = get_first_statement ();
    5194            5 :   if (stmt)
    5195            5 :     return stmt->get_loc ();
    5196              :   else
    5197              :     return NULL;
    5198              : }
    5199              : 
    5200              : /* Get the first statement within a block, if any.  */
    5201              : 
    5202              : recording::statement *
    5203            5 : recording::block::get_first_statement () const
    5204              : {
    5205            5 :   if (m_statements.length ())
    5206            5 :     return m_statements[0];
    5207              :   else
    5208              :     return NULL;
    5209              : }
    5210              : 
    5211              : /* Get the last statement within a block, if any.  */
    5212              : 
    5213              : recording::statement *
    5214         6421 : recording::block::get_last_statement () const
    5215              : {
    5216         6421 :   if (m_statements.length ())
    5217         6326 :     return m_statements[m_statements.length () - 1];
    5218              :   else
    5219              :     return NULL;
    5220              : }
    5221              : 
    5222              : /* Assuming that this block has been terminated, get the successor blocks
    5223              :    as a vector.  Ownership of the vector transfers to the caller, which
    5224              :    must call its release () method.
    5225              : 
    5226              :    Used when validating functions, and when dumping dot representations
    5227              :    of them.  */
    5228              : 
    5229              : vec <recording::block *>
    5230         5993 : recording::block::get_successor_blocks () const
    5231              : {
    5232         5993 :   gcc_assert (m_has_been_terminated);
    5233         5993 :   statement *last_statement = get_last_statement ();
    5234         5993 :   gcc_assert (last_statement);
    5235         5993 :   return last_statement->get_successor_blocks ();
    5236              : }
    5237              : 
    5238              : /* Implementation of pure virtual hook recording::memento::replay_into
    5239              :    for recording::block.  */
    5240              : 
    5241              : void
    5242         5833 : recording::block::replay_into (replayer *)
    5243              : {
    5244         5833 :   set_playback_obj (m_func->playback_function ()
    5245         5833 :                       ->new_block (playback_string (m_name)));
    5246         5833 : }
    5247              : 
    5248              : /* Implementation of recording::memento::make_debug_string for
    5249              :    blocks.  */
    5250              : 
    5251              : recording::string *
    5252         3663 : recording::block::make_debug_string ()
    5253              : {
    5254         3663 :   if (m_name)
    5255              :     return m_name;
    5256              :   else
    5257         1213 :     return string::from_printf (m_ctxt,
    5258              :                                 "<UNNAMED BLOCK %p>",
    5259         1213 :                                 (void *)this);
    5260              : }
    5261              : 
    5262              : /* Implementation of recording::memento::write_reproducer for blocks. */
    5263              : 
    5264              : void
    5265         3667 : recording::block::write_reproducer (reproducer &r)
    5266              : {
    5267         3667 :   const char *id = r.make_identifier (this, "block");
    5268         3667 :   r.write ("  gcc_jit_block *%s =\n"
    5269              :            "    gcc_jit_function_new_block (%s, %s);\n",
    5270              :            id,
    5271         3667 :            r.get_identifier (m_func),
    5272         3667 :            m_name ? m_name->get_debug_string () : "NULL");
    5273         3667 : }
    5274              : 
    5275              : /* Disable warnings about missing quoting in GCC diagnostics for
    5276              :    the pp_printf calls.  Their format strings deliberately don't
    5277              :    follow GCC diagnostic conventions.  */
    5278              : #if __GNUC__ >= 10
    5279              : #  pragma GCC diagnostic push
    5280              : #  pragma GCC diagnostic ignored "-Wformat-diag"
    5281              : #endif
    5282              : 
    5283              : /* Dump a block in graphviz form into PP, capturing the block name (if
    5284              :    any) and the statements.  */
    5285              : 
    5286              : void
    5287            0 : recording::block::dump_to_dot (pretty_printer *pp)
    5288              : {
    5289            0 :   pp_printf (pp,
    5290              :              ("\tblock_%d "
    5291              :               "[shape=record,style=filled,fillcolor=white,label=\"{"),
    5292              :              m_index);
    5293            0 :   pp_write_text_to_stream (pp);
    5294            0 :   if (m_name)
    5295              :     {
    5296            0 :       pp_string (pp, m_name->c_str ());
    5297            0 :       pp_string (pp, ":");
    5298            0 :       pp_newline (pp);
    5299            0 :       pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
    5300              :     }
    5301              : 
    5302              :   int i;
    5303              :   statement *s;
    5304            0 :   FOR_EACH_VEC_ELT (m_statements, i, s)
    5305              :     {
    5306            0 :       pp_string (pp, s->get_debug_string ());
    5307            0 :       pp_newline (pp);
    5308            0 :       pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
    5309              :     }
    5310              : 
    5311            0 :   pp_string (pp,
    5312              :              "}\"];\n\n");
    5313            0 :   pp_flush (pp);
    5314            0 : }
    5315              : 
    5316              : /* Dump the out-edges of the block in graphviz form into PP.  */
    5317              : 
    5318              : void
    5319            0 : recording::block::dump_edges_to_dot (pretty_printer *pp)
    5320              : {
    5321            0 :   vec <block *> successors = get_successor_blocks ();
    5322            0 :   int i;
    5323            0 :   block *succ;
    5324            0 :   FOR_EACH_VEC_ELT (successors, i, succ)
    5325            0 :     pp_printf (pp,
    5326              :                "\tblock_%d:s -> block_%d:n;\n",
    5327              :                m_index, succ->m_index);
    5328            0 :   successors.release ();
    5329            0 : }
    5330              : 
    5331              : #if __GNUC__ >= 10
    5332              : #  pragma GCC diagnostic pop
    5333              : #endif
    5334              : 
    5335              : namespace recording {
    5336              : static const enum tls_model tls_models[] = {
    5337              :   TLS_MODEL_NONE, /* GCC_JIT_TLS_MODEL_NONE */
    5338              :   TLS_MODEL_GLOBAL_DYNAMIC, /* GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC */
    5339              :   TLS_MODEL_LOCAL_DYNAMIC, /* GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC */
    5340              :   TLS_MODEL_INITIAL_EXEC, /* GCC_JIT_TLS_MODEL_INITIAL_EXEC */
    5341              :   TLS_MODEL_LOCAL_EXEC, /* GCC_JIT_TLS_MODEL_LOCAL_EXEC */
    5342              : };
    5343              : } /* namespace recording */
    5344              : 
    5345              : /* The implementation of class gcc::jit::recording::global.  */
    5346              : 
    5347              : /* Implementation of pure virtual hook recording::memento::replay_into
    5348              :    for recording::global.  */
    5349              : 
    5350              : void
    5351         1061 : recording::global::replay_into (replayer *r)
    5352              : {
    5353         1061 :   playback::lvalue *global = m_initializer
    5354         1076 :   ? r->new_global_initialized (playback_location (r, m_loc),
    5355              :                                  m_kind,
    5356           15 :                                  m_type->playback_type (),
    5357           15 :                                  m_type->dereference ()->get_size (),
    5358           15 :                                  m_initializer_num_bytes
    5359           15 :                                  / m_type->dereference ()->get_size (),
    5360           15 :                                  m_initializer,
    5361              :                                  playback_string (m_name),
    5362              :                                  m_flags,
    5363           15 :                                  m_string_attributes,
    5364           15 :                                  m_readonly)
    5365         1046 :     : r->new_global (playback_location (r, m_loc),
    5366              :                      m_kind,
    5367         1046 :                      m_type->playback_type (),
    5368              :                      playback_string (m_name),
    5369              :                      m_flags,
    5370         1046 :                      m_string_attributes,
    5371         1046 :                      m_readonly);
    5372              : 
    5373         1061 :   if (m_tls_model != GCC_JIT_TLS_MODEL_NONE)
    5374           15 :     global->set_tls_model (recording::tls_models[m_tls_model]);
    5375              : 
    5376         1061 :   if (m_link_section != NULL)
    5377            5 :     global->set_link_section (m_link_section->c_str ());
    5378              : 
    5379         1061 :   if (m_reg_name != NULL)
    5380           15 :     global->set_register_name (m_reg_name->c_str ());
    5381              : 
    5382         1061 :   if (m_alignment != 0)
    5383            5 :     global->set_alignment (m_alignment);
    5384              : 
    5385         1061 :   set_playback_obj (global);
    5386         1061 : }
    5387              : 
    5388              : /* Override the default implementation of
    5389              :    recording::memento::write_to_dump for globals.
    5390              :    This will be of the form:
    5391              : 
    5392              :    GCC_JIT_GLOBAL_EXPORTED:
    5393              :       "TYPE NAME;"
    5394              :       e.g. "int foo;"
    5395              : 
    5396              :    GCC_JIT_GLOBAL_INTERNAL:
    5397              :       "static TYPE NAME;"
    5398              :       e.g. "static int foo;"
    5399              : 
    5400              :    GCC_JIT_GLOBAL_IMPORTED:
    5401              :       "extern TYPE NAME;"
    5402              :       e.g. "extern int foo;"
    5403              : 
    5404              :    These are written to the top of the dump by
    5405              :    recording::context::dump_to_file.  */
    5406              : 
    5407              : void
    5408            0 : recording::global::write_to_dump (dump &d)
    5409              : {
    5410            0 :   if (d.update_locations ())
    5411            0 :     m_loc = d.make_location ();
    5412              : 
    5413            0 :   switch (m_kind)
    5414              :     {
    5415            0 :     default:
    5416            0 :       gcc_unreachable ();
    5417              : 
    5418              :     case GCC_JIT_GLOBAL_EXPORTED:
    5419              :       break;
    5420              : 
    5421            0 :     case GCC_JIT_GLOBAL_INTERNAL:
    5422            0 :       d.write ("static ");
    5423            0 :       break;
    5424              : 
    5425            0 :     case GCC_JIT_GLOBAL_IMPORTED:
    5426            0 :       d.write ("extern ");
    5427            0 :       break;
    5428              :     }
    5429              : 
    5430            0 :   for (auto attr: m_string_attributes)
    5431              :   {
    5432            0 :     gcc_jit_variable_attribute& name = std::get<0>(attr);
    5433            0 :     std::string& value = std::get<1>(attr);
    5434            0 :     const char* attribute = variable_attribute_to_string (name);
    5435              : 
    5436            0 :     if (attribute)
    5437            0 :       d.write ("__attribute(%s(\"%s\"))__\n", attribute, value.c_str());
    5438            0 :   }
    5439            0 :   d.write ("%s %s",
    5440            0 :            m_type->get_debug_string (),
    5441              :            get_debug_string ());
    5442              : 
    5443            0 :   if (!m_initializer && !m_rvalue_init)
    5444              :     {
    5445            0 :       d.write (";\n");
    5446              :     }
    5447            0 :   else if (m_initializer)
    5448              :     {
    5449            0 :       d.write ("=\n  { ");
    5450            0 :       const unsigned char *p = (const unsigned char *)m_initializer;
    5451            0 :       for (size_t i = 0; i < m_initializer_num_bytes; i++)
    5452              :         {
    5453            0 :           d.write ("0x%x, ", p[i]);
    5454            0 :           if (i && !(i % 64))
    5455            0 :             d.write ("\n    ");
    5456              :         }
    5457            0 :       d.write ("};\n");
    5458              :     }
    5459            0 :   else if (m_rvalue_init)
    5460              :     {
    5461            0 :       d.write (" = ");
    5462            0 :       d.write ("%s", m_rvalue_init->get_debug_string ());
    5463            0 :       d.write (";\n");
    5464              :     }
    5465              : 
    5466            0 :   return;
    5467              : }
    5468              : 
    5469              : /* A table of enum gcc_jit_global_kind values expressed in string
    5470              :    form.  */
    5471              : 
    5472              : static const char * const global_kind_reproducer_strings[] = {
    5473              :   "GCC_JIT_GLOBAL_EXPORTED",
    5474              :   "GCC_JIT_GLOBAL_INTERNAL",
    5475              :   "GCC_JIT_GLOBAL_IMPORTED"
    5476              : };
    5477              : 
    5478              : template <typename T>
    5479              : void
    5480           15 : recording::global::write_initializer_reproducer (const char *id, reproducer &r)
    5481              : {
    5482           15 :   const char *init_id = r.make_tmp_identifier ("init_for", this);
    5483           15 :   r.write ("  %s %s[] =\n    {",
    5484           15 :            m_type->dereference ()->get_debug_string (),
    5485              :            init_id);
    5486              : 
    5487           15 :   const T *p = (const T *)m_initializer;
    5488        20555 :   for (size_t i = 0; i < m_initializer_num_bytes / sizeof (T); i++)
    5489              :     {
    5490        20540 :       r.write ("%" PRIu64 ", ", (uint64_t)p[i]);
    5491        20540 :       if (i && !(i % 64))
    5492          315 :         r.write ("\n    ");
    5493              :     }
    5494           15 :   r.write ("};\n");
    5495           15 :   r.write ("  gcc_jit_global_set_initializer (%s, %s, sizeof (%s));\n",
    5496              :            id, init_id, init_id);
    5497           15 : }
    5498              : 
    5499              : /* Implementation of recording::memento::write_reproducer for globals. */
    5500              : 
    5501              : static const char * const tls_model_enum_strings[] = {
    5502              :   "GCC_JIT_TLS_MODEL_NONE",
    5503              :   "GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC",
    5504              :   "GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC",
    5505              :   "GCC_JIT_TLS_MODEL_INITIAL_EXEC",
    5506              :   "GCC_JIT_TLS_MODEL_LOCAL_EXEC",
    5507              : };
    5508              : 
    5509              : static const char * const gcc_jit_variable_attribute_enum_strings[] = {
    5510              :   "GCC_JIT_VARIABLE_ATTRIBUTE_VISIBILITY",
    5511              : };
    5512              : 
    5513              : void
    5514         2153 : recording::global::write_reproducer (reproducer &r)
    5515              : {
    5516         2153 :   const char *id = r.make_identifier (this, "block");
    5517         4306 :   r.write ("  gcc_jit_lvalue *%s =\n"
    5518              :     "    gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
    5519              :     "                                %s, /* gcc_jit_location *loc */\n"
    5520              :     "                                %s, /* enum gcc_jit_global_kind kind */\n"
    5521              :     "                                %s, /* gcc_jit_type *type */\n"
    5522              :     "                                %s); /* const char *name */\n",
    5523              :     id,
    5524              :     r.get_identifier (get_context ()),
    5525         2153 :     r.get_identifier (m_loc),
    5526         2153 :     global_kind_reproducer_strings[m_kind],
    5527              :     r.get_identifier_as_type (get_type ()),
    5528         2153 :     m_name->get_debug_string ());
    5529              : 
    5530         2153 :   if (m_tls_model != GCC_JIT_TLS_MODEL_NONE)
    5531           10 :     r.write ("  gcc_jit_lvalue_set_tls_model (%s, /* gcc_jit_lvalue *lvalue */\n"
    5532              :              "                                %s); /* enum gcc_jit_tls_model model */\n",
    5533              :              id,
    5534           10 :              tls_model_enum_strings[m_tls_model]);
    5535              : 
    5536         2153 :   if (m_link_section != NULL)
    5537            5 :     r.write ("  gcc_jit_lvalue_set_link_section (%s, /* gcc_jit_lvalue *lvalue */\n"
    5538              :         "                                  \"%s\"); /* */\n",
    5539              :      id,
    5540            5 :      m_link_section->c_str ());
    5541              : 
    5542         2158 :   for (auto attribute : m_string_attributes)
    5543            5 :     r.write("  gcc_jit_lvalue_add_string_attribute (%s, %s, \"%s\");\n",
    5544              :             id,
    5545            5 :             gcc_jit_variable_attribute_enum_strings[std::get<0>(attribute)],
    5546           10 :             std::get<1>(attribute).c_str());
    5547              : 
    5548         2153 :   if (m_readonly)
    5549           10 :     r.write ("  gcc_jit_global_set_readonly (%s /* gcc_jit_lvalue *lvalue */);\n",
    5550              :      id);
    5551              : 
    5552         2153 :   if (m_initializer)
    5553           15 :     switch (m_type->dereference ()->get_size ())
    5554              :       {
    5555           10 :       case 1:
    5556           10 :         write_initializer_reproducer<uint8_t> (id, r);
    5557           10 :         break;
    5558            0 :       case 2:
    5559            0 :         write_initializer_reproducer<uint16_t> (id, r);
    5560            0 :         break;
    5561            5 :       case 4:
    5562            5 :         write_initializer_reproducer<uint32_t> (id, r);
    5563            5 :         break;
    5564            0 :       case 8:
    5565            0 :         write_initializer_reproducer<uint64_t> (id, r);
    5566            0 :         break;
    5567            0 :       default:
    5568              :         /* This function is serving on sizes returned by 'get_size',
    5569              :            these are all covered by the previous cases.  */
    5570            0 :         gcc_unreachable ();
    5571              :       }
    5572         2153 : }
    5573              : 
    5574              : /* The implementation of the various const-handling classes:
    5575              :    gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>.  */
    5576              : 
    5577              : /* Explicit specialization of the various mementos we're interested in.  */
    5578              : template class recording::memento_of_new_rvalue_from_const <int>;
    5579              : template class recording::memento_of_new_rvalue_from_const <long>;
    5580              : template class recording::memento_of_new_rvalue_from_const <double>;
    5581              : template class recording::memento_of_new_rvalue_from_const <void *>;
    5582              : 
    5583              : /* Implementation of the pure virtual hook recording::memento::replay_into
    5584              :    for recording::memento_of_new_rvalue_from_const <HOST_TYPE>.  */
    5585              : 
    5586              : template <typename HOST_TYPE>
    5587              : void
    5588         6469 : recording::
    5589              : memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
    5590              : {
    5591              :     set_playback_obj
    5592         6469 :       (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
    5593              :                                              m_value));
    5594         6469 : }
    5595              : 
    5596              : /* The make_debug_string and write_reproducer methods vary between the
    5597              :    various
    5598              :      memento_of_new_rvalue_from_const <HOST_TYPE>
    5599              :    classes, so we explicitly write specializations of them.
    5600              : 
    5601              :    I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
    5602              :    namespaces are written out explicitly, which is why most of this file
    5603              :    doesn't abbreviate things by entering the "recording" namespace.
    5604              : 
    5605              :    However, these specializations are required to be in the same namespace
    5606              :    as the template, hence we now have to enter the gcc::jit::recording
    5607              :    namespace.  */
    5608              : 
    5609              : namespace recording
    5610              : {
    5611              : 
    5612              : /* The make_debug_string specialization for <int>, which renders it as
    5613              :      (TARGET_TYPE)LITERAL
    5614              :    e.g.
    5615              :      "(int)42".  */
    5616              : 
    5617              : template <>
    5618              : string *
    5619         4710 : memento_of_new_rvalue_from_const <int>::make_debug_string ()
    5620              : {
    5621         4710 :   return string::from_printf (m_ctxt,
    5622              :                               "(%s)%i",
    5623         4710 :                               m_type->get_debug_string (),
    5624         4710 :                               m_value);
    5625              : }
    5626              : 
    5627              : /* The get_wide_int specialization for <int>.  */
    5628              : 
    5629              : template <>
    5630              : bool
    5631         1470 : memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const
    5632              : {
    5633         1470 :   *out = wi::shwi (m_value, sizeof (m_value) * 8);
    5634         1470 :   return true;
    5635              : }
    5636              : 
    5637              : /* The write_reproducer specialization for <int>.  */
    5638              : 
    5639              : template <>
    5640              : void
    5641         4675 : memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
    5642              : {
    5643         4675 :   const char *id = r.make_identifier (this, "rvalue");
    5644         4675 :   r.write ("  gcc_jit_rvalue *%s =\n"
    5645              :     "    gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
    5646              :     "                                         %s, /* gcc_jit_type *numeric_type */\n"
    5647              :     "                                         %i); /* int value */\n",
    5648              :     id,
    5649              :     r.get_identifier (get_context ()),
    5650              :     r.get_identifier_as_type (m_type),
    5651              :     m_value);
    5652         4675 : }
    5653              : 
    5654              : /* The make_debug_string specialization for <long>, rendering it as
    5655              :      (TARGET_TYPE)LITERAL
    5656              :    e.g.
    5657              :      "(long)42".  */
    5658              : 
    5659              : template <>
    5660              : string *
    5661           70 : memento_of_new_rvalue_from_const <long>::make_debug_string ()
    5662              : {
    5663           70 :   return string::from_printf (m_ctxt,
    5664              :                               "(%s)%li",
    5665           70 :                               m_type->get_debug_string (),
    5666           70 :                               m_value);
    5667              : }
    5668              : 
    5669              : /* The get_wide_int specialization for <long>.  */
    5670              : 
    5671              : template <>
    5672              : bool
    5673            0 : memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const
    5674              : {
    5675            0 :   *out = wi::shwi (m_value, sizeof (m_value) * 8);
    5676            0 :   return true;
    5677              : }
    5678              : 
    5679              : /* The write_reproducer specialization for <long>.  */
    5680              : 
    5681              : template <>
    5682              : void
    5683           55 : recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
    5684              : {
    5685           55 :   const char *id = r.make_identifier (this, "rvalue");
    5686              : 
    5687              :   /* We have to special-case LONG_MIN, since e.g.
    5688              :        -9223372036854775808L
    5689              :      is parsed as
    5690              :        -(9223372036854775808L)
    5691              :      and hence we'd get:
    5692              :         error: integer constant is so large that it is unsigned [-Werror]
    5693              :         Workaround this by writing (LONG_MIN + 1) - 1.  */
    5694           55 :   if (m_value == LONG_MIN)
    5695              :     {
    5696           10 :       r.write ("  gcc_jit_rvalue *%s =\n"
    5697              :                "    gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
    5698              :                "                                          %s, /* gcc_jit_type *numeric_type */\n"
    5699              :                "                                          %ldL - 1); /* long value */\n",
    5700              :                id,
    5701              :                r.get_identifier (get_context ()),
    5702              :                r.get_identifier_as_type (m_type),
    5703              :                m_value + 1);
    5704           10 :       return;
    5705              :     }
    5706              : 
    5707           45 :   r.write ("  gcc_jit_rvalue *%s =\n"
    5708              :            "    gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
    5709              :            "                                          %s, /* gcc_jit_type *numeric_type */\n"
    5710              :            "                                          %ldL); /* long value */\n",
    5711              :            id,
    5712              :            r.get_identifier (get_context ()),
    5713              :            r.get_identifier_as_type (m_type),
    5714              :            m_value);
    5715              :            }
    5716              : 
    5717              : /* The make_debug_string specialization for <double>, rendering it as
    5718              :      (TARGET_TYPE)LITERAL
    5719              :    e.g.
    5720              :      "(float)42.0".  */
    5721              : 
    5722              : template <>
    5723              : string *
    5724          165 : memento_of_new_rvalue_from_const <double>::make_debug_string ()
    5725              : {
    5726          165 :   return string::from_printf (m_ctxt,
    5727              :                               "(%s)%f",
    5728          165 :                               m_type->get_debug_string (),
    5729          165 :                               m_value);
    5730              : }
    5731              : 
    5732              : /* The get_wide_int specialization for <double>.  */
    5733              : 
    5734              : template <>
    5735              : bool
    5736            0 : memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
    5737              : {
    5738            0 :   return false;
    5739              : }
    5740              : 
    5741              : /* The write_reproducer specialization for <double>.  */
    5742              : 
    5743              : template <>
    5744              : void
    5745          145 : recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
    5746              : {
    5747          145 :   const char *id = r.make_identifier (this, "rvalue");
    5748          145 :   r.write ("  gcc_jit_rvalue *%s =\n"
    5749              :     "    gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
    5750              :     "                                            %s, /* gcc_jit_type *numeric_type */\n"
    5751              :     "                                            %f); /* double value */\n",
    5752              :     id,
    5753              :     r.get_identifier (get_context ()),
    5754              :     r.get_identifier_as_type (m_type),
    5755              :     m_value);
    5756          145 : }
    5757              : 
    5758              : /* The make_debug_string specialization for <void *>, rendering it as
    5759              :      (TARGET_TYPE)HEX
    5760              :    e.g.
    5761              :      "(int *)0xdeadbeef"
    5762              : 
    5763              :    Zero is rendered as NULL e.g.
    5764              :      "(int *)NULL".  */
    5765              : 
    5766              : template <>
    5767              : string *
    5768          120 : memento_of_new_rvalue_from_const <void *>::make_debug_string ()
    5769              : {
    5770          120 :   if (m_value != NULL)
    5771           55 :     return string::from_printf (m_ctxt,
    5772              :                                 "(%s)%p",
    5773          110 :                                 m_type->get_debug_string (), m_value);
    5774              :   else
    5775           65 :     return string::from_printf (m_ctxt,
    5776              :                                 "(%s)NULL",
    5777          130 :                                 m_type->get_debug_string ());
    5778              : }
    5779              : 
    5780              : /* The get_wide_int specialization for <void *>.  */
    5781              : 
    5782              : template <>
    5783              : bool
    5784            0 : memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const
    5785              : {
    5786            0 :   return false;
    5787              : }
    5788              : 
    5789              : /* Implementation of recording::memento::write_reproducer for <void *>
    5790              :    values. */
    5791              : 
    5792              : template <>
    5793              : void
    5794          110 : memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
    5795              : {
    5796          110 :   const char *id = r.make_identifier (this, "rvalue");
    5797          110 :   if (m_value)
    5798           50 :     r.write ("  gcc_jit_rvalue *%s =\n"
    5799              :              "    gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
    5800              :              "                                         %s, /* gcc_jit_type *pointer_type */\n"
    5801              :              "                                         (void *)%p); /* void *value */\n",
    5802              :              id,
    5803              :              r.get_identifier (get_context ()),
    5804              :              r.get_identifier_as_type (m_type),
    5805              :              m_value);
    5806              :   else
    5807           60 :     r.write ("  gcc_jit_rvalue *%s =\n"
    5808              :              "    gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
    5809              :              "                          %s); /* gcc_jit_type *pointer_type */\n",
    5810              :              id,
    5811              :              r.get_identifier (get_context ()),
    5812              :              r.get_identifier_as_type (m_type));
    5813          110 : }
    5814              : 
    5815              : /* We're done specializing make_debug_string and write_reproducer, so we
    5816              :    can exit the gcc::jit::recording namespace.  */
    5817              : 
    5818              : } // namespace recording
    5819              : 
    5820              : /* The implementation of class gcc::jit::recording::memento_of_typeinfo.  */
    5821              : 
    5822              : /* Implementation of pure virtual hook recording::memento::replay_into
    5823              :    for recording::memento_of_typeinfo.  */
    5824              : 
    5825              : void
    5826           30 : recording::memento_of_typeinfo::replay_into (replayer *r)
    5827              : {
    5828           30 :   switch (m_info_type)
    5829              :   {
    5830           15 :   case TYPE_INFO_ALIGN_OF:
    5831           15 :     set_playback_obj (r->new_alignof (m_type->playback_type ()));
    5832           15 :     break;
    5833           15 :   case TYPE_INFO_SIZE_OF:
    5834           15 :     set_playback_obj (r->new_sizeof (m_type->playback_type ()));
    5835           15 :     break;
    5836              :   }
    5837           30 : }
    5838              : 
    5839              : /* Implementation of recording::memento::make_debug_string for
    5840              :    sizeof expressions.  */
    5841              : 
    5842              : recording::string *
    5843           20 : recording::memento_of_typeinfo::make_debug_string ()
    5844              : {
    5845           20 :   const char* ident = "";
    5846           20 :   switch (m_info_type)
    5847              :   {
    5848           10 :     case TYPE_INFO_ALIGN_OF:
    5849           10 :       ident = "_Alignof";
    5850           10 :       break;
    5851           10 :     case TYPE_INFO_SIZE_OF:
    5852           10 :       ident = "sizeof";
    5853           10 :       break;
    5854              :   }
    5855           20 :   return string::from_printf (m_ctxt,
    5856              :                               "%s (%s)",
    5857              :                               ident,
    5858           20 :                               m_type->get_debug_string ());
    5859              : }
    5860              : 
    5861              : /* Implementation of recording::memento::write_reproducer for sizeof
    5862              :    expressions.  */
    5863              : 
    5864              : void
    5865           20 : recording::memento_of_typeinfo::write_reproducer (reproducer &r)
    5866              : {
    5867           20 :   const char* type = "";
    5868           20 :   switch (m_info_type)
    5869              :   {
    5870           10 :     case TYPE_INFO_ALIGN_OF:
    5871           10 :       type = "align";
    5872           10 :       break;
    5873           10 :     case TYPE_INFO_SIZE_OF:
    5874           10 :       type = "size";
    5875           10 :       break;
    5876              :   }
    5877           20 :   const char *id = r.make_identifier (this, "rvalue");
    5878           20 :   r.write ("  gcc_jit_rvalue *%s =\n"
    5879              :     "    gcc_jit_context_new_%sof (%s, /* gcc_jit_context *ctxt */\n"
    5880              :     "                                (gcc_jit_type *) %s); /* gcc_jit_type *type */\n",
    5881              :     id,
    5882              :     type,
    5883              :     r.get_identifier (get_context ()),
    5884           20 :     r.get_identifier (m_type));
    5885           20 : }
    5886              : 
    5887              : /* The implementation of class gcc::jit::recording::memento_of_new_string_literal.  */
    5888              : 
    5889              : /* Implementation of pure virtual hook recording::memento::replay_into
    5890              :    for recording::memento_of_new_string_literal.  */
    5891              : 
    5892              : void
    5893          187 : recording::memento_of_new_string_literal::replay_into (replayer *r)
    5894              : {
    5895          187 :   set_playback_obj (r->new_string_literal (m_value->c_str ()));
    5896          187 : }
    5897              : 
    5898              : /* Implementation of recording::memento::make_debug_string for
    5899              :    string literals.  */
    5900              : 
    5901              : recording::string *
    5902         1931 : recording::memento_of_new_string_literal::make_debug_string ()
    5903              : {
    5904         1931 :   return string::from_printf (m_ctxt,
    5905              :                               "%s",
    5906         1931 :                               m_value->get_debug_string ());
    5907              : }
    5908              : 
    5909              : /* Implementation of recording::memento::write_reproducer for string literal
    5910              :    values. */
    5911              : 
    5912              : void
    5913         1906 : recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
    5914              : {
    5915         1906 :   const char *id = r.make_identifier (this, "rvalue");
    5916         1906 :   r.write ("  gcc_jit_rvalue *%s =\n"
    5917              :     "    gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
    5918              :     "                                        %s); /* const char *value */\n",
    5919              :     id,
    5920              :     r.get_identifier (get_context ()),
    5921         1906 :     m_value->get_debug_string ());
    5922         1906 : }
    5923              : 
    5924              : /* The implementation of class
    5925              :    gcc::jit::recording::memento_of_new_rvalue_from_vector.  */
    5926              : 
    5927              : /* The constructor for
    5928              :    gcc::jit::recording::memento_of_new_rvalue_from_vector.  */
    5929              : 
    5930          120 : recording::memento_of_new_rvalue_from_vector::
    5931              : memento_of_new_rvalue_from_vector (context *ctxt,
    5932              :                                    location *loc,
    5933              :                                    vector_type *type,
    5934          120 :                                    rvalue **elements)
    5935              : : rvalue (ctxt, loc, type),
    5936          120 :   m_vector_type (type),
    5937          120 :   m_elements ()
    5938              : {
    5939          600 :   for (unsigned i = 0; i < type->get_num_units (); i++)
    5940          480 :     m_elements.safe_push (elements[i]);
    5941          120 : }
    5942              : 
    5943              : /* Implementation of pure virtual hook recording::memento::replay_into
    5944              :    for recording::memento_of_new_rvalue_from_vector.  */
    5945              : 
    5946              : void
    5947          120 : recording::memento_of_new_rvalue_from_vector::replay_into (replayer *r)
    5948              : {
    5949          120 :   auto_vec<playback::rvalue *> playback_elements;
    5950          120 :   playback_elements.create (m_elements.length ());
    5951          600 :   for (unsigned i = 0; i< m_elements.length (); i++)
    5952          480 :     playback_elements.safe_push (m_elements[i]->playback_rvalue ());
    5953              : 
    5954          120 :   set_playback_obj (r->new_rvalue_from_vector (playback_location (r, m_loc),
    5955          120 :                                                m_type->playback_type (),
    5956              :                                                playback_elements));
    5957          120 : }
    5958              : 
    5959              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    5960              :    for recording::memento_of_new_rvalue_from_vector.  */
    5961              : 
    5962              : void
    5963           60 : recording::memento_of_new_rvalue_from_vector::visit_children (rvalue_visitor *v)
    5964              : {
    5965          300 :   for (unsigned i = 0; i< m_elements.length (); i++)
    5966          240 :     v->visit (m_elements[i]);
    5967           60 : }
    5968              : 
    5969              : /* Implementation of recording::memento::make_debug_string for
    5970              :    vectors.  */
    5971              : 
    5972              : recording::string *
    5973          105 : recording::memento_of_new_rvalue_from_vector::make_debug_string ()
    5974              : {
    5975          105 :   comma_separated_string elements (m_elements, get_precedence ());
    5976              : 
    5977              :   /* Now build a string.  */
    5978          105 :   string *result = string::from_printf (m_ctxt,
    5979              :                                         "{%s}",
    5980              :                                         elements.as_char_ptr ());
    5981              : 
    5982          210 :  return result;
    5983              : 
    5984          105 : }
    5985              : 
    5986              : /* Implementation of recording::memento::write_reproducer for
    5987              :    vectors.  */
    5988              : 
    5989              : void
    5990          100 : recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer &r)
    5991              : {
    5992          100 :   const char *id = r.make_identifier (this, "vector");
    5993          100 :   const char *elements_id = r.make_tmp_identifier ("elements_for_", this);
    5994          100 :   r.write ("  gcc_jit_rvalue *%s[%i] = {\n",
    5995              :            elements_id,
    5996              :            m_elements.length ());
    5997          500 :   for (unsigned i = 0; i< m_elements.length (); i++)
    5998          400 :     r.write ("    %s,\n", r.get_identifier_as_rvalue (m_elements[i]));
    5999          100 :   r.write ("  };\n");
    6000          200 :   r.write ("  gcc_jit_rvalue *%s =\n"
    6001              :            "    gcc_jit_context_new_rvalue_from_vector (%s, /* gcc_jit_context *ctxt */\n"
    6002              :            "                                            %s, /* gcc_jit_location *loc */\n"
    6003              :            "                                            %s, /* gcc_jit_type *vec_type */\n"
    6004              :            "                                            %i, /* size_t num_elements  */ \n"
    6005              :            "                                            %s); /* gcc_jit_rvalue **elements*/\n",
    6006              :            id,
    6007              :            r.get_identifier (get_context ()),
    6008          100 :            r.get_identifier (m_loc),
    6009          100 :            r.get_identifier (m_vector_type),
    6010              :            m_elements.length (),
    6011              :            elements_id);
    6012          100 : }
    6013              : 
    6014              : /* The implementation of class
    6015              :    gcc::jit::recording::memento_of_new_rvalue_vector_perm.  */
    6016              : 
    6017              : /* The constructor for
    6018              :    gcc::jit::recording::memento_of_new_rvalue_vector_perm.  */
    6019              : 
    6020           15 : recording::memento_of_new_rvalue_vector_perm::
    6021              : memento_of_new_rvalue_vector_perm (context *ctxt,
    6022              :                                    location *loc,
    6023              :                                    rvalue *elements1,
    6024              :                                    rvalue *elements2,
    6025           15 :                                    rvalue *mask)
    6026              : : rvalue (ctxt, loc, elements1->get_type ()),
    6027           15 :   m_elements1 (elements1),
    6028           15 :   m_elements2 (elements2),
    6029           15 :   m_mask (mask)
    6030              : {
    6031           15 : }
    6032              : 
    6033              : /* Implementation of pure virtual hook recording::memento::replay_into
    6034              :    for recording::memento_of_new_rvalue_vector_perm.  */
    6035              : 
    6036              : void
    6037           15 : recording::memento_of_new_rvalue_vector_perm::replay_into (replayer *r)
    6038              : {
    6039           15 :   playback::rvalue *playback_elements1 = m_elements1->playback_rvalue ();
    6040           15 :   playback::rvalue *playback_elements2 = m_elements2->playback_rvalue ();
    6041           15 :   playback::rvalue *playback_mask = m_mask->playback_rvalue ();
    6042              : 
    6043           15 :   set_playback_obj (r->new_rvalue_vector_perm (playback_location (r, m_loc),
    6044              :                     playback_elements1,
    6045              :                     playback_elements2,
    6046              :                     playback_mask));
    6047           15 : }
    6048              : 
    6049              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    6050              :    for recording::memento_of_new_rvalue_from_vector.  */
    6051              : 
    6052              :     void
    6053           15 : recording::memento_of_new_rvalue_vector_perm::visit_children (rvalue_visitor *v)
    6054              : {
    6055           15 :   v->visit (m_elements1);
    6056           15 :   v->visit (m_elements2);
    6057           15 :   v->visit (m_mask);
    6058           15 : }
    6059              : 
    6060              : /* Implementation of recording::memento::make_debug_string for
    6061              :    vectors.  */
    6062              : 
    6063              :     recording::string *
    6064           10 : recording::memento_of_new_rvalue_vector_perm::make_debug_string ()
    6065              : {
    6066              :     /* Now build a string.  */
    6067           10 :     string *result = string::from_printf (m_ctxt,
    6068              :                 "shufflevector (%s, %s, %s)",
    6069           10 :                 m_elements1->get_debug_string (),
    6070           10 :                 m_elements2->get_debug_string (),
    6071           10 :                 m_mask->get_debug_string ());
    6072              : 
    6073           10 :     return result;
    6074              : 
    6075              : }
    6076              : 
    6077              : /* Implementation of recording::memento::write_reproducer for
    6078              :    vectors.  */
    6079              : 
    6080              :     void
    6081           10 : recording::memento_of_new_rvalue_vector_perm::write_reproducer (reproducer &r)
    6082              : {
    6083           10 :     const char *id = r.make_identifier (this, "vector");
    6084           20 :   r.write ("  gcc_jit_rvalue *%s =\n"
    6085              :            "    gcc_jit_context_new_rvalue_vector_perm (%s, /* gcc_jit_context *ctxt */\n"
    6086              :            "                                            %s, /* gcc_jit_location *loc */\n"
    6087              :            "                                            %s, /* gcc_jit_rvalue **elements1*/\n"
    6088              :            "                                            %s, /* gcc_jit_rvalue **elements2*/\n"
    6089              :            "                                            %s); /* gcc_jit_rvalue **mask*/\n",
    6090              :            id,
    6091              :            r.get_identifier (get_context ()),
    6092           10 :            r.get_identifier (m_loc),
    6093              :            r.get_identifier_as_rvalue (m_elements1),
    6094              :            r.get_identifier_as_rvalue (m_elements2),
    6095              :            r.get_identifier_as_rvalue (m_mask));
    6096           10 : }
    6097              : 
    6098              : void
    6099          165 : recording::ctor::visit_children (rvalue_visitor *v)
    6100              : {
    6101          555 :   for (unsigned int i = 0; i < m_values.length (); i++)
    6102          390 :     v->visit (m_values[i]);
    6103          165 : }
    6104              : 
    6105              : recording::string *
    6106          450 : recording::ctor::make_debug_string ()
    6107              : {
    6108              :   //Make a compound literal-ish
    6109          450 :   pretty_printer pp;
    6110              : 
    6111          450 :   pp_string (&pp, "(");
    6112          450 :   pp_string (&pp, m_type->get_debug_string ());
    6113          450 :   pp_string (&pp, ") {");
    6114              : 
    6115          450 :   size_t field_n = m_fields.length ();
    6116          450 :   size_t values_n = m_values.length ();
    6117              : 
    6118          450 :   if (!field_n && !values_n)
    6119              :     ;
    6120          410 :   else if (!field_n && values_n)
    6121              :     {
    6122          680 :       for (size_t i = 0; i < values_n; i++)
    6123              :         {
    6124          520 :           if (m_values[i])
    6125          470 :             pp_string (&pp, m_values[i]->get_debug_string ());
    6126              :           else
    6127           50 :             pp_string (&pp, "0");
    6128          520 :           if (i + 1 != values_n)
    6129          360 :             pp_string (&pp, ", ");
    6130              :         }
    6131              :     }
    6132          250 :   else if (field_n && values_n)
    6133              :     {
    6134          660 :       for (size_t i = 0; i < values_n; i++)
    6135              :         {
    6136          410 :           pp_string (&pp, ".");
    6137          410 :           pp_string (&pp, m_fields[i]->get_debug_string ());
    6138          410 :           pp_string (&pp, "=");
    6139          410 :           if (m_values[i])
    6140          350 :             pp_string (&pp, m_values[i]->get_debug_string ());
    6141              :           else
    6142           60 :             pp_string (&pp, "0");
    6143          410 :           if (i + 1 != values_n)
    6144          160 :             pp_string (&pp, ", ");
    6145              :         }
    6146              :     }
    6147              :   /* m_fields are never populated with m_values empty.  */
    6148              : 
    6149          450 :   pp_string (&pp, "}");
    6150              : 
    6151          450 :   return new_string (pp_formatted_text (&pp));
    6152          450 : }
    6153              : 
    6154              : void
    6155          450 : recording::ctor::write_reproducer (reproducer &r)
    6156              : {
    6157          450 :   const char *id = r.make_identifier (this, "rvalue");
    6158          450 :   type *type = get_type ();
    6159              : 
    6160          450 :   r.write ("  gcc_jit_rvalue *%s;\n", id);
    6161          450 :   r.write ("  {\n"); /* Open scope for locals.  */
    6162              : 
    6163          450 :   if (type->is_union ())
    6164              :     {
    6165           50 :       if (m_values.length () == 0)
    6166           10 :         r.write ("    gcc_jit_rvalue *value = NULL;\n");
    6167              :       else
    6168           40 :         r.write ("    gcc_jit_rvalue *value = %s;\n",
    6169           40 :                  r.get_identifier_as_rvalue (m_values[0]));
    6170              : 
    6171           50 :       if (m_fields.length () == 0)
    6172           10 :         r.write ("    gcc_jit_field *field = NULL;\n");
    6173              :       else
    6174           40 :         r.write ("    gcc_jit_field *field = %s;\n",
    6175           40 :                  r.get_identifier (m_fields[0]));
    6176              :     }
    6177              :   else
    6178              :     {
    6179              :       /* Write the array of values.  */
    6180          400 :       if (m_values.length () == 0)
    6181           30 :         r.write ("    gcc_jit_rvalue **values = NULL;\n");
    6182              :       else
    6183              :         {
    6184          370 :           r.write ("    gcc_jit_rvalue *values[] = {\n");
    6185         1260 :           for (size_t i = 0; i < m_values.length (); i++)
    6186          890 :             r.write ("        %s,\n", r.get_identifier_as_rvalue (m_values[i]));
    6187          370 :           r.write ("      };\n");
    6188              :         }
    6189              :       /* Write the array of fields.  */
    6190          400 :       if (m_fields.length () == 0)
    6191          190 :         r.write ("    gcc_jit_field **fields = NULL;\n");
    6192              :       else
    6193              :         {
    6194          210 :           r.write ("    gcc_jit_field *fields[] = {\n");
    6195          580 :           for (size_t i = 0; i < m_fields.length (); i++)
    6196          370 :             r.write ("        %s,\n", r.get_identifier (m_fields[i]));
    6197          210 :           r.write ("      };\n");
    6198              :         }
    6199              :     }
    6200          450 :   if (type->is_array ())
    6201          500 :     r.write (
    6202              : "    %s =\n"
    6203              : "      gcc_jit_context_new_array_constructor (%s,\n"
    6204              : "                                             %s, /* gcc_jit_location *loc */\n"
    6205              : "                                             %s, /* gcc_jit_type *type */\n"
    6206              : "                                             %i, /* int num_values */\n"
    6207              : "                                             values);\n",
    6208              :            id,
    6209              :            r.get_identifier (get_context ()),
    6210          170 :            r.get_identifier (m_loc),
    6211              :            r.get_identifier_as_type (get_type ()),
    6212              :            m_values.length ());
    6213          280 :   else if (type->is_struct ())
    6214          670 :     r.write (
    6215              : "    %s =\n"
    6216              : "      gcc_jit_context_new_struct_constructor (%s,\n"
    6217              : "                                              %s, /* loc */\n"
    6218              : "                                              %s, /* gcc_jit_type *type */\n"
    6219              : "                                              %i, /* int num_values */\n"
    6220              : "                                              fields,\n"
    6221              : "                                              values);\n",
    6222              :            id,
    6223              :            r.get_identifier (get_context ()),
    6224          230 :            r.get_identifier (m_loc),
    6225              :            r.get_identifier_as_type (get_type ()),
    6226              :            m_values.length ());
    6227           50 :   else if (type->is_union ())
    6228          100 :     r.write (
    6229              : "    %s =\n"
    6230              : "      gcc_jit_context_new_union_constructor (%s,\n"
    6231              : "                                             %s, /* loc */\n"
    6232              : "                                             %s, /* gcc_jit_type *type */\n"
    6233              : "                                             field,\n"
    6234              : "                                             value);\n",
    6235              :            id,
    6236              :            r.get_identifier (get_context ()),
    6237           50 :            r.get_identifier (m_loc),
    6238              :            r.get_identifier_as_type (get_type ()));
    6239              :   else
    6240            0 :     gcc_unreachable ();
    6241              : 
    6242          450 :   r.write ("  }\n"); /* Close scope for locals.  */
    6243          450 : }
    6244              : 
    6245              : void
    6246          675 : recording::ctor::replay_into (replayer *r)
    6247              : {
    6248          675 :   auto_vec<playback::rvalue *> playback_values;
    6249          675 :   auto_vec<playback::field *> playback_fields;
    6250              : 
    6251          675 :   int n = m_values.length ();
    6252              : 
    6253          675 :   type *type = get_type ();
    6254              : 
    6255              :   /* Handle arrays, and return.  */
    6256          675 :   if (type->is_array ())
    6257              :     {
    6258          255 :       playback_values.reserve (n, false);
    6259              : 
    6260         1035 :       for (int i = 0; i < n; i++)
    6261              :         {
    6262              :           /* null m_values element indicates zero ctor.  */
    6263         1560 :           playback_values.quick_push (m_values[i] ?
    6264          705 :                                       m_values[i]->playback_rvalue () :
    6265          780 :                                       NULL);
    6266              :         }
    6267          255 :       set_playback_obj (r->new_ctor (playback_location (r, m_loc),
    6268              :                                      get_type ()->playback_type (),
    6269              :                                      NULL,
    6270              :                                      &playback_values));
    6271          255 :       return;
    6272              :     }
    6273              :   /* ... else handle unions and structs.  */
    6274              : 
    6275          420 :   playback_values.reserve (n, false);
    6276          420 :   playback_fields.reserve (n, false);
    6277              : 
    6278         1035 :   for (int i = 0; i < n; i++)
    6279              :     {
    6280              :       /* null m_values element indicates zero ctor.  */
    6281         1230 :       playback_values.quick_push (m_values[i] ?
    6282          525 :                                     m_values[i]->playback_rvalue () :
    6283          615 :                                     NULL);
    6284          615 :       playback_fields.quick_push (m_fields[i]->playback_field ());
    6285              :     }
    6286              : 
    6287          420 :   set_playback_obj (r->new_ctor (playback_location (r, m_loc),
    6288              :                                  get_type ()->playback_type (),
    6289              :                                  &playback_fields,
    6290              :                                  &playback_values));
    6291          675 : }
    6292              : 
    6293              : /* The implementation of class gcc::jit::recording::unary_op.  */
    6294              : 
    6295              : /* Implementation of pure virtual hook recording::memento::replay_into
    6296              :    for recording::unary_op.  */
    6297              : 
    6298              : void
    6299          128 : recording::unary_op::replay_into (replayer *r)
    6300              : {
    6301          128 :   set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
    6302              :                                      m_op,
    6303              :                                      get_type ()->playback_type (),
    6304          128 :                                      m_a->playback_rvalue ()));
    6305          128 : }
    6306              : 
    6307              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    6308              :    for recording::unary_op.  */
    6309              : void
    6310           60 : recording::unary_op::visit_children (rvalue_visitor *v)
    6311              : {
    6312           60 :   v->visit (m_a);
    6313           60 : }
    6314              : 
    6315              : /* Implementation of recording::memento::make_debug_string for
    6316              :    unary ops.  */
    6317              : 
    6318              : static const char * const unary_op_strings[] = {
    6319              :   "-", /* GCC_JIT_UNARY_OP_MINUS */
    6320              :   "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
    6321              :   "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
    6322              :   "abs ", /* GCC_JIT_UNARY_OP_ABS */
    6323              : };
    6324              : 
    6325              : recording::string *
    6326          113 : recording::unary_op::make_debug_string ()
    6327              : {
    6328          226 :   return string::from_printf (m_ctxt,
    6329              :                               "%s(%s)",
    6330          113 :                               unary_op_strings[m_op],
    6331          113 :                               m_a->get_debug_string ());
    6332              : }
    6333              : 
    6334              : const char * const unary_op_reproducer_strings[] = {
    6335              :   "GCC_JIT_UNARY_OP_MINUS",
    6336              :   "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
    6337              :   "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
    6338              :   "GCC_JIT_UNARY_OP_ABS"
    6339              : };
    6340              : 
    6341              : /* Implementation of recording::memento::write_reproducer for unary ops.  */
    6342              : 
    6343              : void
    6344           93 : recording::unary_op::write_reproducer (reproducer &r)
    6345              : {
    6346           93 :   const char *id = r.make_identifier (this, "rvalue");
    6347          186 :   r.write ("  gcc_jit_rvalue *%s =\n"
    6348              :            "    gcc_jit_context_new_unary_op (%s,\n"
    6349              :            "                                  %s, /* gcc_jit_location *loc */\n"
    6350              :            "                                  %s, /* enum gcc_jit_unary_op op */\n"
    6351              :            "                                  %s, /* gcc_jit_type *result_type */\n"
    6352              :            "                                  %s); /* gcc_jit_rvalue *a */\n",
    6353              :            id,
    6354              :            r.get_identifier (get_context ()),
    6355           93 :            r.get_identifier (m_loc),
    6356           93 :            unary_op_reproducer_strings[m_op],
    6357              :            r.get_identifier_as_type (get_type ()),
    6358              :            r.get_identifier_as_rvalue (m_a));
    6359           93 : }
    6360              : 
    6361              : /* The implementation of class gcc::jit::recording::binary_op.  */
    6362              : 
    6363              : /* Implementation of pure virtual hook recording::memento::replay_into
    6364              :    for recording::binary_op.  */
    6365              : 
    6366              : void
    6367         3360 : recording::binary_op::replay_into (replayer *r)
    6368              : {
    6369         3360 :   set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
    6370              :                                       m_op,
    6371              :                                       get_type ()->playback_type (),
    6372         3360 :                                       m_a->playback_rvalue (),
    6373         3360 :                                       m_b->playback_rvalue ()));
    6374         3360 : }
    6375              : 
    6376              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    6377              :    for recording::binary_op.  */
    6378              : void
    6379         1877 : recording::binary_op::visit_children (rvalue_visitor *v)
    6380              : {
    6381         1877 :   v->visit (m_a);
    6382         1877 :   v->visit (m_b);
    6383         1877 : }
    6384              : 
    6385              : /* Implementation of recording::memento::make_debug_string for
    6386              :    binary ops.  */
    6387              : 
    6388              : static const char * const binary_op_strings[] = {
    6389              :   "+", /* GCC_JIT_BINARY_OP_PLUS */
    6390              :   "-", /* GCC_JIT_BINARY_OP_MINUS */
    6391              :   "*", /* GCC_JIT_BINARY_OP_MULT */
    6392              :   "/", /* GCC_JIT_BINARY_OP_DIVIDE */
    6393              :   "%", /* GCC_JIT_BINARY_OP_MODULO */
    6394              :   "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
    6395              :   "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
    6396              :   "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
    6397              :   "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
    6398              :   "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
    6399              :   "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
    6400              :   ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
    6401              : };
    6402              : 
    6403              : recording::string *
    6404         1714 : recording::binary_op::make_debug_string ()
    6405              : {
    6406         1714 :   enum precedence prec = get_precedence ();
    6407         1714 :   return string::from_printf (m_ctxt,
    6408              :                               "%s %s %s",
    6409         1714 :                               m_a->get_debug_string_parens (prec),
    6410         1714 :                               binary_op_strings[m_op],
    6411         1714 :                               m_b->get_debug_string_parens (prec));
    6412              : }
    6413              : 
    6414              : const char * const binary_op_reproducer_strings[] = {
    6415              :   "GCC_JIT_BINARY_OP_PLUS",
    6416              :   "GCC_JIT_BINARY_OP_MINUS",
    6417              :   "GCC_JIT_BINARY_OP_MULT",
    6418              :   "GCC_JIT_BINARY_OP_DIVIDE",
    6419              :   "GCC_JIT_BINARY_OP_MODULO",
    6420              :   "GCC_JIT_BINARY_OP_BITWISE_AND",
    6421              :   "GCC_JIT_BINARY_OP_BITWISE_XOR",
    6422              :   "GCC_JIT_BINARY_OP_BITWISE_OR",
    6423              :   "GCC_JIT_BINARY_OP_LOGICAL_AND",
    6424              :   "GCC_JIT_BINARY_OP_LOGICAL_OR",
    6425              :   "GCC_JIT_BINARY_OP_LSHIFT",
    6426              :   "GCC_JIT_BINARY_OP_RSHIFT"
    6427              : };
    6428              : 
    6429              : /* Implementation of recording::memento::write_reproducer for binary ops.  */
    6430              : 
    6431              : void
    6432         1550 : recording::binary_op::write_reproducer (reproducer &r)
    6433              : {
    6434         1550 :   const char *id = r.make_identifier (this, "rvalue");
    6435         3100 :   r.write ("  gcc_jit_rvalue *%s =\n"
    6436              :            "    gcc_jit_context_new_binary_op (%s,\n"
    6437              :            "                                   %s, /* gcc_jit_location *loc */\n"
    6438              :            "                                   %s, /* enum gcc_jit_binary_op op */\n"
    6439              :            "                                   %s, /* gcc_jit_type *result_type */\n"
    6440              :            "                                   %s, /* gcc_jit_rvalue *a */\n"
    6441              :            "                                   %s); /* gcc_jit_rvalue *b */\n",
    6442              :            id,
    6443              :            r.get_identifier (get_context ()),
    6444         1550 :            r.get_identifier (m_loc),
    6445         1550 :            binary_op_reproducer_strings[m_op],
    6446              :            r.get_identifier_as_type (get_type ()),
    6447              :            r.get_identifier_as_rvalue (m_a),
    6448              :            r.get_identifier_as_rvalue (m_b));
    6449         1550 : }
    6450              : 
    6451              : namespace recording {
    6452              : static const enum precedence binary_op_precedence[] = {
    6453              :   PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
    6454              :   PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
    6455              : 
    6456              :   PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
    6457              :   PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
    6458              :   PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
    6459              : 
    6460              :   PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
    6461              :   PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
    6462              :   PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
    6463              :   PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
    6464              :   PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
    6465              :   PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
    6466              :   PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
    6467              : };
    6468              : } /* namespace recording */
    6469              : 
    6470              : enum recording::precedence
    6471         2706 : recording::binary_op::get_precedence () const
    6472              : {
    6473         2706 :   return binary_op_precedence[m_op];
    6474              : }
    6475              : 
    6476              : /* The implementation of class gcc::jit::recording::comparison.  */
    6477              : 
    6478              : /* Implementation of recording::memento::make_debug_string for
    6479              :    comparisons.  */
    6480              : 
    6481              : static const char * const comparison_strings[] =
    6482              : {
    6483              :   "==", /* GCC_JIT_COMPARISON_EQ */
    6484              :   "!=", /* GCC_JIT_COMPARISON_NE */
    6485              :   "<",  /* GCC_JIT_COMPARISON_LT */
    6486              :   "<=", /* GCC_JIT_COMPARISON_LE */
    6487              :   ">",  /* GCC_JIT_COMPARISON_GT */
    6488              :   ">=", /* GCC_JIT_COMPARISON_GE */
    6489              : };
    6490              : 
    6491              : recording::string *
    6492          901 : recording::comparison::make_debug_string ()
    6493              : {
    6494          901 :   enum precedence prec = get_precedence ();
    6495          901 :   return string::from_printf (m_ctxt,
    6496              :                               "%s %s %s",
    6497          901 :                               m_a->get_debug_string_parens (prec),
    6498          901 :                               comparison_strings[m_op],
    6499          901 :                               m_b->get_debug_string_parens (prec));
    6500              : }
    6501              : 
    6502              : /* A table of enum gcc_jit_comparison values expressed in string
    6503              :    form.  */
    6504              : 
    6505              : static const char * const comparison_reproducer_strings[] =
    6506              : {
    6507              :   "GCC_JIT_COMPARISON_EQ",
    6508              :   "GCC_JIT_COMPARISON_NE",
    6509              :   "GCC_JIT_COMPARISON_LT",
    6510              :   "GCC_JIT_COMPARISON_LE",
    6511              :   "GCC_JIT_COMPARISON_GT",
    6512              :   "GCC_JIT_COMPARISON_GE"
    6513              : };
    6514              : 
    6515              : /* Implementation of recording::memento::write_reproducer for comparisons.  */
    6516              : 
    6517              : void
    6518          756 : recording::comparison::write_reproducer (reproducer &r)
    6519              : {
    6520          756 :   const char *id = r.make_identifier (this, "rvalue");
    6521         1512 :   r.write ("  gcc_jit_rvalue *%s =\n"
    6522              :            "    gcc_jit_context_new_comparison (%s,\n"
    6523              :            "                                    %s, /* gcc_jit_location *loc */\n"
    6524              :            "                                    %s, /* enum gcc_jit_comparison op */\n"
    6525              :            "                                    %s, /* gcc_jit_rvalue *a */\n"
    6526              :            "                                    %s); /* gcc_jit_rvalue *b */\n",
    6527              :            id,
    6528              :            r.get_identifier (get_context ()),
    6529          756 :            r.get_identifier (m_loc),
    6530          756 :            comparison_reproducer_strings[m_op],
    6531              :            r.get_identifier_as_rvalue (m_a),
    6532              :            r.get_identifier_as_rvalue (m_b));
    6533          756 : }
    6534              : 
    6535              : /* Implementation of pure virtual hook recording::memento::replay_into
    6536              :    for recording::comparison.  */
    6537              : 
    6538              : void
    6539         1509 : recording::comparison::replay_into (replayer *r)
    6540              : {
    6541         1509 :   set_playback_obj (r->new_comparison (playback_location (r, m_loc),
    6542              :                                        m_op,
    6543         1509 :                                        m_a->playback_rvalue (),
    6544         1509 :                                        m_b->playback_rvalue (),
    6545         1509 :                                        m_type->playback_type ()));
    6546         1509 : }
    6547              : 
    6548              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    6549              :    for recording::comparison.  */
    6550              : 
    6551              : void
    6552         1325 : recording::comparison::visit_children (rvalue_visitor *v)
    6553              : {
    6554         1325 :   v->visit (m_a);
    6555         1325 :   v->visit (m_b);
    6556         1325 : }
    6557              : 
    6558              : namespace recording {
    6559              : static const enum precedence comparison_precedence[] =
    6560              : {
    6561              :   PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
    6562              :   PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
    6563              : 
    6564              :   PRECEDENCE_RELATIONAL,  /* GCC_JIT_COMPARISON_LT */
    6565              :   PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
    6566              :   PRECEDENCE_RELATIONAL,  /* GCC_JIT_COMPARISON_GT */
    6567              :   PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
    6568              : };
    6569              : } /* namespace recording */
    6570              : 
    6571              : enum recording::precedence
    6572         1051 : recording::comparison::get_precedence () const
    6573              : {
    6574         1051 :   return comparison_precedence[m_op];
    6575              : }
    6576              : 
    6577              : /* Implementation of pure virtual hook recording::memento::replay_into
    6578              :    for recording::cast.  */
    6579              : 
    6580              : void
    6581          379 : recording::cast::replay_into (replayer *r)
    6582              : {
    6583          379 :   set_playback_obj (r->new_cast (playback_location (r, m_loc),
    6584          379 :                                  m_rvalue->playback_rvalue (),
    6585              :                                  get_type ()->playback_type ()));
    6586          379 : }
    6587              : 
    6588              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    6589              :    for recording::cast.  */
    6590              : void
    6591          173 : recording::cast::visit_children (rvalue_visitor *v)
    6592              : {
    6593          173 :   v->visit (m_rvalue);
    6594          173 : }
    6595              : 
    6596              : /* Implementation of recording::memento::make_debug_string for
    6597              :    casts.  */
    6598              : 
    6599              : recording::string *
    6600          295 : recording::cast::make_debug_string ()
    6601              : {
    6602          295 :   enum precedence prec = get_precedence ();
    6603          295 :   return string::from_printf (m_ctxt,
    6604              :                               "(%s)%s",
    6605          295 :                               get_type ()->get_debug_string (),
    6606          295 :                               m_rvalue->get_debug_string_parens (prec));
    6607              : }
    6608              : 
    6609              : /* Implementation of recording::memento::write_reproducer for casts.  */
    6610              : 
    6611              : void
    6612          255 : recording::cast::write_reproducer (reproducer &r)
    6613              : {
    6614          255 :   const char *id = r.make_identifier (this, "rvalue");
    6615          510 :   r.write ("  gcc_jit_rvalue *%s =\n"
    6616              :            "    gcc_jit_context_new_cast (%s,\n"
    6617              :            "                              %s, /* gcc_jit_location *loc */\n"
    6618              :            "                              %s, /* gcc_jit_rvalue *rvalue */\n"
    6619              :            "                              %s); /* gcc_jit_type *type */\n",
    6620              :            id,
    6621              :            r.get_identifier (get_context ()),
    6622          255 :            r.get_identifier (m_loc),
    6623              :            r.get_identifier_as_rvalue (m_rvalue),
    6624              :            r.get_identifier_as_type (get_type ()));
    6625          255 : }
    6626              : 
    6627              : /* Implementation of pure virtual hook recording::memento::replay_into
    6628              :    for recording::bitcast.  */
    6629              : 
    6630              : void
    6631           25 : recording::bitcast::replay_into (replayer *r)
    6632              : {
    6633           25 :   set_playback_obj (r->new_bitcast (playback_location (r, m_loc),
    6634           25 :                                     m_rvalue->playback_rvalue (),
    6635              :                                     get_type ()->playback_type ()));
    6636           25 : }
    6637              : 
    6638              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    6639              :    for recording::bitcast.  */
    6640              : void
    6641           25 : recording::bitcast::visit_children (rvalue_visitor *v)
    6642              : {
    6643           25 :   v->visit (m_rvalue);
    6644           25 : }
    6645              : 
    6646              : /* Implementation of recording::memento::make_debug_string for
    6647              :    casts.  */
    6648              : 
    6649              : recording::string *
    6650           20 : recording::bitcast::make_debug_string ()
    6651              : {
    6652           20 :   enum precedence prec = get_precedence ();
    6653           20 :   return string::from_printf (m_ctxt,
    6654              :                               "bitcast(%s, %s)",
    6655           20 :                               m_rvalue->get_debug_string_parens (prec),
    6656           20 :                               get_type ()->get_debug_string ());
    6657              : }
    6658              : 
    6659              : /* Implementation of recording::memento::write_reproducer for casts.  */
    6660              : 
    6661              : void
    6662           20 : recording::bitcast::write_reproducer (reproducer &r)
    6663              : {
    6664           20 :   const char *id = r.make_identifier (this, "rvalue");
    6665           40 :   r.write ("  gcc_jit_rvalue *%s =\n"
    6666              :            "    gcc_jit_context_new_bitcast (%s,\n"
    6667              :            "                                 %s, /* gcc_jit_location *loc */\n"
    6668              :            "                                 %s, /* gcc_jit_rvalue *rvalue */\n"
    6669              :            "                                 %s); /* gcc_jit_type *type */\n",
    6670              :            id,
    6671              :            r.get_identifier (get_context ()),
    6672           20 :            r.get_identifier (m_loc),
    6673              :            r.get_identifier_as_rvalue (m_rvalue),
    6674              :            r.get_identifier_as_type (get_type ()));
    6675           20 : }
    6676              : 
    6677              : /* The implementation of class gcc::jit::recording::base_call.  */
    6678              : 
    6679              : /* The constructor for gcc::jit::recording::base_call.  */
    6680              : 
    6681          820 : recording::base_call::base_call (context *ctxt,
    6682              :                                  location *loc,
    6683              :                                  type *type_,
    6684              :                                  int numargs,
    6685          820 :                                  rvalue **args)
    6686              : : rvalue (ctxt, loc, type_),
    6687          820 :   m_args (),
    6688          820 :   m_require_tail_call (0)
    6689              : {
    6690         1987 :   for (int i = 0; i< numargs; i++)
    6691         1167 :     m_args.safe_push (args[i]);
    6692          820 : }
    6693              : 
    6694              : /* Subroutine for use by call and call_though_ptr's write_reproducer
    6695              :    methods.  */
    6696              : 
    6697              : void
    6698          601 : recording::base_call::write_reproducer_tail_call (reproducer &r,
    6699              :                                                   const char *id)
    6700              : {
    6701          601 :   if (m_require_tail_call)
    6702              :     {
    6703           15 :       r.write ("  gcc_jit_rvalue_set_bool_require_tail_call (%s,  /* gcc_jit_rvalue *call*/\n"
    6704              :                "                                             %i); /* int require_tail_call*/\n",
    6705              :                id,
    6706              :                1);
    6707              :     }
    6708          601 : }
    6709              : 
    6710              : /* The implementation of class gcc::jit::recording::call.  */
    6711              : 
    6712              : /* The constructor for gcc::jit::recording::call.  */
    6713              : 
    6714          805 : recording::call::call (recording::context *ctxt,
    6715              :                        recording::location *loc,
    6716              :                        recording::function *func,
    6717              :                        int numargs,
    6718          805 :                        rvalue **args)
    6719              : : base_call (ctxt, loc, func->get_return_type (), numargs, args),
    6720          805 :   m_func (func)
    6721              : {
    6722          805 : }
    6723              : 
    6724              : /* Implementation of pure virtual hook recording::memento::replay_into
    6725              :    for recording::call.  */
    6726              : 
    6727              : void
    6728          805 : recording::call::replay_into (replayer *r)
    6729              : {
    6730          805 :   auto_vec<playback::rvalue *> playback_args;
    6731          805 :   playback_args.create (m_args.length ());
    6732         1927 :   for (unsigned i = 0; i< m_args.length (); i++)
    6733         1122 :     playback_args.safe_push (m_args[i]->playback_rvalue ());
    6734              : 
    6735          805 :   set_playback_obj (r->new_call (playback_location (r, m_loc),
    6736          805 :                                  m_func->playback_function (),
    6737              :                                  &playback_args,
    6738          805 :                                  m_require_tail_call));
    6739          805 : }
    6740              : 
    6741              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    6742              :    for recording::call.  */
    6743              : 
    6744              : void
    6745          660 : recording::call::visit_children (rvalue_visitor *v)
    6746              : {
    6747         1642 :   for (unsigned i = 0; i< m_args.length (); i++)
    6748          982 :     v->visit (m_args[i]);
    6749          660 : }
    6750              : 
    6751              : /* Implementation of recording::memento::make_debug_string for
    6752              :    function calls.  */
    6753              : 
    6754              : recording::string *
    6755          606 : recording::call::make_debug_string ()
    6756              : {
    6757              :   /* First, build a buffer for the arguments.  */
    6758          606 :   comma_separated_string args (m_args, get_precedence ());
    6759              : 
    6760              :   /* ...and use it to get the string for the call as a whole.  */
    6761          606 :   string *result = string::from_printf (m_ctxt,
    6762              :                                         "%s (%s)",
    6763          606 :                                         m_func->get_debug_string (),
    6764              :                                         args.as_char_ptr ());
    6765              : 
    6766         1212 :   return result;
    6767          606 : }
    6768              : 
    6769              : void
    6770          591 : recording::call::write_reproducer (reproducer &r)
    6771              : {
    6772          591 :   const char *id = r.make_identifier (this, "call");
    6773          591 :   const char *args_id = r.make_tmp_identifier ("args_for_", this);
    6774          591 :   r.write ("  gcc_jit_rvalue *%s[%i] = {\n",
    6775              :            args_id,
    6776              :            m_args.length ());
    6777         1387 :   for (unsigned i = 0; i< m_args.length (); i++)
    6778          796 :     r.write ("    %s,\n", r.get_identifier_as_rvalue (m_args[i]));
    6779          591 :   r.write ("  };\n");
    6780         1182 :   r.write ("  gcc_jit_rvalue *%s =\n"
    6781              :            "    gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
    6782              :            "                              %s, /* gcc_jit_location *loc */\n"
    6783              :            "                              %s, /* gcc_jit_function *func */\n"
    6784              :            "                              %i, /* int numargs  */ \n"
    6785              :            "                              %s); /* gcc_jit_rvalue **args*/\n",
    6786              :            id,
    6787              :            r.get_identifier (get_context ()),
    6788          591 :            r.get_identifier (m_loc),
    6789          591 :            r.get_identifier (m_func),
    6790              :            m_args.length (),
    6791              :            args_id);
    6792          591 :   write_reproducer_tail_call (r, id);
    6793          591 : }
    6794              : 
    6795              : /* The implementation of class gcc::jit::recording::call_through_ptr.  */
    6796              : 
    6797              : /* The constructor for recording::call_through_ptr. */
    6798              : 
    6799           15 : recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
    6800              :                                                recording::location *loc,
    6801              :                                                recording::rvalue *fn_ptr,
    6802              :                                                int numargs,
    6803           15 :                                                rvalue **args)
    6804              : : base_call (ctxt, loc,
    6805           15 :              fn_ptr->get_type ()->dereference ()
    6806           15 :                ->as_a_function_type ()->get_return_type (),
    6807              :              numargs, args),
    6808           15 :   m_fn_ptr (fn_ptr)
    6809              : {
    6810           15 : }
    6811              : 
    6812              : /* Implementation of pure virtual hook recording::memento::replay_into
    6813              :    for recording::call_through_ptr.  */
    6814              : 
    6815              : void
    6816           15 : recording::call_through_ptr::replay_into (replayer *r)
    6817              : {
    6818           15 :   auto_vec<playback::rvalue *> playback_args;
    6819           15 :   playback_args.create (m_args.length ());
    6820           60 :   for (unsigned i = 0; i< m_args.length (); i++)
    6821           45 :     playback_args.safe_push (m_args[i]->playback_rvalue ());
    6822              : 
    6823           15 :   set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
    6824           15 :                                              m_fn_ptr->playback_rvalue (),
    6825              :                                              &playback_args,
    6826           15 :                                              m_require_tail_call));
    6827           15 : }
    6828              : 
    6829              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    6830              :    for recording::call_through_ptr.  */
    6831              : 
    6832              : void
    6833           15 : recording::call_through_ptr::visit_children (rvalue_visitor *v)
    6834              : {
    6835           15 :   v->visit (m_fn_ptr);
    6836           60 :   for (unsigned i = 0; i< m_args.length (); i++)
    6837           45 :     v->visit (m_args[i]);
    6838           15 : }
    6839              : 
    6840              : /* Implementation of recording::memento::make_debug_string for
    6841              :    calls through function ptrs.  */
    6842              : 
    6843              : recording::string *
    6844           10 : recording::call_through_ptr::make_debug_string ()
    6845              : {
    6846           10 :   enum precedence prec = get_precedence ();
    6847              :   /* First, build a buffer for the arguments.  */
    6848              :   /* Calculate length of said buffer.  */
    6849           10 :   size_t sz = 1; /* nil terminator */
    6850           40 :   for (unsigned i = 0; i< m_args.length (); i++)
    6851              :     {
    6852           30 :       sz += strlen (m_args[i]->get_debug_string_parens (prec));
    6853           30 :       sz += 2; /* ", " separator */
    6854              :     }
    6855              : 
    6856              :   /* Now allocate and populate the buffer.  */
    6857           10 :   char *argbuf = new char[sz];
    6858           10 :   size_t len = 0;
    6859              : 
    6860           50 :   for (unsigned i = 0; i< m_args.length (); i++)
    6861              :     {
    6862           30 :       strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
    6863           30 :       len += strlen (m_args[i]->get_debug_string_parens (prec));
    6864           70 :       if (i + 1 < m_args.length ())
    6865              :         {
    6866           20 :           strcpy (argbuf + len, ", ");
    6867           20 :           len += 2;
    6868              :         }
    6869              :     }
    6870           10 :   argbuf[len] = '\0';
    6871              : 
    6872              :   /* ...and use it to get the string for the call as a whole.  */
    6873           10 :   string *result = string::from_printf (m_ctxt,
    6874              :                                         "%s (%s)",
    6875           10 :                                         m_fn_ptr->get_debug_string_parens (prec),
    6876              :                                         argbuf);
    6877              : 
    6878           10 :   delete[] argbuf;
    6879              : 
    6880           10 :   return result;
    6881              : }
    6882              : 
    6883              : /* Implementation of recording::memento::write_reproducer for
    6884              :    call_through_ptr.  */
    6885              : 
    6886              : void
    6887           10 : recording::call_through_ptr::write_reproducer (reproducer &r)
    6888              : {
    6889           10 :   const char *id = r.make_identifier (this, "call");
    6890           10 :   const char *args_id = r.make_tmp_identifier ("args_for_", this);
    6891           10 :   r.write ("  gcc_jit_rvalue *%s[%i] = {\n",
    6892              :              args_id,
    6893              :              m_args.length ());
    6894           40 :   for (unsigned i = 0; i< m_args.length (); i++)
    6895           30 :     r.write ("    %s,\n", r.get_identifier_as_rvalue (m_args[i]));
    6896           10 :   r.write ("  };\n");
    6897           30 :   r.write ("  gcc_jit_rvalue *%s =\n"
    6898              :            "    gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
    6899              :            "                              %s, /* gcc_jit_location *loc */\n"
    6900              :            "                              %s, /* gcc_jit_rvalue *fn_ptr */\n"
    6901              :            "                              %i, /* int numargs  */ \n"
    6902              :            "                              %s); /* gcc_jit_rvalue **args*/\n",
    6903              :            id,
    6904              :            r.get_identifier (get_context ()),
    6905           10 :            r.get_identifier (m_loc),
    6906              :            r.get_identifier_as_rvalue (m_fn_ptr),
    6907              :            m_args.length (),
    6908              :            args_id);
    6909           10 :   write_reproducer_tail_call (r, id);
    6910           10 : }
    6911              : 
    6912              : /* The implementation of class gcc::jit::recording::array_access.  */
    6913              : 
    6914              : /* Implementation of pure virtual hook recording::memento::replay_into
    6915              :    for recording::array_access.  */
    6916              : 
    6917              : void
    6918          474 : recording::array_access::replay_into (replayer *r)
    6919              : {
    6920          948 :   set_playback_obj (
    6921          474 :     r->new_array_access (playback_location (r, m_loc),
    6922          474 :                          m_ptr->playback_rvalue (),
    6923          474 :                          m_index->playback_rvalue ()));
    6924          474 : }
    6925              : 
    6926              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    6927              :    for recording::array_access.  */
    6928              : 
    6929              : void
    6930          266 : recording::array_access::visit_children (rvalue_visitor *v)
    6931              : {
    6932          266 :   v->visit (m_ptr);
    6933          266 :   v->visit (m_index);
    6934          266 : }
    6935              : 
    6936              : /* Implementation of recording::memento::make_debug_string for
    6937              :    array accesses.  */
    6938              : 
    6939              : recording::string *
    6940          190 : recording::array_access::make_debug_string ()
    6941              : {
    6942          190 :   enum precedence prec = get_precedence ();
    6943          190 :   return string::from_printf (m_ctxt,
    6944              :                               "%s[%s]",
    6945          190 :                               m_ptr->get_debug_string_parens (prec),
    6946          190 :                               m_index->get_debug_string_parens (prec));
    6947              : }
    6948              : 
    6949              : /* Implementation of recording::memento::write_reproducer for
    6950              :    array_access.  */
    6951              : 
    6952              : void
    6953          190 : recording::array_access::write_reproducer (reproducer &r)
    6954              : {
    6955          190 :   const char *id = r.make_identifier (this, "lvalue");
    6956          380 :   r.write ("  gcc_jit_lvalue *%s = \n"
    6957              :            "    gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
    6958              :            "                                      %s, /*gcc_jit_location *loc */\n"
    6959              :            "                                      %s, /* gcc_jit_rvalue *ptr */\n"
    6960              :            "                                      %s); /* gcc_jit_rvalue *index */\n",
    6961              :            id,
    6962              :            r.get_identifier (get_context ()),
    6963          190 :            r.get_identifier (m_loc),
    6964              :            r.get_identifier_as_rvalue (m_ptr),
    6965              :            r.get_identifier_as_rvalue (m_index));
    6966          190 : }
    6967              : 
    6968              : /* The implementation of class gcc::jit::recording::convert_vector.  */
    6969              : 
    6970              : /* Implementation of pure virtual hook recording::memento::replay_into
    6971              :    for recording::convert_vector.  */
    6972              : 
    6973              : void
    6974           15 : recording::convert_vector::replay_into (replayer *r)
    6975              : {
    6976           30 :   set_playback_obj (
    6977           15 :     r->convert_vector (playback_location (r, m_loc),
    6978           15 :                           m_vector->playback_rvalue (),
    6979           15 :                           m_type->playback_type ()));
    6980           15 : }
    6981              : 
    6982              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    6983              :    for recording::convert_vector.  */
    6984              : 
    6985              : void
    6986           15 : recording::convert_vector::visit_children (rvalue_visitor *v)
    6987              : {
    6988           15 :   v->visit (m_vector);
    6989           15 : }
    6990              : 
    6991              : /* The implementation of class gcc::jit::recording::vector_access.  */
    6992              : 
    6993              : /* Implementation of pure virtual hook recording::memento::replay_into
    6994              :    for recording::vector_access.  */
    6995              : 
    6996              : void
    6997           15 : recording::vector_access::replay_into (replayer *r)
    6998              : {
    6999           30 :   set_playback_obj (
    7000           15 :     r->new_vector_access (playback_location (r, m_loc),
    7001           15 :                           m_vector->playback_rvalue (),
    7002           15 :                           m_index->playback_rvalue ()));
    7003           15 : }
    7004              : 
    7005              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    7006              :    for recording::vector_access.  */
    7007              : 
    7008              : void
    7009           15 : recording::vector_access::visit_children (rvalue_visitor *v)
    7010              : {
    7011           15 :   v->visit (m_vector);
    7012           15 :   v->visit (m_index);
    7013           15 : }
    7014              : 
    7015              : /* Implementation of recording::memento::make_debug_string for
    7016              :    array accesses.  */
    7017              : 
    7018              : recording::string *
    7019           10 : recording::convert_vector::make_debug_string ()
    7020              : {
    7021           10 :   enum precedence prec = get_precedence ();
    7022           10 :   return string::from_printf (m_ctxt,
    7023              :                               "(%s)%s",
    7024           10 :                               m_type->get_debug_string (),
    7025           10 :                               m_vector->get_debug_string_parens (prec));
    7026              : }
    7027              : 
    7028              : /* Implementation of recording::memento::write_reproducer for
    7029              :    convert_vector.  */
    7030              : 
    7031              : void
    7032           10 : recording::convert_vector::write_reproducer (reproducer &r)
    7033              : {
    7034           10 :   const char *id = r.make_identifier (this, "lvalue");
    7035           20 :   r.write ("  gcc_jit_rvalue *%s = \n"
    7036              :            "    gcc_jit_context_convert_vector (%s, /* gcc_jit_context *ctxt */\n"
    7037              :            "                                    %s, /*gcc_jit_location *loc */\n"
    7038              :            "                                    %s, /* gcc_jit_rvalue *vector */\n"
    7039              :            "                                    %s); /* gcc_jit_type *type */\n",
    7040              :            id,
    7041              :            r.get_identifier (get_context ()),
    7042           10 :            r.get_identifier (m_loc),
    7043              :            r.get_identifier_as_rvalue (m_vector),
    7044              :            r.get_identifier_as_type (m_type));
    7045           10 : }
    7046              : 
    7047              : recording::string *
    7048           10 : recording::vector_access::make_debug_string ()
    7049              : {
    7050           10 :   enum precedence prec = get_precedence ();
    7051           10 :   return string::from_printf (m_ctxt,
    7052              :                               "%s[%s]",
    7053           10 :                               m_vector->get_debug_string_parens (prec),
    7054           10 :                               m_index->get_debug_string_parens (prec));
    7055              : }
    7056              : 
    7057              : /* Implementation of recording::memento::write_reproducer for
    7058              :    vector_access.  */
    7059              : 
    7060              : void
    7061           10 : recording::vector_access::write_reproducer (reproducer &r)
    7062              : {
    7063           10 :   const char *id = r.make_identifier (this, "lvalue");
    7064           20 :   r.write ("  gcc_jit_lvalue *%s = \n"
    7065              :            "    gcc_jit_context_new_vector_access (%s, /* gcc_jit_context *ctxt */\n"
    7066              :            "                                       %s, /*gcc_jit_location *loc */\n"
    7067              :            "                                       %s, /* gcc_jit_rvalue *vector */\n"
    7068              :            "                                       %s); /* gcc_jit_rvalue *index */\n",
    7069              :            id,
    7070              :            r.get_identifier (get_context ()),
    7071           10 :            r.get_identifier (m_loc),
    7072              :            r.get_identifier_as_rvalue (m_vector),
    7073              :            r.get_identifier_as_rvalue (m_index));
    7074           10 : }
    7075              : 
    7076              : /* The implementation of class gcc::jit::recording::access_field_of_lvalue.  */
    7077              : 
    7078              : /* Implementation of pure virtual hook recording::memento::replay_into
    7079              :    for recording::access_field_of_lvalue.  */
    7080              : 
    7081              : void
    7082          199 : recording::access_field_of_lvalue::replay_into (replayer *r)
    7083              : {
    7084          398 :   set_playback_obj (
    7085          199 :     m_lvalue->playback_lvalue ()
    7086          199 :       ->access_field (playback_location (r, m_loc),
    7087          199 :                       m_field->playback_field ()));
    7088              : 
    7089          199 : }
    7090              : 
    7091              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    7092              :    for recording::access_field_of_lvalue.  */
    7093              : 
    7094              : void
    7095          169 : recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
    7096              : {
    7097          169 :   v->visit (m_lvalue);
    7098          169 : }
    7099              : 
    7100              : /* Implementation of recording::memento::make_debug_string for
    7101              :    accessing a field of an lvalue.  */
    7102              : 
    7103              : recording::string *
    7104          184 : recording::access_field_of_lvalue::make_debug_string ()
    7105              : {
    7106          184 :   enum precedence prec = get_precedence ();
    7107          184 :   return string::from_printf (m_ctxt,
    7108              :                               "%s.%s",
    7109          184 :                               m_lvalue->get_debug_string_parens (prec),
    7110          184 :                               m_field->get_debug_string ());
    7111              : }
    7112              : 
    7113              : /* Implementation of recording::memento::write_reproducer for
    7114              :    access_field_of_lvalue.  */
    7115              : 
    7116              : void
    7117          184 : recording::access_field_of_lvalue::write_reproducer (reproducer &r)
    7118              : {
    7119          184 :   const char *id = r.make_identifier (this, "lvalue");
    7120          184 :   r.write ("  gcc_jit_lvalue *%s = \n"
    7121              :            "    gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
    7122              :            "                                 %s, /*gcc_jit_location *loc */\n"
    7123              :            "                                 %s);\n",
    7124              :            id,
    7125              :            r.get_identifier_as_lvalue (m_lvalue),
    7126          184 :            r.get_identifier (m_loc),
    7127          184 :            r.get_identifier (m_field));
    7128          184 : }
    7129              : 
    7130              : /* The implementation of class gcc::jit::recording::access_field_rvalue.  */
    7131              : 
    7132              : /* Implementation of pure virtual hook recording::memento::replay_into
    7133              :    for recording::access_field_rvalue.  */
    7134              : 
    7135              : void
    7136          139 : recording::access_field_rvalue::replay_into (replayer *r)
    7137              : {
    7138          278 :   set_playback_obj (
    7139          139 :     m_rvalue->playback_rvalue ()
    7140          139 :       ->access_field (playback_location (r, m_loc),
    7141          139 :                       m_field->playback_field ()));
    7142          139 : }
    7143              : 
    7144              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    7145              :    for recording::access_field_rvalue.  */
    7146              : 
    7147              : void
    7148           55 : recording::access_field_rvalue::visit_children (rvalue_visitor *v)
    7149              : {
    7150           55 :   v->visit (m_rvalue);
    7151           55 : }
    7152              : 
    7153              : /* Implementation of recording::memento::make_debug_string for
    7154              :    accessing a field of an rvalue.  */
    7155              : 
    7156              : recording::string *
    7157          104 : recording::access_field_rvalue::make_debug_string ()
    7158              : {
    7159          104 :   enum precedence prec = get_precedence ();
    7160          104 :   return string::from_printf (m_ctxt,
    7161              :                               "%s.%s",
    7162          104 :                               m_rvalue->get_debug_string_parens (prec),
    7163          104 :                               m_field->get_debug_string ());
    7164              : }
    7165              : 
    7166              : /* Implementation of recording::memento::write_reproducer for
    7167              :    access_field_rvalue.  */
    7168              : 
    7169              : void
    7170          104 : recording::access_field_rvalue::write_reproducer (reproducer &r)
    7171              : {
    7172          104 :   const char *id = r.make_identifier (this, "rvalue");
    7173          104 :   r.write ("  gcc_jit_rvalue *%s = \n"
    7174              :            "    gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
    7175              :            "                                 %s, /*gcc_jit_location *loc */\n"
    7176              :            "                                 %s);\n",
    7177              :            id,
    7178              :            r.get_identifier_as_rvalue (m_rvalue),
    7179          104 :            r.get_identifier (m_loc),
    7180          104 :            r.get_identifier (m_field));
    7181          104 : }
    7182              : 
    7183              : /* The implementation of class
    7184              :    gcc::jit::recording::dereference_field_rvalue.  */
    7185              : 
    7186              : /* Implementation of pure virtual hook recording::memento::replay_into
    7187              :    for recording::dereference_field_rvalue.  */
    7188              : 
    7189              : void
    7190         1548 : recording::dereference_field_rvalue::replay_into (replayer *r)
    7191              : {
    7192         3096 :   set_playback_obj (
    7193         1548 :     m_rvalue->playback_rvalue ()->
    7194         1548 :       dereference_field (playback_location (r, m_loc),
    7195         1548 :                          m_field->playback_field ()));
    7196         1548 : }
    7197              : 
    7198              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    7199              :    for recording::dereference_field_rvalue.  */
    7200              : 
    7201              : void
    7202          939 : recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
    7203              : {
    7204          939 :   v->visit (m_rvalue);
    7205          939 : }
    7206              : 
    7207              : /* Implementation of recording::memento::make_debug_string for
    7208              :    dereferencing a field of an rvalue.  */
    7209              : 
    7210              : recording::string *
    7211         1106 : recording::dereference_field_rvalue::make_debug_string ()
    7212              : {
    7213         1106 :   enum precedence prec = get_precedence ();
    7214         1106 :   return string::from_printf (m_ctxt,
    7215              :                               "%s->%s",
    7216         1106 :                               m_rvalue->get_debug_string_parens (prec),
    7217         1106 :                               m_field->get_debug_string ());
    7218              : }
    7219              : 
    7220              : /* Implementation of recording::memento::write_reproducer for
    7221              :    dereference_field_rvalue.  */
    7222              : 
    7223              : void
    7224         1092 : recording::dereference_field_rvalue::write_reproducer (reproducer &r)
    7225              : {
    7226         1092 :   const char *id = r.make_identifier (this, "lvalue");
    7227         1092 :   r.write ("  gcc_jit_lvalue *%s=\n"
    7228              :            "    gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
    7229              :            "                                      %s, /* gcc_jit_location *loc */\n"
    7230              :            "                                      %s); /* gcc_jit_field *field */\n",
    7231              :            id,
    7232              :            r.get_identifier_as_rvalue (m_rvalue),
    7233         1092 :            r.get_identifier (m_loc),
    7234         1092 :            r.get_identifier (m_field));
    7235         1092 : }
    7236              : 
    7237              : /* The implementation of class gcc::jit::recording::dereference_rvalue.  */
    7238              : 
    7239              : /* Implementation of pure virtual hook recording::memento::replay_into
    7240              :    for recording::dereference_rvalue.  */
    7241              : 
    7242              : void
    7243          684 : recording::dereference_rvalue::replay_into (replayer *r)
    7244              : {
    7245         1368 :   set_playback_obj (
    7246          684 :     m_rvalue->playback_rvalue ()->
    7247          684 :       dereference (playback_location (r, m_loc)));
    7248          684 : }
    7249              : 
    7250              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    7251              :    for recording::dereference_rvalue.  */
    7252              : 
    7253              : void
    7254          474 : recording::dereference_rvalue::visit_children (rvalue_visitor *v)
    7255              : {
    7256          474 :   v->visit (m_rvalue);
    7257          474 : }
    7258              : 
    7259              : /* Implementation of recording::memento::make_debug_string for
    7260              :    dereferencing an rvalue.  */
    7261              : 
    7262              : recording::string *
    7263          599 : recording::dereference_rvalue::make_debug_string ()
    7264              : {
    7265          599 :   enum precedence prec = get_precedence ();
    7266          599 :   return string::from_printf (m_ctxt,
    7267              :                               "*%s",
    7268          599 :                               m_rvalue->get_debug_string_parens (prec));
    7269              : }
    7270              : 
    7271              : /* Implementation of recording::memento::write_reproducer for
    7272              :    dereference_rvalue.  */
    7273              : 
    7274              : void
    7275          599 : recording::dereference_rvalue::write_reproducer (reproducer &r)
    7276              : {
    7277          599 :   const char *id = r.make_identifier (this, "dereference");
    7278          599 :   r.write ("  gcc_jit_lvalue *%s =\n"
    7279              :            "    gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
    7280              :            "                                %s); /* gcc_jit_location *loc */\n",
    7281              :            id,
    7282              :            r.get_identifier_as_rvalue (m_rvalue),
    7283          599 :            r.get_identifier (m_loc));
    7284          599 : }
    7285              : 
    7286              : /* The implementation of class gcc::jit::recording::get_address_of_lvalue.  */
    7287              : 
    7288              : /* Implementation of pure virtual hook recording::memento::replay_into
    7289              :    for recording::get_address_of_lvalue.  */
    7290              : 
    7291              : void
    7292          498 : recording::get_address_of_lvalue::replay_into (replayer *r)
    7293              : {
    7294          996 :   set_playback_obj (
    7295          498 :     m_lvalue->playback_lvalue ()->
    7296          498 :       get_address (playback_location (r, m_loc)));
    7297          498 : }
    7298              : 
    7299              : /* Implementation of pure virtual hook recording::rvalue::visit_children
    7300              :    for recording::get_address_of_lvalue.  */
    7301              : 
    7302              : void
    7303           75 : recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
    7304              : {
    7305           75 :   v->visit (m_lvalue);
    7306           75 : }
    7307              : 
    7308              : /* Implementation of recording::memento::make_debug_string for
    7309              :    getting the address of an lvalue.  */
    7310              : 
    7311              : recording::string *
    7312          358 : recording::get_address_of_lvalue::make_debug_string ()
    7313              : {
    7314          358 :   enum precedence prec = get_precedence ();
    7315          358 :   return string::from_printf (m_ctxt,
    7316              :                               "&%s",
    7317          358 :                               m_lvalue->get_debug_string_parens (prec));
    7318              : }
    7319              : 
    7320              : /* Implementation of recording::memento::write_reproducer for
    7321              :    get_address_of_lvalue.  */
    7322              : 
    7323              : void
    7324          353 : recording::get_address_of_lvalue::write_reproducer (reproducer &r)
    7325              : {
    7326          353 :   const char *id = r.make_identifier (this, "address_of");
    7327          353 :   r.write ("  gcc_jit_rvalue *%s =\n"
    7328              :            "    gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
    7329              :            "                                %s); /* gcc_jit_location *loc */\n",
    7330              :            id,
    7331              :            r.get_identifier_as_lvalue (m_lvalue),
    7332          353 :            r.get_identifier (m_loc));
    7333          353 : }
    7334              : 
    7335              : /* The implementation of class gcc::jit::recording::function_pointer.  */
    7336              : 
    7337              : /* Implementation of pure virtual hook recording::memento::replay_into
    7338              :    for recording::function_pointer.  */
    7339              : 
    7340              : void
    7341           15 : recording::function_pointer::replay_into (replayer *r)
    7342              : {
    7343           30 :   set_playback_obj (
    7344           15 :     m_fn->playback_function ()->
    7345           15 :       get_address (playback_location (r, m_loc)));
    7346           15 : }
    7347              : 
    7348              : void
    7349           15 : recording::function_pointer::visit_children (rvalue_visitor *)
    7350              : {
    7351              :   /* Empty.  */
    7352           15 : }
    7353              : 
    7354              : /* Implementation of recording::memento::make_debug_string for
    7355              :    getting the address of an lvalue.  */
    7356              : 
    7357              : recording::string *
    7358           10 : recording::function_pointer::make_debug_string ()
    7359              : {
    7360           10 :   return string::from_printf (m_ctxt,
    7361              :                               "%s",
    7362           10 :                               m_fn->get_debug_string ());
    7363              : }
    7364              : 
    7365              : /* Implementation of recording::memento::write_reproducer for
    7366              :    function_pointer.  */
    7367              : 
    7368              : void
    7369           10 : recording::function_pointer::write_reproducer (reproducer &r)
    7370              : {
    7371           10 :   const char *id = r.make_identifier (this, "address_of");
    7372           10 :   r.write ("  gcc_jit_rvalue *%s =\n"
    7373              :            "    gcc_jit_function_get_address (%s, /* gcc_jit_function *fn */\n"
    7374              :            "                                  %s); /* gcc_jit_location *loc */\n",
    7375              :            id,
    7376           10 :            r.get_identifier (m_fn),
    7377           10 :            r.get_identifier (m_loc));
    7378           10 : }
    7379              : 
    7380              : /* The implementation of class gcc::jit::recording::local.  */
    7381              : 
    7382              : /* Implementation of pure virtual hook recording::memento::replay_into
    7383              :    for recording::local.  */
    7384              : 
    7385              : void
    7386         2192 : recording::local::replay_into (replayer *r)
    7387              : {
    7388         2192 :   playback::lvalue *obj = m_func->playback_function ()
    7389         2192 :       ->new_local (playback_location (r, m_loc),
    7390         2192 :                    m_type->playback_type (),
    7391              :                    playback_string (m_name),
    7392         2192 :                    m_string_attributes);
    7393              : 
    7394         2192 :   if (m_reg_name != NULL)
    7395            5 :     obj->set_register_name (m_reg_name->c_str ());
    7396              : 
    7397         2192 :   if (m_alignment != 0)
    7398            5 :     obj->set_alignment (m_alignment);
    7399              : 
    7400         2192 :   set_playback_obj (obj);
    7401         2192 : }
    7402              : 
    7403              : /* Override the default implementation of
    7404              :    recording::memento::write_to_dump for locals by writing
    7405              :       TYPE NAME;
    7406              :    for use at the top of the function body as if it were a
    7407              :    declaration.  */
    7408              : 
    7409              : void
    7410           16 : recording::local::write_to_dump (dump &d)
    7411              : {
    7412           16 :   if (d.update_locations ())
    7413           16 :     m_loc = d.make_location ();
    7414           32 :   d.write ("  %s %s;\n",
    7415           16 :            m_type->get_debug_string (),
    7416              :            get_debug_string ());
    7417           16 : }
    7418              : 
    7419              : void
    7420         2779 : recording::local::write_reproducer (reproducer &r)
    7421              : {
    7422         2779 :   const char *id = r.make_identifier (this, "local");
    7423         2779 :   if (m_name)
    7424         5548 :     r.write ("  gcc_jit_lvalue *%s =\n"
    7425              :              "    gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
    7426              :              "                                %s, /* gcc_jit_location *loc */\n"
    7427              :              "                                %s, /* gcc_jit_type *type */\n"
    7428              :              "                                %s); /* const char *name */\n",
    7429              :              id,
    7430         2774 :              r.get_identifier (m_func),
    7431         2774 :              r.get_identifier (m_loc),
    7432              :              r.get_identifier_as_type (m_type),
    7433              :              m_name->get_debug_string ());
    7434              :   else
    7435           10 :     r.write ("  gcc_jit_lvalue *%s =\n"
    7436              :              "    gcc_jit_function_new_temp (%s, /* gcc_jit_function *func */\n"
    7437              :              "                               %s, /* gcc_jit_location *loc */\n"
    7438              :              "                               %s); /* gcc_jit_type *type */\n",
    7439              :              id,
    7440            5 :              r.get_identifier (m_func),
    7441            5 :              r.get_identifier (m_loc),
    7442              :              r.get_identifier_as_type (m_type));
    7443         2779 : }
    7444              : 
    7445              : /* The implementation of class gcc::jit::recording::statement.  */
    7446              : 
    7447              : /* We poison the default implementation of
    7448              :    gcc::jit::recording::statement::get_successor_blocks
    7449              :    since this vfunc must only ever be called on terminator
    7450              :    statements.  */
    7451              : 
    7452              : vec <recording::block *>
    7453            0 : recording::statement::get_successor_blocks () const
    7454              : {
    7455              :   /* The base class implementation is for non-terminating statements,
    7456              :      and thus should never be called.  */
    7457            0 :   gcc_unreachable ();
    7458              :   vec <block *> result;
    7459              :   result.create (0);
    7460              :   return result;
    7461              : }
    7462              : 
    7463              : /* Extend the default implementation of
    7464              :    recording::memento::write_to_dump for statements by (if requested)
    7465              :    updating the location of the statement to the current location in
    7466              :    the dumpfile.  */
    7467              : 
    7468              : void
    7469          156 : recording::statement::write_to_dump (dump &d)
    7470              : {
    7471          156 :   memento::write_to_dump (d);
    7472          156 :   if (d.update_locations ())
    7473          156 :     m_loc = d.make_location ();
    7474          156 : }
    7475              : 
    7476              : /* The implementation of class gcc::jit::recording::eval.  */
    7477              : 
    7478              : /* Implementation of pure virtual hook recording::memento::replay_into
    7479              :    for recording::eval.  */
    7480              : 
    7481              : void
    7482          256 : recording::eval::replay_into (replayer *r)
    7483              : {
    7484          256 :   playback_block (get_block ())
    7485          256 :     ->add_eval (playback_location (r),
    7486          256 :                 m_rvalue->playback_rvalue ());
    7487          256 : }
    7488              : 
    7489              : /* Implementation of recording::memento::make_debug_string for
    7490              :    an eval statement.  */
    7491              : 
    7492              : recording::string *
    7493            8 : recording::eval::make_debug_string ()
    7494              : {
    7495            8 :   return string::from_printf (m_ctxt,
    7496              :                               "(void)%s;",
    7497            8 :                               m_rvalue->get_debug_string ());
    7498              : }
    7499              : 
    7500              : /* Implementation of recording::memento::write_reproducer for
    7501              :    eval statements.  */
    7502              : 
    7503              : void
    7504         1954 : recording::eval::write_reproducer (reproducer &r)
    7505              : {
    7506         1954 :   r.write ("  gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
    7507              :            "                          %s, /* gcc_jit_location *loc */\n"
    7508              :            "                          %s); /* gcc_jit_rvalue *rvalue */\n",
    7509         1954 :            r.get_identifier (get_block ()),
    7510         1954 :            r.get_identifier (get_loc ()),
    7511              :            r.get_identifier_as_rvalue (m_rvalue));
    7512         1954 : }
    7513              : 
    7514              : /* The implementation of class gcc::jit::recording::assignment.  */
    7515              : 
    7516              : /* Implementation of pure virtual hook recording::memento::replay_into
    7517              :    for recording::assignment.  */
    7518              : 
    7519              : void
    7520         4445 : recording::assignment::replay_into (replayer *r)
    7521              : {
    7522         4445 :   playback_block (get_block ())
    7523         8890 :     ->add_assignment (playback_location (r),
    7524         4445 :                       m_lvalue->playback_lvalue (),
    7525         4445 :                       m_rvalue->playback_rvalue ());
    7526         4445 : }
    7527              : 
    7528              : /* Implementation of recording::memento::make_debug_string for
    7529              :    an assignment statement.  */
    7530              : 
    7531              : recording::string *
    7532           60 : recording::assignment::make_debug_string ()
    7533              : {
    7534           60 :   return string::from_printf (m_ctxt,
    7535              :                               "%s = %s;",
    7536           60 :                               m_lvalue->get_debug_string (),
    7537           60 :                               m_rvalue->get_debug_string ());
    7538              : }
    7539              : 
    7540              : /* Implementation of recording::memento::write_reproducer for
    7541              :    assignment statements.  */
    7542              : 
    7543              : void
    7544         2181 : recording::assignment::write_reproducer (reproducer &r)
    7545              : {
    7546         2181 :   r.write ("  gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
    7547              :            "                                %s, /* gcc_jit_location *loc */\n"
    7548              :            "                                %s, /* gcc_jit_lvalue *lvalue */\n"
    7549              :            "                                %s); /* gcc_jit_rvalue *rvalue */\n",
    7550         2181 :            r.get_identifier (get_block ()),
    7551         2181 :            r.get_identifier (get_loc ()),
    7552              :            r.get_identifier_as_lvalue (m_lvalue),
    7553              :            r.get_identifier_as_rvalue (m_rvalue));
    7554         2181 : }
    7555              : 
    7556              : /* The implementation of class gcc::jit::recording::assignment_op.  */
    7557              : 
    7558              : /* Implementation of pure virtual hook recording::memento::replay_into
    7559              :    for recording::assignment_op.  */
    7560              : 
    7561              : void
    7562          484 : recording::assignment_op::replay_into (replayer *r)
    7563              : {
    7564          484 :   playback::type *result_type =
    7565          484 :     m_lvalue->playback_lvalue ()->get_type ();
    7566              : 
    7567          484 :   playback::rvalue *binary_op =
    7568          484 :     r->new_binary_op (playback_location (r),
    7569              :                       m_op,
    7570              :                       result_type,
    7571          484 :                       m_lvalue->playback_rvalue (),
    7572          484 :                       m_rvalue->playback_rvalue ());
    7573              : 
    7574          484 :   playback_block (get_block ())
    7575          484 :     ->add_assignment (playback_location (r),
    7576          484 :                       m_lvalue->playback_lvalue (),
    7577              :                       binary_op);
    7578          484 : }
    7579              : 
    7580              : /* Implementation of recording::memento::make_debug_string for
    7581              :    an assignment_op statement.  */
    7582              : 
    7583              : recording::string *
    7584            0 : recording::assignment_op::make_debug_string ()
    7585              : {
    7586            0 :   return string::from_printf (m_ctxt,
    7587              :                               "%s %s= %s;",
    7588            0 :                               m_lvalue->get_debug_string (),
    7589            0 :                               binary_op_strings[m_op],
    7590            0 :                               m_rvalue->get_debug_string ());
    7591              : }
    7592              : 
    7593              : /* Implementation of recording::memento::write_reproducer for
    7594              :    assignment_op statements.  */
    7595              : 
    7596              : void
    7597          210 : recording::assignment_op::write_reproducer (reproducer &r)
    7598              : {
    7599          420 :   r.write ("  gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
    7600              :            "                                   %s, /* gcc_jit_location *loc */\n"
    7601              :            "                                   %s, /* gcc_jit_lvalue *lvalue */\n"
    7602              :            "                                   %s, /* enum gcc_jit_binary_op op */\n"
    7603              :            "                                   %s); /* gcc_jit_rvalue *rvalue */\n",
    7604          210 :            r.get_identifier (get_block ()),
    7605          210 :            r.get_identifier (get_loc ()),
    7606              :            r.get_identifier_as_lvalue (m_lvalue),
    7607          210 :            binary_op_reproducer_strings[m_op],
    7608              :            r.get_identifier_as_rvalue (m_rvalue));
    7609          210 : }
    7610              : 
    7611              : /* The implementation of class gcc::jit::recording::comment.  */
    7612              : 
    7613              : /* Implementation of pure virtual hook recording::memento::replay_into
    7614              :    for recording::comment.  */
    7615              : 
    7616              : void
    7617          458 : recording::comment::replay_into (replayer *r)
    7618              : {
    7619          458 :   playback_block (get_block ())
    7620          458 :     ->add_comment (playback_location (r),
    7621          458 :                    m_text->c_str ());
    7622          458 : }
    7623              : 
    7624              : /* Implementation of recording::memento::make_debug_string for
    7625              :    a comment "statement".  */
    7626              : 
    7627              : recording::string *
    7628           44 : recording::comment::make_debug_string ()
    7629              : {
    7630           44 :   return string::from_printf (m_ctxt,
    7631              :                               "/* %s */",
    7632           44 :                               m_text->c_str ());
    7633              : }
    7634              : 
    7635              : /* Implementation of recording::memento::write_reproducer for
    7636              :    comments.  */
    7637              : 
    7638              : void
    7639          248 : recording::comment::write_reproducer (reproducer &r)
    7640              : {
    7641          248 :   r.write ("  gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
    7642              :            "                             %s, /* gcc_jit_location *loc */\n"
    7643              :            "                             %s); /* const char *text */\n",
    7644          248 :            r.get_identifier (get_block ()),
    7645          248 :            r.get_identifier (get_loc ()),
    7646          248 :            m_text->get_debug_string ());
    7647          248 : }
    7648              : 
    7649              : /* The implementation of class gcc::jit::recording::conditional.  */
    7650              : 
    7651              : /* Implementation of pure virtual hook recording::memento::replay_into
    7652              :    for recording::conditional.  */
    7653              : 
    7654              : void
    7655          879 : recording::conditional::replay_into (replayer *r)
    7656              : {
    7657          879 :   playback_block (get_block ())
    7658          879 :     ->add_conditional (playback_location (r),
    7659          879 :                        m_boolval->playback_rvalue (),
    7660              :                        playback_block (m_on_true),
    7661              :                        playback_block (m_on_false));
    7662          879 : }
    7663              : 
    7664              : /* Override the poisoned default implementation of
    7665              :    gcc::jit::recording::statement::get_successor_blocks
    7666              : 
    7667              :    A conditional jump has 2 successor blocks.  */
    7668              : 
    7669              : vec <recording::block *>
    7670          879 : recording::conditional::get_successor_blocks () const
    7671              : {
    7672          879 :   vec <block *> result;
    7673          879 :   result.create (2);
    7674          879 :   result.quick_push (m_on_true);
    7675          879 :   result.quick_push (m_on_false);
    7676          879 :   return result;
    7677              : }
    7678              : 
    7679              : /* Implementation of recording::memento::make_debug_string for
    7680              :    a conditional jump statement.  */
    7681              : 
    7682              : recording::string *
    7683           16 : recording::conditional::make_debug_string ()
    7684              : {
    7685           16 :   if (m_on_false)
    7686           32 :     return string::from_printf (m_ctxt,
    7687              :                                 "if (%s) goto %s; else goto %s;",
    7688           16 :                                 m_boolval->get_debug_string (),
    7689           16 :                                 m_on_true->get_debug_string (),
    7690           16 :                                 m_on_false->get_debug_string ());
    7691              :   else
    7692            0 :     return string::from_printf (m_ctxt,
    7693              :                                 "if (%s) goto %s;",
    7694            0 :                                 m_boolval->get_debug_string (),
    7695            0 :                                 m_on_true->get_debug_string ());
    7696              : }
    7697              : 
    7698              : /* Implementation of recording::memento::write_reproducer for
    7699              :    conditional statements.  */
    7700              : 
    7701              : void
    7702          336 : recording::conditional::write_reproducer (reproducer &r)
    7703              : {
    7704          336 :   r.write ("  gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
    7705              :            "                                      %s, /* gcc_jit_location *loc */\n"
    7706              :            "                                      %s, /* gcc_jit_rvalue *boolval */\n"
    7707              :            "                                      %s, /* gcc_jit_block *on_true */\n"
    7708              :            "                                      %s); /* gcc_jit_block *on_false */\n",
    7709          336 :            r.get_identifier (get_block ()),
    7710          336 :            r.get_identifier (get_loc ()),
    7711              :            r.get_identifier_as_rvalue (m_boolval),
    7712          336 :            r.get_identifier (m_on_true),
    7713          336 :            r.get_identifier (m_on_false));
    7714          336 : }
    7715              : 
    7716              : /* The implementation of class gcc::jit::recording::jump.  */
    7717              : 
    7718              : /* Implementation of pure virtual hook recording::memento::replay_into
    7719              :    for recording::jump.  */
    7720              : 
    7721              : void
    7722         1202 : recording::jump::replay_into (replayer *r)
    7723              : {
    7724         1202 :   playback_block (get_block ())
    7725         1202 :     ->add_jump (playback_location (r),
    7726         1202 :                 m_target->playback_block ());
    7727         1202 : }
    7728              : 
    7729              : /* Override the poisoned default implementation of
    7730              :    gcc::jit::recording::statement::get_successor_blocks
    7731              : 
    7732              :    An unconditional jump has 1 successor block.  */
    7733              : 
    7734              : vec <recording::block *>
    7735         1202 : recording::jump::get_successor_blocks () const
    7736              : {
    7737         1202 :   vec <block *> result;
    7738         1202 :   result.create (1);
    7739         1202 :   result.quick_push (m_target);
    7740         1202 :   return result;
    7741              : }
    7742              : 
    7743              : /* Implementation of recording::memento::make_debug_string for
    7744              :    a unconditional jump statement.  */
    7745              : 
    7746              : recording::string *
    7747            0 : recording::jump::make_debug_string ()
    7748              : {
    7749            0 :   return string::from_printf (m_ctxt,
    7750              :                               "goto %s;",
    7751            0 :                               m_target->get_debug_string ());
    7752              : }
    7753              : 
    7754              : /* Implementation of recording::memento::write_reproducer for
    7755              :    jump statements.  */
    7756              : 
    7757              : void
    7758          245 : recording::jump::write_reproducer (reproducer &r)
    7759              : {
    7760          245 :   r.write ("  gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
    7761              :            "                               %s, /* gcc_jit_location *loc */\n"
    7762              :            "                               %s); /* gcc_jit_block *target */\n",
    7763          245 :            r.get_identifier (get_block ()),
    7764          245 :            r.get_identifier (get_loc ()),
    7765          245 :            r.get_identifier (m_target));
    7766          245 : }
    7767              : 
    7768              : /* The implementation of class gcc::jit::recording::return_.  */
    7769              : 
    7770              : /* Implementation of pure virtual hook recording::memento::replay_into
    7771              :    for recording::return_.  */
    7772              : 
    7773              : void
    7774         3702 : recording::return_::replay_into (replayer *r)
    7775              : {
    7776         3702 :   playback_block (get_block ())
    7777         7404 :     ->add_return (playback_location (r),
    7778         3702 :                   m_rvalue ? m_rvalue->playback_rvalue () : NULL);
    7779         3702 : }
    7780              : 
    7781              : /* Override the poisoned default implementation of
    7782              :    gcc::jit::recording::statement::get_successor_blocks
    7783              : 
    7784              :    A return statement has no successor block.  */
    7785              : 
    7786              : vec <recording::block *>
    7787         3872 : recording::return_::get_successor_blocks () const
    7788              : {
    7789         3872 :   vec <block *> result;
    7790         3872 :   result.create (0);
    7791         3872 :   return result;
    7792              : }
    7793              : 
    7794              : /* Implementation of recording::memento::make_debug_string for
    7795              :    a return statement (covers both those with and without rvalues).  */
    7796              : 
    7797              : recording::string *
    7798           48 : recording::return_::make_debug_string ()
    7799              : {
    7800           48 :   if (m_rvalue)
    7801           39 :     return string::from_printf (m_ctxt,
    7802              :                                 "return %s;",
    7803           39 :                                 m_rvalue->get_debug_string ());
    7804              :   else
    7805            9 :     return string::from_printf (m_ctxt,
    7806            9 :                                 "return;");
    7807              : }
    7808              : 
    7809              : /* Implementation of recording::memento::write_reproducer for
    7810              :    return statements.  */
    7811              : 
    7812              : void
    7813         2628 : recording::return_::write_reproducer (reproducer &r)
    7814              : {
    7815         2628 :   if (m_rvalue)
    7816         2090 :     r.write ("  gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
    7817              :              "                                 %s, /* gcc_jit_location *loc */\n"
    7818              :              "                                 %s); /* gcc_jit_rvalue *rvalue */\n",
    7819         2090 :              r.get_identifier (get_block ()),
    7820         2090 :              r.get_identifier (get_loc ()),
    7821              :              r.get_identifier_as_rvalue (m_rvalue));
    7822              :   else
    7823          538 :     r.write ("  gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
    7824              :              "                                      %s); /* gcc_jit_location *loc */\n",
    7825          538 :              r.get_identifier (get_block ()),
    7826          538 :              r.get_identifier (get_loc ()));
    7827         2628 : }
    7828              : 
    7829              : /* The implementation of class gcc::jit::recording::case_.  */
    7830              : 
    7831              : void
    7832           75 : recording::case_::write_reproducer (reproducer &r)
    7833              : {
    7834           75 :   const char *id = r.make_identifier (this, "case");
    7835           75 :   const char *fmt =
    7836              :     "  gcc_jit_case *%s = \n"
    7837              :     "    gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
    7838              :     "                              %s, /* gcc_jit_rvalue *min_value */\n"
    7839              :     "                              %s, /* gcc_jit_rvalue *max_value */\n"
    7840              :     "                              %s); /* gcc_jit_block *dest_block */\n";
    7841           75 :   r.write (fmt,
    7842              :            id,
    7843              :            r.get_identifier (get_context ()),
    7844              :            r.get_identifier_as_rvalue (m_min_value),
    7845              :            r.get_identifier_as_rvalue (m_max_value),
    7846           75 :            r.get_identifier (m_dest_block));
    7847           75 : }
    7848              : 
    7849              : recording::string *
    7850           75 : recording::case_::make_debug_string ()
    7851              : {
    7852           75 :   return string::from_printf (get_context (),
    7853              :                               "case %s ... %s: goto %s;",
    7854           75 :                               m_min_value->get_debug_string (),
    7855           75 :                               m_max_value->get_debug_string (),
    7856           75 :                               m_dest_block->get_debug_string ());
    7857              : }
    7858              : 
    7859              : /* The implementation of class gcc::jit::recording::switch_.  */
    7860              : 
    7861              : /* gcc::jit::recording::switch_'s constructor.  */
    7862              : 
    7863           20 : recording::switch_::switch_ (block *b,
    7864              :                              location *loc,
    7865              :                              rvalue *expr,
    7866              :                              block *default_block,
    7867              :                              int num_cases,
    7868           20 :                              case_ **cases)
    7869              : : statement (b, loc),
    7870           20 :   m_expr (expr),
    7871           20 :   m_default_block (default_block)
    7872              : {
    7873           20 :   m_cases.reserve_exact (num_cases);
    7874          100 :   for (int i = 0; i< num_cases; i++)
    7875           80 :     m_cases.quick_push (cases[i]);
    7876           20 : }
    7877              : 
    7878              : /* Implementation of pure virtual hook recording::memento::replay_into
    7879              :    for recording::switch_.  */
    7880              : 
    7881              : void
    7882           20 : recording::switch_::replay_into (replayer *r)
    7883              : {
    7884           20 :   auto_vec <playback::case_> pcases;
    7885           20 :   int i;
    7886           20 :   recording::case_ *rcase;
    7887           40 :   pcases.reserve_exact (m_cases.length ());
    7888          100 :   FOR_EACH_VEC_ELT (m_cases, i, rcase)
    7889              :     {
    7890           80 :       playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (),
    7891              :                              rcase->get_max_value ()->playback_rvalue (),
    7892           80 :                              rcase->get_dest_block ()->playback_block ());
    7893           80 :       pcases.safe_push (pcase);
    7894              :     }
    7895           20 :   playback_block (get_block ())
    7896           40 :     ->add_switch (playback_location (r),
    7897           20 :                   m_expr->playback_rvalue (),
    7898           20 :                   m_default_block->playback_block (),
    7899              :                   &pcases);
    7900           20 : }
    7901              : 
    7902              : /* Override the poisoned default implementation of
    7903              :    gcc::jit::recording::statement::get_successor_blocks
    7904              : 
    7905              :    A switch statement has (NUM_CASES + 1) successor blocks.  */
    7906              : 
    7907              : vec <recording::block *>
    7908           20 : recording::switch_::get_successor_blocks () const
    7909              : {
    7910           20 :   vec <block *> result;
    7911           40 :   result.create (m_cases.length () + 1);
    7912           20 :   result.quick_push (m_default_block);
    7913           20 :   int i;
    7914           20 :   case_ *c;
    7915          120 :   FOR_EACH_VEC_ELT (m_cases, i, c)
    7916           80 :     result.quick_push (c->get_dest_block ());
    7917           20 :   return result;
    7918              : }
    7919              : 
    7920              : /* Implementation of recording::memento::make_debug_string for
    7921              :    a switch statement.  */
    7922              : 
    7923              : recording::string *
    7924           15 : recording::switch_::make_debug_string ()
    7925              : {
    7926           15 :   auto_vec <char> cases_str;
    7927           15 :   int i;
    7928           15 :   case_ *c;
    7929           75 :   FOR_EACH_VEC_ELT (m_cases, i, c)
    7930              :     {
    7931           60 :       size_t len = strlen (c->get_debug_string ());
    7932           60 :       unsigned idx = cases_str.length ();
    7933           60 :       cases_str.safe_grow (idx + 1 + len, true);
    7934           60 :       cases_str[idx] = ' ';
    7935           60 :       memcpy (&(cases_str[idx + 1]),
    7936           60 :               c->get_debug_string (),
    7937              :               len);
    7938              :     }
    7939           15 :   cases_str.safe_push ('\0');
    7940              : 
    7941           30 :   return string::from_printf (m_ctxt,
    7942              :                               "switch (%s) {default: goto %s;%s}",
    7943           15 :                               m_expr->get_debug_string (),
    7944           15 :                               m_default_block->get_debug_string (),
    7945           15 :                               &cases_str[0]);
    7946           15 : }
    7947              : 
    7948              : /* Implementation of recording::memento::write_reproducer for
    7949              :    switch statements.  */
    7950              : 
    7951              : void
    7952           15 : recording::switch_::write_reproducer (reproducer &r)
    7953              : {
    7954           15 :   r.make_identifier (this, "switch");
    7955           15 :   int i;
    7956           15 :   case_ *c;
    7957           15 :   const char *cases_id =
    7958           15 :     r.make_tmp_identifier ("cases_for", this);
    7959           15 :   r.write ("  gcc_jit_case *%s[%i] = {\n",
    7960              :            cases_id,
    7961              :            m_cases.length ());
    7962           90 :   FOR_EACH_VEC_ELT (m_cases, i, c)
    7963           60 :     r.write ("    %s,\n", r.get_identifier (c));
    7964           15 :   r.write ("  };\n");
    7965           15 :   const char *fmt =
    7966              :     "  gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
    7967              :     "                                 %s, /* gcc_jit_location *loc */\n"
    7968              :     "                                 %s, /* gcc_jit_rvalue *expr */\n"
    7969              :     "                                 %s, /* gcc_jit_block *default_block */\n"
    7970              :     "                                 %i, /* int num_cases */\n"
    7971              :     "                                 %s); /* gcc_jit_case **cases */\n";
    7972           30 :     r.write (fmt,
    7973           15 :              r.get_identifier (get_block ()),
    7974           15 :              r.get_identifier (get_loc ()),
    7975              :              r.get_identifier_as_rvalue (m_expr),
    7976           15 :              r.get_identifier (m_default_block),
    7977              :              m_cases.length (),
    7978              :              cases_id);
    7979           15 : }
    7980              : 
    7981              : /* class asm_operand : public memento.  */
    7982              : 
    7983          100 : recording::asm_operand::asm_operand (extended_asm *ext_asm,
    7984              :                                      string *asm_symbolic_name,
    7985          100 :                                      string *constraint)
    7986              : : memento (ext_asm->get_context ()),
    7987          100 :   m_ext_asm (ext_asm),
    7988          100 :   m_asm_symbolic_name (asm_symbolic_name),
    7989          100 :   m_constraint (constraint)
    7990              : {
    7991          100 : }
    7992              : 
    7993              : void
    7994          100 : recording::asm_operand::print (pretty_printer *pp) const
    7995              : {
    7996          100 :   if (m_asm_symbolic_name)
    7997              :     {
    7998           20 :       pp_character (pp, '[');
    7999           20 :       pp_string (pp, m_asm_symbolic_name->c_str ());
    8000           20 :       pp_character (pp, ']');
    8001           20 :       pp_space (pp);
    8002              :     }
    8003          100 :   pp_string (pp, m_constraint->get_debug_string ());
    8004              :   /* Subclass will add lvalue/rvalue.  */
    8005          100 : }
    8006              : 
    8007              : recording::string *
    8008            0 : recording::asm_operand::make_debug_string ()
    8009              : {
    8010            0 :   pretty_printer pp;
    8011            0 :   print (&pp);
    8012            0 :   return m_ctxt->new_string (pp_formatted_text (&pp), false);
    8013            0 : }
    8014              : 
    8015              : /* class output_asm_operand : public asm_operand.  */
    8016              : 
    8017              : void
    8018           40 : recording::output_asm_operand::write_reproducer (reproducer &r)
    8019              : {
    8020           40 :   const char *fmt =
    8021              :     "  gcc_jit_extended_asm_add_output_operand (%s, /* gcc_jit_extended_asm *ext_asm */\n"
    8022              :     "                                           %s, /* const char *asm_symbolic_name */\n"
    8023              :     "                                           %s, /* const char *constraint */\n"
    8024              :     "                                           %s); /* gcc_jit_lvalue *dest */\n";
    8025           40 :   r.write (fmt,
    8026           40 :            r.get_identifier (m_ext_asm),
    8027           40 :            (m_asm_symbolic_name
    8028           10 :             ? m_asm_symbolic_name->get_debug_string () : "NULL"),
    8029           40 :            m_constraint->get_debug_string (),
    8030           40 :            r.get_identifier (m_dest));
    8031           40 : }
    8032              : 
    8033              : void
    8034           40 : recording::output_asm_operand::print (pretty_printer *pp) const
    8035              : {
    8036           40 :   asm_operand::print (pp);
    8037           40 :   pp_string (pp, " (");
    8038           40 :   pp_string (pp, m_dest->get_debug_string ());
    8039           40 :   pp_string (pp, ")");
    8040           40 : }
    8041              : 
    8042              : /* class input_asm_operand : public asm_operand.  */
    8043              : 
    8044              : void
    8045           60 : recording::input_asm_operand::write_reproducer (reproducer &r)
    8046              : {
    8047           60 :   const char *fmt =
    8048              :     "  gcc_jit_extended_asm_add_input_operand (%s, /* gcc_jit_extended_asm *ext_asm */\n"
    8049              :     "                                          %s, /* const char *asm_symbolic_name */\n"
    8050              :     "                                          %s, /* const char *constraint */\n"
    8051              :     "                                          %s); /* gcc_jit_rvalue *src */\n";
    8052          120 :   r.write (fmt,
    8053           60 :            r.get_identifier (m_ext_asm),
    8054           60 :            (m_asm_symbolic_name
    8055           10 :             ? m_asm_symbolic_name->get_debug_string () : "NULL"),
    8056           60 :            m_constraint->get_debug_string (),
    8057              :            r.get_identifier_as_rvalue (m_src));
    8058           60 : }
    8059              : 
    8060              : void
    8061           60 : recording::input_asm_operand::print (pretty_printer *pp) const
    8062              : {
    8063           60 :   asm_operand::print (pp);
    8064           60 :   pp_string (pp, " (");
    8065           60 :   pp_string (pp, m_src->get_debug_string ());
    8066           60 :   pp_string (pp, ")");
    8067           60 : }
    8068              : 
    8069              : /* The implementation of class gcc::jit::recording::extended_asm.  */
    8070              : 
    8071              : void
    8072           40 : recording::extended_asm::add_output_operand (const char *asm_symbolic_name,
    8073              :                                              const char *constraint,
    8074              :                                              lvalue *dest)
    8075              : {
    8076           40 :   output_asm_operand *op
    8077              :     = new output_asm_operand (this,
    8078              :                               new_string (asm_symbolic_name),
    8079              :                               new_string (constraint),
    8080           40 :                               dest);
    8081           40 :   m_ctxt->record (op);
    8082           40 :   m_output_ops.safe_push (op);
    8083           40 : }
    8084              : 
    8085              : void
    8086           60 : recording::extended_asm::add_input_operand (const char *asm_symbolic_name,
    8087              :                                             const char *constraint,
    8088              :                                             rvalue *src)
    8089              : {
    8090           60 :   input_asm_operand *op
    8091              :     = new input_asm_operand (this,
    8092              :                              new_string (asm_symbolic_name),
    8093              :                              new_string (constraint),
    8094           60 :                              src);
    8095           60 :   m_ctxt->record (op);
    8096           60 :   m_input_ops.safe_push (op);
    8097           60 : }
    8098              : 
    8099              : void
    8100           50 : recording::extended_asm::add_clobber (const char *victim)
    8101              : {
    8102           50 :   m_clobbers.safe_push (new_string (victim));
    8103           50 : }
    8104              : 
    8105              : /* Implementation of recording::memento::replay_into
    8106              :    for recording::extended_asm.  */
    8107              : 
    8108              : void
    8109           70 : recording::extended_asm::replay_into (replayer *r)
    8110              : {
    8111           70 :   auto_vec<playback::asm_operand> playback_output_ops;
    8112           70 :   auto_vec<playback::asm_operand> playback_input_ops;
    8113           70 :   auto_vec<const char *> playback_clobbers;
    8114           70 :   auto_vec<playback::block *> playback_goto_blocks;
    8115              : 
    8116              :   /* Populate outputs.  */
    8117           70 :   {
    8118           70 :     output_asm_operand *rec_asm_op;
    8119           70 :     unsigned i;
    8120          110 :     FOR_EACH_VEC_ELT (m_output_ops, i, rec_asm_op)
    8121              :       {
    8122           40 :         playback::asm_operand playback_asm_op
    8123              :           (rec_asm_op->get_symbolic_name (),
    8124              :            rec_asm_op->get_constraint (),
    8125           50 :            rec_asm_op->get_lvalue ()->playback_lvalue ()->as_tree ());
    8126           40 :         playback_output_ops.safe_push (playback_asm_op);
    8127              :       }
    8128              :   }
    8129              : 
    8130              :   /* Populate inputs.  */
    8131              :   {
    8132              :     input_asm_operand *rec_asm_op;
    8133              :     unsigned i;
    8134          130 :     FOR_EACH_VEC_ELT (m_input_ops, i, rec_asm_op)
    8135              :       {
    8136           60 :         playback::asm_operand playback_asm_op
    8137              :           (rec_asm_op->get_symbolic_name (),
    8138              :            rec_asm_op->get_constraint (),
    8139           70 :            rec_asm_op->get_rvalue ()->playback_rvalue ()->as_tree ());
    8140           60 :         playback_input_ops.safe_push (playback_asm_op);
    8141              :       }
    8142              :   }
    8143              : 
    8144              :   /* Populate clobbers.  */
    8145              :   {
    8146              :     string *rec_clobber;
    8147              :     unsigned i;
    8148          120 :     FOR_EACH_VEC_ELT (m_clobbers, i, rec_clobber)
    8149           50 :       playback_clobbers.safe_push (rec_clobber->c_str ());
    8150              :   }
    8151              : 
    8152              :   /* Populate playback blocks if an "asm goto".  */
    8153           70 :   maybe_populate_playback_blocks (&playback_goto_blocks);
    8154              : 
    8155           70 :   playback_block (get_block ())
    8156          140 :     ->add_extended_asm (playback_location (r),
    8157           70 :                         m_asm_template->c_str (),
    8158           70 :                         m_is_volatile, m_is_inline,
    8159              :                         &playback_output_ops,
    8160              :                         &playback_input_ops,
    8161              :                         &playback_clobbers,
    8162              :                         &playback_goto_blocks);
    8163           70 : }
    8164              : 
    8165              : /* Implementation of recording::memento::make_debug_string for
    8166              :    an extended_asm "statement".  */
    8167              : 
    8168              : recording::string *
    8169           70 : recording::extended_asm::make_debug_string ()
    8170              : {
    8171           70 :   pretty_printer pp;
    8172           70 :   pp_string (&pp, "asm ");
    8173           70 :   if (m_is_volatile)
    8174           20 :     pp_string (&pp, "volatile ");
    8175           70 :   if (m_is_inline)
    8176            0 :     pp_string (&pp, "inline ");
    8177           70 :   if (is_goto ())
    8178           20 :     pp_string (&pp, "goto ");
    8179           70 :   pp_character (&pp, '(');
    8180           70 :   pp_string (&pp, m_asm_template->get_debug_string ());
    8181           70 :   pp_string (&pp, " : ");
    8182           70 :   unsigned i;
    8183           70 :   {
    8184           70 :     output_asm_operand *asm_op;
    8185          180 :     FOR_EACH_VEC_ELT (m_output_ops, i, asm_op)
    8186              :       {
    8187           40 :         if (i > 0)
    8188            0 :           pp_string (&pp, ", ");
    8189           40 :         asm_op->print (&pp);
    8190              :       }
    8191              :   }
    8192           70 :   pp_string (&pp, " : ");
    8193           70 :   {
    8194           70 :     input_asm_operand *asm_op;
    8195          200 :     FOR_EACH_VEC_ELT (m_input_ops, i, asm_op)
    8196              :       {
    8197           60 :         if (i > 0)
    8198           20 :           pp_string (&pp, ", ");
    8199           60 :         asm_op->print (&pp);
    8200              :       }
    8201              :   }
    8202           70 :   pp_string (&pp, " : ");
    8203           70 :   string *rec_clobber;
    8204          190 :   FOR_EACH_VEC_ELT (m_clobbers, i, rec_clobber)
    8205              :       {
    8206           50 :         if (i > 0)
    8207            0 :           pp_string (&pp, ", ");
    8208           50 :         pp_string (&pp, rec_clobber->get_debug_string ());
    8209              :       }
    8210           70 :   maybe_print_gotos (&pp);
    8211           70 :   pp_character (&pp, ')');
    8212           70 :   return new_string (pp_formatted_text (&pp));
    8213           70 : }
    8214              : 
    8215              : void
    8216           70 : recording::extended_asm::write_flags (reproducer &r)
    8217              : {
    8218           70 :   if (m_is_volatile)
    8219           20 :     r.write ("  gcc_jit_extended_asm_set_volatile_flag (%s, 1);\n",
    8220              :              r.get_identifier (this));
    8221           70 :   if (m_is_inline)
    8222            0 :     r.write ("  gcc_jit_extended_asm_set_inline_flag (%s, 1);\n",
    8223              :              r.get_identifier (this));
    8224           70 : }
    8225              : 
    8226              : void
    8227           70 : recording::extended_asm::write_clobbers (reproducer &r)
    8228              : {
    8229           70 :   string *clobber;
    8230           70 :   unsigned i;
    8231          120 :   FOR_EACH_VEC_ELT (m_clobbers, i, clobber)
    8232           50 :     r.write ("  gcc_jit_extended_asm_add_clobber (%s, %s);\n",
    8233              :              r.get_identifier (this),
    8234              :              clobber->get_debug_string ());
    8235           70 : }
    8236              : 
    8237              : /* Implementation of recording::memento::write_reproducer for
    8238              :    extended_asm_simple.  */
    8239              : 
    8240              : void
    8241           50 : recording::extended_asm_simple::write_reproducer (reproducer &r)
    8242              : {
    8243           50 :   const char *id = r.make_identifier (this, "extended_asm");
    8244           50 :   r.write ("  gcc_jit_extended_asm *%s =\n"
    8245              :            "    gcc_jit_block_add_extended_asm (%s, /*gcc_jit_block *block */\n"
    8246              :            "                                    %s, /* gcc_jit_location *loc */\n"
    8247              :            "                                    %s); /* const char *asm_template */\n",
    8248              :            id,
    8249           50 :            r.get_identifier (get_block ()),
    8250           50 :            r.get_identifier (get_loc ()),
    8251           50 :            m_asm_template->get_debug_string ());
    8252           50 :   write_flags (r);
    8253           50 :   write_clobbers (r);
    8254           50 : }
    8255              : 
    8256              : void
    8257            0 : recording::extended_asm::
    8258              : maybe_populate_playback_blocks (auto_vec <playback::block *> *)
    8259              : {
    8260              :   /* Do nothing; not an "asm goto".  */
    8261            0 : }
    8262              : 
    8263              : /* The implementation of class gcc::jit::recording::extended_asm_goto.  */
    8264              : 
    8265              : /* recording::extended_asm_goto's ctor.  */
    8266              : 
    8267           20 : recording::extended_asm_goto::extended_asm_goto (block *b,
    8268              :                                                  location *loc,
    8269              :                                                  string *asm_template,
    8270              :                                                  int num_goto_blocks,
    8271              :                                                  block **goto_blocks,
    8272           20 :                                                  block *fallthrough_block)
    8273              : : extended_asm (b, loc, asm_template),
    8274           40 :   m_goto_blocks (num_goto_blocks),
    8275           20 :   m_fallthrough_block (fallthrough_block)
    8276              : {
    8277           40 :   for (int i = 0; i < num_goto_blocks; i++)
    8278           20 :     m_goto_blocks.quick_push (goto_blocks[i]);
    8279           20 : }
    8280              : 
    8281              : /* Implementation of recording::memento::replay_into
    8282              :    for recording::extended_asm_goto.  */
    8283              : 
    8284              : void
    8285           20 : recording::extended_asm_goto::replay_into (replayer *r)
    8286              : {
    8287              :   /* Chain up to base class impl.  */
    8288           20 :   recording::extended_asm::replay_into (r);
    8289              : 
    8290              :   /* ...and potentially add a goto for the fallthrough.  */
    8291           20 :   if (m_fallthrough_block)
    8292           20 :     playback_block (get_block ())
    8293           20 :       ->add_jump (playback_location (r),
    8294           20 :                   m_fallthrough_block->playback_block ());
    8295           20 : }
    8296              : 
    8297              : /* Implementation of recording::memento::write_reproducer for
    8298              :    extended_asm_goto.  */
    8299              : 
    8300              : void
    8301           20 : recording::extended_asm_goto::write_reproducer (reproducer &r)
    8302              : {
    8303           20 :   const char *id = r.make_identifier (this, "extended_asm");
    8304           20 :   const char *blocks_id = r.make_tmp_identifier ("blocks_for", this);
    8305           20 :   r.write ("  gcc_jit_block *%s[%i] = {\n",
    8306              :            blocks_id,
    8307              :            m_goto_blocks.length ());
    8308           20 :   int i;
    8309           20 :   block *b;
    8310           60 :   FOR_EACH_VEC_ELT (m_goto_blocks, i, b)
    8311           20 :     r.write ("    %s,\n", r.get_identifier (b));
    8312           20 :   r.write ("  };\n");
    8313           40 :   r.write ("  gcc_jit_extended_asm *%s =\n"
    8314              :            "    gcc_jit_block_end_with_extended_asm_goto (%s, /*gcc_jit_block *block */\n"
    8315              :            "                                              %s, /* gcc_jit_location *loc */\n"
    8316              :            "                                              %s, /* const char *asm_template */\n"
    8317              :            "                                              %i, /* int num_goto_blocks */\n"
    8318              :            "                                              %s, /* gcc_jit_block **goto_blocks */\n"
    8319              :            "                                              %s); /* gcc_jit_block *fallthrough_block */\n",
    8320              :            id,
    8321           20 :            r.get_identifier (get_block ()),
    8322           20 :            r.get_identifier (get_loc ()),
    8323           20 :            m_asm_template->get_debug_string (),
    8324              :            m_goto_blocks.length (),
    8325              :            blocks_id,
    8326           20 :            (m_fallthrough_block
    8327           20 :             ? r.get_identifier (m_fallthrough_block)
    8328              :             : "NULL"));
    8329           20 :   write_flags (r);
    8330           20 :   write_clobbers (r);
    8331           20 : }
    8332              : 
    8333              : /* Override the poisoned default implementation of
    8334              :    gcc::jit::recording::statement::get_successor_blocks
    8335              : 
    8336              :    An extended_asm_goto can jump to the m_goto_blocks, and to
    8337              :    the (optional) m_fallthrough_block.  */
    8338              : 
    8339              : vec <recording::block *>
    8340           20 : recording::extended_asm_goto::get_successor_blocks () const
    8341              : {
    8342           20 :   vec <block *> result;
    8343           40 :   result.create (m_goto_blocks.length () + 1);
    8344           20 :   if (m_fallthrough_block)
    8345           20 :     result.quick_push (m_fallthrough_block);
    8346           20 :   result.splice (m_goto_blocks);
    8347           20 :   return result;
    8348              : }
    8349              : 
    8350              : /* Vfunc for use by recording::extended_asm::make_debug_string.  */
    8351              : 
    8352              : void
    8353           20 : recording::extended_asm_goto::maybe_print_gotos (pretty_printer *pp) const
    8354              : {
    8355           20 :   pp_string (pp, " : ");
    8356           20 :   unsigned i;
    8357           20 :   block *b;
    8358           60 :   FOR_EACH_VEC_ELT (m_goto_blocks, i, b)
    8359              :     {
    8360           20 :       if (i > 0)
    8361            0 :         pp_string (pp, ", ");
    8362           20 :       pp_string (pp, b->get_debug_string ());
    8363              :     }
    8364              :   /* Non-C syntax here.  */
    8365           20 :   if (m_fallthrough_block)
    8366           20 :     pp_printf (pp, " [fallthrough: %s]",
    8367              :                m_fallthrough_block->get_debug_string ());
    8368           20 : }
    8369              : 
    8370              : /* Vfunc for use by recording::extended_asm::replay_into.  */
    8371              : 
    8372              : void
    8373           20 : recording::extended_asm_goto::
    8374              : maybe_populate_playback_blocks (auto_vec <playback::block *> *out)
    8375              : {
    8376           20 :   unsigned i;
    8377           20 :   block *b;
    8378           40 :   FOR_EACH_VEC_ELT (m_goto_blocks, i, b)
    8379           20 :     out->safe_push (b->playback_block ());
    8380           20 : }
    8381              : 
    8382              : /* class top_level_asm : public memento.  */
    8383              : 
    8384           10 : recording::top_level_asm::top_level_asm (context *ctxt,
    8385              :                                          location *loc,
    8386           10 :                                          string *asm_stmts)
    8387              : : memento (ctxt),
    8388           10 :   m_loc (loc),
    8389           10 :   m_asm_stmts (asm_stmts)
    8390              : {
    8391           10 : }
    8392              : 
    8393              : /* Implementation of recording::memento::replay_into for top-level asm.  */
    8394              : 
    8395              : void
    8396           10 : recording::top_level_asm::replay_into (replayer *r)
    8397              : {
    8398           10 :   r->add_top_level_asm (m_asm_stmts->c_str ());
    8399           10 : }
    8400              : 
    8401              : /* Implementation of recording::memento::make_debug_string for
    8402              :    top-level asm.  */
    8403              : 
    8404              : recording::string *
    8405            0 : recording::top_level_asm::make_debug_string ()
    8406              : {
    8407            0 :   return string::from_printf (m_ctxt, "asm (%s)",
    8408            0 :                               m_asm_stmts->get_debug_string ());
    8409              : }
    8410              : 
    8411              : /* Override the default implementation of
    8412              :    recording::memento::write_to_dump.
    8413              :    Don't indent the string.  */
    8414              : 
    8415              : void
    8416            0 : recording::top_level_asm::write_to_dump (dump &d)
    8417              : {
    8418            0 :   d.write ("%s;\n", get_debug_string ());
    8419            0 : }
    8420              : 
    8421              : /* Implementation of recording::memento::write_reproducer for top-level asm. */
    8422              : 
    8423              : void
    8424           10 : recording::top_level_asm::write_reproducer (reproducer &r)
    8425              : {
    8426           10 :   r.write ("  gcc_jit_context_add_top_level_asm (%s, /* gcc_jit_context *ctxt */\n"
    8427              :            "                                     %s, /* gcc_jit_location *loc */\n"
    8428              :            "                                     %s); /* const char *asm_stmts */\n",
    8429              :            r.get_identifier (get_context ()),
    8430           10 :            r.get_identifier (m_loc),
    8431           10 :            m_asm_stmts->get_debug_string ());
    8432           10 : }
    8433              : 
    8434              : void
    8435          850 : recording::global_init_rvalue::replay_into (replayer *r)
    8436              : {
    8437          850 :   r->global_set_init_rvalue (m_variable->playback_lvalue (),
    8438          850 :                              m_init->playback_rvalue ());
    8439          850 : }
    8440              : 
    8441              : void
    8442          590 : recording::global_init_rvalue::write_reproducer (reproducer &r)
    8443              : {
    8444         1180 :   r.write (
    8445              :     "  gcc_jit_global_set_initializer_rvalue (%s, /* lvalue *global */\n"
    8446              :     "                                         %s);/* rvalue *init */\n",
    8447          590 :     r.get_identifier (m_variable),
    8448              :     r.get_identifier_as_rvalue (m_init));
    8449          590 : }
    8450              : 
    8451              : void
    8452            0 : recording::global_init_rvalue::write_to_dump (dump &d)
    8453              : {
    8454            0 :   d.write ("%s;\n", get_debug_string ());
    8455            0 : }
    8456              : 
    8457              : recording::string *
    8458            0 : recording::global_init_rvalue::make_debug_string ()
    8459              : {
    8460            0 :     return string::from_printf (m_ctxt, "%s = %s",
    8461            0 :       m_variable->get_debug_string (),
    8462            0 :       m_init->get_debug_string ());
    8463              : }
    8464              : 
    8465              : enum strip_flags {
    8466              :   STRIP_FLAG_NONE,
    8467              :   STRIP_FLAG_ARR,
    8468              :   STRIP_FLAG_VEC
    8469              : };
    8470              : 
    8471              : /* Strips type down to array, vector or base type (whichever comes first)
    8472              : 
    8473              :    Also saves 'ptr_depth' and sets 'flags' for array or vector types.  */
    8474              : static
    8475              : recording::type *
    8476          460 : strip_and_count (recording::type *type_to_strip,
    8477              :                  int &ptr_depth,
    8478              :                  strip_flags &flags)
    8479              : {
    8480          460 :   recording::type *t = type_to_strip;
    8481              : 
    8482          810 :   while (true)
    8483              :     {
    8484          810 :       if (!t)
    8485            0 :         gcc_unreachable (); /* Should only happen on corrupt input.  */
    8486              : 
    8487          810 :       recording::type *pointed_to_type = t->is_pointer ();
    8488          810 :       if (pointed_to_type != NULL)
    8489              :         {
    8490           90 :           ptr_depth++;
    8491           90 :           t = pointed_to_type;
    8492           90 :           continue;
    8493              :         }
    8494              : 
    8495          720 :       recording::type *array_el = t->is_array ();
    8496          720 :       if (array_el != NULL)
    8497              :         {
    8498           30 :           flags = STRIP_FLAG_ARR;
    8499           30 :           break;
    8500              :         }
    8501              : 
    8502          690 :       recording::type *vec = t->dyn_cast_vector_type ();
    8503          690 :       if (vec != NULL)
    8504              :         {
    8505            0 :           flags = STRIP_FLAG_VEC;
    8506            0 :           break;
    8507              :         }
    8508              : 
    8509              :       /* unqualified () returns 'this' on base types.  */
    8510          690 :       recording::type *next = t->unqualified ();
    8511          690 :       if (next == t)
    8512              :         {
    8513              :           break;
    8514              :         }
    8515              :       t = next;
    8516              :     }
    8517              : 
    8518          460 :   return t;
    8519              : }
    8520              : 
    8521              : /* Strip qualifiers and count pointer depth, returning true
    8522              :    if the types' base type and pointer depth are
    8523              :    the same, otherwise false.
    8524              : 
    8525              :    For array and vector types the number of element also
    8526              :    has to match.
    8527              : 
    8528              :    Do not call this directly.  Call 'types_kinda_same'.  */
    8529              : bool
    8530          230 : types_kinda_same_internal (recording::type *a, recording::type *b)
    8531              : {
    8532          230 :   int ptr_depth_a = 0;
    8533          230 :   int ptr_depth_b = 0;
    8534          230 :   recording::type *base_a;
    8535          230 :   recording::type *base_b;
    8536              : 
    8537          230 :   strip_flags flags_a = STRIP_FLAG_NONE;
    8538          230 :   strip_flags flags_b = STRIP_FLAG_NONE;
    8539              : 
    8540          230 :   base_a = strip_and_count (a, ptr_depth_a, flags_a);
    8541          230 :   base_b = strip_and_count (b, ptr_depth_b, flags_b);
    8542              : 
    8543          230 :   if (ptr_depth_a != ptr_depth_b)
    8544              :     return false;
    8545              : 
    8546          230 :   if (base_a == base_b)
    8547              :     return true;
    8548              : 
    8549           30 :   if (flags_a != flags_b)
    8550              :     return false;
    8551              : 
    8552              :   /* If the "base type" is an array or vector we might need to
    8553              :      check deeper.  */
    8554           30 :   if (flags_a == STRIP_FLAG_ARR)
    8555              :     {
    8556           15 :       recording::array_type *arr_a =
    8557              :         static_cast<recording::array_type*> (base_a);
    8558           15 :       recording::array_type *arr_b =
    8559              :         static_cast<recording::array_type*> (base_b);
    8560              : 
    8561           15 :       if (arr_a->num_elements () != arr_b->num_elements ())
    8562              :         return false;
    8563              : 
    8564              :       /* is_array returns element type.  */
    8565           15 :       recording::type *el_a = arr_a->is_array ();
    8566           15 :       recording::type *el_b = arr_b->is_array ();
    8567              : 
    8568           15 :       if (el_a == el_b)
    8569              :         return true;
    8570              : 
    8571              :       return types_kinda_same_internal (el_a, el_b);
    8572              :     }
    8573           15 :   if (flags_a == STRIP_FLAG_VEC)
    8574              :     {
    8575            0 :       recording::vector_type *arr_a =
    8576              :         static_cast<recording::vector_type*> (base_a);
    8577            0 :       recording::vector_type *arr_b =
    8578              :         static_cast<recording::vector_type*> (base_b);
    8579              : 
    8580            0 :       if (arr_a->get_num_units () != arr_b->get_num_units ())
    8581              :         return false;
    8582              : 
    8583            0 :       recording::type *el_a = arr_a->get_element_type ();
    8584            0 :       recording::type *el_b = arr_b->get_element_type ();
    8585              : 
    8586            0 :       if (el_a == el_b)
    8587              :         return true;
    8588              : 
    8589              :       return types_kinda_same_internal (el_a, el_b);
    8590              :     }
    8591              : 
    8592              :   return false;
    8593              : }
    8594              : 
    8595              : } // namespace gcc::jit
    8596              : 
    8597              : } // namespace gcc
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.