1/* Internals of libgccjit: classes for recording calls made to the JIT API.
2   Copyright (C) 2013-2015 Free Software Foundation, Inc.
3   Contributed by David Malcolm <dmalcolm@redhat.com>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3.  If not see
19<http://www.gnu.org/licenses/>.  */
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "tm.h"
25#include "pretty-print.h"
26#include "hash-map.h"
27#include "toplev.h"
28
29#include <pthread.h>
30
31#include "jit-common.h"
32#include "jit-builtins.h"
33#include "jit-logging.h"
34#include "jit-recording.h"
35#include "jit-playback.h"
36
37namespace gcc {
38namespace jit {
39
40// class dump
41
42dump::dump (recording::context &ctxt,
43	    const char *filename,
44	    bool update_locations)
45: m_ctxt (ctxt),
46  m_filename (filename),
47  m_update_locations (update_locations),
48  m_line (0),
49  m_column (0)
50{
51  m_file = fopen (filename, "w");
52  if (!m_file)
53    ctxt.add_error (NULL,
54		    "error opening dump file %s for writing: %s",
55		    filename,
56		    xstrerror (errno));
57}
58
59dump::~dump ()
60{
61  if (m_file)
62    {
63      int err = fclose (m_file);
64      if (err)
65	m_ctxt.add_error (NULL,
66			  "error closing dump file %s: %s",
67			  m_filename,
68			  xstrerror (errno));
69    }
70}
71
72/* Write the given message to the dump, using printf-formatting
73   conventions, updating the line/column within the dump.
74
75   Emit an error on the context if a failure occurs.  */
76
77void
78dump::write (const char *fmt, ...)
79{
80  int len;
81  va_list ap;
82  char *buf;
83
84  /* If there was an error opening the file, we've already reported it.
85     Don't attempt further work.  */
86  if (!m_file)
87    return;
88
89  va_start (ap, fmt);
90  len = vasprintf (&buf, fmt, ap);
91  va_end (ap);
92
93  if (buf == NULL || len < 0)
94    {
95      m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
96			m_filename);
97      return;
98    }
99
100  if (fwrite (buf, strlen (buf), 1, m_file) != 1)
101    m_ctxt.add_error (NULL, "error writing to dump file %s",
102		      m_filename);
103
104  /* Flush after each line, to ease debugging crashes.  */
105  fflush (m_file);
106
107  /* Update line/column: */
108  for (const char *ptr = buf; *ptr; ptr++)
109    {
110      if ('\n' == *ptr)
111	{
112	  m_line++;
113	  m_column = 0;
114	}
115      else
116	m_column++;
117    }
118
119  free (buf);
120}
121
122/* Construct a gcc::jit::recording::location instance for the current
123   location within the dump.  */
124
125recording::location *
126dump::make_location () const
127{
128  return m_ctxt.new_location (m_filename, m_line, m_column,
129			      /* We need to flag such locations as *not*
130				 created by the user, so that
131				 reproducer::get_identifier can cope with
132				 them appearing *after* the memento that
133				 refers to them.  */
134			      false);
135}
136
137/* A collection of allocations, all of which can be released together, to
138   avoid needing to track and release them individually.  */
139
140class allocator
141{
142 public:
143  ~allocator ();
144
145  char *
146  xstrdup_printf (const char *, ...)
147    ATTRIBUTE_RETURNS_NONNULL
148    GNU_PRINTF(2, 3);
149
150  char *
151  xstrdup_printf_va (const char *, va_list ap)
152    ATTRIBUTE_RETURNS_NONNULL
153    GNU_PRINTF(2, 0);
154
155 private:
156  auto_vec <void *> m_buffers;
157};
158
159/* allocator's destructor.  Call "free" on all of the allocations.  */
160
161allocator::~allocator ()
162{
163  unsigned i;
164  void *buffer;
165  FOR_EACH_VEC_ELT (m_buffers, i, buffer)
166    free (buffer);
167}
168
169/* Formatted printing, allocating to a buffer (or exiting the process if
170   the allocation fails).
171
172   The buffer exists until the allocator is cleaned up, and is freed at
173   that point, so the caller doesn't need to track the result.  */
174
175char *
176allocator::xstrdup_printf (const char *fmt, ...)
177{
178  char *result;
179  va_list ap;
180  va_start (ap, fmt);
181  result = xstrdup_printf_va (fmt, ap);
182  va_end (ap);
183  return result;
184}
185
186/* Formatted printing, allocating to a buffer (or exiting the process if
187   the allocation fails).
188
189   The buffer exists until the allocator is cleaned up, and is freed at
190   that point, so the caller doesn't need to track the result.  */
191
192char *
193allocator::xstrdup_printf_va (const char *fmt, va_list ap)
194{
195  char *result = xvasprintf (fmt, ap);
196  m_buffers.safe_push (result);
197  return result;
198}
199
200/* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
201   implementing gcc_jit_context_dump_reproducer_to_file.  */
202
203class reproducer : public dump
204{
205 public:
206  reproducer (recording::context &ctxt,
207	      const char *filename);
208
209  void
210  write_params (const vec <recording::context *> &contexts);
211
212  void
213  write_args (const vec <recording::context *> &contexts);
214
215  const char *
216  make_identifier (recording::memento *m, const char *prefix);
217
218  const char *
219  make_tmp_identifier (const char *prefix, recording::memento *m);
220
221  const char *
222  get_identifier (recording::context *ctxt);
223
224  const char *
225  get_identifier (recording::memento *m);
226
227  const char *
228  get_identifier_as_rvalue (recording::rvalue *m);
229
230  const char *
231  get_identifier_as_lvalue (recording::lvalue *m);
232
233  const char *
234  get_identifier_as_type (recording::type *m);
235
236  char *
237  xstrdup_printf (const char *, ...)
238    ATTRIBUTE_RETURNS_NONNULL
239    GNU_PRINTF(2, 3);
240
241 private:
242  hash_map<recording::memento *, const char *> m_identifiers;
243  allocator m_allocator;
244};
245
246/* gcc::jit::reproducer's constructor.  */
247
248reproducer::reproducer (recording::context &ctxt,
249			const char *filename) :
250  dump (ctxt, filename, 0),
251  m_identifiers (),
252  m_allocator ()
253{
254}
255
256/* Write out a list of contexts as a set of parameters within a
257   C function declaration.  */
258
259void
260reproducer::write_params (const vec <recording::context *> &contexts)
261{
262  unsigned i;
263  recording::context *ctxt;
264  FOR_EACH_VEC_ELT (contexts, i, ctxt)
265    {
266      write ("gcc_jit_context *%s",
267	     get_identifier (ctxt));
268      if (i < contexts.length () - 1)
269	write (",\n"
270	       "             ");
271    }
272}
273
274/* Write out a list of contexts as a set of arguments within a call
275   to a C function.  */
276
277void
278reproducer::write_args (const vec <recording::context *> &contexts)
279{
280  unsigned i;
281  recording::context *ctxt;
282  FOR_EACH_VEC_ELT (contexts, i, ctxt)
283    {
284      write ("%s",
285	     get_identifier (ctxt));
286      if (i < contexts.length () - 1)
287	write (",\n"
288	       "               ");
289    }
290}
291
292/* Generate a C identifier for the given memento, associating the generated
293   buffer with the memento (for future calls to get_identifier et al).
294
295   The reproducer will eventually clean up the buffer in its dtor.  */
296const char *
297reproducer::make_identifier (recording::memento *m, const char *prefix)
298{
299  char *result;
300  if (strlen (m->get_debug_string ()) < 100)
301    {
302      result = m_allocator.xstrdup_printf ("%s_%s_%p",
303					   prefix,
304					   m->get_debug_string (),
305					   (void *) m);
306      for (char *p = result; *p; p++)
307	if (!ISALNUM (*p))
308	  *p = '_';
309    }
310  else
311    result = m_allocator.xstrdup_printf ("%s_%p",
312					 prefix, (void *) m);
313  m_identifiers.put (m, result);
314  return result;
315}
316
317/* Generate a C identifier for a temporary variable.
318   The reproducer will eventually clean up the buffer in its dtor.  */
319
320const char *
321reproducer::make_tmp_identifier (const char *prefix, recording::memento *m)
322{
323  return m_allocator.xstrdup_printf ("%s_%s",
324				     prefix, get_identifier (m));
325}
326
327/* Generate a C identifier for the given context.
328   The reproducer will eventually clean up the buffer in its dtor.  */
329
330const char *
331reproducer::get_identifier (recording::context *ctxt)
332{
333  return m_allocator.xstrdup_printf ("ctxt_%p",
334				     (void *)ctxt);
335}
336
337/* Locate the C identifier for the given memento, which is assumed to
338   have already been created via make_identifier.  */
339
340const char *
341reproducer::get_identifier (recording::memento *m)
342{
343  if (!m)
344    return "NULL";
345
346  /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
347     and hence these locations appear in the context's memento list
348     out-of-order: they appear in the context's memento list *after*
349     the memento that refers to them.  For this case, it's simplest to
350     pretend that they're NULL when writing out the code to recreate the
351     memento that uses them.  */
352  if (recording::location *loc = m->dyn_cast_location ())
353    if (!loc->created_by_user ())
354      return "NULL";
355
356  const char **slot = m_identifiers.get (m);
357  if (!slot)
358    {
359      get_context ().add_error (NULL,
360				"unable to find identifier for %p: %s",
361				(void *)m,
362				m->get_debug_string ());
363      gcc_unreachable ();
364    }
365  return *slot;
366}
367
368/* Locate the C identifier for the given rvalue, wrapping it within
369   a gcc_*_as_rvalue upcast if necessary.  */
370
371const char *
372reproducer::get_identifier_as_rvalue (recording::rvalue *m)
373{
374  return m->access_as_rvalue (*this);
375}
376
377/* Locate the C identifier for the given lvalue, wrapping it within
378   a gcc_*_as_lvalue upcast if necessary.  */
379
380const char *
381reproducer::get_identifier_as_lvalue (recording::lvalue *m)
382{
383  return m->access_as_lvalue (*this);
384}
385
386/* Locate the C identifier for the given type, wrapping it within
387   a gcc_*_as_type upcast if necessary.  */
388
389const char *
390reproducer::get_identifier_as_type (recording::type *m)
391{
392  return m->access_as_type (*this);
393}
394
395/* Formatted printing, allocating to a buffer (or exiting the process if
396   the allocation fails).
397
398   The buffer exists until the allocator is cleaned up, and is freed at
399   that point, so the caller doesn't need to track the result.
400
401   Note that we can't use ggc_printf since we're not within the compiler
402   proper (when within gcc_jit_context_dump_reproducer_to_file).  */
403
404char *
405reproducer::xstrdup_printf (const char *fmt, ...)
406{
407  char *result;
408  va_list ap;
409  va_start (ap, fmt);
410  result = m_allocator.xstrdup_printf_va (fmt, ap);
411  va_end (ap);
412  return result;
413}
414
415/**********************************************************************
416 Recording.
417 **********************************************************************/
418
419/* Get the playback::location for the given recording::location,
420   handling a NULL input with a NULL output.  */
421
422playback::location *
423recording::playback_location (replayer *r, recording::location *loc)
424{
425  if (loc)
426    return loc->playback_location (r);
427  else
428    return NULL;
429}
430
431/* Get a const char * for the given recording::string
432   handling a NULL input with a NULL output.  */
433
434const char *
435recording::playback_string (recording::string *str)
436{
437  if (str)
438    return str->c_str ();
439  else
440    return NULL;
441}
442
443/* Get the playback::block for the given recording::block,
444   handling a NULL input with a NULL output.  */
445
446playback::block *
447recording::playback_block (recording::block *b)
448{
449  if (b)
450    return b->playback_block ();
451  else
452    return NULL;
453}
454
455/* Methods of cc::jit::recording::context.  */
456
457/* The constructor for gcc::jit::recording::context, used by
458   gcc_jit_context_acquire and gcc_jit_context_new_child_context.  */
459
460recording::context::context (context *parent_ctxt)
461  : log_user (NULL),
462    m_parent_ctxt (parent_ctxt),
463    m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this),
464    m_error_count (0),
465    m_first_error_str (NULL),
466    m_owns_first_error_str (false),
467    m_last_error_str (NULL),
468    m_owns_last_error_str (false),
469    m_mementos (),
470    m_compound_types (),
471    m_globals (),
472    m_functions (),
473    m_FILE_type (NULL),
474    m_builtins_manager(NULL)
475{
476  if (parent_ctxt)
477    {
478      /* Inherit options from parent.  */
479      for (unsigned i = 0;
480	   i < sizeof (m_str_options) / sizeof (m_str_options[0]);
481	   i++)
482	{
483	  const char *parent_opt = parent_ctxt->m_str_options[i];
484	  m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
485	}
486      memcpy (m_int_options,
487	      parent_ctxt->m_int_options,
488	      sizeof (m_int_options));
489      memcpy (m_bool_options,
490	      parent_ctxt->m_bool_options,
491	      sizeof (m_bool_options));
492      memcpy (m_inner_bool_options,
493	      parent_ctxt->m_inner_bool_options,
494	      sizeof (m_inner_bool_options));
495      set_logger (parent_ctxt->get_logger ());
496    }
497  else
498    {
499      memset (m_str_options, 0, sizeof (m_str_options));
500      memset (m_int_options, 0, sizeof (m_int_options));
501      memset (m_bool_options, 0, sizeof (m_bool_options));
502      memset (m_inner_bool_options, 0, sizeof (m_inner_bool_options));
503    }
504
505  memset (m_basic_types, 0, sizeof (m_basic_types));
506}
507
508/* The destructor for gcc::jit::recording::context, implicitly used by
509   gcc_jit_context_release.  */
510
511recording::context::~context ()
512{
513  JIT_LOG_SCOPE (get_logger ());
514  int i;
515  memento *m;
516  FOR_EACH_VEC_ELT (m_mementos, i, m)
517    {
518      delete m;
519    }
520
521  for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
522    free (m_str_options[i]);
523
524  char *optname;
525  FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
526    free (optname);
527
528  if (m_builtins_manager)
529    delete m_builtins_manager;
530
531  if (m_owns_first_error_str)
532    free (m_first_error_str);
533
534  if (m_owns_last_error_str)
535    if (m_last_error_str != m_first_error_str)
536      free (m_last_error_str);
537}
538
539/* Add the given mememto to the list of those tracked by this
540   gcc::jit::recording::context, so that e.g. it can be deleted
541   when this context is released.  */
542
543void
544recording::context::record (memento *m)
545{
546  gcc_assert (m);
547
548  m_mementos.safe_push (m);
549}
550
551/* Replay this context (and any parents) into the given replayer.  */
552
553void
554recording::context::replay_into (replayer *r)
555{
556  JIT_LOG_SCOPE (get_logger ());
557  int i;
558  memento *m;
559
560  /* If we have a parent context, we must replay it.  This will
561     recursively walk backwards up the historical tree, then replay things
562     forwards "in historical order", starting with the ultimate parent
563     context, until we reach the "this" context.
564
565     Note that we fully replay the parent, then fully replay the child,
566     which means that inter-context references can only exist from child
567     to parent, not the other way around.
568
569     All of this replaying is suboptimal - it would be better to do the
570     work for the parent context *once*, rather than replaying the parent
571     every time we replay each child.  However, fixing this requires deep
572     surgery to lifetime-management: we'd need every context family tree
573     to have its own GC heap, and to initialize the GCC code to use that
574     heap (with a mutex on such a heap).  */
575  if (m_parent_ctxt)
576    m_parent_ctxt->replay_into (r);
577
578  if (r->errors_occurred ())
579    return;
580
581  /* Replay this context's saved operations into r.  */
582  FOR_EACH_VEC_ELT (m_mementos, i, m)
583    {
584      /* Disabled low-level debugging, here if we need it: print what
585	 we're replaying.
586	 Note that the calls to get_debug_string might lead to more
587	 mementos being created for the strings.
588	 This can also be used to exercise the debug_string
589	 machinery.  */
590      if (0)
591	printf ("context %p replaying (%p): %s\n",
592		(void *)this, (void *)m, m->get_debug_string ());
593
594      m->replay_into (r);
595
596      if (r->errors_occurred ())
597	return;
598    }
599}
600
601/* During a playback, we associate objects from the recording with
602   their counterparts during this playback.
603
604   For simplicity, we store this within the recording objects.
605
606   The following method cleans away these associations, to ensure that
607   we never have out-of-date associations lingering on subsequent
608   playbacks (the objects pointed to are GC-managed, but the
609   recording objects don't own refs to them).  */
610
611void
612recording::context::disassociate_from_playback ()
613{
614  JIT_LOG_SCOPE (get_logger ());
615  int i;
616  memento *m;
617
618  if (m_parent_ctxt)
619    m_parent_ctxt->disassociate_from_playback ();
620
621  FOR_EACH_VEC_ELT (m_mementos, i, m)
622    {
623      m->set_playback_obj (NULL);
624    }
625}
626
627/* Create a recording::string instance and add it to this context's list
628   of mementos.
629
630   This creates a fresh copy of the given 0-terminated buffer.  */
631
632recording::string *
633recording::context::new_string (const char *text)
634{
635  if (!text)
636    return NULL;
637
638  recording::string *result = new string (this, text);
639  record (result);
640  return result;
641}
642
643/* Create a recording::location instance and add it to this context's
644   list of mementos.
645
646   Implements the post-error-checking part of
647   gcc_jit_context_new_location.  */
648
649recording::location *
650recording::context::new_location (const char *filename,
651				  int line,
652				  int column,
653				  bool created_by_user)
654{
655  recording::location *result =
656    new recording::location (this,
657			     new_string (filename),
658			     line, column,
659			     created_by_user);
660  record (result);
661  return result;
662}
663
664/* If we haven't seen this enum value yet, create a recording::type
665   instance and add it to this context's list of mementos.
666
667   If we have seen it before, reuse our cached value, so that repeated
668   calls on the context give the same object.
669
670   If we have a parent context, the cache is within the ultimate
671   ancestor context.
672
673   Implements the post-error-checking part of
674   gcc_jit_context_get_type.  */
675
676recording::type *
677recording::context::get_type (enum gcc_jit_types kind)
678{
679  if (!m_basic_types[kind])
680    {
681      if (m_parent_ctxt)
682	m_basic_types[kind] = m_parent_ctxt->get_type (kind);
683      else
684	{
685	  recording::type *result = new memento_of_get_type (this, kind);
686	  record (result);
687	  m_basic_types[kind] = result;
688	}
689    }
690
691  return m_basic_types[kind];
692}
693
694/* Get a recording::type instance for the given size and signedness.
695   This is implemented in terms of recording::context::get_type
696   above.
697
698   Implements the post-error-checking part of
699   gcc_jit_context_get_int_type.  */
700
701recording::type *
702recording::context::get_int_type (int num_bytes, int is_signed)
703{
704  /* We can't use a switch here since some of the values are macros affected
705     by options; e.g. i386.h has
706       #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
707     Compare with tree.c's make_or_reuse_type.  Note that the _SIZE macros
708     are in bits, rather than bytes.
709  */
710  const int num_bits = num_bytes * 8;
711  if (num_bits == INT_TYPE_SIZE)
712    return get_type (is_signed
713		     ? GCC_JIT_TYPE_INT
714		     : GCC_JIT_TYPE_UNSIGNED_INT);
715  if (num_bits == CHAR_TYPE_SIZE)
716    return get_type (is_signed
717		     ? GCC_JIT_TYPE_SIGNED_CHAR
718		     : GCC_JIT_TYPE_UNSIGNED_CHAR);
719  if (num_bits == SHORT_TYPE_SIZE)
720    return get_type (is_signed
721		     ? GCC_JIT_TYPE_SHORT
722		     : GCC_JIT_TYPE_UNSIGNED_SHORT);
723  if (num_bits == LONG_TYPE_SIZE)
724    return get_type (is_signed
725		     ? GCC_JIT_TYPE_LONG
726		     : GCC_JIT_TYPE_UNSIGNED_LONG);
727  if (num_bits == LONG_LONG_TYPE_SIZE)
728    return get_type (is_signed
729		     ? GCC_JIT_TYPE_LONG_LONG
730		     : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
731
732  /* Some other size, not corresponding to the C int types.  */
733  /* To be written: support arbitrary other sizes, sharing by
734     memoizing at the recording::context level?  */
735  gcc_unreachable ();
736}
737
738/* Create a recording::type instance and add it to this context's list
739   of mementos.
740
741   Implements the post-error-checking part of
742   gcc_jit_context_new_array_type.  */
743
744recording::type *
745recording::context::new_array_type (recording::location *loc,
746				    recording::type *element_type,
747				    int num_elements)
748{
749  if (struct_ *s = element_type->dyn_cast_struct ())
750    if (!s->get_fields ())
751      {
752	add_error (NULL,
753		   "cannot create an array of type %s"
754		   " until the fields have been set",
755		   s->get_name ()->c_str ());
756	return NULL;
757      }
758  recording::type *result =
759    new recording::array_type (this, loc, element_type, num_elements);
760  record (result);
761  return result;
762}
763
764/* Create a recording::field instance and add it to this context's list
765   of mementos.
766
767   Implements the post-error-checking part of
768   gcc_jit_context_new_field.  */
769
770recording::field *
771recording::context::new_field (recording::location *loc,
772			       recording::type *type,
773			       const char *name)
774{
775  recording::field *result =
776    new recording::field (this, loc, type, new_string (name));
777  record (result);
778  return result;
779}
780
781/* Create a recording::struct_ instance and add it to this context's
782   list of mementos and list of compound types.
783
784   Implements the post-error-checking part of
785   gcc_jit_context_new_struct_type.  */
786
787recording::struct_ *
788recording::context::new_struct_type (recording::location *loc,
789				     const char *name)
790{
791  recording::struct_ *result = new struct_ (this, loc, new_string (name));
792  record (result);
793  m_compound_types.safe_push (result);
794  return result;
795}
796
797/* Create a recording::union_ instance and add it to this context's
798   list of mementos and list of compound types.
799
800   Implements the first post-error-checking part of
801   gcc_jit_context_new_union_type.  */
802
803recording::union_ *
804recording::context::new_union_type (recording::location *loc,
805				    const char *name)
806{
807  recording::union_ *result = new union_ (this, loc, new_string (name));
808  record (result);
809  m_compound_types.safe_push (result);
810  return result;
811}
812
813/* Create a recording::function_type instance and add it to this context's
814   list of mementos.
815
816   Used by new_function_ptr_type and by builtins_manager::make_fn_type.  */
817
818recording::function_type *
819recording::context::new_function_type (recording::type *return_type,
820				       int num_params,
821				       recording::type **param_types,
822				       int is_variadic)
823{
824  recording::function_type *fn_type
825    = new function_type (this,
826			 return_type,
827			 num_params,
828			 param_types,
829			 is_variadic);
830  record (fn_type);
831  return fn_type;
832}
833
834/* Create a recording::type instance and add it to this context's list
835   of mementos.
836
837   Implements the post-error-checking part of
838   gcc_jit_context_new_function_ptr_type.  */
839
840recording::type *
841recording::context::new_function_ptr_type (recording::location *, /* unused loc */
842					   recording::type *return_type,
843					   int num_params,
844					   recording::type **param_types,
845					   int is_variadic)
846{
847  recording::function_type *fn_type
848    = new_function_type (return_type,
849			 num_params,
850			 param_types,
851			 is_variadic);
852
853  /* Return a pointer-type to the the function type.  */
854  return fn_type->get_pointer ();
855}
856
857/* Create a recording::param instance and add it to this context's list
858   of mementos.
859
860   Implements the post-error-checking part of
861   gcc_jit_context_new_param.  */
862
863recording::param *
864recording::context::new_param (recording::location *loc,
865			       recording::type *type,
866			       const char *name)
867{
868  recording::param *result = new recording::param (this, loc, type, new_string (name));
869  record (result);
870  return result;
871}
872
873/* Create a recording::function instance and add it to this context's list
874   of mementos and list of functions.
875
876   Implements the post-error-checking part of
877   gcc_jit_context_new_function.  */
878
879recording::function *
880recording::context::new_function (recording::location *loc,
881				  enum gcc_jit_function_kind kind,
882				  recording::type *return_type,
883				  const char *name,
884				  int num_params,
885				  recording::param **params,
886				  int is_variadic,
887				  enum built_in_function builtin_id)
888{
889  recording::function *result =
890    new recording::function (this,
891			     loc, kind, return_type,
892			     new_string (name),
893			     num_params, params, is_variadic,
894			     builtin_id);
895  record (result);
896  m_functions.safe_push (result);
897
898  return result;
899}
900
901/* Locate the builtins_manager (if any) for this family of contexts,
902   creating it if it doesn't exist already.
903
904   All of the recording contexts in a family share one builtins_manager:
905   if we have a child context, follow the parent links to get the
906   ultimate ancestor context, and look for it/store it there.  */
907
908builtins_manager *
909recording::context::get_builtins_manager ()
910{
911  if (m_parent_ctxt)
912    return m_parent_ctxt->get_builtins_manager ();
913
914  if (!m_builtins_manager)
915    m_builtins_manager = new builtins_manager (this);
916
917  return m_builtins_manager;
918}
919
920/* Get a recording::function instance, which is lazily-created and added
921   to the context's lists of mementos.
922
923   Implements the post-error-checking part of
924   gcc_jit_context_get_builtin_function.  */
925
926recording::function *
927recording::context::get_builtin_function (const char *name)
928{
929  builtins_manager *bm = get_builtins_manager ();
930  return bm->get_builtin_function (name);
931}
932
933/* Create a recording::global instance and add it to this context's list
934   of mementos.
935
936   Implements the post-error-checking part of
937   gcc_jit_context_new_global.  */
938
939recording::lvalue *
940recording::context::new_global (recording::location *loc,
941				enum gcc_jit_global_kind kind,
942				recording::type *type,
943				const char *name)
944{
945  recording::global *result =
946    new recording::global (this, loc, kind, type, new_string (name));
947  record (result);
948  m_globals.safe_push (result);
949
950  return result;
951}
952
953/* Create a recording::memento_of_new_string_literal instance and add it
954   to this context's list of mementos.
955
956   Implements the post-error-checking part of
957   gcc_jit_context_new_string_literal.  */
958
959recording::rvalue *
960recording::context::new_string_literal (const char *value)
961{
962  recording::rvalue *result =
963    new memento_of_new_string_literal (this, NULL, new_string (value));
964  record (result);
965  return result;
966}
967
968/* Create a recording::unary_op instance and add it to this context's
969   list of mementos.
970
971   Implements the post-error-checking part of
972   gcc_jit_context_new_unary_op.  */
973
974recording::rvalue *
975recording::context::new_unary_op (recording::location *loc,
976				  enum gcc_jit_unary_op op,
977				  recording::type *result_type,
978				  recording::rvalue *a)
979{
980  recording::rvalue *result =
981    new unary_op (this, loc, op, result_type, a);
982  record (result);
983  return result;
984}
985
986/* Create a recording::binary_op instance and add it to this context's
987   list of mementos.
988
989   Implements the post-error-checking part of
990   gcc_jit_context_new_binary_op.  */
991
992recording::rvalue *
993recording::context::new_binary_op (recording::location *loc,
994				   enum gcc_jit_binary_op op,
995				   recording::type *result_type,
996				   recording::rvalue *a,
997				   recording::rvalue *b)
998{
999  recording::rvalue *result =
1000    new binary_op (this, loc, op, result_type, a, b);
1001  record (result);
1002  return result;
1003}
1004
1005/* Create a recording::comparison instance and add it to this context's
1006   list of mementos.
1007
1008   Implements the post-error-checking part of
1009   gcc_jit_context_new_comparison.  */
1010
1011recording::rvalue *
1012recording::context::new_comparison (recording::location *loc,
1013				    enum gcc_jit_comparison op,
1014				    recording::rvalue *a,
1015				    recording::rvalue *b)
1016{
1017  recording::rvalue *result = new comparison (this, loc, op, a, b);
1018  record (result);
1019  return result;
1020}
1021
1022/* Create a recording::cast instance and add it to this context's list
1023   of mementos.
1024
1025   Implements the post-error-checking part of
1026   gcc_jit_context_new_cast.  */
1027
1028recording::rvalue *
1029recording::context::new_cast (recording::location *loc,
1030			      recording::rvalue *expr,
1031			      recording::type *type_)
1032{
1033  recording::rvalue *result = new cast (this, loc, expr, type_);
1034  record (result);
1035  return result;
1036}
1037
1038/* Create a recording::call instance and add it to this context's list
1039   of mementos.
1040
1041   Implements the post-error-checking part of
1042   gcc_jit_context_new_call.  */
1043
1044recording::rvalue *
1045recording::context::new_call (recording::location *loc,
1046			      function *func,
1047			      int numargs , recording::rvalue **args)
1048{
1049  recording::rvalue *result = new call (this, loc, func, numargs, args);
1050  record (result);
1051  return result;
1052}
1053
1054/* Create a recording::call_through_ptr instance and add it to this
1055   context's list of mementos.
1056
1057   Implements the post-error-checking part of
1058   gcc_jit_context_new_call_through_ptr.  */
1059
1060recording::rvalue *
1061recording::context::new_call_through_ptr (recording::location *loc,
1062					  recording::rvalue *fn_ptr,
1063					  int numargs,
1064					  recording::rvalue **args)
1065  {
1066  recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
1067  record (result);
1068  return result;
1069}
1070
1071/* Create a recording::array_access instance and add it to this context's list
1072   of mementos.
1073
1074   Implements the post-error-checking part of
1075   gcc_jit_context_new_array_access.  */
1076
1077recording::lvalue *
1078recording::context::new_array_access (recording::location *loc,
1079				      recording::rvalue *ptr,
1080				      recording::rvalue *index)
1081{
1082  recording::lvalue *result = new array_access (this, loc, ptr, index);
1083  record (result);
1084  return result;
1085}
1086
1087/* Create a recording::case_ instance and add it to this context's list
1088   of mementos.
1089
1090   Implements the post-error-checking part of
1091   gcc_jit_context_new_case.  */
1092
1093recording::case_ *
1094recording::context::new_case (recording::rvalue *min_value,
1095			      recording::rvalue *max_value,
1096			      recording::block *block)
1097{
1098  recording::case_ *result = new case_ (this, min_value, max_value, block);
1099  record (result);
1100  return result;
1101}
1102
1103/* Set the given string option for this context, or add an error if
1104   it's not recognized.
1105
1106   Implements the post-error-checking part of
1107   gcc_jit_context_set_str_option.  */
1108
1109void
1110recording::context::set_str_option (enum gcc_jit_str_option opt,
1111				    const char *value)
1112{
1113  if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
1114    {
1115      add_error (NULL,
1116		 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
1117      return;
1118    }
1119  free (m_str_options[opt]);
1120  m_str_options[opt] = value ? xstrdup (value) : NULL;
1121  log_str_option (opt);
1122}
1123
1124/* Set the given integer option for this context, or add an error if
1125   it's not recognized.
1126
1127   Implements the post-error-checking part of
1128   gcc_jit_context_set_int_option.  */
1129
1130void
1131recording::context::set_int_option (enum gcc_jit_int_option opt,
1132				    int value)
1133{
1134  if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
1135    {
1136      add_error (NULL,
1137		 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
1138      return;
1139    }
1140  m_int_options[opt] = value;
1141  log_int_option (opt);
1142}
1143
1144/* Set the given boolean option for this context, or add an error if
1145   it's not recognized.
1146
1147   Implements the post-error-checking part of
1148   gcc_jit_context_set_bool_option.  */
1149
1150void
1151recording::context::set_bool_option (enum gcc_jit_bool_option opt,
1152				     int value)
1153{
1154  if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
1155    {
1156      add_error (NULL,
1157		 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
1158      return;
1159    }
1160  m_bool_options[opt] = value ? true : false;
1161  log_bool_option (opt);
1162}
1163
1164void
1165recording::context::set_inner_bool_option (enum inner_bool_option inner_opt,
1166					   int value)
1167{
1168  gcc_assert (inner_opt >= 0 && inner_opt < NUM_INNER_BOOL_OPTIONS);
1169  m_inner_bool_options[inner_opt] = value ? true : false;
1170  log_inner_bool_option (inner_opt);
1171}
1172
1173
1174/* Add the given optname to this context's list of extra options.
1175
1176   Implements the post-error-checking part of
1177   gcc_jit_context_add_command_line_option.  */
1178
1179void
1180recording::context::add_command_line_option (const char *optname)
1181{
1182  m_command_line_options.safe_push (xstrdup (optname));
1183}
1184
1185/* Add any user-provided extra options, starting with any from
1186   parent contexts.
1187   Called by playback::context::make_fake_args.  */
1188
1189void
1190recording::context::append_command_line_options (vec <char *> *argvec)
1191{
1192  if (m_parent_ctxt)
1193    m_parent_ctxt->append_command_line_options (argvec);
1194
1195  int i;
1196  char *optname;
1197  FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1198    argvec->safe_push (xstrdup (optname));
1199}
1200
1201/* Add the given dumpname/out_ptr pair to this context's list of requested
1202   dumps.
1203
1204   Implements the post-error-checking part of
1205   gcc_jit_context_enable_dump.  */
1206
1207void
1208recording::context::enable_dump (const char *dumpname,
1209				 char **out_ptr)
1210{
1211  requested_dump d;
1212  gcc_assert (dumpname);
1213  gcc_assert (out_ptr);
1214
1215  d.m_dumpname = dumpname;
1216  d.m_out_ptr = out_ptr;
1217  *out_ptr = NULL;
1218  m_requested_dumps.safe_push (d);
1219}
1220
1221/* Validate this context, and if it passes, compile it to memory
1222   (within a mutex).
1223
1224   Implements the post-error-checking part of
1225   gcc_jit_context_compile.  */
1226
1227result *
1228recording::context::compile ()
1229{
1230  JIT_LOG_SCOPE (get_logger ());
1231
1232  log_all_options ();
1233
1234  validate ();
1235
1236  if (errors_occurred ())
1237    return NULL;
1238
1239  /* Set up a compile_to_memory playback context.  */
1240  ::gcc::jit::playback::compile_to_memory replayer (this);
1241
1242  /* Use it.  */
1243  replayer.compile ();
1244
1245  /* Get the jit::result (or NULL) from the
1246     compile_to_memory playback context.  */
1247  return replayer.get_result_obj ();
1248}
1249
1250/* Validate this context, and if it passes, compile it to a file
1251   (within a mutex).
1252
1253   Implements the post-error-checking part of
1254   gcc_jit_context_compile_to_file.  */
1255
1256void
1257recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
1258				     const char *output_path)
1259{
1260  JIT_LOG_SCOPE (get_logger ());
1261
1262  log_all_options ();
1263
1264  validate ();
1265
1266  if (errors_occurred ())
1267    return;
1268
1269  /* Set up a compile_to_file playback context.  */
1270  ::gcc::jit::playback::compile_to_file replayer (this,
1271						  output_kind,
1272						  output_path);
1273
1274  /* Use it.  */
1275  replayer.compile ();
1276}
1277
1278/* Format the given error using printf's conventions, print
1279   it to stderr, and add it to the context.  */
1280
1281void
1282recording::context::add_error (location *loc, const char *fmt, ...)
1283{
1284  va_list ap;
1285  va_start (ap, fmt);
1286  add_error_va (loc, fmt, ap);
1287  va_end (ap);
1288}
1289
1290/* Format the given error using printf's conventions, print
1291   it to stderr, and add it to the context.  */
1292
1293void
1294recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
1295{
1296  int len;
1297  char *malloced_msg;
1298  const char *errmsg;
1299  bool has_ownership;
1300
1301  JIT_LOG_SCOPE (get_logger ());
1302
1303  len = vasprintf (&malloced_msg, fmt, ap);
1304  if (malloced_msg == NULL || len < 0)
1305    {
1306      errmsg = "out of memory generating error message";
1307      has_ownership = false;
1308    }
1309  else
1310    {
1311      errmsg = malloced_msg;
1312      has_ownership = true;
1313    }
1314  if (get_logger ())
1315    get_logger ()->log ("error %i: %s", m_error_count, errmsg);
1316
1317  const char *ctxt_progname =
1318    get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
1319  if (!ctxt_progname)
1320    ctxt_progname = "libgccjit.so";
1321
1322  if (loc)
1323    fprintf (stderr, "%s: %s: error: %s\n",
1324	     ctxt_progname,
1325	     loc->get_debug_string (),
1326	     errmsg);
1327  else
1328    fprintf (stderr, "%s: error: %s\n",
1329	     ctxt_progname,
1330	     errmsg);
1331
1332  if (!m_error_count)
1333    {
1334      m_first_error_str = const_cast <char *> (errmsg);
1335      m_owns_first_error_str = has_ownership;
1336    }
1337
1338  if (m_owns_last_error_str)
1339    if (m_last_error_str != m_first_error_str)
1340      free (m_last_error_str);
1341  m_last_error_str = const_cast <char *> (errmsg);
1342  m_owns_last_error_str = has_ownership;
1343
1344  m_error_count++;
1345}
1346
1347/* Get the message for the first error that occurred on this context, or
1348   NULL if no errors have occurred on it.
1349
1350   Implements the post-error-checking part of
1351   gcc_jit_context_get_first_error.  */
1352
1353const char *
1354recording::context::get_first_error () const
1355{
1356  return m_first_error_str;
1357}
1358
1359/* Get the message for the last error that occurred on this context, or
1360   NULL if no errors have occurred on it.
1361
1362   Implements the post-error-checking part of
1363   gcc_jit_context_get_last_error.  */
1364
1365const char *
1366recording::context::get_last_error () const
1367{
1368  return m_last_error_str;
1369}
1370
1371/* Lazily generate and record a recording::type representing an opaque
1372   struct named "FILE".
1373
1374   For use if client code tries to dereference the result of
1375   get_type (GCC_JIT_TYPE_FILE_PTR).  */
1376
1377recording::type *
1378recording::context::get_opaque_FILE_type ()
1379{
1380  if (!m_FILE_type)
1381    m_FILE_type = new_struct_type (NULL, "FILE");
1382  return m_FILE_type;
1383}
1384
1385/* Dump a C-like representation of the given context to the given path.
1386   If UPDATE_LOCATIONS is true, update the locations within the
1387   context's mementos to point to the dumpfile.
1388
1389   Implements the post-error-checking part of
1390   gcc_jit_context_dump_to_file.  */
1391
1392void
1393recording::context::dump_to_file (const char *path, bool update_locations)
1394{
1395  int i;
1396  dump d (*this, path, update_locations);
1397
1398  /* Forward declaration of structs and unions.  */
1399  compound_type *st;
1400  FOR_EACH_VEC_ELT (m_compound_types, i, st)
1401    {
1402      d.write ("%s;\n\n", st->get_debug_string ());
1403    }
1404
1405  /* Content of structs, where set.  */
1406  FOR_EACH_VEC_ELT (m_compound_types, i, st)
1407    if (st->get_fields ())
1408      {
1409	st->get_fields ()->write_to_dump (d);
1410	d.write ("\n");
1411      }
1412
1413  /* Globals.  */
1414  global *g;
1415  FOR_EACH_VEC_ELT (m_globals, i, g)
1416    {
1417      g->write_to_dump (d);
1418    }
1419  if (!m_globals.is_empty ())
1420    d.write ("\n");
1421
1422  function *fn;
1423  FOR_EACH_VEC_ELT (m_functions, i, fn)
1424    {
1425      fn->write_to_dump (d);
1426    }
1427}
1428
1429static const char * const
1430 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
1431  "GCC_JIT_STR_OPTION_PROGNAME"
1432};
1433
1434static const char * const
1435 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
1436  "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1437};
1438
1439static const char * const
1440 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
1441  "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1442  "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1443  "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1444  "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1445  "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1446  "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1447  "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1448  "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1449};
1450
1451static const char * const
1452 inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = {
1453  "gcc_jit_context_set_bool_allow_unreachable_blocks"
1454};
1455
1456/* Write the current value of all options to the log file (if any).  */
1457
1458void
1459recording::context::log_all_options () const
1460{
1461  int opt_idx;
1462
1463  if (!get_logger ())
1464    return;
1465
1466  for (opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1467    log_str_option ((enum gcc_jit_str_option)opt_idx);
1468
1469  for (opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1470    log_int_option ((enum gcc_jit_int_option)opt_idx);
1471
1472  for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1473    log_bool_option ((enum gcc_jit_bool_option)opt_idx);
1474  for (opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1475    log_inner_bool_option ((enum inner_bool_option)opt_idx);
1476}
1477
1478/* Write the current value of the given string option to the
1479   log file (if any).  */
1480
1481void
1482recording::context::log_str_option (enum gcc_jit_str_option opt) const
1483{
1484  gcc_assert (opt < GCC_JIT_NUM_STR_OPTIONS);
1485  if (get_logger ())
1486    {
1487      if (m_str_options[opt])
1488	log ("%s: \"%s\"",
1489	     str_option_reproducer_strings[opt],
1490	     m_str_options[opt]);
1491      else
1492	log ("%s: NULL",
1493	     str_option_reproducer_strings[opt]);
1494    }
1495}
1496
1497/* Write the current value of the given int option to the
1498   log file (if any).  */
1499
1500void
1501recording::context::log_int_option (enum gcc_jit_int_option opt) const
1502{
1503  gcc_assert (opt < GCC_JIT_NUM_INT_OPTIONS);
1504  if (get_logger ())
1505    log ("%s: %i",
1506	 int_option_reproducer_strings[opt],
1507	 m_int_options[opt]);
1508}
1509
1510/* Write the current value of the given bool option to the
1511   log file (if any).  */
1512
1513void
1514recording::context::log_bool_option (enum gcc_jit_bool_option opt) const
1515{
1516  gcc_assert (opt < GCC_JIT_NUM_BOOL_OPTIONS);
1517  if (get_logger ())
1518    log ("%s: %s",
1519	 bool_option_reproducer_strings[opt],
1520	 m_bool_options[opt] ? "true" : "false");
1521}
1522
1523/* Write the current value of the given "inner" bool option to the
1524   log file (if any).  */
1525
1526void
1527recording::context::log_inner_bool_option (enum inner_bool_option opt) const
1528{
1529  gcc_assert (opt < NUM_INNER_BOOL_OPTIONS);
1530  if (get_logger ())
1531    log ("%s: %s",
1532	 inner_bool_option_reproducer_strings[opt],
1533	 m_inner_bool_options[opt] ? "true" : "false");
1534}
1535
1536/* Write C source code to PATH that attempts to replay the API
1537   calls made to this context (and its parents), for use in
1538   minimizing test cases for libgccjit.
1539
1540   Implements the post-error-checking part of
1541   gcc_jit_context_dump_reproducer_to_file.  */
1542
1543void
1544recording::context::dump_reproducer_to_file (const char *path)
1545{
1546  JIT_LOG_SCOPE (get_logger ());
1547  reproducer r (*this, path);
1548
1549  /* Generate the "ancestry" of this context, as a list.  */
1550  auto_vec <context *> ascending_contexts;
1551  for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
1552    ascending_contexts.safe_push (ctxt);
1553
1554  /* Reverse the list, giving a list of contexts from
1555     top-most parent context down through to youngest child context.
1556     We will use this list as the parameters of the functions in
1557     our generated file.  */
1558  unsigned num_ctxts = ascending_contexts.length ();
1559  auto_vec <context *> contexts (num_ctxts);
1560  for (unsigned i = 0; i < num_ctxts; i++)
1561    contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
1562
1563  /* contexts[0] should be the top-level context.  */
1564  gcc_assert (contexts[0]);
1565  gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
1566
1567  /* The final element in contexts should be "this".  */
1568  gcc_assert (contexts[contexts.length () - 1] == this);
1569  gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
1570	      == contexts[0]);
1571
1572  r.write ("/* This code was autogenerated by"
1573	   " gcc_jit_context_dump_reproducer_to_file.\n\n");
1574  print_version (r.get_file (), "  ", false);
1575  r.write ("*/\n");
1576  r.write ("#include <libgccjit.h>\n\n");
1577  r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1578  r.write ("static void\nset_options (");
1579  r.write_params (contexts);
1580  r.write (");\n\n");
1581  r.write ("static void\ncreate_code (");
1582  r.write_params (contexts);
1583  r.write (");\n\n");
1584  r.write ("int\nmain (int argc, const char **argv)\n");
1585  r.write ("{\n");
1586  for (unsigned i = 0; i < num_ctxts; i++)
1587    r.write ("  gcc_jit_context *%s;\n",
1588	     r.get_identifier (contexts[i]));
1589  r.write ("  gcc_jit_result *result;\n"
1590	   "\n");
1591
1592  /* Create the contexts.
1593     The top-level context is acquired from a clean slate, the others as
1594     children of the prior context.  */
1595  r.write ("  %s = gcc_jit_context_acquire ();\n",
1596	   r.get_identifier (contexts[0]));
1597  for (unsigned i = 1; i < num_ctxts; i++)
1598    r.write ("  %s = gcc_jit_context_new_child_context (%s);\n",
1599	     r.get_identifier (contexts[i]),
1600	     r.get_identifier (contexts[i - 1]));
1601  r.write ("  set_options (");
1602  r.write_args (contexts);
1603  r.write (");\n");
1604  r.write ("  create_code (");
1605  r.write_args (contexts);
1606  r.write (");\n");
1607
1608  r.write ("  result = gcc_jit_context_compile (%s);\n",
1609	   r.get_identifier (this));
1610
1611  for (unsigned i = num_ctxts; i > 0; i--)
1612    r.write ("  gcc_jit_context_release (%s);\n",
1613	     r.get_identifier (contexts[i - 1]));
1614
1615  r.write ("  gcc_jit_result_release (result);\n"
1616	   "  return 0;\n"
1617	   "}\n\n");
1618
1619  /* Define (char *) variables for use in calls to
1620     gcc_jit_context_enable_dump.  */
1621  for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1622    {
1623      if (m_requested_dumps.length ())
1624	{
1625	  r.write ("/* Requested dumps for %s.  */\n",
1626		   r.get_identifier (contexts[ctxt_idx]));
1627	  for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1628	    r.write ("static char *dump_%p;\n",
1629		     (void *)&m_requested_dumps[i]);
1630	  r.write ("\n");
1631	}
1632    }
1633
1634  /* Write out values of options.  */
1635  r.write ("static void\nset_options (");
1636  r.write_params (contexts);
1637  r.write (")\n{\n");
1638  for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1639    {
1640      if (ctxt_idx > 0)
1641	r.write ("\n");
1642
1643      r.write ("  /* Set options for %s.  */\n",
1644	       r.get_identifier (contexts[ctxt_idx]));
1645
1646      r.write ("  /* String options.  */\n");
1647      for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1648	{
1649	  r.write ("  gcc_jit_context_set_str_option (%s,\n"
1650		   "                                  %s,\n",
1651		   r.get_identifier (contexts[ctxt_idx]),
1652		   str_option_reproducer_strings[opt_idx]);
1653	  if (m_str_options[opt_idx])
1654	    r.write ("                                  \"%s\");\n",
1655		     m_str_options[opt_idx]);
1656	  else
1657	    r.write ("                                  NULL);\n");
1658	}
1659      r.write ("  /* Int options.  */\n");
1660      for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1661	r.write ("  gcc_jit_context_set_int_option (%s,\n"
1662		 "                                  %s,\n"
1663		 "                                  %i);\n",
1664		 r.get_identifier (contexts[ctxt_idx]),
1665		 int_option_reproducer_strings[opt_idx],
1666		 m_int_options[opt_idx]);
1667      r.write ("  /* Boolean options.  */\n");
1668      for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1669	r.write ("  gcc_jit_context_set_bool_option (%s,\n"
1670		 "                                  %s,\n"
1671		 "                                  %i);\n",
1672		 r.get_identifier (contexts[ctxt_idx]),
1673		 bool_option_reproducer_strings[opt_idx],
1674		 m_bool_options[opt_idx]);
1675      for (int opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1676	r.write ("  %s (%s, %i);\n",
1677		 inner_bool_option_reproducer_strings[opt_idx],
1678		 r.get_identifier (contexts[ctxt_idx]),
1679		 m_inner_bool_options[opt_idx]);
1680
1681      if (!m_command_line_options.is_empty ())
1682	{
1683	  int i;
1684	  char *optname;
1685	  r.write ("  /* User-provided command-line options.  */\n");
1686	  FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1687	    r.write ("  gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1688		     r.get_identifier (contexts[ctxt_idx]),
1689		     optname);
1690	}
1691
1692      if (m_requested_dumps.length ())
1693	{
1694	  r.write ("  /* Requested dumps.  */\n");
1695	  /* Dumpfiles that were requested via gcc_jit_context_enable_dump.  */
1696	  for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1697	    {
1698	      r.write ("  gcc_jit_context_enable_dump (%s,\n"
1699		       "                               \"%s\",\n"
1700		       "                               &dump_%p);\n",
1701		       r.get_identifier (contexts[ctxt_idx]),
1702		       m_requested_dumps[i].m_dumpname,
1703		       (void *)&m_requested_dumps[i]);
1704	    }
1705	}
1706    }
1707  r.write ("}\n\n");
1708
1709  r.write ("static void\ncreate_code (");
1710  r.write_params (contexts);
1711  r.write (")\n"
1712	   "{\n");
1713  for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1714    {
1715      memento *m;
1716      int i;
1717      if (ctxt_idx > 0)
1718	r.write ("\n\n");
1719
1720      r.write ("  /* Replay of API calls for %s.  */\n",
1721	       r.get_identifier (contexts[ctxt_idx]));
1722      FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
1723	m->write_reproducer (r);
1724    }
1725  r.write ("}\n");
1726}
1727
1728/* Copy the requested dumps within this context and all ancestors into
1729   OUT. */
1730
1731void
1732recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
1733{
1734  if (m_parent_ctxt)
1735    m_parent_ctxt->get_all_requested_dumps (out);
1736
1737  out->reserve (m_requested_dumps.length ());
1738  out->splice (m_requested_dumps);
1739}
1740
1741/* This is a pre-compilation check for the context (and any parents).
1742
1743   Detect errors within the context, adding errors if any are found.  */
1744
1745void
1746recording::context::validate ()
1747{
1748  JIT_LOG_SCOPE (get_logger ());
1749
1750  if (m_parent_ctxt)
1751    m_parent_ctxt->validate ();
1752
1753  int i;
1754  function *fn;
1755  FOR_EACH_VEC_ELT (m_functions, i, fn)
1756    fn->validate ();
1757}
1758
1759/* The implementation of class gcc::jit::recording::memento.  */
1760
1761/* Get a (const char *) debug description of the given memento, by
1762   calling the pure-virtual make_debug_string hook, caching the
1763   result.
1764
1765   It is intended that this should only be called in debugging and
1766   error-handling paths, so this doesn't need to be particularly
1767   optimized.  */
1768
1769const char *
1770recording::memento::get_debug_string ()
1771{
1772  if (!m_debug_string)
1773    m_debug_string = make_debug_string ();
1774  return m_debug_string->c_str ();
1775}
1776
1777/* Default implementation of recording::memento::write_to_dump, writing
1778   an indented form of the memento's debug string to the dump.  */
1779
1780void
1781recording::memento::write_to_dump (dump &d)
1782{
1783  d.write("  %s\n", get_debug_string ());
1784}
1785
1786/* The implementation of class gcc::jit::recording::string.  */
1787
1788/* Constructor for gcc::jit::recording::string::string, allocating a
1789   copy of the given text using new char[].  */
1790
1791recording::string::string (context *ctxt, const char *text)
1792  : memento (ctxt)
1793{
1794  m_len = strlen (text);
1795  m_buffer = new char[m_len + 1];
1796  strcpy (m_buffer, text);
1797}
1798
1799/* Destructor for gcc::jit::recording::string::string.  */
1800
1801recording::string::~string ()
1802{
1803  delete[] m_buffer;
1804}
1805
1806/* Function for making gcc::jit::recording::string instances on a
1807   context via printf-style formatting.
1808
1809   It is intended that this should only be called in debugging and
1810   error-handling paths, so this doesn't need to be particularly
1811   optimized, hence the double-copy of the string is acceptable.  */
1812
1813recording::string *
1814recording::string::from_printf (context *ctxt, const char *fmt, ...)
1815{
1816  int len;
1817  va_list ap;
1818  char *buf;
1819  recording::string *result;
1820
1821  va_start (ap, fmt);
1822  len = vasprintf (&buf, fmt, ap);
1823  va_end (ap);
1824
1825  if (buf == NULL || len < 0)
1826    {
1827      ctxt->add_error (NULL, "malloc failure");
1828      return NULL;
1829    }
1830
1831  result = ctxt->new_string (buf);
1832  free (buf);
1833  return result;
1834}
1835
1836/* Implementation of recording::memento::make_debug_string for strings,
1837   wrapping the given string in quotes and escaping as necessary.  */
1838
1839recording::string *
1840recording::string::make_debug_string ()
1841{
1842  /* Hack to avoid infinite recursion into strings when logging all
1843     mementos: don't re-escape strings:  */
1844  if (m_buffer[0] == '"')
1845    return this;
1846
1847  /* Wrap in quotes and do escaping etc */
1848
1849  size_t sz = (1 /* opening quote */
1850	       + (m_len * 2) /* each char might get escaped */
1851	       + 1 /* closing quote */
1852	       + 1); /* nil termintator */
1853  char *tmp = new char[sz];
1854  size_t len = 0;
1855
1856#define APPEND(CH)  do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1857  APPEND('"'); /* opening quote */
1858  for (size_t i = 0; i < m_len ; i++)
1859    {
1860      char ch = m_buffer[i];
1861      if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
1862	APPEND('\\');
1863      APPEND(ch);
1864    }
1865  APPEND('"'); /* closing quote */
1866#undef APPEND
1867  tmp[len] = '\0'; /* nil termintator */
1868
1869  string *result = m_ctxt->new_string (tmp);
1870
1871  delete[] tmp;
1872  return result;
1873}
1874
1875/* Implementation of recording::memento::write_reproducer for strings. */
1876
1877void
1878recording::string::write_reproducer (reproducer &)
1879{
1880  /* Empty.  */
1881}
1882
1883/* The implementation of class gcc::jit::recording::location.  */
1884
1885/* Implementation of recording::memento::replay_into for locations.
1886
1887   Create a new playback::location and store it into the
1888   recording::location's m_playback_obj field.  */
1889
1890void
1891recording::location::replay_into (replayer *r)
1892{
1893  m_playback_obj = r->new_location (this,
1894				    m_filename->c_str (),
1895				    m_line,
1896				    m_column);
1897}
1898
1899/* Implementation of recording::memento::make_debug_string for locations,
1900   turning them into the usual form:
1901     FILENAME:LINE:COLUMN
1902   like we do when emitting diagnostics.  */
1903
1904recording::string *
1905recording::location::make_debug_string ()
1906{
1907  return string::from_printf (m_ctxt,
1908			      "%s:%i:%i",
1909			      m_filename->c_str (), m_line, m_column);
1910}
1911
1912/* Implementation of recording::memento::write_reproducer for locations. */
1913
1914void
1915recording::location::write_reproducer (reproducer &r)
1916{
1917  const char *id = r.make_identifier (this, "loc");
1918  r.write ("  gcc_jit_location *%s =\n"
1919	   "    gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1920	   "    %s, /* const char *filename */\n"
1921	   "    %i, /* int line */\n"
1922	   "    %i);/* int column */\n",
1923	   id,
1924	   r.get_identifier (get_context ()),
1925	   m_filename->get_debug_string (),
1926	   m_line, m_column);
1927}
1928
1929/* The implementation of class gcc::jit::recording::type.  */
1930
1931/* Given a type T, get the type T*.
1932
1933   If this doesn't already exist, generate a new memento_of_get_pointer
1934   instance and add it to this type's context's list of mementos.
1935
1936   Otherwise, use the cached type.
1937
1938   Implements the post-error-checking part of
1939   gcc_jit_type_get_pointer.  */
1940
1941recording::type *
1942recording::type::get_pointer ()
1943{
1944  if (!m_pointer_to_this_type)
1945    {
1946      m_pointer_to_this_type = new memento_of_get_pointer (this);
1947      m_ctxt->record (m_pointer_to_this_type);
1948    }
1949  return m_pointer_to_this_type;
1950}
1951
1952/* Given a type T, get the type const T.
1953
1954   Implements the post-error-checking part of
1955   gcc_jit_type_get_const.  */
1956
1957recording::type *
1958recording::type::get_const ()
1959{
1960  recording::type *result = new memento_of_get_const (this);
1961  m_ctxt->record (result);
1962  return result;
1963}
1964
1965/* Given a type T, get the type volatile T.
1966
1967   Implements the post-error-checking part of
1968   gcc_jit_type_get_volatile.  */
1969
1970recording::type *
1971recording::type::get_volatile ()
1972{
1973  recording::type *result = new memento_of_get_volatile (this);
1974  m_ctxt->record (result);
1975  return result;
1976}
1977
1978const char *
1979recording::type::access_as_type (reproducer &r)
1980{
1981  return r.get_identifier (this);
1982}
1983
1984/* Implementation of pure virtual hook recording::type::dereference for
1985   recording::memento_of_get_type.  */
1986
1987recording::type *
1988recording::memento_of_get_type::dereference ()
1989{
1990  switch (m_kind)
1991    {
1992    default: gcc_unreachable ();
1993
1994    case GCC_JIT_TYPE_VOID:
1995      return NULL;
1996
1997    case GCC_JIT_TYPE_VOID_PTR:
1998      return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
1999
2000    case GCC_JIT_TYPE_BOOL:
2001    case GCC_JIT_TYPE_CHAR:
2002    case GCC_JIT_TYPE_SIGNED_CHAR:
2003    case GCC_JIT_TYPE_UNSIGNED_CHAR:
2004    case GCC_JIT_TYPE_SHORT:
2005    case GCC_JIT_TYPE_UNSIGNED_SHORT:
2006    case GCC_JIT_TYPE_INT:
2007    case GCC_JIT_TYPE_UNSIGNED_INT:
2008    case GCC_JIT_TYPE_LONG:
2009    case GCC_JIT_TYPE_UNSIGNED_LONG:
2010    case GCC_JIT_TYPE_LONG_LONG:
2011    case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2012    case GCC_JIT_TYPE_FLOAT:
2013    case GCC_JIT_TYPE_DOUBLE:
2014    case GCC_JIT_TYPE_LONG_DOUBLE:
2015    case GCC_JIT_TYPE_COMPLEX_FLOAT:
2016    case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2017    case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2018      /* Not a pointer: */
2019      return NULL;
2020
2021    case GCC_JIT_TYPE_CONST_CHAR_PTR:
2022      return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
2023
2024    case GCC_JIT_TYPE_SIZE_T:
2025      /* Not a pointer: */
2026      return NULL;
2027
2028    case GCC_JIT_TYPE_FILE_PTR:
2029      /* Give the client code back an opaque "struct FILE".  */
2030      return m_ctxt->get_opaque_FILE_type ();
2031    }
2032}
2033
2034/* Implementation of pure virtual hook recording::type::is_int for
2035   recording::memento_of_get_type.  */
2036
2037bool
2038recording::memento_of_get_type::is_int () const
2039{
2040  switch (m_kind)
2041    {
2042    default: gcc_unreachable ();
2043
2044    case GCC_JIT_TYPE_VOID:
2045      return false;
2046
2047    case GCC_JIT_TYPE_VOID_PTR:
2048      return false;
2049
2050    case GCC_JIT_TYPE_BOOL:
2051      return false;
2052
2053    case GCC_JIT_TYPE_CHAR:
2054    case GCC_JIT_TYPE_SIGNED_CHAR:
2055    case GCC_JIT_TYPE_UNSIGNED_CHAR:
2056    case GCC_JIT_TYPE_SHORT:
2057    case GCC_JIT_TYPE_UNSIGNED_SHORT:
2058    case GCC_JIT_TYPE_INT:
2059    case GCC_JIT_TYPE_UNSIGNED_INT:
2060    case GCC_JIT_TYPE_LONG:
2061    case GCC_JIT_TYPE_UNSIGNED_LONG:
2062    case GCC_JIT_TYPE_LONG_LONG:
2063    case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2064      return true;
2065
2066    case GCC_JIT_TYPE_FLOAT:
2067    case GCC_JIT_TYPE_DOUBLE:
2068    case GCC_JIT_TYPE_LONG_DOUBLE:
2069      return false;
2070
2071    case GCC_JIT_TYPE_CONST_CHAR_PTR:
2072      return false;
2073
2074    case GCC_JIT_TYPE_SIZE_T:
2075      return true;
2076
2077    case GCC_JIT_TYPE_FILE_PTR:
2078      return false;
2079
2080    case GCC_JIT_TYPE_COMPLEX_FLOAT:
2081    case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2082    case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2083      return false;
2084    }
2085}
2086
2087/* Implementation of pure virtual hook recording::type::is_float for
2088   recording::memento_of_get_type.  */
2089
2090bool
2091recording::memento_of_get_type::is_float () const
2092{
2093  switch (m_kind)
2094    {
2095    default: gcc_unreachable ();
2096
2097    case GCC_JIT_TYPE_VOID:
2098      return false;
2099
2100    case GCC_JIT_TYPE_VOID_PTR:
2101      return false;
2102
2103    case GCC_JIT_TYPE_BOOL:
2104      return false;
2105
2106    case GCC_JIT_TYPE_CHAR:
2107    case GCC_JIT_TYPE_SIGNED_CHAR:
2108    case GCC_JIT_TYPE_UNSIGNED_CHAR:
2109    case GCC_JIT_TYPE_SHORT:
2110    case GCC_JIT_TYPE_UNSIGNED_SHORT:
2111    case GCC_JIT_TYPE_INT:
2112    case GCC_JIT_TYPE_UNSIGNED_INT:
2113    case GCC_JIT_TYPE_LONG:
2114    case GCC_JIT_TYPE_UNSIGNED_LONG:
2115    case GCC_JIT_TYPE_LONG_LONG:
2116    case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2117      return false;
2118
2119    case GCC_JIT_TYPE_FLOAT:
2120    case GCC_JIT_TYPE_DOUBLE:
2121    case GCC_JIT_TYPE_LONG_DOUBLE:
2122      return true;
2123
2124    case GCC_JIT_TYPE_CONST_CHAR_PTR:
2125      return false;
2126
2127    case GCC_JIT_TYPE_SIZE_T:
2128      return false;
2129
2130    case GCC_JIT_TYPE_FILE_PTR:
2131      return false;
2132
2133    case GCC_JIT_TYPE_COMPLEX_FLOAT:
2134    case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2135    case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2136      return true;
2137    }
2138}
2139
2140/* Implementation of pure virtual hook recording::type::is_bool for
2141   recording::memento_of_get_type.  */
2142
2143bool
2144recording::memento_of_get_type::is_bool () const
2145{
2146  switch (m_kind)
2147    {
2148    default: gcc_unreachable ();
2149
2150    case GCC_JIT_TYPE_VOID:
2151      return false;
2152
2153    case GCC_JIT_TYPE_VOID_PTR:
2154      return false;
2155
2156    case GCC_JIT_TYPE_BOOL:
2157      return true;
2158
2159    case GCC_JIT_TYPE_CHAR:
2160    case GCC_JIT_TYPE_SIGNED_CHAR:
2161    case GCC_JIT_TYPE_UNSIGNED_CHAR:
2162    case GCC_JIT_TYPE_SHORT:
2163    case GCC_JIT_TYPE_UNSIGNED_SHORT:
2164    case GCC_JIT_TYPE_INT:
2165    case GCC_JIT_TYPE_UNSIGNED_INT:
2166    case GCC_JIT_TYPE_LONG:
2167    case GCC_JIT_TYPE_UNSIGNED_LONG:
2168    case GCC_JIT_TYPE_LONG_LONG:
2169    case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2170      return false;
2171
2172    case GCC_JIT_TYPE_FLOAT:
2173    case GCC_JIT_TYPE_DOUBLE:
2174    case GCC_JIT_TYPE_LONG_DOUBLE:
2175      return false;
2176
2177    case GCC_JIT_TYPE_CONST_CHAR_PTR:
2178      return false;
2179
2180    case GCC_JIT_TYPE_SIZE_T:
2181      return false;
2182
2183    case GCC_JIT_TYPE_FILE_PTR:
2184      return false;
2185
2186    case GCC_JIT_TYPE_COMPLEX_FLOAT:
2187    case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2188    case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2189      return false;
2190    }
2191}
2192
2193/* Implementation of pure virtual hook recording::memento::replay_into
2194   for recording::memento_of_get_type.  */
2195
2196void
2197recording::memento_of_get_type::replay_into (replayer *r)
2198{
2199  set_playback_obj (r->get_type (m_kind));
2200}
2201
2202/* The implementation of class gcc::jit::recording::memento_of_get_type.  */
2203
2204/* Descriptive strings for each of enum gcc_jit_types.  */
2205
2206static const char * const get_type_strings[] = {
2207  "void",    /* GCC_JIT_TYPE_VOID */
2208  "void *",  /* GCC_JIT_TYPE_VOID_PTR */
2209
2210  "bool",  /* GCC_JIT_TYPE_BOOL */
2211
2212  "char",           /* GCC_JIT_TYPE_CHAR */
2213  "signed char",    /* GCC_JIT_TYPE_SIGNED_CHAR */
2214  "unsigned char",  /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2215
2216  "short",           /* GCC_JIT_TYPE_SHORT */
2217  "unsigned short",  /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2218
2219  "int",           /* GCC_JIT_TYPE_INT */
2220  "unsigned int",  /* GCC_JIT_TYPE_UNSIGNED_INT */
2221
2222  "long",           /* GCC_JIT_TYPE_LONG  */
2223  "unsigned long",  /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2224
2225  "long long",           /* GCC_JIT_TYPE_LONG_LONG */
2226  "unsigned long long",  /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2227
2228  "float",        /* GCC_JIT_TYPE_FLOAT */
2229  "double",       /* GCC_JIT_TYPE_DOUBLE */
2230  "long double",  /* GCC_JIT_TYPE_LONG_DOUBLE */
2231
2232  "const char *",  /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2233
2234  "size_t",  /* GCC_JIT_TYPE_SIZE_T */
2235
2236  "FILE *",  /* GCC_JIT_TYPE_FILE_PTR */
2237
2238  "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2239  "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2240  "complex long double"  /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2241
2242};
2243
2244/* Implementation of recording::memento::make_debug_string for
2245   results of get_type, using a simple table of type names.  */
2246
2247recording::string *
2248recording::memento_of_get_type::make_debug_string ()
2249{
2250  return m_ctxt->new_string (get_type_strings[m_kind]);
2251}
2252
2253static const char * const get_type_enum_strings[] = {
2254  "GCC_JIT_TYPE_VOID",
2255  "GCC_JIT_TYPE_VOID_PTR",
2256  "GCC_JIT_TYPE_BOOL",
2257  "GCC_JIT_TYPE_CHAR",
2258  "GCC_JIT_TYPE_SIGNED_CHAR",
2259  "GCC_JIT_TYPE_UNSIGNED_CHAR",
2260  "GCC_JIT_TYPE_SHORT",
2261  "GCC_JIT_TYPE_UNSIGNED_SHORT",
2262  "GCC_JIT_TYPE_INT",
2263  "GCC_JIT_TYPE_UNSIGNED_INT",
2264  "GCC_JIT_TYPE_LONG",
2265  "GCC_JIT_TYPE_UNSIGNED_LONG",
2266  "GCC_JIT_TYPE_LONG_LONG",
2267  "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2268  "GCC_JIT_TYPE_FLOAT",
2269  "GCC_JIT_TYPE_DOUBLE",
2270  "GCC_JIT_TYPE_LONG_DOUBLE",
2271  "GCC_JIT_TYPE_CONST_CHAR_PTR",
2272  "GCC_JIT_TYPE_SIZE_T",
2273  "GCC_JIT_TYPE_FILE_PTR",
2274  "GCC_JIT_TYPE_COMPLEX_FLOAT",
2275  "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2276  "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2277};
2278
2279void
2280recording::memento_of_get_type::write_reproducer (reproducer &r)
2281{
2282  const char *id = r.make_identifier (this, "type");
2283  r.write ("  gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2284	   id,
2285	   r.get_identifier (get_context ()),
2286	   get_type_enum_strings[m_kind]);
2287}
2288
2289/* The implementation of class gcc::jit::recording::memento_of_get_pointer.  */
2290
2291/* Override of default implementation of
2292   recording::type::accepts_writes_from for get_pointer.
2293
2294   Require a pointer type, and allowing writes to
2295   (const T *) from a (T*), but not the other way around.  */
2296
2297bool
2298recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2299{
2300  /* Must be a pointer type: */
2301  type *rtype_points_to = rtype->is_pointer ();
2302  if (!rtype_points_to)
2303    return false;
2304
2305  /* It's OK to assign to a (const T *) from a (T *).  */
2306  return m_other_type->unqualified ()
2307    ->accepts_writes_from (rtype_points_to);
2308}
2309
2310/* Implementation of pure virtual hook recording::memento::replay_into
2311   for recording::memento_of_get_pointer.  */
2312
2313void
2314recording::memento_of_get_pointer::replay_into (replayer *)
2315{
2316  set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2317}
2318
2319/* Implementation of recording::memento::make_debug_string for
2320   results of get_pointer, adding " *" to the underlying type,
2321   with special-casing to handle function pointer types.  */
2322
2323recording::string *
2324recording::memento_of_get_pointer::make_debug_string ()
2325{
2326  /* Special-case function pointer types, to put the "*" in parens between
2327     the return type and the params (for one level of dereferencing, at
2328     least).  */
2329  if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2330    return fn_type->make_debug_string_with_ptr ();
2331
2332  return string::from_printf (m_ctxt,
2333			      "%s *", m_other_type->get_debug_string ());
2334}
2335
2336/* Implementation of recording::memento::write_reproducer for get_pointer.  */
2337
2338void
2339recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2340{
2341  /* We need to special-case function pointer types; see the notes in
2342     recording::function_type::write_deferred_reproducer.  */
2343  if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2344    {
2345      fn_type->write_deferred_reproducer (r, this);
2346      return;
2347    }
2348
2349  const char *id = r.make_identifier (this, "type");
2350  r.write ("  gcc_jit_type *%s =\n"
2351	   "    gcc_jit_type_get_pointer (%s);\n",
2352	   id,
2353	   r.get_identifier_as_type (m_other_type));
2354}
2355
2356/* The implementation of class gcc::jit::recording::memento_of_get_const.  */
2357
2358/* Implementation of pure virtual hook recording::memento::replay_into
2359   for recording::memento_of_get_const.  */
2360
2361void
2362recording::memento_of_get_const::replay_into (replayer *)
2363{
2364  set_playback_obj (m_other_type->playback_type ()->get_const ());
2365}
2366
2367/* Implementation of recording::memento::make_debug_string for
2368   results of get_const, prepending "const ".  */
2369
2370recording::string *
2371recording::memento_of_get_const::make_debug_string ()
2372{
2373  return string::from_printf (m_ctxt,
2374			      "const %s", m_other_type->get_debug_string ());
2375}
2376
2377/* Implementation of recording::memento::write_reproducer for const types. */
2378
2379void
2380recording::memento_of_get_const::write_reproducer (reproducer &r)
2381{
2382  const char *id = r.make_identifier (this, "type");
2383  r.write ("  gcc_jit_type *%s =\n"
2384	   "    gcc_jit_type_get_const (%s);\n",
2385	   id,
2386	   r.get_identifier_as_type (m_other_type));
2387}
2388
2389/* The implementation of class gcc::jit::recording::memento_of_get_volatile.  */
2390
2391/* Implementation of pure virtual hook recording::memento::replay_into
2392   for recording::memento_of_get_volatile.  */
2393
2394void
2395recording::memento_of_get_volatile::replay_into (replayer *)
2396{
2397  set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2398}
2399
2400/* Implementation of recording::memento::make_debug_string for
2401   results of get_volatile, prepending "volatile ".  */
2402
2403recording::string *
2404recording::memento_of_get_volatile::make_debug_string ()
2405{
2406  return string::from_printf (m_ctxt,
2407			      "volatile %s", m_other_type->get_debug_string ());
2408}
2409
2410/* Implementation of recording::memento::write_reproducer for volatile
2411   types. */
2412
2413void
2414recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2415{
2416  const char *id = r.make_identifier (this, "type");
2417  r.write ("  gcc_jit_type *%s =\n"
2418	   "    gcc_jit_type_get_volatile (%s);\n",
2419	   id,
2420	   r.get_identifier_as_type (m_other_type));
2421}
2422
2423/* The implementation of class gcc::jit::recording::array_type */
2424
2425/* Implementation of pure virtual hook recording::type::dereference for
2426   recording::array_type.  */
2427
2428recording::type *
2429recording::array_type::dereference ()
2430{
2431  return m_element_type;
2432}
2433
2434/* Implementation of pure virtual hook recording::memento::replay_into
2435   for recording::array_type.  */
2436
2437void
2438recording::array_type::replay_into (replayer *r)
2439{
2440  set_playback_obj (r->new_array_type (playback_location (r, m_loc),
2441				       m_element_type->playback_type (),
2442				       m_num_elements));
2443}
2444
2445/* Implementation of recording::memento::make_debug_string for
2446   results of new_array_type.  */
2447
2448recording::string *
2449recording::array_type::make_debug_string ()
2450{
2451  return string::from_printf (m_ctxt,
2452			      "%s[%d]",
2453			      m_element_type->get_debug_string (),
2454			      m_num_elements);
2455}
2456
2457/* Implementation of recording::memento::write_reproducer for array
2458   types. */
2459
2460void
2461recording::array_type::write_reproducer (reproducer &r)
2462{
2463  const char *id = r.make_identifier (this, "array_type");
2464  r.write ("  gcc_jit_type *%s =\n"
2465	   "    gcc_jit_context_new_array_type (%s,\n"
2466	   "                                    %s, /* gcc_jit_location *loc */\n"
2467	   "                                    %s, /* gcc_jit_type *element_type */\n"
2468	   "                                    %i); /* int num_elements */\n",
2469	   id,
2470	   r.get_identifier (get_context ()),
2471	   r.get_identifier (m_loc),
2472	   r.get_identifier_as_type (m_element_type),
2473	   m_num_elements);
2474}
2475
2476/* The implementation of class gcc::jit::recording::function_type */
2477
2478/* Constructor for gcc::jit::recording::function_type.  */
2479
2480recording::function_type::function_type (context *ctxt,
2481					 type *return_type,
2482					 int num_params,
2483					 type **param_types,
2484					 int is_variadic)
2485: type (ctxt),
2486  m_return_type (return_type),
2487  m_param_types (),
2488  m_is_variadic (is_variadic)
2489{
2490  for (int i = 0; i< num_params; i++)
2491    m_param_types.safe_push (param_types[i]);
2492}
2493
2494/* Implementation of pure virtual hook recording::type::dereference for
2495   recording::function_type.  */
2496
2497recording::type *
2498recording::function_type::dereference ()
2499{
2500  return NULL;
2501}
2502
2503/* Implementation of pure virtual hook recording::memento::replay_into
2504   for recording::function_type.  */
2505
2506void
2507recording::function_type::replay_into (replayer *r)
2508{
2509  /* Convert m_param_types to a vec of playback type.  */
2510  auto_vec <playback::type *> param_types;
2511  int i;
2512  recording::type *type;
2513  param_types.create (m_param_types.length ());
2514  FOR_EACH_VEC_ELT (m_param_types, i, type)
2515    param_types.safe_push (type->playback_type ());
2516
2517  set_playback_obj (r->new_function_type (m_return_type->playback_type (),
2518					  &param_types,
2519					  m_is_variadic));
2520}
2521
2522/* Special-casing for make_debug_string for get_pointer results for
2523   handling (one level) of pointers to functions.  */
2524
2525recording::string *
2526recording::function_type::make_debug_string_with_ptr ()
2527{
2528  return make_debug_string_with ("(*) ");
2529}
2530
2531/* Implementation of recording::memento::make_debug_string for
2532   results of new_function_type.  */
2533
2534recording::string *
2535recording::function_type::make_debug_string ()
2536{
2537  return make_debug_string_with ("");
2538}
2539
2540/* Build a debug string representation of the form:
2541
2542     RESULT_TYPE INSERT (PARAM_TYPES)
2543
2544   for use when handling 0 and 1 level of indirection to this
2545   function type.  */
2546
2547recording::string *
2548recording::function_type::make_debug_string_with (const char *insert)
2549{
2550  /* First, build a buffer for the arguments.  */
2551  /* Calculate length of said buffer.  */
2552  size_t sz = 1; /* nil terminator */
2553  for (unsigned i = 0; i< m_param_types.length (); i++)
2554    {
2555      sz += strlen (m_param_types[i]->get_debug_string ());
2556      sz += 2; /* ", " separator */
2557    }
2558  if (m_is_variadic)
2559    sz += 5; /* ", ..." separator and ellipsis */
2560
2561  /* Now allocate and populate the buffer.  */
2562  char *argbuf = new char[sz];
2563  size_t len = 0;
2564
2565  for (unsigned i = 0; i< m_param_types.length (); i++)
2566    {
2567      strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
2568      len += strlen (m_param_types[i]->get_debug_string ());
2569      if (i + 1 < m_param_types.length ())
2570	{
2571	  strcpy (argbuf + len, ", ");
2572	  len += 2;
2573	}
2574    }
2575  if (m_is_variadic)
2576    {
2577      if (m_param_types.length ())
2578	{
2579	  strcpy (argbuf + len, ", ");
2580	  len += 2;
2581	}
2582      strcpy (argbuf + len, "...");
2583      len += 3;
2584    }
2585  argbuf[len] = '\0';
2586
2587  /* ...and use it to get the string for the call as a whole.  */
2588  string *result = string::from_printf (m_ctxt,
2589					"%s %s(%s)",
2590					m_return_type->get_debug_string (),
2591					insert,
2592					argbuf);
2593
2594  delete[] argbuf;
2595
2596  return result;
2597}
2598
2599/* Implementation of recording::memento::write_reproducer for function
2600   types.  */
2601
2602void
2603recording::function_type::write_reproducer (reproducer &)
2604{
2605  /* see notes below.  */
2606}
2607
2608/* There's a get_pointer within context::new_function_ptr_type:
2609   the type received by client code isn't the memento for the
2610   function_type, but instead the result of get_pointer on it.
2611
2612   Hence we can't directly write a reproducer that gives function_type.
2613   Instead we special-case things within get_pointer, detecting this
2614   case, calling the following function.  */
2615
2616void
2617recording::function_type::write_deferred_reproducer (reproducer &r,
2618						     memento *ptr_type)
2619{
2620  gcc_assert (ptr_type);
2621  r.make_identifier (this, "function_type");
2622  const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
2623  const char *param_types_id = r.make_tmp_identifier ("params_for", this);
2624  r.write ("  gcc_jit_type *%s[%i] = {\n",
2625	   param_types_id,
2626	   m_param_types.length ());
2627  int i;
2628  type *param_type;
2629  FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2630    r.write ("    %s,\n", r.get_identifier_as_type (param_type));
2631  r.write ("  };\n");
2632  r.write ("  gcc_jit_type *%s =\n"
2633	   "    gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2634	   "                                           %s, /* gcc_jit_location *loc */\n"
2635	   "                                           %s, /* gcc_jit_type *return_type */\n"
2636	   "                                           %i, /* int num_params */\n"
2637	   "                                           %s, /* gcc_jit_type **param_types */\n"
2638	   "                                           %i); /* int is_variadic */\n",
2639	   ptr_id,
2640	   r.get_identifier (get_context ()),
2641	   "NULL", /* location is not stored */
2642	   r.get_identifier_as_type (m_return_type),
2643	   m_param_types.length (),
2644	   param_types_id,
2645	   m_is_variadic);
2646}
2647
2648/* The implementation of class gcc::jit::recording::field.  */
2649
2650/* Implementation of pure virtual hook recording::memento::replay_into
2651   for recording::field.  */
2652
2653void
2654recording::field::replay_into (replayer *r)
2655{
2656  set_playback_obj (r->new_field (playback_location (r, m_loc),
2657				  m_type->playback_type (),
2658				  playback_string (m_name)));
2659}
2660
2661/* Override the default implementation of
2662   recording::memento::write_to_dump.  Dump each field
2663   by dumping a line of the form:
2664      TYPE NAME;
2665   so that we can build up a struct/union field-byfield.  */
2666
2667void
2668recording::field::write_to_dump (dump &d)
2669{
2670  d.write ("  %s %s;\n",
2671	   m_type->get_debug_string (),
2672	   m_name->c_str ());
2673}
2674
2675/* Implementation of recording::memento::make_debug_string for
2676   results of new_field.  */
2677
2678recording::string *
2679recording::field::make_debug_string ()
2680{
2681  return m_name;
2682}
2683
2684/* Implementation of recording::memento::write_reproducer for fields.  */
2685
2686void
2687recording::field::write_reproducer (reproducer &r)
2688{
2689  const char *id = r.make_identifier (this, "field");
2690  r.write("  gcc_jit_field *%s =\n"
2691	  "    gcc_jit_context_new_field (%s,\n"
2692	  "                               %s, /* gcc_jit_location *loc */\n"
2693	  "                               %s, /* gcc_jit_type *type, */\n"
2694	  "                               %s); /* const char *name */\n",
2695	  id,
2696	  r.get_identifier (get_context ()),
2697	  r.get_identifier (m_loc),
2698	  r.get_identifier_as_type (m_type),
2699	  m_name->get_debug_string ());
2700}
2701
2702/* The implementation of class gcc::jit::recording::compound_type */
2703
2704/* The constructor for gcc::jit::recording::compound_type.  */
2705
2706recording::compound_type::compound_type (context *ctxt,
2707					 location *loc,
2708					 string *name)
2709: type (ctxt),
2710  m_loc (loc),
2711  m_name (name),
2712  m_fields (NULL)
2713{
2714}
2715
2716/* Set the fields of a compound type.
2717
2718   Implements the post-error-checking part of
2719   gcc_jit_struct_set_fields, and is also used by
2720   gcc_jit_context_new_union_type.  */
2721
2722void
2723recording::compound_type::set_fields (location *loc,
2724				      int num_fields,
2725				      field **field_array)
2726{
2727  m_loc = loc;
2728  gcc_assert (NULL == m_fields);
2729
2730  m_fields = new fields (this, num_fields, field_array);
2731  m_ctxt->record (m_fields);
2732}
2733
2734/* Implementation of pure virtual hook recording::type::dereference for
2735   recording::compound_type.  */
2736
2737recording::type *
2738recording::compound_type::dereference ()
2739{
2740  return NULL; /* not a pointer */
2741}
2742
2743/* The implementation of class gcc::jit::recording::struct_.  */
2744
2745/* The constructor for gcc::jit::recording::struct_.  */
2746
2747recording::struct_::struct_ (context *ctxt,
2748			     location *loc,
2749			     string *name)
2750: compound_type (ctxt, loc, name)
2751{
2752}
2753
2754/* Implementation of pure virtual hook recording::memento::replay_into
2755   for recording::struct_.  */
2756
2757void
2758recording::struct_::replay_into (replayer *r)
2759{
2760  set_playback_obj (
2761    r->new_compound_type (playback_location (r, get_loc ()),
2762			  get_name ()->c_str (),
2763			  true /* is_struct */));
2764}
2765
2766const char *
2767recording::struct_::access_as_type (reproducer &r)
2768{
2769  return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2770			   r.get_identifier (this));
2771}
2772
2773/* Implementation of recording::memento::make_debug_string for
2774   structs.  */
2775
2776recording::string *
2777recording::struct_::make_debug_string ()
2778{
2779  return string::from_printf (m_ctxt,
2780			      "struct %s", get_name ()->c_str ());
2781}
2782
2783void
2784recording::struct_::write_reproducer (reproducer &r)
2785{
2786  const char *id = r.make_identifier (this, "struct");
2787  r.write ("  gcc_jit_struct *%s =\n"
2788	   "    gcc_jit_context_new_opaque_struct (%s,\n"
2789	   "                                       %s, /* gcc_jit_location *loc */\n"
2790	   "                                       %s); /* const char *name */\n",
2791	   id,
2792	   r.get_identifier (get_context ()),
2793	   r.get_identifier (get_loc ()),
2794	   get_name ()->get_debug_string ());
2795}
2796
2797/* The implementation of class gcc::jit::recording::union_.  */
2798
2799/* The constructor for gcc::jit::recording::union_.  */
2800
2801recording::union_::union_ (context *ctxt,
2802			   location *loc,
2803			   string *name)
2804: compound_type (ctxt, loc, name)
2805{
2806}
2807
2808/* Implementation of pure virtual hook recording::memento::replay_into
2809   for recording::union_.  */
2810
2811void
2812recording::union_::replay_into (replayer *r)
2813{
2814  set_playback_obj (
2815    r->new_compound_type (playback_location (r, get_loc ()),
2816			  get_name ()->c_str (),
2817			  false /* is_struct */));
2818}
2819
2820/* Implementation of recording::memento::make_debug_string for
2821   unions.  */
2822
2823recording::string *
2824recording::union_::make_debug_string ()
2825{
2826  return string::from_printf (m_ctxt,
2827			      "union %s", get_name ()->c_str ());
2828}
2829
2830/* Implementation of recording::memento::write_reproducer for unions.  */
2831
2832void
2833recording::union_::write_reproducer (reproducer &r)
2834{
2835  const char *id = r.make_identifier (this, "union");
2836
2837  const char *fields_id = r.make_tmp_identifier ("fields_for", this);
2838  r.write ("  gcc_jit_field *%s[%i] = {\n",
2839	   fields_id,
2840	   get_fields ()->length ());
2841  for (int i = 0; i < get_fields ()->length (); i++)
2842    r.write ("    %s,\n", r.get_identifier (get_fields ()->get_field (i)));
2843  r.write ("  };\n");
2844
2845  r.write ("  gcc_jit_type *%s =\n"
2846	   "    gcc_jit_context_new_union_type (%s,\n"
2847	   "                                    %s, /* gcc_jit_location *loc */\n"
2848	   "                                    %s, /* const char *name */\n"
2849	   "                                    %i, /* int num_fields */\n"
2850	   "                                    %s); /* gcc_jit_field **fields */\n",
2851	   id,
2852	   r.get_identifier (get_context ()),
2853	   r.get_identifier (get_loc ()),
2854	   get_name ()->get_debug_string (),
2855	   get_fields ()->length (),
2856	   fields_id);
2857}
2858
2859/* The implementation of class gcc::jit::recording::fields.  */
2860
2861/* The constructor for gcc::jit::recording::fields.  */
2862
2863recording::fields::fields (compound_type *struct_or_union,
2864			   int num_fields,
2865			   field **fields)
2866: memento (struct_or_union->m_ctxt),
2867  m_struct_or_union (struct_or_union),
2868  m_fields ()
2869{
2870  for (int i = 0; i < num_fields; i++)
2871    {
2872      gcc_assert (fields[i]->get_container () == NULL);
2873      fields[i]->set_container (m_struct_or_union);
2874      m_fields.safe_push (fields[i]);
2875    }
2876}
2877
2878/* Implementation of pure virtual hook recording::memento::replay_into
2879   for recording::fields.  */
2880
2881void
2882recording::fields::replay_into (replayer *)
2883{
2884  auto_vec<playback::field *> playback_fields;
2885  playback_fields.create (m_fields.length ());
2886  for (unsigned i = 0; i < m_fields.length (); i++)
2887    playback_fields.safe_push (m_fields[i]->playback_field ());
2888  m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
2889}
2890
2891/* Override the default implementation of
2892   recording::memento::write_to_dump by writing a union/struct
2893   declaration of this form:
2894
2895      struct/union NAME {
2896	TYPE_1 NAME_1;
2897	TYPE_2 NAME_2;
2898	....
2899	TYPE_N NAME_N;
2900      };
2901
2902    to the dump.  */
2903
2904void
2905recording::fields::write_to_dump (dump &d)
2906{
2907  int i;
2908  field *f;
2909
2910  d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
2911  FOR_EACH_VEC_ELT (m_fields, i, f)
2912    f->write_to_dump (d);
2913  d.write ("};\n");
2914}
2915
2916/* Implementation of recording::memento::write_reproducer for the fields
2917   subclass.  */
2918
2919void
2920recording::fields::write_reproducer (reproducer &r)
2921{
2922  if (m_struct_or_union)
2923    if (NULL == m_struct_or_union->dyn_cast_struct ())
2924      /* We have a union; the fields have already been written by
2925	 union::write_reproducer.  */
2926      return;
2927
2928  const char *fields_id = r.make_identifier (this, "fields");
2929  r.write ("  gcc_jit_field *%s[%i] = {\n",
2930	   fields_id,
2931	   m_fields.length ());
2932  int i;
2933  field *field;
2934  FOR_EACH_VEC_ELT (m_fields, i, field)
2935    r.write ("    %s,\n", r.get_identifier (field));
2936  r.write ("  };\n");
2937
2938  r.write ("  gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
2939	   "                             %s, /* gcc_jit_location *loc */\n"
2940	   "                             %i, /* int num_fields */\n"
2941	   "                             %s); /* gcc_jit_field **fields */\n",
2942	   r.get_identifier (m_struct_or_union),
2943	   r.get_identifier ((memento *)NULL),
2944	   m_fields.length (),
2945	   fields_id);
2946}
2947
2948/* Implementation of recording::memento::make_debug_string for
2949   field tables.  */
2950
2951recording::string *
2952recording::fields::make_debug_string ()
2953{
2954  return string::from_printf (m_ctxt,
2955			      "fields");
2956}
2957
2958/* The implementation of class gcc::jit::recording::rvalue.  */
2959
2960/* Create a recording::access_field_rvalue instance and add it to
2961   the rvalue's context's list of mementos.
2962
2963   Implements the post-error-checking part of
2964   gcc_jit_rvalue_access_field.  */
2965
2966recording::rvalue *
2967recording::rvalue::access_field (recording::location *loc,
2968				 field *field)
2969{
2970  recording::rvalue *result =
2971    new access_field_rvalue (m_ctxt, loc, this, field);
2972  m_ctxt->record (result);
2973  return result;
2974}
2975
2976/* Create a recording::dereference_field_rvalue instance and add it to
2977   the rvalue's context's list of mementos.
2978
2979   Implements the post-error-checking part of
2980   gcc_jit_rvalue_dereference_field.  */
2981
2982recording::lvalue *
2983recording::rvalue::dereference_field (recording::location *loc,
2984				      field *field)
2985{
2986  recording::lvalue *result =
2987    new dereference_field_rvalue (m_ctxt, loc, this, field);
2988  m_ctxt->record (result);
2989  return result;
2990}
2991
2992/* Create a recording::dereference_rvalue instance and add it to the
2993   rvalue's context's list of mementos.
2994
2995   Implements the post-error-checking part of
2996   gcc_jit_rvalue_dereference.  */
2997
2998recording::lvalue *
2999recording::rvalue::dereference (recording::location *loc)
3000{
3001  recording::lvalue *result =
3002    new dereference_rvalue (m_ctxt, loc, this);
3003  m_ctxt->record (result);
3004  return result;
3005}
3006
3007/* An rvalue visitor, for validating that every rvalue within an expression
3008   trees within "STMT" has the correct scope (e.g. no access to locals
3009   of a different function).  */
3010
3011class rvalue_usage_validator : public recording::rvalue_visitor
3012{
3013 public:
3014  rvalue_usage_validator (const char *api_funcname,
3015			  recording::context *ctxt,
3016			  recording::statement *stmt);
3017
3018  void
3019  visit (recording::rvalue *rvalue);
3020
3021 private:
3022  const char *m_api_funcname;
3023  recording::context *m_ctxt;
3024  recording::statement *m_stmt;
3025};
3026
3027/* The trivial constructor for rvalue_usage_validator.  */
3028
3029rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
3030						recording::context *ctxt,
3031						recording::statement *stmt)
3032  : m_api_funcname (api_funcname),
3033    m_ctxt (ctxt),
3034    m_stmt (stmt)
3035{
3036}
3037
3038/* Verify that the given rvalue is in the correct scope.  */
3039
3040void
3041rvalue_usage_validator::visit (recording::rvalue *rvalue)
3042{
3043  gcc_assert (m_stmt->get_block ());
3044  recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
3045
3046  /* Most rvalues don't have a scope (only locals and params).  */
3047  if (rvalue->get_scope ())
3048    {
3049      if (rvalue->get_scope () != stmt_scope)
3050	m_ctxt->add_error
3051	  (rvalue->get_loc (),
3052	   "%s:"
3053	   " rvalue %s (type: %s)"
3054	   " has scope limited to function %s"
3055	   " but was used within function %s"
3056	   " (in statement: %s)",
3057	   m_api_funcname,
3058	   rvalue->get_debug_string (),
3059	   rvalue->get_type ()->get_debug_string (),
3060	   rvalue->get_scope ()->get_debug_string (),
3061	   stmt_scope->get_debug_string (),
3062	   m_stmt->get_debug_string ());
3063    }
3064  else
3065    {
3066      if (rvalue->dyn_cast_param ())
3067	m_ctxt->add_error
3068	  (rvalue->get_loc (),
3069	   "%s:"
3070	   " param %s (type: %s)"
3071	   " was used within function %s"
3072	   " (in statement: %s)"
3073	   " but is not associated with any function",
3074	   m_api_funcname,
3075	   rvalue->get_debug_string (),
3076	   rvalue->get_type ()->get_debug_string (),
3077	   stmt_scope->get_debug_string (),
3078	   m_stmt->get_debug_string ());
3079    }
3080}
3081
3082/* Verify that it's valid to use this rvalue (and all expressions
3083   in the tree below it) within the given statement.
3084
3085   For example, we must reject attempts to use a local from one
3086   function within a different function here, or we'll get
3087   an ICE deep inside toplev::main.  */
3088
3089void
3090recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
3091{
3092  rvalue_usage_validator v (api_funcname,
3093			    s->get_context (),
3094			    s);
3095
3096  /* Verify that it's OK to use this rvalue within s.  */
3097  v.visit (this);
3098
3099  /* Traverse the expression tree below "this", verifying all rvalues
3100     within it.  */
3101  visit_children (&v);
3102}
3103
3104/* Set the scope of this rvalue to be the given function.  This can only
3105   be done once on a given rvalue.  */
3106
3107void
3108recording::rvalue::set_scope (function *scope)
3109{
3110  gcc_assert (scope);
3111  gcc_assert (NULL == m_scope);
3112  m_scope = scope;
3113}
3114
3115
3116/* Implementation of recording::rvalue::access_as_rvalue for rvalues
3117   themselves.
3118   Instances of rvalue don't need an upcast call.  */
3119
3120const char *
3121recording::rvalue::access_as_rvalue (reproducer &r)
3122{
3123  return r.get_identifier (this);
3124}
3125
3126/* Return a debug string for the given rvalue, wrapping it in parentheses
3127   if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3128   stronger precedence that this rvalue's precedence.
3129
3130   For example, given:
3131
3132           MULT
3133          /    \
3134       PLUS     MINUS
3135      /    \   /     \
3136     A      B C       D
3137
3138   we want to emit:
3139
3140     (A + B) * (C - D)
3141
3142   since MULT has strong precedence than PLUS and MINUS, whereas for:
3143
3144           PLUS
3145          /    \
3146       MULT     DIVIDE
3147      /    \   /      \
3148     A      B C        D
3149
3150   we can simply emit:
3151
3152     A * B + C / D
3153
3154   since PLUS has weaker precedence than MULT and DIVIDE.  */
3155
3156const char *
3157recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
3158{
3159  enum precedence this_prec = get_precedence ();
3160
3161  /* If this_prec has stronger precedence than outer_prec, we don't
3162     need to wrap this in parens within the outer debug string.
3163     Stronger precedences occur earlier than weaker within the enum,
3164     so this is a less than test.  Equal precedences don't need
3165     parentheses.  */
3166  if (this_prec <= outer_prec)
3167    return get_debug_string();
3168
3169  /* Otherwise, we need parentheses.  */
3170
3171  /* Lazily-build and cache m_parenthesized_string.  */
3172  if (!m_parenthesized_string)
3173    {
3174      const char *debug_string = get_debug_string ();
3175      m_parenthesized_string = string::from_printf (get_context (),
3176						    "(%s)",
3177						    debug_string);
3178    }
3179  gcc_assert (m_parenthesized_string);
3180  return m_parenthesized_string->c_str ();
3181}
3182
3183
3184/* The implementation of class gcc::jit::recording::lvalue.  */
3185
3186/* Create a recording::new_access_field_of_lvalue instance and add it to
3187   the lvalue's context's list of mementos.
3188
3189   Implements the post-error-checking part of
3190   gcc_jit_lvalue_access_field.  */
3191
3192recording::lvalue *
3193recording::lvalue::access_field (recording::location *loc,
3194				 field *field)
3195{
3196  recording::lvalue *result =
3197    new access_field_of_lvalue (m_ctxt, loc, this, field);
3198  m_ctxt->record (result);
3199  return result;
3200}
3201
3202/* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3203   Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3204   upcast call.  */
3205
3206const char *
3207recording::lvalue::access_as_rvalue (reproducer &r)
3208{
3209  return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3210			   r.get_identifier (this));
3211}
3212
3213/* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3214   Instances of lvalue don't need to be upcast.  */
3215
3216const char *
3217recording::lvalue::access_as_lvalue (reproducer &r)
3218{
3219  return r.get_identifier (this);
3220}
3221
3222/* Create a recording::get_address_of_lvalue instance and add it to
3223   the lvalue's context's list of mementos.
3224
3225   Implements the post-error-checking part of
3226   gcc_jit_lvalue_get_address.  */
3227
3228recording::rvalue *
3229recording::lvalue::get_address (recording::location *loc)
3230{
3231  recording::rvalue *result =
3232    new get_address_of_lvalue (m_ctxt, loc, this);
3233  m_ctxt->record (result);
3234  return result;
3235}
3236
3237/* The implementation of class gcc::jit::recording::param.  */
3238
3239/* Implementation of pure virtual hook recording::memento::replay_into
3240   for recording::param.  */
3241
3242void
3243recording::param::replay_into (replayer *r)
3244{
3245  set_playback_obj (r->new_param (playback_location (r, m_loc),
3246				  m_type->playback_type (),
3247				  m_name->c_str ()));
3248}
3249
3250/* Implementation of recording::rvalue::access_as_rvalue for params.
3251   Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3252   upcast call.  */
3253
3254const char *
3255recording::param::access_as_rvalue (reproducer &r)
3256{
3257  return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3258			   r.get_identifier (this));
3259}
3260
3261/* Implementation of recording::lvalue::access_as_lvalue for params.
3262   Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3263   upcast call.  */
3264
3265const char *
3266recording::param::access_as_lvalue (reproducer &r)
3267{
3268  return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3269			   r.get_identifier (this));
3270}
3271
3272/* Implementation of recording::memento::write_reproducer for params. */
3273
3274void
3275recording::param::write_reproducer (reproducer &r)
3276{
3277  const char *id = r.make_identifier (this, "param");
3278  r.write ("  gcc_jit_param *%s =\n"
3279	   "    gcc_jit_context_new_param (%s,\n"
3280	   "                               %s, /* gcc_jit_location *loc */\n"
3281	   "                               %s, /*gcc_jit_type *type */\n"
3282	   "                               %s); /* const char *name */\n",
3283	   id,
3284    r.get_identifier (get_context ()),
3285	   r.get_identifier (m_loc),
3286	   r.get_identifier_as_type (m_type),
3287	   m_name->get_debug_string ());
3288}
3289
3290/* The implementation of class gcc::jit::recording::function.  */
3291
3292/* gcc::jit::recording::function's constructor.  */
3293
3294recording::function::function (context *ctxt,
3295			       recording::location *loc,
3296			       enum gcc_jit_function_kind kind,
3297			       type *return_type,
3298			       recording::string *name,
3299			       int num_params,
3300			       recording::param **params,
3301			       int is_variadic,
3302			       enum built_in_function builtin_id)
3303: memento (ctxt),
3304  m_loc (loc),
3305  m_kind (kind),
3306  m_return_type (return_type),
3307  m_name (name),
3308  m_params (),
3309  m_is_variadic (is_variadic),
3310  m_builtin_id (builtin_id),
3311  m_locals (),
3312  m_blocks ()
3313{
3314  for (int i = 0; i< num_params; i++)
3315    {
3316      param *param = params[i];
3317      gcc_assert (param);
3318
3319      /* Associate each param with this function.
3320
3321	 Verify that the param doesn't already have a function.  */
3322      if (param->get_scope ())
3323	{
3324	  /* We've already rejected attempts to reuse a param between
3325	     different functions (within gcc_jit_context_new_function), so
3326	     if the param *does* already have a function, it must be being
3327	     reused within the params array for this function.  We must
3328	     produce an error for this reuse (blocking the compile), since
3329	     otherwise we'd have an ICE later on.  */
3330	  gcc_assert (this == param->get_scope ());
3331	  ctxt->add_error
3332	    (loc,
3333	     "gcc_jit_context_new_function:"
3334	     " parameter %s (type: %s)"
3335	     " is used more than once when creating function %s",
3336	     param->get_debug_string (),
3337	     param->get_type ()->get_debug_string (),
3338	     name->c_str ());
3339	}
3340      else
3341	{
3342	  /* The normal, non-error case: associate this function with the
3343	     param.  */
3344	  param->set_scope (this);
3345	}
3346
3347      m_params.safe_push (param);
3348    }
3349}
3350
3351/* Implementation of pure virtual hook recording::memento::replay_into
3352   for recording::function.  */
3353
3354void
3355recording::function::replay_into (replayer *r)
3356{
3357  /* Convert m_params to a vec of playback param.  */
3358  auto_vec <playback::param *> params;
3359  int i;
3360  recording::param *param;
3361  params.create (m_params.length ());
3362  FOR_EACH_VEC_ELT (m_params, i, param)
3363    params.safe_push (param->playback_param ());
3364
3365  set_playback_obj (r->new_function (playback_location (r, m_loc),
3366				     m_kind,
3367				     m_return_type->playback_type (),
3368				     m_name->c_str (),
3369				     &params,
3370				     m_is_variadic,
3371				     m_builtin_id));
3372}
3373
3374/* Create a recording::local instance and add it to
3375   the functions's context's list of mementos, and to the function's
3376   list of locals.
3377
3378   Implements the post-error-checking part of
3379   gcc_jit_function_new_local.  */
3380
3381recording::lvalue *
3382recording::function::new_local (recording::location *loc,
3383				type *type,
3384				const char *name)
3385{
3386  local *result = new local (this, loc, type, new_string (name));
3387  m_ctxt->record (result);
3388  m_locals.safe_push (result);
3389  return result;
3390}
3391
3392/* Create a recording::block instance and add it to
3393   the functions's context's list of mementos, and to the function's
3394   list of blocks.
3395
3396   Implements the post-error-checking part of
3397   gcc_jit_function_new_block.  */
3398
3399recording::block*
3400recording::function::new_block (const char *name)
3401{
3402  gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
3403
3404  recording::block *result =
3405    new recording::block (this, m_blocks.length (), new_string (name));
3406  m_ctxt->record (result);
3407  m_blocks.safe_push (result);
3408  return result;
3409}
3410
3411/* Override the default implementation of
3412   recording::memento::write_to_dump by dumping a C-like
3413   representation of the function; either like a prototype
3414   for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3415   all other kinds of function.  */
3416
3417void
3418recording::function::write_to_dump (dump &d)
3419{
3420  switch (m_kind)
3421    {
3422    default: gcc_unreachable ();
3423    case GCC_JIT_FUNCTION_EXPORTED:
3424    case GCC_JIT_FUNCTION_IMPORTED:
3425      d.write ("extern ");
3426      break;
3427    case GCC_JIT_FUNCTION_INTERNAL:
3428      d.write ("static ");
3429      break;
3430    case GCC_JIT_FUNCTION_ALWAYS_INLINE:
3431      d.write ("static inline ");
3432      break;
3433     }
3434  d.write ("%s\n", m_return_type->get_debug_string ());
3435
3436  if (d.update_locations ())
3437    m_loc = d.make_location ();
3438
3439  d.write ("%s (", get_debug_string ());
3440
3441  int i;
3442  recording::param *param;
3443  FOR_EACH_VEC_ELT (m_params, i, param)
3444    {
3445      if (i > 0)
3446	d.write (", ");
3447      d.write ("%s %s",
3448	       param->get_type ()->get_debug_string (),
3449	       param->get_debug_string ());
3450    }
3451  d.write (")");
3452  if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
3453    {
3454      d.write ("; /* (imported) */\n\n");
3455    }
3456  else
3457    {
3458      int i;
3459      local *var = NULL;
3460      block *b;
3461      d.write ("\n{\n");
3462
3463      /* Write locals: */
3464      FOR_EACH_VEC_ELT (m_locals, i, var)
3465	var->write_to_dump (d);
3466      if (m_locals.length ())
3467	d.write ("\n");
3468
3469      /* Write each block: */
3470      FOR_EACH_VEC_ELT (m_blocks, i, b)
3471	{
3472	  if (i > 0)
3473	    d.write ("\n");
3474	  b->write_to_dump (d);
3475	}
3476
3477      d.write ("}\n\n");
3478    }
3479}
3480
3481/* Pre-compilation validation of a function, for those things we can't
3482   check until the context is (supposedly) fully-populated.  */
3483
3484void
3485recording::function::validate ()
3486{
3487  /* Complain about empty functions with non-void return type.  */
3488  if (m_kind != GCC_JIT_FUNCTION_IMPORTED
3489      && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
3490    if (0 == m_blocks.length ())
3491      m_ctxt->add_error (m_loc,
3492			 "function %s returns non-void (type: %s)"
3493			 " but has no blocks",
3494			 get_debug_string (),
3495			 m_return_type->get_debug_string ());
3496
3497  /* Check that all blocks are terminated.  */
3498  int num_invalid_blocks = 0;
3499  {
3500    int i;
3501    block *b;
3502
3503    FOR_EACH_VEC_ELT (m_blocks, i, b)
3504      if (!b->validate ())
3505	num_invalid_blocks++;
3506  }
3507
3508  /* Check that all blocks are reachable.  */
3509  if (!m_ctxt->get_inner_bool_option
3510        (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
3511      && m_blocks.length () > 0 && 0 == num_invalid_blocks)
3512    {
3513      /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3514	 flag, starting at the initial block.  */
3515      auto_vec<block *> worklist (m_blocks.length ());
3516      worklist.safe_push (m_blocks[0]);
3517      while (worklist.length () > 0)
3518	{
3519	  block *b = worklist.pop ();
3520	  b->m_is_reachable = true;
3521
3522	  /* Add successor blocks that aren't yet marked to the worklist.  */
3523	  /* We checked that each block has a terminating statement above .  */
3524	  vec <block *> successors = b->get_successor_blocks ();
3525	  int i;
3526	  block *succ;
3527	  FOR_EACH_VEC_ELT (successors, i, succ)
3528	    if (!succ->m_is_reachable)
3529	      worklist.safe_push (succ);
3530	  successors.release ();
3531	}
3532
3533      /* Now complain about any blocks that haven't been marked.  */
3534      {
3535	int i;
3536	block *b;
3537	FOR_EACH_VEC_ELT (m_blocks, i, b)
3538	  if (!b->m_is_reachable)
3539	    m_ctxt->add_error (b->get_loc (),
3540			       "unreachable block: %s",
3541			       b->get_debug_string ());
3542      }
3543    }
3544}
3545
3546/* Implements the post-error-checking part of
3547   gcc_jit_function_dump_to_dot.  */
3548
3549void
3550recording::function::dump_to_dot (const char *path)
3551{
3552  FILE *fp  = fopen (path, "w");
3553  if (!fp)
3554    return;
3555
3556  pretty_printer the_pp;
3557  the_pp.buffer->stream = fp;
3558
3559  pretty_printer *pp = &the_pp;
3560
3561  pp_printf (pp,
3562	     "digraph %s {\n", get_debug_string ());
3563
3564  /* Blocks: */
3565  {
3566    int i;
3567    block *b;
3568    FOR_EACH_VEC_ELT (m_blocks, i, b)
3569      b->dump_to_dot (pp);
3570  }
3571
3572  /* Edges: */
3573  {
3574    int i;
3575    block *b;
3576    FOR_EACH_VEC_ELT (m_blocks, i, b)
3577      b->dump_edges_to_dot (pp);
3578  }
3579
3580  pp_printf (pp, "}\n");
3581  pp_flush (pp);
3582  fclose (fp);
3583}
3584
3585/* Implementation of recording::memento::make_debug_string for
3586   functions.  */
3587
3588recording::string *
3589recording::function::make_debug_string ()
3590{
3591  return m_name;
3592}
3593
3594/* A table of enum gcc_jit_function_kind values expressed in string
3595   form.  */
3596
3597static const char * const names_of_function_kinds[] = {
3598  "GCC_JIT_FUNCTION_EXPORTED",
3599  "GCC_JIT_FUNCTION_INTERNAL",
3600  "GCC_JIT_FUNCTION_IMPORTED",
3601  "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3602};
3603
3604/* Implementation of recording::memento::write_reproducer for functions. */
3605
3606void
3607recording::function::write_reproducer (reproducer &r)
3608{
3609  const char *id = r.make_identifier (this, "func");
3610
3611  if (m_builtin_id)
3612    {
3613      r.write ("  gcc_jit_function *%s =\n"
3614	       "    gcc_jit_context_get_builtin_function (%s,\n"
3615	       "                                          %s);\n",
3616	       id,
3617	       r.get_identifier (get_context ()),
3618	       m_name->get_debug_string ());
3619      return;
3620    }
3621  const char *params_id = r.make_tmp_identifier ("params_for", this);
3622  r.write ("  gcc_jit_param *%s[%i] = {\n",
3623	   params_id,
3624	   m_params.length ());
3625  int i;
3626  param *param;
3627  FOR_EACH_VEC_ELT (m_params, i, param)
3628    r.write ("    %s,\n", r.get_identifier (param));
3629  r.write ("  };\n");
3630  r.write ("  gcc_jit_function *%s =\n"
3631	   "    gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3632	   "                                  %s, /* gcc_jit_location *loc */\n"
3633	   "                                  %s, /* enum gcc_jit_function_kind kind */\n"
3634	   "                                  %s, /* gcc_jit_type *return_type */\n"
3635	   "                                  %s, /* const char *name */\n"
3636	   "                                  %i, /* int num_params */\n"
3637	   "                                  %s, /* gcc_jit_param **params */\n"
3638	   "                                  %i); /* int is_variadic */\n",
3639	   id,
3640	   r.get_identifier (get_context ()),
3641	   r.get_identifier (m_loc),
3642	   names_of_function_kinds[m_kind],
3643	   r.get_identifier_as_type (m_return_type),
3644	   m_name->get_debug_string (),
3645	   m_params.length (),
3646	   params_id,
3647	   m_is_variadic);
3648}
3649
3650
3651/* The implementation of class gcc::jit::recording::block.  */
3652
3653/* Create a recording::eval instance and add it to
3654   the block's context's list of mementos, and to the block's
3655   list of statements.
3656
3657   Implements the heart of gcc_jit_block_add_eval.  */
3658
3659recording::statement *
3660recording::block::add_eval (recording::location *loc,
3661			    recording::rvalue *rvalue)
3662{
3663  statement *result = new eval (this, loc, rvalue);
3664  m_ctxt->record (result);
3665  m_statements.safe_push (result);
3666  return result;
3667}
3668
3669/* Create a recording::assignment instance and add it to
3670   the block's context's list of mementos, and to the block's
3671   list of statements.
3672
3673   Implements the heart of gcc_jit_block_add_assignment.  */
3674
3675recording::statement *
3676recording::block::add_assignment (recording::location *loc,
3677				  recording::lvalue *lvalue,
3678				  recording::rvalue *rvalue)
3679{
3680  statement *result = new assignment (this, loc, lvalue, rvalue);
3681  m_ctxt->record (result);
3682  m_statements.safe_push (result);
3683  return result;
3684}
3685
3686/* Create a recording::assignment_op instance and add it to
3687   the block's context's list of mementos, and to the block's
3688   list of statements.
3689
3690   Implements the heart of gcc_jit_block_add_assignment_op.  */
3691
3692recording::statement *
3693recording::block::add_assignment_op (recording::location *loc,
3694				     recording::lvalue *lvalue,
3695				     enum gcc_jit_binary_op op,
3696				     recording::rvalue *rvalue)
3697{
3698  statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
3699  m_ctxt->record (result);
3700  m_statements.safe_push (result);
3701  return result;
3702}
3703
3704/* Create a recording::comment instance and add it to
3705   the block's context's list of mementos, and to the block's
3706   list of statements.
3707
3708   Implements the heart of gcc_jit_block_add_comment.  */
3709
3710recording::statement *
3711recording::block::add_comment (recording::location *loc,
3712			       const char *text)
3713{
3714  statement *result = new comment (this, loc, new_string (text));
3715  m_ctxt->record (result);
3716  m_statements.safe_push (result);
3717  return result;
3718}
3719
3720/* Create a recording::end_with_conditional instance and add it to
3721   the block's context's list of mementos, and to the block's
3722   list of statements.
3723
3724   Implements the heart of gcc_jit_block_end_with_conditional.  */
3725
3726recording::statement *
3727recording::block::end_with_conditional (recording::location *loc,
3728					recording::rvalue *boolval,
3729					recording::block *on_true,
3730					recording::block *on_false)
3731{
3732  statement *result = new conditional (this, loc, boolval, on_true, on_false);
3733  m_ctxt->record (result);
3734  m_statements.safe_push (result);
3735  m_has_been_terminated = true;
3736  return result;
3737}
3738
3739/* Create a recording::end_with_jump instance and add it to
3740   the block's context's list of mementos, and to the block's
3741   list of statements.
3742
3743   Implements the heart of gcc_jit_block_end_with_jump.  */
3744
3745recording::statement *
3746recording::block::end_with_jump (recording::location *loc,
3747				 recording::block *target)
3748{
3749  statement *result = new jump (this, loc, target);
3750  m_ctxt->record (result);
3751  m_statements.safe_push (result);
3752  m_has_been_terminated = true;
3753  return result;
3754}
3755
3756/* Create a recording::end_with_return instance and add it to
3757   the block's context's list of mementos, and to the block's
3758   list of statements.
3759
3760   Implements the post-error-checking parts of
3761   gcc_jit_block_end_with_return and
3762   gcc_jit_block_end_with_void_return.  */
3763
3764recording::statement *
3765recording::block::end_with_return (recording::location *loc,
3766				   recording::rvalue *rvalue)
3767{
3768  /* This is used by both gcc_jit_function_add_return and
3769     gcc_jit_function_add_void_return; rvalue will be non-NULL for
3770     the former and NULL for the latter.  */
3771  statement *result = new return_ (this, loc, rvalue);
3772  m_ctxt->record (result);
3773  m_statements.safe_push (result);
3774  m_has_been_terminated = true;
3775  return result;
3776}
3777
3778/* Create a recording::switch_ instance and add it to
3779   the block's context's list of mementos, and to the block's
3780   list of statements.
3781
3782   Implements the heart of gcc_jit_block_end_with_switch.  */
3783
3784recording::statement *
3785recording::block::end_with_switch (recording::location *loc,
3786				   recording::rvalue *expr,
3787				   recording::block *default_block,
3788				   int num_cases,
3789				   recording::case_ **cases)
3790{
3791  statement *result = new switch_ (this, loc,
3792				   expr,
3793				   default_block,
3794				   num_cases,
3795				   cases);
3796  m_ctxt->record (result);
3797  m_statements.safe_push (result);
3798  m_has_been_terminated = true;
3799  return result;
3800}
3801
3802/* Override the default implementation of
3803   recording::memento::write_to_dump for blocks by writing
3804   an unindented block name as a label, followed by the indented
3805   statements:
3806
3807    BLOCK_NAME:
3808      STATEMENT_1;
3809      STATEMENT_2;
3810      ...
3811      STATEMENT_N;  */
3812
3813void
3814recording::block::write_to_dump (dump &d)
3815{
3816  d.write ("%s:\n", get_debug_string ());
3817
3818  int i;
3819  statement *s;
3820  FOR_EACH_VEC_ELT (m_statements, i, s)
3821    s->write_to_dump (d);
3822}
3823
3824/* Validate a block by ensuring that it has been terminated.  */
3825
3826bool
3827recording::block::validate ()
3828{
3829  /* Check for termination.  */
3830  if (!has_been_terminated ())
3831    {
3832      statement *stmt = get_last_statement ();
3833      location *loc = stmt ? stmt->get_loc () : NULL;
3834      m_func->get_context ()->add_error (loc,
3835					 "unterminated block in %s: %s",
3836					 m_func->get_debug_string (),
3837					 get_debug_string ());
3838      return false;
3839    }
3840
3841  return true;
3842}
3843
3844/* Get the source-location of a block by using that of the first
3845   statement within it, if any.  */
3846
3847recording::location *
3848recording::block::get_loc () const
3849{
3850  recording::statement *stmt = get_first_statement ();
3851  if (stmt)
3852    return stmt->get_loc ();
3853  else
3854    return NULL;
3855}
3856
3857/* Get the first statement within a block, if any.  */
3858
3859recording::statement *
3860recording::block::get_first_statement () const
3861{
3862  if (m_statements.length ())
3863    return m_statements[0];
3864  else
3865    return NULL;
3866}
3867
3868/* Get the last statement within a block, if any.  */
3869
3870recording::statement *
3871recording::block::get_last_statement () const
3872{
3873  if (m_statements.length ())
3874    return m_statements[m_statements.length () - 1];
3875  else
3876    return NULL;
3877}
3878
3879/* Assuming that this block has been terminated, get the successor blocks
3880   as a vector.  Ownership of the vector transfers to the caller, which
3881   must call its release () method.
3882
3883   Used when validating functions, and when dumping dot representations
3884   of them.  */
3885
3886vec <recording::block *>
3887recording::block::get_successor_blocks () const
3888{
3889  gcc_assert (m_has_been_terminated);
3890  statement *last_statement = get_last_statement ();
3891  gcc_assert (last_statement);
3892  return last_statement->get_successor_blocks ();
3893}
3894
3895/* Implementation of pure virtual hook recording::memento::replay_into
3896   for recording::block.  */
3897
3898void
3899recording::block::replay_into (replayer *)
3900{
3901  set_playback_obj (m_func->playback_function ()
3902		      ->new_block (playback_string (m_name)));
3903}
3904
3905/* Implementation of recording::memento::make_debug_string for
3906   blocks.  */
3907
3908recording::string *
3909recording::block::make_debug_string ()
3910{
3911  if (m_name)
3912    return m_name;
3913  else
3914    return string::from_printf (m_ctxt,
3915				"<UNNAMED BLOCK %p>",
3916				(void *)this);
3917}
3918
3919/* Implementation of recording::memento::write_reproducer for blocks. */
3920
3921void
3922recording::block::write_reproducer (reproducer &r)
3923{
3924  const char *id = r.make_identifier (this, "block");
3925  r.write ("  gcc_jit_block *%s =\n"
3926	   "    gcc_jit_function_new_block (%s, %s);\n",
3927	   id,
3928	   r.get_identifier (m_func),
3929	   m_name ? m_name->get_debug_string () : "NULL");
3930}
3931
3932/* Dump a block in graphviz form into PP, capturing the block name (if
3933   any) and the statements.  */
3934
3935void
3936recording::block::dump_to_dot (pretty_printer *pp)
3937{
3938  pp_printf (pp,
3939	     ("\tblock_%d "
3940	      "[shape=record,style=filled,fillcolor=white,label=\"{"),
3941	     m_index);
3942  pp_write_text_to_stream (pp);
3943  if (m_name)
3944    {
3945      pp_string (pp, m_name->c_str ());
3946      pp_string (pp, ":");
3947      pp_newline (pp);
3948      pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3949    }
3950
3951  int i;
3952  statement *s;
3953  FOR_EACH_VEC_ELT (m_statements, i, s)
3954    {
3955      pp_string (pp, s->get_debug_string ());
3956      pp_newline (pp);
3957      pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3958    }
3959
3960  pp_printf (pp,
3961	     "}\"];\n\n");
3962  pp_flush (pp);
3963}
3964
3965/* Dump the out-edges of the block in graphviz form into PP.  */
3966
3967void
3968recording::block::dump_edges_to_dot (pretty_printer *pp)
3969{
3970  vec <block *> successors = get_successor_blocks ();
3971  int i;
3972  block *succ;
3973  FOR_EACH_VEC_ELT (successors, i, succ)
3974    pp_printf (pp,
3975	       "\tblock_%d:s -> block_%d:n;\n",
3976	       m_index, succ->m_index);
3977  successors.release ();
3978}
3979
3980/* The implementation of class gcc::jit::recording::global.  */
3981
3982/* Implementation of pure virtual hook recording::memento::replay_into
3983   for recording::global.  */
3984
3985void
3986recording::global::replay_into (replayer *r)
3987{
3988  set_playback_obj (r->new_global (playback_location (r, m_loc),
3989				   m_kind,
3990				   m_type->playback_type (),
3991				   playback_string (m_name)));
3992}
3993
3994/* Override the default implementation of
3995   recording::memento::write_to_dump for globals.
3996   This will be of the form:
3997
3998   GCC_JIT_GLOBAL_EXPORTED:
3999      "TYPE NAME;"
4000      e.g. "int foo;"
4001
4002   GCC_JIT_GLOBAL_INTERNAL:
4003      "static TYPE NAME;"
4004      e.g. "static int foo;"
4005
4006   GCC_JIT_GLOBAL_IMPORTED:
4007      "extern TYPE NAME;"
4008      e.g. "extern int foo;"
4009
4010   These are written to the top of the dump by
4011   recording::context::dump_to_file.  */
4012
4013void
4014recording::global::write_to_dump (dump &d)
4015{
4016  if (d.update_locations ())
4017    m_loc = d.make_location ();
4018
4019  switch (m_kind)
4020    {
4021    default:
4022      gcc_unreachable ();
4023
4024    case GCC_JIT_GLOBAL_EXPORTED:
4025      break;
4026
4027    case GCC_JIT_GLOBAL_INTERNAL:
4028      d.write ("static ");
4029      break;
4030
4031    case GCC_JIT_GLOBAL_IMPORTED:
4032      d.write ("extern ");
4033      break;
4034    }
4035  d.write ("%s %s;\n",
4036	   m_type->get_debug_string (),
4037	   get_debug_string ());
4038}
4039
4040/* A table of enum gcc_jit_global_kind values expressed in string
4041   form.  */
4042
4043static const char * const global_kind_reproducer_strings[] = {
4044  "GCC_JIT_GLOBAL_EXPORTED",
4045  "GCC_JIT_GLOBAL_INTERNAL",
4046  "GCC_JIT_GLOBAL_IMPORTED"
4047};
4048
4049/* Implementation of recording::memento::write_reproducer for globals. */
4050
4051void
4052recording::global::write_reproducer (reproducer &r)
4053{
4054  const char *id = r.make_identifier (this, "block");
4055  r.write ("  gcc_jit_lvalue *%s =\n"
4056    "    gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4057    "                                %s, /* gcc_jit_location *loc */\n"
4058    "                                %s, /* enum gcc_jit_global_kind kind */\n"
4059    "                                %s, /* gcc_jit_type *type */\n"
4060    "                                %s); /* const char *name */\n",
4061    id,
4062    r.get_identifier (get_context ()),
4063    r.get_identifier (m_loc),
4064    global_kind_reproducer_strings[m_kind],
4065    r.get_identifier_as_type (get_type ()),
4066    m_name->get_debug_string ());
4067}
4068
4069/* The implementation of the various const-handling classes:
4070   gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>.  */
4071
4072/* Explicit specialization of the various mementos we're interested in.  */
4073template class recording::memento_of_new_rvalue_from_const <int>;
4074template class recording::memento_of_new_rvalue_from_const <long>;
4075template class recording::memento_of_new_rvalue_from_const <double>;
4076template class recording::memento_of_new_rvalue_from_const <void *>;
4077
4078/* Implementation of the pure virtual hook recording::memento::replay_into
4079   for recording::memento_of_new_rvalue_from_const <HOST_TYPE>.  */
4080
4081template <typename HOST_TYPE>
4082void
4083recording::
4084memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
4085{
4086    set_playback_obj
4087      (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
4088					     m_value));
4089}
4090
4091/* The make_debug_string and write_reproducer methods vary between the
4092   various
4093     memento_of_new_rvalue_from_const <HOST_TYPE>
4094   classes, so we explicitly write specializations of them.
4095
4096   I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4097   namespaces are written out explicitly, which is why most of this file
4098   doesn't abbreviate things by entering the "recording" namespace.
4099
4100   However, these specializations are required to be in the same namespace
4101   as the template, hence we now have to enter the gcc::jit::recording
4102   namespace.  */
4103
4104namespace recording
4105{
4106
4107/* The make_debug_string specialization for <int>, which renders it as
4108     (TARGET_TYPE)LITERAL
4109   e.g.
4110     "(int)42".  */
4111
4112template <>
4113string *
4114memento_of_new_rvalue_from_const <int>::make_debug_string ()
4115{
4116  return string::from_printf (m_ctxt,
4117			      "(%s)%i",
4118			      m_type->get_debug_string (),
4119			      m_value);
4120}
4121
4122/* The get_wide_int specialization for <int>.  */
4123
4124template <>
4125bool
4126memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const
4127{
4128  *out = wi::shwi (m_value, sizeof (m_value) * 8);
4129  return true;
4130}
4131
4132/* The write_reproducer specialization for <int>.  */
4133
4134template <>
4135void
4136memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
4137{
4138  const char *id = r.make_identifier (this, "rvalue");
4139  r.write ("  gcc_jit_rvalue *%s =\n"
4140    "    gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4141    "                                         %s, /* gcc_jit_type *numeric_type */\n"
4142    "                                         %i); /* int value */\n",
4143    id,
4144    r.get_identifier (get_context ()),
4145    r.get_identifier_as_type (m_type),
4146    m_value);
4147}
4148
4149/* The make_debug_string specialization for <long>, rendering it as
4150     (TARGET_TYPE)LITERAL
4151   e.g.
4152     "(long)42".  */
4153
4154template <>
4155string *
4156memento_of_new_rvalue_from_const <long>::make_debug_string ()
4157{
4158  return string::from_printf (m_ctxt,
4159			      "(%s)%li",
4160			      m_type->get_debug_string (),
4161			      m_value);
4162}
4163
4164/* The get_wide_int specialization for <long>.  */
4165
4166template <>
4167bool
4168memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const
4169{
4170  *out = wi::shwi (m_value, sizeof (m_value) * 8);
4171  return true;
4172}
4173
4174/* The write_reproducer specialization for <long>.  */
4175
4176template <>
4177void
4178recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
4179{
4180  const char *id = r.make_identifier (this, "rvalue");
4181
4182  /* We have to special-case LONG_MIN, since e.g.
4183       -9223372036854775808L
4184     is parsed as
4185       -(9223372036854775808L)
4186     and hence we'd get:
4187	error: integer constant is so large that it is unsigned [-Werror]
4188	Workaround this by writing (LONG_MIN + 1) - 1.  */
4189  if (m_value == LONG_MIN)
4190    {
4191      r.write ("  gcc_jit_rvalue *%s =\n"
4192	       "    gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4193	       "                                          %s, /* gcc_jit_type *numeric_type */\n"
4194	       "                                          %ldL - 1); /* long value */\n",
4195	       id,
4196	       r.get_identifier (get_context ()),
4197	       r.get_identifier_as_type (m_type),
4198	       m_value + 1);;
4199      return;
4200    }
4201
4202  r.write ("  gcc_jit_rvalue *%s =\n"
4203	   "    gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4204	   "                                          %s, /* gcc_jit_type *numeric_type */\n"
4205	   "                                          %ldL); /* long value */\n",
4206	   id,
4207	   r.get_identifier (get_context ()),
4208	   r.get_identifier_as_type (m_type),
4209	   m_value);
4210	   }
4211
4212/* The make_debug_string specialization for <double>, rendering it as
4213     (TARGET_TYPE)LITERAL
4214   e.g.
4215     "(float)42.0".  */
4216
4217template <>
4218string *
4219memento_of_new_rvalue_from_const <double>::make_debug_string ()
4220{
4221  return string::from_printf (m_ctxt,
4222			      "(%s)%f",
4223			      m_type->get_debug_string (),
4224			      m_value);
4225}
4226
4227/* The get_wide_int specialization for <double>.  */
4228
4229template <>
4230bool
4231memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
4232{
4233  return false;
4234}
4235
4236/* The write_reproducer specialization for <double>.  */
4237
4238template <>
4239void
4240recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
4241{
4242  const char *id = r.make_identifier (this, "rvalue");
4243  r.write ("  gcc_jit_rvalue *%s =\n"
4244    "    gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4245    "                                            %s, /* gcc_jit_type *numeric_type */\n"
4246    "                                            %f); /* double value */\n",
4247    id,
4248    r.get_identifier (get_context ()),
4249    r.get_identifier_as_type (m_type),
4250    m_value);
4251}
4252
4253/* The make_debug_string specialization for <void *>, rendering it as
4254     (TARGET_TYPE)HEX
4255   e.g.
4256     "(int *)0xdeadbeef"
4257
4258   Zero is rendered as NULL e.g.
4259     "(int *)NULL".  */
4260
4261template <>
4262string *
4263memento_of_new_rvalue_from_const <void *>::make_debug_string ()
4264{
4265  if (m_value != NULL)
4266    return string::from_printf (m_ctxt,
4267				"(%s)%p",
4268				m_type->get_debug_string (), m_value);
4269  else
4270    return string::from_printf (m_ctxt,
4271				"(%s)NULL",
4272				m_type->get_debug_string ());
4273}
4274
4275/* The get_wide_int specialization for <void *>.  */
4276
4277template <>
4278bool
4279memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const
4280{
4281  return false;
4282}
4283
4284/* Implementation of recording::memento::write_reproducer for <void *>
4285   values. */
4286
4287template <>
4288void
4289memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
4290{
4291  const char *id = r.make_identifier (this, "rvalue");
4292  if (m_value)
4293    r.write ("  gcc_jit_rvalue *%s =\n"
4294	     "    gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4295	     "                                         %s, /* gcc_jit_type *pointer_type */\n"
4296	     "                                         (void *)%p); /* void *value */\n",
4297	     id,
4298	     r.get_identifier (get_context ()),
4299	     r.get_identifier_as_type (m_type),
4300	     m_value);
4301  else
4302    r.write ("  gcc_jit_rvalue *%s =\n"
4303	     "    gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4304	     "                          %s); /* gcc_jit_type *pointer_type */\n",
4305	     id,
4306	     r.get_identifier (get_context ()),
4307	     r.get_identifier_as_type (m_type));
4308}
4309
4310/* We're done specializing make_debug_string and write_reproducer, so we
4311   can exit the gcc::jit::recording namespace.  */
4312
4313} // namespace recording
4314
4315/* The implementation of class gcc::jit::recording::memento_of_new_string_literal.  */
4316
4317/* Implementation of pure virtual hook recording::memento::replay_into
4318   for recording::memento_of_new_string_literal.  */
4319
4320void
4321recording::memento_of_new_string_literal::replay_into (replayer *r)
4322{
4323  set_playback_obj (r->new_string_literal (m_value->c_str ()));
4324}
4325
4326/* Implementation of recording::memento::make_debug_string for
4327   string literals.  */
4328
4329recording::string *
4330recording::memento_of_new_string_literal::make_debug_string ()
4331{
4332  return string::from_printf (m_ctxt,
4333			      "%s",
4334			      m_value->get_debug_string ());
4335}
4336
4337/* Implementation of recording::memento::write_reproducer for string literal
4338   values. */
4339
4340void
4341recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
4342{
4343  const char *id = r.make_identifier (this, "rvalue");
4344  r.write ("  gcc_jit_rvalue *%s =\n"
4345    "    gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4346    "                                        %s); /* const char *value */\n",
4347    id,
4348    r.get_identifier (get_context ()),
4349    m_value->get_debug_string ());
4350}
4351
4352/* The implementation of class gcc::jit::recording::unary_op.  */
4353
4354/* Implementation of pure virtual hook recording::memento::replay_into
4355   for recording::unary_op.  */
4356
4357void
4358recording::unary_op::replay_into (replayer *r)
4359{
4360  set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
4361				     m_op,
4362				     get_type ()->playback_type (),
4363				     m_a->playback_rvalue ()));
4364}
4365
4366/* Implementation of pure virtual hook recording::rvalue::visit_children
4367   for recording::unary_op.  */
4368void
4369recording::unary_op::visit_children (rvalue_visitor *v)
4370{
4371  v->visit (m_a);
4372}
4373
4374/* Implementation of recording::memento::make_debug_string for
4375   unary ops.  */
4376
4377static const char * const unary_op_strings[] = {
4378  "-", /* GCC_JIT_UNARY_OP_MINUS */
4379  "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4380  "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4381  "abs ", /* GCC_JIT_UNARY_OP_ABS */
4382};
4383
4384recording::string *
4385recording::unary_op::make_debug_string ()
4386{
4387  return string::from_printf (m_ctxt,
4388			      "%s(%s)",
4389			      unary_op_strings[m_op],
4390			      m_a->get_debug_string ());
4391}
4392
4393static const char * const unary_op_reproducer_strings[] = {
4394  "GCC_JIT_UNARY_OP_MINUS",
4395  "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4396  "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4397  "GCC_JIT_UNARY_OP_ABS"
4398};
4399
4400/* Implementation of recording::memento::write_reproducer for unary ops.  */
4401
4402void
4403recording::unary_op::write_reproducer (reproducer &r)
4404{
4405  const char *id = r.make_identifier (this, "rvalue");
4406  r.write ("  gcc_jit_rvalue *%s =\n"
4407	   "    gcc_jit_context_new_unary_op (%s,\n"
4408	   "                                  %s, /* gcc_jit_location *loc */\n"
4409	   "                                  %s, /* enum gcc_jit_unary_op op */\n"
4410	   "                                  %s, /* gcc_jit_type *result_type */\n"
4411	   "                                  %s); /* gcc_jit_rvalue *a */\n",
4412	   id,
4413	   r.get_identifier (get_context ()),
4414	   r.get_identifier (m_loc),
4415	   unary_op_reproducer_strings[m_op],
4416	   r.get_identifier_as_type (get_type ()),
4417	   r.get_identifier_as_rvalue (m_a));
4418}
4419
4420/* The implementation of class gcc::jit::recording::binary_op.  */
4421
4422/* Implementation of pure virtual hook recording::memento::replay_into
4423   for recording::binary_op.  */
4424
4425void
4426recording::binary_op::replay_into (replayer *r)
4427{
4428  set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
4429				      m_op,
4430				      get_type ()->playback_type (),
4431				      m_a->playback_rvalue (),
4432				      m_b->playback_rvalue ()));
4433}
4434
4435/* Implementation of pure virtual hook recording::rvalue::visit_children
4436   for recording::binary_op.  */
4437void
4438recording::binary_op::visit_children (rvalue_visitor *v)
4439{
4440  v->visit (m_a);
4441  v->visit (m_b);
4442}
4443
4444/* Implementation of recording::memento::make_debug_string for
4445   binary ops.  */
4446
4447static const char * const binary_op_strings[] = {
4448  "+", /* GCC_JIT_BINARY_OP_PLUS */
4449  "-", /* GCC_JIT_BINARY_OP_MINUS */
4450  "*", /* GCC_JIT_BINARY_OP_MULT */
4451  "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4452  "%", /* GCC_JIT_BINARY_OP_MODULO */
4453  "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4454  "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4455  "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4456  "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4457  "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4458  "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4459  ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4460};
4461
4462recording::string *
4463recording::binary_op::make_debug_string ()
4464{
4465  enum precedence prec = get_precedence ();
4466  return string::from_printf (m_ctxt,
4467			      "%s %s %s",
4468			      m_a->get_debug_string_parens (prec),
4469			      binary_op_strings[m_op],
4470			      m_b->get_debug_string_parens (prec));
4471}
4472
4473static const char * const binary_op_reproducer_strings[] = {
4474  "GCC_JIT_BINARY_OP_PLUS",
4475  "GCC_JIT_BINARY_OP_MINUS",
4476  "GCC_JIT_BINARY_OP_MULT",
4477  "GCC_JIT_BINARY_OP_DIVIDE",
4478  "GCC_JIT_BINARY_OP_MODULO",
4479  "GCC_JIT_BINARY_OP_BITWISE_AND",
4480  "GCC_JIT_BINARY_OP_BITWISE_XOR",
4481  "GCC_JIT_BINARY_OP_BITWISE_OR",
4482  "GCC_JIT_BINARY_OP_LOGICAL_AND",
4483  "GCC_JIT_BINARY_OP_LOGICAL_OR",
4484  "GCC_JIT_BINARY_OP_LSHIFT",
4485  "GCC_JIT_BINARY_OP_RSHIFT"
4486};
4487
4488/* Implementation of recording::memento::write_reproducer for binary ops.  */
4489
4490void
4491recording::binary_op::write_reproducer (reproducer &r)
4492{
4493  const char *id = r.make_identifier (this, "rvalue");
4494  r.write ("  gcc_jit_rvalue *%s =\n"
4495	   "    gcc_jit_context_new_binary_op (%s,\n"
4496	   "                                   %s, /* gcc_jit_location *loc */\n"
4497	   "                                   %s, /* enum gcc_jit_binary_op op */\n"
4498	   "                                   %s, /* gcc_jit_type *result_type */\n"
4499	   "                                   %s, /* gcc_jit_rvalue *a */\n"
4500	   "                                   %s); /* gcc_jit_rvalue *b */\n",
4501	   id,
4502	   r.get_identifier (get_context ()),
4503	   r.get_identifier (m_loc),
4504	   binary_op_reproducer_strings[m_op],
4505	   r.get_identifier_as_type (get_type ()),
4506	   r.get_identifier_as_rvalue (m_a),
4507	   r.get_identifier_as_rvalue (m_b));
4508}
4509
4510namespace recording {
4511static const enum precedence binary_op_precedence[] = {
4512  PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
4513  PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
4514
4515  PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
4516  PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
4517  PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
4518
4519  PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4520  PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4521  PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4522  PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4523  PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4524  PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
4525  PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
4526};
4527} /* namespace recording */
4528
4529enum recording::precedence
4530recording::binary_op::get_precedence () const
4531{
4532  return binary_op_precedence[m_op];
4533}
4534
4535/* The implementation of class gcc::jit::recording::comparison.  */
4536
4537/* Implementation of recording::memento::make_debug_string for
4538   comparisons.  */
4539
4540static const char * const comparison_strings[] =
4541{
4542  "==", /* GCC_JIT_COMPARISON_EQ */
4543  "!=", /* GCC_JIT_COMPARISON_NE */
4544  "<",  /* GCC_JIT_COMPARISON_LT */
4545  "<=", /* GCC_JIT_COMPARISON_LE */
4546  ">",  /* GCC_JIT_COMPARISON_GT */
4547  ">=", /* GCC_JIT_COMPARISON_GE */
4548};
4549
4550recording::string *
4551recording::comparison::make_debug_string ()
4552{
4553  enum precedence prec = get_precedence ();
4554  return string::from_printf (m_ctxt,
4555			      "%s %s %s",
4556			      m_a->get_debug_string_parens (prec),
4557			      comparison_strings[m_op],
4558			      m_b->get_debug_string_parens (prec));
4559}
4560
4561/* A table of enum gcc_jit_comparison values expressed in string
4562   form.  */
4563
4564static const char * const comparison_reproducer_strings[] =
4565{
4566  "GCC_JIT_COMPARISON_EQ",
4567  "GCC_JIT_COMPARISON_NE",
4568  "GCC_JIT_COMPARISON_LT",
4569  "GCC_JIT_COMPARISON_LE",
4570  "GCC_JIT_COMPARISON_GT",
4571  "GCC_JIT_COMPARISON_GE"
4572};
4573
4574/* Implementation of recording::memento::write_reproducer for comparisons.  */
4575
4576void
4577recording::comparison::write_reproducer (reproducer &r)
4578{
4579  const char *id = r.make_identifier (this, "rvalue");
4580  r.write ("  gcc_jit_rvalue *%s =\n"
4581	   "    gcc_jit_context_new_comparison (%s,\n"
4582	   "                                    %s, /* gcc_jit_location *loc */\n"
4583	   "                                    %s, /* enum gcc_jit_comparison op */\n"
4584	   "                                    %s, /* gcc_jit_rvalue *a */\n"
4585	   "                                    %s); /* gcc_jit_rvalue *b */\n",
4586	   id,
4587	   r.get_identifier (get_context ()),
4588	   r.get_identifier (m_loc),
4589	   comparison_reproducer_strings[m_op],
4590	   r.get_identifier_as_rvalue (m_a),
4591	   r.get_identifier_as_rvalue (m_b));
4592}
4593
4594/* Implementation of pure virtual hook recording::memento::replay_into
4595   for recording::comparison.  */
4596
4597void
4598recording::comparison::replay_into (replayer *r)
4599{
4600  set_playback_obj (r->new_comparison (playback_location (r, m_loc),
4601				       m_op,
4602				       m_a->playback_rvalue (),
4603				       m_b->playback_rvalue ()));
4604}
4605
4606/* Implementation of pure virtual hook recording::rvalue::visit_children
4607   for recording::comparison.  */
4608
4609void
4610recording::comparison::visit_children (rvalue_visitor *v)
4611{
4612  v->visit (m_a);
4613  v->visit (m_b);
4614}
4615
4616namespace recording {
4617static const enum precedence comparison_precedence[] =
4618{
4619  PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
4620  PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
4621
4622  PRECEDENCE_RELATIONAL,  /* GCC_JIT_COMPARISON_LT */
4623  PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
4624  PRECEDENCE_RELATIONAL,  /* GCC_JIT_COMPARISON_GT */
4625  PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
4626};
4627} /* namespace recording */
4628
4629enum recording::precedence
4630recording::comparison::get_precedence () const
4631{
4632  return comparison_precedence[m_op];
4633}
4634
4635/* Implementation of pure virtual hook recording::memento::replay_into
4636   for recording::cast.  */
4637
4638void
4639recording::cast::replay_into (replayer *r)
4640{
4641  set_playback_obj (r->new_cast (playback_location (r, m_loc),
4642				 m_rvalue->playback_rvalue (),
4643				 get_type ()->playback_type ()));
4644}
4645
4646/* Implementation of pure virtual hook recording::rvalue::visit_children
4647   for recording::cast.  */
4648void
4649recording::cast::visit_children (rvalue_visitor *v)
4650{
4651  v->visit (m_rvalue);
4652}
4653
4654/* Implementation of recording::memento::make_debug_string for
4655   casts.  */
4656
4657recording::string *
4658recording::cast::make_debug_string ()
4659{
4660  enum precedence prec = get_precedence ();
4661  return string::from_printf (m_ctxt,
4662			      "(%s)%s",
4663			      get_type ()->get_debug_string (),
4664			      m_rvalue->get_debug_string_parens (prec));
4665}
4666
4667/* Implementation of recording::memento::write_reproducer for casts.  */
4668
4669void
4670recording::cast::write_reproducer (reproducer &r)
4671{
4672  const char *id = r.make_identifier (this, "rvalue");
4673  r.write ("  gcc_jit_rvalue *%s =\n"
4674	   "    gcc_jit_context_new_cast (%s,\n"
4675	   "                              %s, /* gcc_jit_location *loc */\n"
4676	   "                              %s, /* gcc_jit_rvalue *rvalue */\n"
4677	   "                              %s); /* gcc_jit_type *type */\n",
4678	   id,
4679	   r.get_identifier (get_context ()),
4680	   r.get_identifier (m_loc),
4681	   r.get_identifier_as_rvalue (m_rvalue),
4682	   r.get_identifier_as_type (get_type ()));
4683}
4684
4685/* The implementation of class gcc::jit::recording::call.  */
4686
4687/* The constructor for gcc::jit::recording::call.  */
4688
4689recording::call::call (recording::context *ctxt,
4690		       recording::location *loc,
4691		       recording::function *func,
4692		       int numargs,
4693		       rvalue **args)
4694: rvalue (ctxt, loc, func->get_return_type ()),
4695  m_func (func),
4696  m_args ()
4697{
4698  for (int i = 0; i< numargs; i++)
4699    m_args.safe_push (args[i]);
4700}
4701
4702/* Implementation of pure virtual hook recording::memento::replay_into
4703   for recording::call.  */
4704
4705void
4706recording::call::replay_into (replayer *r)
4707{
4708  auto_vec<playback::rvalue *> playback_args;
4709  playback_args.create (m_args.length ());
4710  for (unsigned i = 0; i< m_args.length (); i++)
4711    playback_args.safe_push (m_args[i]->playback_rvalue ());
4712
4713  set_playback_obj (r->new_call (playback_location (r, m_loc),
4714				 m_func->playback_function (),
4715				 &playback_args));
4716}
4717
4718/* Implementation of pure virtual hook recording::rvalue::visit_children
4719   for recording::call.  */
4720
4721void
4722recording::call::visit_children (rvalue_visitor *v)
4723{
4724  for (unsigned i = 0; i< m_args.length (); i++)
4725    v->visit (m_args[i]);
4726}
4727
4728/* Implementation of recording::memento::make_debug_string for
4729   function calls.  */
4730
4731recording::string *
4732recording::call::make_debug_string ()
4733{
4734  enum precedence prec = get_precedence ();
4735  /* First, build a buffer for the arguments.  */
4736  /* Calculate length of said buffer.  */
4737  size_t sz = 1; /* nil terminator */
4738  for (unsigned i = 0; i< m_args.length (); i++)
4739    {
4740      sz += strlen (m_args[i]->get_debug_string_parens (prec));
4741      sz += 2; /* ", " separator */
4742    }
4743
4744  /* Now allocate and populate the buffer.  */
4745  char *argbuf = new char[sz];
4746  size_t len = 0;
4747
4748  for (unsigned i = 0; i< m_args.length (); i++)
4749    {
4750      strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4751      len += strlen (m_args[i]->get_debug_string_parens (prec));
4752      if (i + 1 < m_args.length ())
4753	{
4754	  strcpy (argbuf + len, ", ");
4755	  len += 2;
4756	}
4757    }
4758  argbuf[len] = '\0';
4759
4760  /* ...and use it to get the string for the call as a whole.  */
4761  string *result = string::from_printf (m_ctxt,
4762					"%s (%s)",
4763					m_func->get_debug_string (),
4764					argbuf);
4765
4766  delete[] argbuf;
4767
4768  return result;
4769}
4770
4771void
4772recording::call::write_reproducer (reproducer &r)
4773{
4774  const char *id = r.make_identifier (this, "call");
4775  const char *args_id = r.make_tmp_identifier ("args_for_", this);
4776  r.write ("  gcc_jit_rvalue *%s[%i] = {\n",
4777	   args_id,
4778	   m_args.length ());
4779  for (unsigned i = 0; i< m_args.length (); i++)
4780    r.write ("    %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4781  r.write ("  };\n");
4782  r.write ("  gcc_jit_rvalue *%s =\n"
4783	   "    gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4784	   "                              %s, /* gcc_jit_location *loc */\n"
4785	   "                              %s, /* gcc_jit_function *func */\n"
4786	   "                              %i, /* int numargs  */ \n"
4787	   "                              %s); /* gcc_jit_rvalue **args*/\n",
4788	   id,
4789	   r.get_identifier (get_context ()),
4790	   r.get_identifier (m_loc),
4791	   r.get_identifier (m_func),
4792	   m_args.length (),
4793	   args_id);
4794}
4795
4796/* The implementation of class gcc::jit::recording::call_through_ptr.  */
4797
4798/* The constructor for recording::call_through_ptr. */
4799
4800recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
4801					       recording::location *loc,
4802					       recording::rvalue *fn_ptr,
4803					       int numargs,
4804					       rvalue **args)
4805: rvalue (ctxt, loc,
4806	  fn_ptr->get_type ()->dereference ()
4807	    ->as_a_function_type ()->get_return_type ()),
4808  m_fn_ptr (fn_ptr),
4809  m_args ()
4810{
4811  for (int i = 0; i< numargs; i++)
4812    m_args.safe_push (args[i]);
4813}
4814
4815/* Implementation of pure virtual hook recording::memento::replay_into
4816   for recording::call_through_ptr.  */
4817
4818void
4819recording::call_through_ptr::replay_into (replayer *r)
4820{
4821  auto_vec<playback::rvalue *> playback_args;
4822  playback_args.create (m_args.length ());
4823  for (unsigned i = 0; i< m_args.length (); i++)
4824    playback_args.safe_push (m_args[i]->playback_rvalue ());
4825
4826  set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
4827					     m_fn_ptr->playback_rvalue (),
4828					     &playback_args));
4829}
4830
4831/* Implementation of pure virtual hook recording::rvalue::visit_children
4832   for recording::call_through_ptr.  */
4833
4834void
4835recording::call_through_ptr::visit_children (rvalue_visitor *v)
4836{
4837  v->visit (m_fn_ptr);
4838  for (unsigned i = 0; i< m_args.length (); i++)
4839    v->visit (m_args[i]);
4840}
4841
4842/* Implementation of recording::memento::make_debug_string for
4843   calls through function ptrs.  */
4844
4845recording::string *
4846recording::call_through_ptr::make_debug_string ()
4847{
4848  enum precedence prec = get_precedence ();
4849  /* First, build a buffer for the arguments.  */
4850  /* Calculate length of said buffer.  */
4851  size_t sz = 1; /* nil terminator */
4852  for (unsigned i = 0; i< m_args.length (); i++)
4853    {
4854      sz += strlen (m_args[i]->get_debug_string_parens (prec));
4855      sz += 2; /* ", " separator */
4856    }
4857
4858  /* Now allocate and populate the buffer.  */
4859  char *argbuf = new char[sz];
4860  size_t len = 0;
4861
4862  for (unsigned i = 0; i< m_args.length (); i++)
4863    {
4864      strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4865      len += strlen (m_args[i]->get_debug_string_parens (prec));
4866      if (i + 1 < m_args.length ())
4867	{
4868	  strcpy (argbuf + len, ", ");
4869	  len += 2;
4870	}
4871    }
4872  argbuf[len] = '\0';
4873
4874  /* ...and use it to get the string for the call as a whole.  */
4875  string *result = string::from_printf (m_ctxt,
4876					"%s (%s)",
4877					m_fn_ptr->get_debug_string_parens (prec),
4878					argbuf);
4879
4880  delete[] argbuf;
4881
4882  return result;
4883}
4884
4885/* Implementation of recording::memento::write_reproducer for
4886   call_through_ptr.  */
4887
4888void
4889recording::call_through_ptr::write_reproducer (reproducer &r)
4890{
4891  const char *id = r.make_identifier (this, "call");
4892  const char *args_id = r.make_tmp_identifier ("args_for_", this);
4893  r.write ("  gcc_jit_rvalue *%s[%i] = {\n",
4894	     args_id,
4895	     m_args.length ());
4896  for (unsigned i = 0; i< m_args.length (); i++)
4897    r.write ("    %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4898  r.write ("  };\n");
4899  r.write ("  gcc_jit_rvalue *%s =\n"
4900	   "    gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
4901	   "                              %s, /* gcc_jit_location *loc */\n"
4902	   "                              %s, /* gcc_jit_rvalue *fn_ptr */\n"
4903	   "                              %i, /* int numargs  */ \n"
4904	   "                              %s); /* gcc_jit_rvalue **args*/\n",
4905	   id,
4906	   r.get_identifier (get_context ()),
4907	   r.get_identifier (m_loc),
4908	   r.get_identifier_as_rvalue (m_fn_ptr),
4909	   m_args.length (),
4910	   args_id);
4911}
4912
4913/* The implementation of class gcc::jit::recording::array_access.  */
4914
4915/* Implementation of pure virtual hook recording::memento::replay_into
4916   for recording::array_access.  */
4917
4918void
4919recording::array_access::replay_into (replayer *r)
4920{
4921  set_playback_obj (
4922    r->new_array_access (playback_location (r, m_loc),
4923			 m_ptr->playback_rvalue (),
4924			 m_index->playback_rvalue ()));
4925}
4926
4927/* Implementation of pure virtual hook recording::rvalue::visit_children
4928   for recording::array_access.  */
4929
4930void
4931recording::array_access::visit_children (rvalue_visitor *v)
4932{
4933  v->visit (m_ptr);
4934  v->visit (m_index);
4935}
4936
4937/* Implementation of recording::memento::make_debug_string for
4938   array accesses.  */
4939
4940recording::string *
4941recording::array_access::make_debug_string ()
4942{
4943  enum precedence prec = get_precedence ();
4944  return string::from_printf (m_ctxt,
4945			      "%s[%s]",
4946			      m_ptr->get_debug_string_parens (prec),
4947			      m_index->get_debug_string_parens (prec));
4948}
4949
4950/* Implementation of recording::memento::write_reproducer for
4951   array_access.  */
4952
4953void
4954recording::array_access::write_reproducer (reproducer &r)
4955{
4956  const char *id = r.make_identifier (this, "lvalue");
4957  r.write ("  gcc_jit_lvalue *%s = \n"
4958	   "    gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
4959	   "                                      %s, /*gcc_jit_location *loc */\n"
4960	   "                                      %s, /* gcc_jit_rvalue *ptr */\n"
4961	   "                                      %s); /* gcc_jit_rvalue *index */\n",
4962	   id,
4963	   r.get_identifier (get_context ()),
4964	   r.get_identifier (m_loc),
4965	   r.get_identifier_as_rvalue (m_ptr),
4966	   r.get_identifier_as_rvalue (m_index));
4967}
4968
4969/* The implementation of class gcc::jit::recording::access_field_of_lvalue.  */
4970
4971/* Implementation of pure virtual hook recording::memento::replay_into
4972   for recording::access_field_of_lvalue.  */
4973
4974void
4975recording::access_field_of_lvalue::replay_into (replayer *r)
4976{
4977  set_playback_obj (
4978    m_lvalue->playback_lvalue ()
4979      ->access_field (playback_location (r, m_loc),
4980		      m_field->playback_field ()));
4981
4982}
4983
4984/* Implementation of pure virtual hook recording::rvalue::visit_children
4985   for recording::access_field_of_lvalue.  */
4986
4987void
4988recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
4989{
4990  v->visit (m_lvalue);
4991}
4992
4993/* Implementation of recording::memento::make_debug_string for
4994   accessing a field of an lvalue.  */
4995
4996recording::string *
4997recording::access_field_of_lvalue::make_debug_string ()
4998{
4999  enum precedence prec = get_precedence ();
5000  return string::from_printf (m_ctxt,
5001			      "%s.%s",
5002			      m_lvalue->get_debug_string_parens (prec),
5003			      m_field->get_debug_string ());
5004}
5005
5006/* Implementation of recording::memento::write_reproducer for
5007   access_field_of_lvalue.  */
5008
5009void
5010recording::access_field_of_lvalue::write_reproducer (reproducer &r)
5011{
5012  const char *id = r.make_identifier (this, "lvalue");
5013  r.write ("  gcc_jit_lvalue *%s = \n"
5014	   "    gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5015	   "                                 %s, /*gcc_jit_location *loc */\n"
5016	   "                                 %s);\n",
5017	   id,
5018	   r.get_identifier_as_lvalue (m_lvalue),
5019	   r.get_identifier (m_loc),
5020	   r.get_identifier (m_field));
5021}
5022
5023/* The implementation of class gcc::jit::recording::access_field_rvalue.  */
5024
5025/* Implementation of pure virtual hook recording::memento::replay_into
5026   for recording::access_field_rvalue.  */
5027
5028void
5029recording::access_field_rvalue::replay_into (replayer *r)
5030{
5031  set_playback_obj (
5032    m_rvalue->playback_rvalue ()
5033      ->access_field (playback_location (r, m_loc),
5034		      m_field->playback_field ()));
5035}
5036
5037/* Implementation of pure virtual hook recording::rvalue::visit_children
5038   for recording::access_field_rvalue.  */
5039
5040void
5041recording::access_field_rvalue::visit_children (rvalue_visitor *v)
5042{
5043  v->visit (m_rvalue);
5044}
5045
5046/* Implementation of recording::memento::make_debug_string for
5047   accessing a field of an rvalue.  */
5048
5049recording::string *
5050recording::access_field_rvalue::make_debug_string ()
5051{
5052  enum precedence prec = get_precedence ();
5053  return string::from_printf (m_ctxt,
5054			      "%s.%s",
5055			      m_rvalue->get_debug_string_parens (prec),
5056			      m_field->get_debug_string ());
5057}
5058
5059/* Implementation of recording::memento::write_reproducer for
5060   access_field_rvalue.  */
5061
5062void
5063recording::access_field_rvalue::write_reproducer (reproducer &r)
5064{
5065  const char *id = r.make_identifier (this, "rvalue");
5066  r.write ("  gcc_jit_rvalue *%s = \n"
5067	   "    gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5068	   "                                 %s, /*gcc_jit_location *loc */\n"
5069	   "                                 %s);\n",
5070	   id,
5071	   r.get_identifier_as_rvalue (m_rvalue),
5072	   r.get_identifier (m_loc),
5073	   r.get_identifier (m_field));
5074}
5075
5076/* The implementation of class
5077   gcc::jit::recording::dereference_field_rvalue.  */
5078
5079/* Implementation of pure virtual hook recording::memento::replay_into
5080   for recording::dereference_field_rvalue.  */
5081
5082void
5083recording::dereference_field_rvalue::replay_into (replayer *r)
5084{
5085  set_playback_obj (
5086    m_rvalue->playback_rvalue ()->
5087      dereference_field (playback_location (r, m_loc),
5088			 m_field->playback_field ()));
5089}
5090
5091/* Implementation of pure virtual hook recording::rvalue::visit_children
5092   for recording::dereference_field_rvalue.  */
5093
5094void
5095recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
5096{
5097  v->visit (m_rvalue);
5098}
5099
5100/* Implementation of recording::memento::make_debug_string for
5101   dereferencing a field of an rvalue.  */
5102
5103recording::string *
5104recording::dereference_field_rvalue::make_debug_string ()
5105{
5106  enum precedence prec = get_precedence ();
5107  return string::from_printf (m_ctxt,
5108			      "%s->%s",
5109			      m_rvalue->get_debug_string_parens (prec),
5110			      m_field->get_debug_string ());
5111}
5112
5113/* Implementation of recording::memento::write_reproducer for
5114   dereference_field_rvalue.  */
5115
5116void
5117recording::dereference_field_rvalue::write_reproducer (reproducer &r)
5118{
5119  const char *id = r.make_identifier (this, "lvalue");
5120  r.write ("  gcc_jit_lvalue *%s=\n"
5121	   "    gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5122	   "                                      %s, /* gcc_jit_location *loc */\n"
5123	   "                                      %s); /* gcc_jit_field *field */\n",
5124	   id,
5125	   r.get_identifier_as_rvalue (m_rvalue),
5126	   r.get_identifier (m_loc),
5127	   r.get_identifier (m_field));
5128}
5129
5130/* The implementation of class gcc::jit::recording::dereference_rvalue.  */
5131
5132/* Implementation of pure virtual hook recording::memento::replay_into
5133   for recording::dereference_rvalue.  */
5134
5135void
5136recording::dereference_rvalue::replay_into (replayer *r)
5137{
5138  set_playback_obj (
5139    m_rvalue->playback_rvalue ()->
5140      dereference (playback_location (r, m_loc)));
5141}
5142
5143/* Implementation of pure virtual hook recording::rvalue::visit_children
5144   for recording::dereference_rvalue.  */
5145
5146void
5147recording::dereference_rvalue::visit_children (rvalue_visitor *v)
5148{
5149  v->visit (m_rvalue);
5150}
5151
5152/* Implementation of recording::memento::make_debug_string for
5153   dereferencing an rvalue.  */
5154
5155recording::string *
5156recording::dereference_rvalue::make_debug_string ()
5157{
5158  enum precedence prec = get_precedence ();
5159  return string::from_printf (m_ctxt,
5160			      "*%s",
5161			      m_rvalue->get_debug_string_parens (prec));
5162}
5163
5164/* Implementation of recording::memento::write_reproducer for
5165   dereference_rvalue.  */
5166
5167void
5168recording::dereference_rvalue::write_reproducer (reproducer &r)
5169{
5170  const char *id = r.make_identifier (this, "dereference");
5171  r.write ("  gcc_jit_lvalue *%s =\n"
5172	   "    gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5173	   "                                %s); /* gcc_jit_location *loc */\n",
5174	   id,
5175	   r.get_identifier_as_rvalue (m_rvalue),
5176	   r.get_identifier (m_loc));
5177}
5178
5179/* The implementation of class gcc::jit::recording::get_address_of_lvalue.  */
5180
5181/* Implementation of pure virtual hook recording::memento::replay_into
5182   for recording::get_address_of_lvalue.  */
5183
5184void
5185recording::get_address_of_lvalue::replay_into (replayer *r)
5186{
5187  set_playback_obj (
5188    m_lvalue->playback_lvalue ()->
5189      get_address (playback_location (r, m_loc)));
5190}
5191
5192/* Implementation of pure virtual hook recording::rvalue::visit_children
5193   for recording::get_address_of_lvalue.  */
5194
5195void
5196recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
5197{
5198  v->visit (m_lvalue);
5199}
5200
5201/* Implementation of recording::memento::make_debug_string for
5202   getting the address of an lvalue.  */
5203
5204recording::string *
5205recording::get_address_of_lvalue::make_debug_string ()
5206{
5207  enum precedence prec = get_precedence ();
5208  return string::from_printf (m_ctxt,
5209			      "&%s",
5210			      m_lvalue->get_debug_string_parens (prec));
5211}
5212
5213/* Implementation of recording::memento::write_reproducer for
5214   get_address_of_lvalue.  */
5215
5216void
5217recording::get_address_of_lvalue::write_reproducer (reproducer &r)
5218{
5219  const char *id = r.make_identifier (this, "address_of");
5220  r.write ("  gcc_jit_rvalue *%s =\n"
5221	   "    gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5222	   "                                %s); /* gcc_jit_location *loc */\n",
5223	   id,
5224	   r.get_identifier_as_lvalue (m_lvalue),
5225	   r.get_identifier (m_loc));
5226}
5227
5228/* The implementation of class gcc::jit::recording::local.  */
5229
5230/* Implementation of pure virtual hook recording::memento::replay_into
5231   for recording::local.  */
5232
5233void
5234recording::local::replay_into (replayer *r)
5235{
5236  set_playback_obj (
5237    m_func->playback_function ()
5238      ->new_local (playback_location (r, m_loc),
5239		   m_type->playback_type (),
5240		   playback_string (m_name)));
5241}
5242
5243/* Override the default implementation of
5244   recording::memento::write_to_dump for locals by writing
5245      TYPE NAME;
5246   for use at the top of the function body as if it were a
5247   declaration.  */
5248
5249void
5250recording::local::write_to_dump (dump &d)
5251{
5252  if (d.update_locations ())
5253    m_loc = d.make_location ();
5254  d.write("  %s %s;\n",
5255	  m_type->get_debug_string (),
5256	  get_debug_string ());
5257}
5258
5259void
5260recording::local::write_reproducer (reproducer &r)
5261{
5262  const char *id = r.make_identifier (this, "local");
5263  r.write ("  gcc_jit_lvalue *%s =\n"
5264	   "    gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5265	   "                                %s, /* gcc_jit_location *loc */\n"
5266	   "                                %s, /* gcc_jit_type *type */\n"
5267	   "                                %s); /* const char *name */\n",
5268	   id,
5269	   r.get_identifier (m_func),
5270	   r.get_identifier (m_loc),
5271	   r.get_identifier_as_type (m_type),
5272	   m_name->get_debug_string ());
5273}
5274
5275/* The implementation of class gcc::jit::recording::statement.  */
5276
5277/* We poison the default implementation of
5278   gcc::jit::recording::statement::get_successor_blocks
5279   since this vfunc must only ever be called on terminator
5280   statements.  */
5281
5282vec <recording::block *>
5283recording::statement::get_successor_blocks () const
5284{
5285  /* The base class implementation is for non-terminating statements,
5286     and thus should never be called.  */
5287  gcc_unreachable ();
5288  vec <block *> result;
5289  result.create (0);
5290  return result;
5291}
5292
5293/* Extend the default implementation of
5294   recording::memento::write_to_dump for statements by (if requested)
5295   updating the location of the statement to the current location in
5296   the dumpfile.  */
5297
5298void
5299recording::statement::write_to_dump (dump &d)
5300{
5301  memento::write_to_dump (d);
5302  if (d.update_locations ())
5303    m_loc = d.make_location ();
5304}
5305
5306/* The implementation of class gcc::jit::recording::eval.  */
5307
5308/* Implementation of pure virtual hook recording::memento::replay_into
5309   for recording::eval.  */
5310
5311void
5312recording::eval::replay_into (replayer *r)
5313{
5314  playback_block (get_block ())
5315    ->add_eval (playback_location (r),
5316		m_rvalue->playback_rvalue ());
5317}
5318
5319/* Implementation of recording::memento::make_debug_string for
5320   an eval statement.  */
5321
5322recording::string *
5323recording::eval::make_debug_string ()
5324{
5325  return string::from_printf (m_ctxt,
5326			      "(void)%s;",
5327			      m_rvalue->get_debug_string ());
5328}
5329
5330/* Implementation of recording::memento::write_reproducer for
5331   eval statements.  */
5332
5333void
5334recording::eval::write_reproducer (reproducer &r)
5335{
5336  r.write ("  gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5337	   "                          %s, /* gcc_jit_location *loc */\n"
5338	   "                          %s); /* gcc_jit_rvalue *rvalue */\n",
5339	   r.get_identifier (get_block ()),
5340	   r.get_identifier (get_loc ()),
5341	   r.get_identifier_as_rvalue (m_rvalue));
5342}
5343
5344/* The implementation of class gcc::jit::recording::assignment.  */
5345
5346/* Implementation of pure virtual hook recording::memento::replay_into
5347   for recording::assignment.  */
5348
5349void
5350recording::assignment::replay_into (replayer *r)
5351{
5352  playback_block (get_block ())
5353    ->add_assignment (playback_location (r),
5354		      m_lvalue->playback_lvalue (),
5355		      m_rvalue->playback_rvalue ());
5356}
5357
5358/* Implementation of recording::memento::make_debug_string for
5359   an assignment statement.  */
5360
5361recording::string *
5362recording::assignment::make_debug_string ()
5363{
5364  return string::from_printf (m_ctxt,
5365			      "%s = %s;",
5366			      m_lvalue->get_debug_string (),
5367			      m_rvalue->get_debug_string ());
5368}
5369
5370/* Implementation of recording::memento::write_reproducer for
5371   assignment statements.  */
5372
5373void
5374recording::assignment::write_reproducer (reproducer &r)
5375{
5376  r.write ("  gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5377	   "                                %s, /* gcc_jit_location *loc */\n"
5378	   "                                %s, /* gcc_jit_lvalue *lvalue */\n"
5379	   "                                %s); /* gcc_jit_rvalue *rvalue */\n",
5380	   r.get_identifier (get_block ()),
5381	   r.get_identifier (get_loc ()),
5382	   r.get_identifier_as_lvalue (m_lvalue),
5383	   r.get_identifier_as_rvalue (m_rvalue));
5384}
5385
5386/* The implementation of class gcc::jit::recording::assignment_op.  */
5387
5388/* Implementation of pure virtual hook recording::memento::replay_into
5389   for recording::assignment_op.  */
5390
5391void
5392recording::assignment_op::replay_into (replayer *r)
5393{
5394  playback::type *result_type =
5395    m_lvalue->playback_lvalue ()->get_type ();
5396
5397  playback::rvalue *binary_op =
5398    r->new_binary_op (playback_location (r),
5399		      m_op,
5400		      result_type,
5401		      m_lvalue->playback_rvalue (),
5402		      m_rvalue->playback_rvalue ());
5403
5404  playback_block (get_block ())
5405    ->add_assignment (playback_location (r),
5406		      m_lvalue->playback_lvalue (),
5407		      binary_op);
5408}
5409
5410/* Implementation of recording::memento::make_debug_string for
5411   an assignment_op statement.  */
5412
5413recording::string *
5414recording::assignment_op::make_debug_string ()
5415{
5416  return string::from_printf (m_ctxt,
5417			      "%s %s= %s;",
5418			      m_lvalue->get_debug_string (),
5419			      binary_op_strings[m_op],
5420			      m_rvalue->get_debug_string ());
5421}
5422
5423/* Implementation of recording::memento::write_reproducer for
5424   assignment_op statements.  */
5425
5426void
5427recording::assignment_op::write_reproducer (reproducer &r)
5428{
5429  r.write ("  gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5430	   "                                   %s, /* gcc_jit_location *loc */\n"
5431	   "                                   %s, /* gcc_jit_lvalue *lvalue */\n"
5432	   "                                   %s, /* enum gcc_jit_binary_op op */\n"
5433	   "                                   %s); /* gcc_jit_rvalue *rvalue */\n",
5434	   r.get_identifier (get_block ()),
5435	   r.get_identifier (get_loc ()),
5436	   r.get_identifier_as_lvalue (m_lvalue),
5437	   binary_op_reproducer_strings[m_op],
5438	   r.get_identifier_as_rvalue (m_rvalue));
5439}
5440
5441/* The implementation of class gcc::jit::recording::comment.  */
5442
5443/* Implementation of pure virtual hook recording::memento::replay_into
5444   for recording::comment.  */
5445
5446void
5447recording::comment::replay_into (replayer *r)
5448{
5449  playback_block (get_block ())
5450    ->add_comment (playback_location (r),
5451		   m_text->c_str ());
5452}
5453
5454/* Implementation of recording::memento::make_debug_string for
5455   a comment "statement".  */
5456
5457recording::string *
5458recording::comment::make_debug_string ()
5459{
5460  return string::from_printf (m_ctxt,
5461			      "/* %s */",
5462			      m_text->c_str ());
5463}
5464
5465/* Implementation of recording::memento::write_reproducer for
5466   comments.  */
5467
5468void
5469recording::comment::write_reproducer (reproducer &r)
5470{
5471  r.write ("  gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5472	   "                             %s, /* gcc_jit_location *loc */\n"
5473	   "                             %s); /* const char *text */\n",
5474	   r.get_identifier (get_block ()),
5475	   r.get_identifier (get_loc ()),
5476	   m_text->get_debug_string ());
5477}
5478
5479/* The implementation of class gcc::jit::recording::conditional.  */
5480
5481/* Implementation of pure virtual hook recording::memento::replay_into
5482   for recording::conditional.  */
5483
5484void
5485recording::conditional::replay_into (replayer *r)
5486{
5487  playback_block (get_block ())
5488    ->add_conditional (playback_location (r),
5489		       m_boolval->playback_rvalue (),
5490		       playback_block (m_on_true),
5491		       playback_block (m_on_false));
5492}
5493
5494/* Override the poisoned default implementation of
5495   gcc::jit::recording::statement::get_successor_blocks
5496
5497   A conditional jump has 2 successor blocks.  */
5498
5499vec <recording::block *>
5500recording::conditional::get_successor_blocks () const
5501{
5502  vec <block *> result;
5503  result.create (2);
5504  result.quick_push (m_on_true);
5505  result.quick_push (m_on_false);
5506  return result;
5507}
5508
5509/* Implementation of recording::memento::make_debug_string for
5510   a conditional jump statement.  */
5511
5512recording::string *
5513recording::conditional::make_debug_string ()
5514{
5515  if (m_on_false)
5516    return string::from_printf (m_ctxt,
5517				"if (%s) goto %s; else goto %s;",
5518				m_boolval->get_debug_string (),
5519				m_on_true->get_debug_string (),
5520				m_on_false->get_debug_string ());
5521  else
5522    return string::from_printf (m_ctxt,
5523				"if (%s) goto %s;",
5524				m_boolval->get_debug_string (),
5525				m_on_true->get_debug_string ());
5526}
5527
5528/* Implementation of recording::memento::write_reproducer for
5529   conditional statements.  */
5530
5531void
5532recording::conditional::write_reproducer (reproducer &r)
5533{
5534  r.write ("  gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5535	   "                                      %s, /* gcc_jit_location *loc */\n"
5536	   "                                      %s, /* gcc_jit_rvalue *boolval */\n"
5537	   "                                      %s, /* gcc_jit_block *on_true */\n"
5538	   "                                      %s); /* gcc_jit_block *on_false */\n",
5539	   r.get_identifier (get_block ()),
5540	   r.get_identifier (get_loc ()),
5541	   r.get_identifier_as_rvalue (m_boolval),
5542	   r.get_identifier (m_on_true),
5543	   r.get_identifier (m_on_false));
5544}
5545
5546/* The implementation of class gcc::jit::recording::jump.  */
5547
5548/* Implementation of pure virtual hook recording::memento::replay_into
5549   for recording::jump.  */
5550
5551void
5552recording::jump::replay_into (replayer *r)
5553{
5554  playback_block (get_block ())
5555    ->add_jump (playback_location (r),
5556		m_target->playback_block ());
5557}
5558
5559/* Override the poisoned default implementation of
5560   gcc::jit::recording::statement::get_successor_blocks
5561
5562   An unconditional jump has 1 successor block.  */
5563
5564vec <recording::block *>
5565recording::jump::get_successor_blocks () const
5566{
5567  vec <block *> result;
5568  result.create (1);
5569  result.quick_push (m_target);
5570  return result;
5571}
5572
5573/* Implementation of recording::memento::make_debug_string for
5574   a unconditional jump statement.  */
5575
5576recording::string *
5577recording::jump::make_debug_string ()
5578{
5579  return string::from_printf (m_ctxt,
5580			      "goto %s;",
5581			      m_target->get_debug_string ());
5582}
5583
5584/* Implementation of recording::memento::write_reproducer for
5585   jump statements.  */
5586
5587void
5588recording::jump::write_reproducer (reproducer &r)
5589{
5590  r.write ("  gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5591	   "                               %s, /* gcc_jit_location *loc */\n"
5592	   "                               %s); /* gcc_jit_block *target */\n",
5593	   r.get_identifier (get_block ()),
5594	   r.get_identifier (get_loc ()),
5595	   r.get_identifier (m_target));
5596}
5597
5598/* The implementation of class gcc::jit::recording::return_.  */
5599
5600/* Implementation of pure virtual hook recording::memento::replay_into
5601   for recording::return_.  */
5602
5603void
5604recording::return_::replay_into (replayer *r)
5605{
5606  playback_block (get_block ())
5607    ->add_return (playback_location (r),
5608		  m_rvalue ? m_rvalue->playback_rvalue () : NULL);
5609}
5610
5611/* Override the poisoned default implementation of
5612   gcc::jit::recording::statement::get_successor_blocks
5613
5614   A return statement has no successor block.  */
5615
5616vec <recording::block *>
5617recording::return_::get_successor_blocks () const
5618{
5619  vec <block *> result;
5620  result.create (0);
5621  return result;
5622}
5623
5624/* Implementation of recording::memento::make_debug_string for
5625   a return statement (covers both those with and without rvalues).  */
5626
5627recording::string *
5628recording::return_::make_debug_string ()
5629{
5630  if (m_rvalue)
5631    return string::from_printf (m_ctxt,
5632				"return %s;",
5633				m_rvalue->get_debug_string ());
5634  else
5635    return string::from_printf (m_ctxt,
5636				"return;");
5637}
5638
5639/* Implementation of recording::memento::write_reproducer for
5640   return statements.  */
5641
5642void
5643recording::return_::write_reproducer (reproducer &r)
5644{
5645  if (m_rvalue)
5646    r.write ("  gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5647	     "                                 %s, /* gcc_jit_location *loc */\n"
5648	     "                                 %s); /* gcc_jit_rvalue *rvalue */\n",
5649	     r.get_identifier (get_block ()),
5650	     r.get_identifier (get_loc ()),
5651	     r.get_identifier_as_rvalue (m_rvalue));
5652  else
5653    r.write ("  gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5654	     "                                      %s); /* gcc_jit_location *loc */\n",
5655	     r.get_identifier (get_block ()),
5656	     r.get_identifier (get_loc ()));
5657}
5658
5659/* The implementation of class gcc::jit::recording::case_.  */
5660
5661void
5662recording::case_::write_reproducer (reproducer &r)
5663{
5664  const char *id = r.make_identifier (this, "case");
5665  const char *fmt =
5666    "  gcc_jit_case *%s = \n"
5667    "    gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
5668    "                              %s, /* gcc_jit_rvalue *min_value */\n"
5669    "                              %s, /* gcc_jit_rvalue *max_value */\n"
5670    "                              %s); /* gcc_jit_block *dest_block */\n";
5671  r.write (fmt,
5672	   id,
5673	   r.get_identifier (get_context ()),
5674	   r.get_identifier_as_rvalue (m_min_value),
5675	   r.get_identifier_as_rvalue (m_max_value),
5676	   r.get_identifier (m_dest_block));
5677}
5678
5679recording::string *
5680recording::case_::make_debug_string ()
5681{
5682  return string::from_printf (get_context (),
5683			      "case %s ... %s: goto %s;",
5684			      m_min_value->get_debug_string (),
5685			      m_max_value->get_debug_string (),
5686			      m_dest_block->get_debug_string ());
5687}
5688
5689/* The implementation of class gcc::jit::recording::switch_.  */
5690
5691/* gcc::jit::recording::switch_'s constructor.  */
5692
5693recording::switch_::switch_ (block *b,
5694			     location *loc,
5695			     rvalue *expr,
5696			     block *default_block,
5697			     int num_cases,
5698			     case_ **cases)
5699: statement (b, loc),
5700  m_expr (expr),
5701  m_default_block (default_block)
5702{
5703  m_cases.reserve_exact (num_cases);
5704  for (int i = 0; i< num_cases; i++)
5705    m_cases.quick_push (cases[i]);
5706}
5707
5708/* Implementation of pure virtual hook recording::memento::replay_into
5709   for recording::switch_.  */
5710
5711void
5712recording::switch_::replay_into (replayer *r)
5713{
5714  auto_vec <playback::case_> pcases;
5715  int i;
5716  recording::case_ *rcase;
5717  pcases.reserve_exact (m_cases.length ());
5718  FOR_EACH_VEC_ELT (m_cases, i, rcase)
5719    {
5720      playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (),
5721			     rcase->get_max_value ()->playback_rvalue (),
5722			     rcase->get_dest_block ()->playback_block ());
5723      pcases.safe_push (pcase);
5724    }
5725  playback_block (get_block ())
5726    ->add_switch (playback_location (r),
5727		  m_expr->playback_rvalue (),
5728		  m_default_block->playback_block (),
5729		  &pcases);
5730}
5731
5732/* Override the poisoned default implementation of
5733   gcc::jit::recording::statement::get_successor_blocks
5734
5735   A switch statement has (NUM_CASES + 1) successor blocks.  */
5736
5737vec <recording::block *>
5738recording::switch_::get_successor_blocks () const
5739{
5740  vec <block *> result;
5741  result.create (m_cases.length () + 1);
5742  result.quick_push (m_default_block);
5743  int i;
5744  case_ *c;
5745  FOR_EACH_VEC_ELT (m_cases, i, c)
5746    result.quick_push (c->get_dest_block ());
5747  return result;
5748}
5749
5750/* Implementation of recording::memento::make_debug_string for
5751   a switch statement.  */
5752
5753recording::string *
5754recording::switch_::make_debug_string ()
5755{
5756  auto_vec <char> cases_str;
5757  int i;
5758  case_ *c;
5759  FOR_EACH_VEC_ELT (m_cases, i, c)
5760    {
5761      size_t len = strlen (c->get_debug_string ());
5762      unsigned idx = cases_str.length ();
5763      cases_str.safe_grow (idx + 1 + len);
5764      cases_str[idx] = ' ';
5765      memcpy (&(cases_str[idx + 1]),
5766	      c->get_debug_string (),
5767	      len);
5768    }
5769  cases_str.safe_push ('\0');
5770
5771  return string::from_printf (m_ctxt,
5772			      "switch (%s) {default: goto %s;%s}",
5773			      m_expr->get_debug_string (),
5774			      m_default_block->get_debug_string (),
5775			      &cases_str[0]);
5776}
5777
5778/* Implementation of recording::memento::write_reproducer for
5779   switch statements.  */
5780
5781void
5782recording::switch_::write_reproducer (reproducer &r)
5783{
5784  r.make_identifier (this, "switch");
5785  int i;
5786  case_ *c;
5787  const char *cases_id =
5788    r.make_tmp_identifier ("cases_for", this);
5789  r.write ("  gcc_jit_case *%s[%i] = {\n",
5790	   cases_id,
5791	   m_cases.length ());
5792  FOR_EACH_VEC_ELT (m_cases, i, c)
5793    r.write ("    %s,\n", r.get_identifier (c));
5794  r.write ("  };\n");
5795  const char *fmt =
5796    "  gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
5797    "                                 %s, /* gcc_jit_location *loc */\n"
5798    "                                 %s, /* gcc_jit_rvalue *expr */\n"
5799    "                                 %s, /* gcc_jit_block *default_block */\n"
5800    "                                 %i, /* int num_cases */\n"
5801    "                                 %s); /* gcc_jit_case **cases */\n";
5802    r.write (fmt,
5803	     r.get_identifier (get_block ()),
5804	     r.get_identifier (get_loc ()),
5805	     r.get_identifier_as_rvalue (m_expr),
5806	     r.get_identifier (m_default_block),
5807	     m_cases.length (),
5808	     cases_id);
5809}
5810
5811} // namespace gcc::jit
5812
5813} // namespace gcc
5814