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