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