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