2015-05-22 Hristian Kirtchev <kirtchev@adacore.com>
[official-gcc.git] / gcc / jit / jit-recording.c
blob32d7f31a8c353b799deda678f114175bdda9cb30
1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2015 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
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.
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.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "pretty-print.h"
26 #include "hash-map.h"
27 #include "toplev.h"
29 #include <pthread.h>
31 #include "jit-common.h"
32 #include "jit-builtins.h"
33 #include "jit-logging.h"
34 #include "jit-recording.h"
35 #include "jit-playback.h"
37 namespace gcc {
38 namespace jit {
40 // class dump
42 dump::dump (recording::context &ctxt,
43 const char *filename,
44 bool update_locations)
45 : m_ctxt (ctxt),
46 m_filename (filename),
47 m_update_locations (update_locations),
48 m_line (0),
49 m_column (0)
51 m_file = fopen (filename, "w");
52 if (!m_file)
53 ctxt.add_error (NULL,
54 "error opening dump file %s for writing: %s",
55 filename,
56 xstrerror (errno));
59 dump::~dump ()
61 if (m_file)
63 int err = fclose (m_file);
64 if (err)
65 m_ctxt.add_error (NULL,
66 "error closing dump file %s: %s",
67 m_filename,
68 xstrerror (errno));
72 /* Write the given message to the dump, using printf-formatting
73 conventions, updating the line/column within the dump.
75 Emit an error on the context if a failure occurs. */
77 void
78 dump::write (const char *fmt, ...)
80 int len;
81 va_list ap;
82 char *buf;
84 /* If there was an error opening the file, we've already reported it.
85 Don't attempt further work. */
86 if (!m_file)
87 return;
89 va_start (ap, fmt);
90 len = vasprintf (&buf, fmt, ap);
91 va_end (ap);
93 if (buf == NULL || len < 0)
95 m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
96 m_filename);
97 return;
100 if (fwrite (buf, strlen (buf), 1, m_file) != 1)
101 m_ctxt.add_error (NULL, "error writing to dump file %s",
102 m_filename);
104 /* Flush after each line, to ease debugging crashes. */
105 fflush (m_file);
107 /* Update line/column: */
108 for (const char *ptr = buf; *ptr; ptr++)
110 if ('\n' == *ptr)
112 m_line++;
113 m_column = 0;
115 else
116 m_column++;
119 free (buf);
122 /* Construct a gcc::jit::recording::location instance for the current
123 location within the dump. */
125 recording::location *
126 dump::make_location () const
128 return m_ctxt.new_location (m_filename, m_line, m_column,
129 /* We need to flag such locations as *not*
130 created by the user, so that
131 reproducer::get_identifier can cope with
132 them appearing *after* the memento that
133 refers to them. */
134 false);
137 /* A collection of allocations, all of which can be released together, to
138 avoid needing to track and release them individually. */
140 class allocator
142 public:
143 ~allocator ();
145 char *
146 xstrdup_printf (const char *, ...)
147 ATTRIBUTE_RETURNS_NONNULL
148 GNU_PRINTF(2, 3);
150 char *
151 xstrdup_printf_va (const char *, va_list ap)
152 ATTRIBUTE_RETURNS_NONNULL
153 GNU_PRINTF(2, 0);
155 private:
156 auto_vec <void *> m_buffers;
159 /* allocator's destructor. Call "free" on all of the allocations. */
161 allocator::~allocator ()
163 unsigned i;
164 void *buffer;
165 FOR_EACH_VEC_ELT (m_buffers, i, buffer)
166 free (buffer);
169 /* Formatted printing, allocating to a buffer (or exiting the process if
170 the allocation fails).
172 The buffer exists until the allocator is cleaned up, and is freed at
173 that point, so the caller doesn't need to track the result. */
175 char *
176 allocator::xstrdup_printf (const char *fmt, ...)
178 char *result;
179 va_list ap;
180 va_start (ap, fmt);
181 result = xstrdup_printf_va (fmt, ap);
182 va_end (ap);
183 return result;
186 /* Formatted printing, allocating to a buffer (or exiting the process if
187 the allocation fails).
189 The buffer exists until the allocator is cleaned up, and is freed at
190 that point, so the caller doesn't need to track the result. */
192 char *
193 allocator::xstrdup_printf_va (const char *fmt, va_list ap)
195 char *result = xvasprintf (fmt, ap);
196 m_buffers.safe_push (result);
197 return result;
200 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
201 implementing gcc_jit_context_dump_reproducer_to_file. */
203 class reproducer : public dump
205 public:
206 reproducer (recording::context &ctxt,
207 const char *filename);
209 void
210 write_params (const vec <recording::context *> &contexts);
212 void
213 write_args (const vec <recording::context *> &contexts);
215 const char *
216 make_identifier (recording::memento *m, const char *prefix);
218 const char *
219 make_tmp_identifier (const char *prefix, recording::memento *m);
221 const char *
222 get_identifier (recording::context *ctxt);
224 const char *
225 get_identifier (recording::memento *m);
227 const char *
228 get_identifier_as_rvalue (recording::rvalue *m);
230 const char *
231 get_identifier_as_lvalue (recording::lvalue *m);
233 const char *
234 get_identifier_as_type (recording::type *m);
236 char *
237 xstrdup_printf (const char *, ...)
238 ATTRIBUTE_RETURNS_NONNULL
239 GNU_PRINTF(2, 3);
241 private:
242 hash_map<recording::memento *, const char *> m_identifiers;
243 allocator m_allocator;
246 /* gcc::jit::reproducer's constructor. */
248 reproducer::reproducer (recording::context &ctxt,
249 const char *filename) :
250 dump (ctxt, filename, 0),
251 m_identifiers (),
252 m_allocator ()
256 /* Write out a list of contexts as a set of parameters within a
257 C function declaration. */
259 void
260 reproducer::write_params (const vec <recording::context *> &contexts)
262 unsigned i;
263 recording::context *ctxt;
264 FOR_EACH_VEC_ELT (contexts, i, ctxt)
266 write ("gcc_jit_context *%s",
267 get_identifier (ctxt));
268 if (i < contexts.length () - 1)
269 write (",\n"
270 " ");
274 /* Write out a list of contexts as a set of arguments within a call
275 to a C function. */
277 void
278 reproducer::write_args (const vec <recording::context *> &contexts)
280 unsigned i;
281 recording::context *ctxt;
282 FOR_EACH_VEC_ELT (contexts, i, ctxt)
284 write ("%s",
285 get_identifier (ctxt));
286 if (i < contexts.length () - 1)
287 write (",\n"
288 " ");
292 /* Generate a C identifier for the given memento, associating the generated
293 buffer with the memento (for future calls to get_identifier et al).
295 The reproducer will eventually clean up the buffer in its dtor. */
296 const char *
297 reproducer::make_identifier (recording::memento *m, const char *prefix)
299 char *result;
300 if (strlen (m->get_debug_string ()) < 100)
302 result = m_allocator.xstrdup_printf ("%s_%s_%p",
303 prefix,
304 m->get_debug_string (),
305 (void *) m);
306 for (char *p = result; *p; p++)
307 if (!ISALNUM (*p))
308 *p = '_';
310 else
311 result = m_allocator.xstrdup_printf ("%s_%p",
312 prefix, (void *) m);
313 m_identifiers.put (m, result);
314 return result;
317 /* Generate a C identifier for a temporary variable.
318 The reproducer will eventually clean up the buffer in its dtor. */
320 const char *
321 reproducer::make_tmp_identifier (const char *prefix, recording::memento *m)
323 return m_allocator.xstrdup_printf ("%s_%s",
324 prefix, get_identifier (m));
327 /* Generate a C identifier for the given context.
328 The reproducer will eventually clean up the buffer in its dtor. */
330 const char *
331 reproducer::get_identifier (recording::context *ctxt)
333 return m_allocator.xstrdup_printf ("ctxt_%p",
334 (void *)ctxt);
337 /* Locate the C identifier for the given memento, which is assumed to
338 have already been created via make_identifier. */
340 const char *
341 reproducer::get_identifier (recording::memento *m)
343 if (!m)
344 return "NULL";
346 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
347 and hence these locations appear in the context's memento list
348 out-of-order: they appear in the context's memento list *after*
349 the memento that refers to them. For this case, it's simplest to
350 pretend that they're NULL when writing out the code to recreate the
351 memento that uses them. */
352 if (recording::location *loc = m->dyn_cast_location ())
353 if (!loc->created_by_user ())
354 return "NULL";
356 const char **slot = m_identifiers.get (m);
357 if (!slot)
359 get_context ().add_error (NULL,
360 "unable to find identifier for %p: %s",
361 (void *)m,
362 m->get_debug_string ());
363 gcc_unreachable ();
365 return *slot;
368 /* Locate the C identifier for the given rvalue, wrapping it within
369 a gcc_*_as_rvalue upcast if necessary. */
371 const char *
372 reproducer::get_identifier_as_rvalue (recording::rvalue *m)
374 return m->access_as_rvalue (*this);
377 /* Locate the C identifier for the given lvalue, wrapping it within
378 a gcc_*_as_lvalue upcast if necessary. */
380 const char *
381 reproducer::get_identifier_as_lvalue (recording::lvalue *m)
383 return m->access_as_lvalue (*this);
386 /* Locate the C identifier for the given type, wrapping it within
387 a gcc_*_as_type upcast if necessary. */
389 const char *
390 reproducer::get_identifier_as_type (recording::type *m)
392 return m->access_as_type (*this);
395 /* Formatted printing, allocating to a buffer (or exiting the process if
396 the allocation fails).
398 The buffer exists until the allocator is cleaned up, and is freed at
399 that point, so the caller doesn't need to track the result.
401 Note that we can't use ggc_printf since we're not within the compiler
402 proper (when within gcc_jit_context_dump_reproducer_to_file). */
404 char *
405 reproducer::xstrdup_printf (const char *fmt, ...)
407 char *result;
408 va_list ap;
409 va_start (ap, fmt);
410 result = m_allocator.xstrdup_printf_va (fmt, ap);
411 va_end (ap);
412 return result;
415 /**********************************************************************
416 Recording.
417 **********************************************************************/
419 /* Get the playback::location for the given recording::location,
420 handling a NULL input with a NULL output. */
422 playback::location *
423 recording::playback_location (replayer *r, recording::location *loc)
425 if (loc)
426 return loc->playback_location (r);
427 else
428 return NULL;
431 /* Get a const char * for the given recording::string
432 handling a NULL input with a NULL output. */
434 const char *
435 recording::playback_string (recording::string *str)
437 if (str)
438 return str->c_str ();
439 else
440 return NULL;
443 /* Get the playback::block for the given recording::block,
444 handling a NULL input with a NULL output. */
446 playback::block *
447 recording::playback_block (recording::block *b)
449 if (b)
450 return b->playback_block ();
451 else
452 return NULL;
455 /* Methods of cc::jit::recording::context. */
457 /* The constructor for gcc::jit::recording::context, used by
458 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
460 recording::context::context (context *parent_ctxt)
461 : log_user (NULL),
462 m_parent_ctxt (parent_ctxt),
463 m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this),
464 m_error_count (0),
465 m_first_error_str (NULL),
466 m_owns_first_error_str (false),
467 m_last_error_str (NULL),
468 m_owns_last_error_str (false),
469 m_mementos (),
470 m_compound_types (),
471 m_globals (),
472 m_functions (),
473 m_FILE_type (NULL),
474 m_builtins_manager(NULL)
476 if (parent_ctxt)
478 /* Inherit options from parent. */
479 for (unsigned i = 0;
480 i < sizeof (m_str_options) / sizeof (m_str_options[0]);
481 i++)
483 const char *parent_opt = parent_ctxt->m_str_options[i];
484 m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
486 memcpy (m_int_options,
487 parent_ctxt->m_int_options,
488 sizeof (m_int_options));
489 memcpy (m_bool_options,
490 parent_ctxt->m_bool_options,
491 sizeof (m_bool_options));
492 set_logger (parent_ctxt->get_logger ());
494 else
496 memset (m_str_options, 0, sizeof (m_str_options));
497 memset (m_int_options, 0, sizeof (m_int_options));
498 memset (m_bool_options, 0, sizeof (m_bool_options));
501 memset (m_basic_types, 0, sizeof (m_basic_types));
504 /* The destructor for gcc::jit::recording::context, implicitly used by
505 gcc_jit_context_release. */
507 recording::context::~context ()
509 JIT_LOG_SCOPE (get_logger ());
510 int i;
511 memento *m;
512 FOR_EACH_VEC_ELT (m_mementos, i, m)
514 delete m;
517 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
518 free (m_str_options[i]);
520 if (m_builtins_manager)
521 delete m_builtins_manager;
523 if (m_owns_first_error_str)
524 free (m_first_error_str);
526 if (m_owns_last_error_str)
527 if (m_last_error_str != m_first_error_str)
528 free (m_last_error_str);
531 /* Add the given mememto to the list of those tracked by this
532 gcc::jit::recording::context, so that e.g. it can be deleted
533 when this context is released. */
535 void
536 recording::context::record (memento *m)
538 gcc_assert (m);
540 m_mementos.safe_push (m);
543 /* Replay this context (and any parents) into the given replayer. */
545 void
546 recording::context::replay_into (replayer *r)
548 JIT_LOG_SCOPE (get_logger ());
549 int i;
550 memento *m;
552 /* If we have a parent context, we must replay it. This will
553 recursively walk backwards up the historical tree, then replay things
554 forwards "in historical order", starting with the ultimate parent
555 context, until we reach the "this" context.
557 Note that we fully replay the parent, then fully replay the child,
558 which means that inter-context references can only exist from child
559 to parent, not the other way around.
561 All of this replaying is suboptimal - it would be better to do the
562 work for the parent context *once*, rather than replaying the parent
563 every time we replay each child. However, fixing this requires deep
564 surgery to lifetime-management: we'd need every context family tree
565 to have its own GC heap, and to initialize the GCC code to use that
566 heap (with a mutex on such a heap). */
567 if (m_parent_ctxt)
568 m_parent_ctxt->replay_into (r);
570 if (r->errors_occurred ())
571 return;
573 /* Replay this context's saved operations into r. */
574 FOR_EACH_VEC_ELT (m_mementos, i, m)
576 /* Disabled low-level debugging, here if we need it: print what
577 we're replaying.
578 Note that the calls to get_debug_string might lead to more
579 mementos being created for the strings.
580 This can also be used to exercise the debug_string
581 machinery. */
582 if (0)
583 printf ("context %p replaying (%p): %s\n",
584 (void *)this, (void *)m, m->get_debug_string ());
586 m->replay_into (r);
588 if (r->errors_occurred ())
589 return;
593 /* During a playback, we associate objects from the recording with
594 their counterparts during this playback.
596 For simplicity, we store this within the recording objects.
598 The following method cleans away these associations, to ensure that
599 we never have out-of-date associations lingering on subsequent
600 playbacks (the objects pointed to are GC-managed, but the
601 recording objects don't own refs to them). */
603 void
604 recording::context::disassociate_from_playback ()
606 JIT_LOG_SCOPE (get_logger ());
607 int i;
608 memento *m;
610 if (m_parent_ctxt)
611 m_parent_ctxt->disassociate_from_playback ();
613 FOR_EACH_VEC_ELT (m_mementos, i, m)
615 m->set_playback_obj (NULL);
619 /* Create a recording::string instance and add it to this context's list
620 of mementos.
622 This creates a fresh copy of the given 0-terminated buffer. */
624 recording::string *
625 recording::context::new_string (const char *text)
627 if (!text)
628 return NULL;
630 recording::string *result = new string (this, text);
631 record (result);
632 return result;
635 /* Create a recording::location instance and add it to this context's
636 list of mementos.
638 Implements the post-error-checking part of
639 gcc_jit_context_new_location. */
641 recording::location *
642 recording::context::new_location (const char *filename,
643 int line,
644 int column,
645 bool created_by_user)
647 recording::location *result =
648 new recording::location (this,
649 new_string (filename),
650 line, column,
651 created_by_user);
652 record (result);
653 return result;
656 /* If we haven't seen this enum value yet, create a recording::type
657 instance and add it to this context's list of mementos.
659 If we have seen it before, reuse our cached value, so that repeated
660 calls on the context give the same object.
662 If we have a parent context, the cache is within the ultimate
663 ancestor context.
665 Implements the post-error-checking part of
666 gcc_jit_context_get_type. */
668 recording::type *
669 recording::context::get_type (enum gcc_jit_types kind)
671 if (!m_basic_types[kind])
673 if (m_parent_ctxt)
674 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
675 else
677 recording::type *result = new memento_of_get_type (this, kind);
678 record (result);
679 m_basic_types[kind] = result;
683 return m_basic_types[kind];
686 /* Get a recording::type instance for the given size and signedness.
687 This is implemented in terms of recording::context::get_type
688 above.
690 Implements the post-error-checking part of
691 gcc_jit_context_get_int_type. */
693 recording::type *
694 recording::context::get_int_type (int num_bytes, int is_signed)
696 /* We can't use a switch here since some of the values are macros affected
697 by options; e.g. i386.h has
698 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
699 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
700 are in bits, rather than bytes.
702 const int num_bits = num_bytes * 8;
703 if (num_bits == INT_TYPE_SIZE)
704 return get_type (is_signed
705 ? GCC_JIT_TYPE_INT
706 : GCC_JIT_TYPE_UNSIGNED_INT);
707 if (num_bits == CHAR_TYPE_SIZE)
708 return get_type (is_signed
709 ? GCC_JIT_TYPE_SIGNED_CHAR
710 : GCC_JIT_TYPE_UNSIGNED_CHAR);
711 if (num_bits == SHORT_TYPE_SIZE)
712 return get_type (is_signed
713 ? GCC_JIT_TYPE_SHORT
714 : GCC_JIT_TYPE_UNSIGNED_SHORT);
715 if (num_bits == LONG_TYPE_SIZE)
716 return get_type (is_signed
717 ? GCC_JIT_TYPE_LONG
718 : GCC_JIT_TYPE_UNSIGNED_LONG);
719 if (num_bits == LONG_LONG_TYPE_SIZE)
720 return get_type (is_signed
721 ? GCC_JIT_TYPE_LONG_LONG
722 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
724 /* Some other size, not corresponding to the C int types. */
725 /* To be written: support arbitrary other sizes, sharing by
726 memoizing at the recording::context level? */
727 gcc_unreachable ();
730 /* Create a recording::type instance and add it to this context's list
731 of mementos.
733 Implements the post-error-checking part of
734 gcc_jit_context_new_array_type. */
736 recording::type *
737 recording::context::new_array_type (recording::location *loc,
738 recording::type *element_type,
739 int num_elements)
741 if (struct_ *s = element_type->dyn_cast_struct ())
742 if (!s->get_fields ())
744 add_error (NULL,
745 "cannot create an array of type %s"
746 " until the fields have been set",
747 s->get_name ()->c_str ());
748 return NULL;
750 recording::type *result =
751 new recording::array_type (this, loc, element_type, num_elements);
752 record (result);
753 return result;
756 /* Create a recording::field instance and add it to this context's list
757 of mementos.
759 Implements the post-error-checking part of
760 gcc_jit_context_new_field. */
762 recording::field *
763 recording::context::new_field (recording::location *loc,
764 recording::type *type,
765 const char *name)
767 recording::field *result =
768 new recording::field (this, loc, type, new_string (name));
769 record (result);
770 return result;
773 /* Create a recording::struct_ instance and add it to this context's
774 list of mementos and list of compound types.
776 Implements the post-error-checking part of
777 gcc_jit_context_new_struct_type. */
779 recording::struct_ *
780 recording::context::new_struct_type (recording::location *loc,
781 const char *name)
783 recording::struct_ *result = new struct_ (this, loc, new_string (name));
784 record (result);
785 m_compound_types.safe_push (result);
786 return result;
789 /* Create a recording::union_ instance and add it to this context's
790 list of mementos and list of compound types.
792 Implements the first post-error-checking part of
793 gcc_jit_context_new_union_type. */
795 recording::union_ *
796 recording::context::new_union_type (recording::location *loc,
797 const char *name)
799 recording::union_ *result = new union_ (this, loc, new_string (name));
800 record (result);
801 m_compound_types.safe_push (result);
802 return result;
805 /* Create a recording::function_type instance and add it to this context's
806 list of mementos.
808 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
810 recording::function_type *
811 recording::context::new_function_type (recording::type *return_type,
812 int num_params,
813 recording::type **param_types,
814 int is_variadic)
816 recording::function_type *fn_type
817 = new function_type (this,
818 return_type,
819 num_params,
820 param_types,
821 is_variadic);
822 record (fn_type);
823 return fn_type;
826 /* Create a recording::type instance and add it to this context's list
827 of mementos.
829 Implements the post-error-checking part of
830 gcc_jit_context_new_function_ptr_type. */
832 recording::type *
833 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
834 recording::type *return_type,
835 int num_params,
836 recording::type **param_types,
837 int is_variadic)
839 recording::function_type *fn_type
840 = new_function_type (return_type,
841 num_params,
842 param_types,
843 is_variadic);
845 /* Return a pointer-type to the the function type. */
846 return fn_type->get_pointer ();
849 /* Create a recording::param instance and add it to this context's list
850 of mementos.
852 Implements the post-error-checking part of
853 gcc_jit_context_new_param. */
855 recording::param *
856 recording::context::new_param (recording::location *loc,
857 recording::type *type,
858 const char *name)
860 recording::param *result = new recording::param (this, loc, type, new_string (name));
861 record (result);
862 return result;
865 /* Create a recording::function instance and add it to this context's list
866 of mementos and list of functions.
868 Implements the post-error-checking part of
869 gcc_jit_context_new_function. */
871 recording::function *
872 recording::context::new_function (recording::location *loc,
873 enum gcc_jit_function_kind kind,
874 recording::type *return_type,
875 const char *name,
876 int num_params,
877 recording::param **params,
878 int is_variadic,
879 enum built_in_function builtin_id)
881 recording::function *result =
882 new recording::function (this,
883 loc, kind, return_type,
884 new_string (name),
885 num_params, params, is_variadic,
886 builtin_id);
887 record (result);
888 m_functions.safe_push (result);
890 return result;
893 /* Locate the builtins_manager (if any) for this family of contexts,
894 creating it if it doesn't exist already.
896 All of the recording contexts in a family share one builtins_manager:
897 if we have a child context, follow the parent links to get the
898 ultimate ancestor context, and look for it/store it there. */
900 builtins_manager *
901 recording::context::get_builtins_manager ()
903 if (m_parent_ctxt)
904 return m_parent_ctxt->get_builtins_manager ();
906 if (!m_builtins_manager)
907 m_builtins_manager = new builtins_manager (this);
909 return m_builtins_manager;
912 /* Get a recording::function instance, which is lazily-created and added
913 to the context's lists of mementos.
915 Implements the post-error-checking part of
916 gcc_jit_context_get_builtin_function. */
918 recording::function *
919 recording::context::get_builtin_function (const char *name)
921 builtins_manager *bm = get_builtins_manager ();
922 return bm->get_builtin_function (name);
925 /* Create a recording::global instance and add it to this context's list
926 of mementos.
928 Implements the post-error-checking part of
929 gcc_jit_context_new_global. */
931 recording::lvalue *
932 recording::context::new_global (recording::location *loc,
933 enum gcc_jit_global_kind kind,
934 recording::type *type,
935 const char *name)
937 recording::global *result =
938 new recording::global (this, loc, kind, type, new_string (name));
939 record (result);
940 m_globals.safe_push (result);
942 return result;
945 /* Create a recording::memento_of_new_string_literal instance and add it
946 to this context's list of mementos.
948 Implements the post-error-checking part of
949 gcc_jit_context_new_string_literal. */
951 recording::rvalue *
952 recording::context::new_string_literal (const char *value)
954 recording::rvalue *result =
955 new memento_of_new_string_literal (this, NULL, new_string (value));
956 record (result);
957 return result;
960 /* Create a recording::unary_op instance and add it to this context's
961 list of mementos.
963 Implements the post-error-checking part of
964 gcc_jit_context_new_unary_op. */
966 recording::rvalue *
967 recording::context::new_unary_op (recording::location *loc,
968 enum gcc_jit_unary_op op,
969 recording::type *result_type,
970 recording::rvalue *a)
972 recording::rvalue *result =
973 new unary_op (this, loc, op, result_type, a);
974 record (result);
975 return result;
978 /* Create a recording::binary_op instance and add it to this context's
979 list of mementos.
981 Implements the post-error-checking part of
982 gcc_jit_context_new_binary_op. */
984 recording::rvalue *
985 recording::context::new_binary_op (recording::location *loc,
986 enum gcc_jit_binary_op op,
987 recording::type *result_type,
988 recording::rvalue *a,
989 recording::rvalue *b)
991 recording::rvalue *result =
992 new binary_op (this, loc, op, result_type, a, b);
993 record (result);
994 return result;
997 /* Create a recording::comparison instance and add it to this context's
998 list of mementos.
1000 Implements the post-error-checking part of
1001 gcc_jit_context_new_comparison. */
1003 recording::rvalue *
1004 recording::context::new_comparison (recording::location *loc,
1005 enum gcc_jit_comparison op,
1006 recording::rvalue *a,
1007 recording::rvalue *b)
1009 recording::rvalue *result = new comparison (this, loc, op, a, b);
1010 record (result);
1011 return result;
1014 /* Create a recording::cast instance and add it to this context's list
1015 of mementos.
1017 Implements the post-error-checking part of
1018 gcc_jit_context_new_cast. */
1020 recording::rvalue *
1021 recording::context::new_cast (recording::location *loc,
1022 recording::rvalue *expr,
1023 recording::type *type_)
1025 recording::rvalue *result = new cast (this, loc, expr, type_);
1026 record (result);
1027 return result;
1030 /* Create a recording::call instance and add it to this context's list
1031 of mementos.
1033 Implements the post-error-checking part of
1034 gcc_jit_context_new_call. */
1036 recording::rvalue *
1037 recording::context::new_call (recording::location *loc,
1038 function *func,
1039 int numargs , recording::rvalue **args)
1041 recording::rvalue *result = new call (this, loc, func, numargs, args);
1042 record (result);
1043 return result;
1046 /* Create a recording::call_through_ptr instance and add it to this
1047 context's list of mementos.
1049 Implements the post-error-checking part of
1050 gcc_jit_context_new_call_through_ptr. */
1052 recording::rvalue *
1053 recording::context::new_call_through_ptr (recording::location *loc,
1054 recording::rvalue *fn_ptr,
1055 int numargs,
1056 recording::rvalue **args)
1058 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
1059 record (result);
1060 return result;
1063 /* Create a recording::array_access instance and add it to this context's list
1064 of mementos.
1066 Implements the post-error-checking part of
1067 gcc_jit_context_new_array_access. */
1069 recording::lvalue *
1070 recording::context::new_array_access (recording::location *loc,
1071 recording::rvalue *ptr,
1072 recording::rvalue *index)
1074 recording::lvalue *result = new array_access (this, loc, ptr, index);
1075 record (result);
1076 return result;
1079 /* Set the given string option for this context, or add an error if
1080 it's not recognized.
1082 Implements the post-error-checking part of
1083 gcc_jit_context_set_str_option. */
1085 void
1086 recording::context::set_str_option (enum gcc_jit_str_option opt,
1087 const char *value)
1089 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
1091 add_error (NULL,
1092 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
1093 return;
1095 free (m_str_options[opt]);
1096 m_str_options[opt] = value ? xstrdup (value) : NULL;
1097 log_str_option (opt);
1100 /* Set the given integer option for this context, or add an error if
1101 it's not recognized.
1103 Implements the post-error-checking part of
1104 gcc_jit_context_set_int_option. */
1106 void
1107 recording::context::set_int_option (enum gcc_jit_int_option opt,
1108 int value)
1110 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
1112 add_error (NULL,
1113 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
1114 return;
1116 m_int_options[opt] = value;
1117 log_int_option (opt);
1120 /* Set the given boolean option for this context, or add an error if
1121 it's not recognized.
1123 Implements the post-error-checking part of
1124 gcc_jit_context_set_bool_option. */
1126 void
1127 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
1128 int value)
1130 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
1132 add_error (NULL,
1133 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
1134 return;
1136 m_bool_options[opt] = value ? true : false;
1137 log_bool_option (opt);
1140 /* Add the given dumpname/out_ptr pair to this context's list of requested
1141 dumps.
1143 Implements the post-error-checking part of
1144 gcc_jit_context_enable_dump. */
1146 void
1147 recording::context::enable_dump (const char *dumpname,
1148 char **out_ptr)
1150 requested_dump d;
1151 gcc_assert (dumpname);
1152 gcc_assert (out_ptr);
1154 d.m_dumpname = dumpname;
1155 d.m_out_ptr = out_ptr;
1156 *out_ptr = NULL;
1157 m_requested_dumps.safe_push (d);
1160 /* Validate this context, and if it passes, compile it to memory
1161 (within a mutex).
1163 Implements the post-error-checking part of
1164 gcc_jit_context_compile. */
1166 result *
1167 recording::context::compile ()
1169 JIT_LOG_SCOPE (get_logger ());
1171 log_all_options ();
1173 validate ();
1175 if (errors_occurred ())
1176 return NULL;
1178 /* Set up a compile_to_memory playback context. */
1179 ::gcc::jit::playback::compile_to_memory replayer (this);
1181 /* Use it. */
1182 replayer.compile ();
1184 /* Get the jit::result (or NULL) from the
1185 compile_to_memory playback context. */
1186 return replayer.get_result_obj ();
1189 /* Validate this context, and if it passes, compile it to a file
1190 (within a mutex).
1192 Implements the post-error-checking part of
1193 gcc_jit_context_compile_to_file. */
1195 void
1196 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
1197 const char *output_path)
1199 JIT_LOG_SCOPE (get_logger ());
1201 log_all_options ();
1203 validate ();
1205 if (errors_occurred ())
1206 return;
1208 /* Set up a compile_to_file playback context. */
1209 ::gcc::jit::playback::compile_to_file replayer (this,
1210 output_kind,
1211 output_path);
1213 /* Use it. */
1214 replayer.compile ();
1217 /* Format the given error using printf's conventions, print
1218 it to stderr, and add it to the context. */
1220 void
1221 recording::context::add_error (location *loc, const char *fmt, ...)
1223 va_list ap;
1224 va_start (ap, fmt);
1225 add_error_va (loc, fmt, ap);
1226 va_end (ap);
1229 /* Format the given error using printf's conventions, print
1230 it to stderr, and add it to the context. */
1232 void
1233 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
1235 int len;
1236 char *malloced_msg;
1237 const char *errmsg;
1238 bool has_ownership;
1240 JIT_LOG_SCOPE (get_logger ());
1242 len = vasprintf (&malloced_msg, fmt, ap);
1243 if (malloced_msg == NULL || len < 0)
1245 errmsg = "out of memory generating error message";
1246 has_ownership = false;
1248 else
1250 errmsg = malloced_msg;
1251 has_ownership = true;
1253 if (get_logger ())
1254 get_logger ()->log ("error %i: %s", m_error_count, errmsg);
1256 const char *ctxt_progname =
1257 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
1258 if (!ctxt_progname)
1259 ctxt_progname = "libgccjit.so";
1261 if (loc)
1262 fprintf (stderr, "%s: %s: error: %s\n",
1263 ctxt_progname,
1264 loc->get_debug_string (),
1265 errmsg);
1266 else
1267 fprintf (stderr, "%s: error: %s\n",
1268 ctxt_progname,
1269 errmsg);
1271 if (!m_error_count)
1273 m_first_error_str = const_cast <char *> (errmsg);
1274 m_owns_first_error_str = has_ownership;
1277 if (m_owns_last_error_str)
1278 if (m_last_error_str != m_first_error_str)
1279 free (m_last_error_str);
1280 m_last_error_str = const_cast <char *> (errmsg);
1281 m_owns_last_error_str = has_ownership;
1283 m_error_count++;
1286 /* Get the message for the first error that occurred on this context, or
1287 NULL if no errors have occurred on it.
1289 Implements the post-error-checking part of
1290 gcc_jit_context_get_first_error. */
1292 const char *
1293 recording::context::get_first_error () const
1295 return m_first_error_str;
1298 /* Get the message for the last error that occurred on this context, or
1299 NULL if no errors have occurred on it.
1301 Implements the post-error-checking part of
1302 gcc_jit_context_get_last_error. */
1304 const char *
1305 recording::context::get_last_error () const
1307 return m_last_error_str;
1310 /* Lazily generate and record a recording::type representing an opaque
1311 struct named "FILE".
1313 For use if client code tries to dereference the result of
1314 get_type (GCC_JIT_TYPE_FILE_PTR). */
1316 recording::type *
1317 recording::context::get_opaque_FILE_type ()
1319 if (!m_FILE_type)
1320 m_FILE_type = new_struct_type (NULL, "FILE");
1321 return m_FILE_type;
1324 /* Dump a C-like representation of the given context to the given path.
1325 If UPDATE_LOCATIONS is true, update the locations within the
1326 context's mementos to point to the dumpfile.
1328 Implements the post-error-checking part of
1329 gcc_jit_context_dump_to_file. */
1331 void
1332 recording::context::dump_to_file (const char *path, bool update_locations)
1334 int i;
1335 dump d (*this, path, update_locations);
1337 /* Forward declaration of structs and unions. */
1338 compound_type *st;
1339 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1341 d.write ("%s;\n\n", st->get_debug_string ());
1344 /* Content of structs, where set. */
1345 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1346 if (st->get_fields ())
1348 st->get_fields ()->write_to_dump (d);
1349 d.write ("\n");
1352 /* Globals. */
1353 global *g;
1354 FOR_EACH_VEC_ELT (m_globals, i, g)
1356 g->write_to_dump (d);
1358 if (!m_globals.is_empty ())
1359 d.write ("\n");
1361 function *fn;
1362 FOR_EACH_VEC_ELT (m_functions, i, fn)
1364 fn->write_to_dump (d);
1368 static const char * const
1369 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
1370 "GCC_JIT_STR_OPTION_PROGNAME"
1373 static const char * const
1374 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
1375 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1378 static const char * const
1379 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
1380 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1381 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1382 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1383 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1384 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1385 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1386 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1387 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1391 /* Write the current value of all options to the log file (if any). */
1393 void
1394 recording::context::log_all_options () const
1396 int opt_idx;
1398 if (!get_logger ())
1399 return;
1401 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1402 log_str_option ((enum gcc_jit_str_option)opt_idx);
1404 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1405 log_int_option ((enum gcc_jit_int_option)opt_idx);
1407 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1408 log_bool_option ((enum gcc_jit_bool_option)opt_idx);
1411 /* Write the current value of the given string option to the
1412 log file (if any). */
1414 void
1415 recording::context::log_str_option (enum gcc_jit_str_option opt) const
1417 gcc_assert (opt < GCC_JIT_NUM_STR_OPTIONS);
1418 if (get_logger ())
1420 if (m_str_options[opt])
1421 log ("%s: \"%s\"",
1422 str_option_reproducer_strings[opt],
1423 m_str_options[opt]);
1424 else
1425 log ("%s: NULL",
1426 str_option_reproducer_strings[opt]);
1430 /* Write the current value of the given int option to the
1431 log file (if any). */
1433 void
1434 recording::context::log_int_option (enum gcc_jit_int_option opt) const
1436 gcc_assert (opt < GCC_JIT_NUM_INT_OPTIONS);
1437 if (get_logger ())
1438 log ("%s: %i",
1439 int_option_reproducer_strings[opt],
1440 m_int_options[opt]);
1443 /* Write the current value of the given bool option to the
1444 log file (if any). */
1446 void
1447 recording::context::log_bool_option (enum gcc_jit_bool_option opt) const
1449 gcc_assert (opt < GCC_JIT_NUM_BOOL_OPTIONS);
1450 if (get_logger ())
1451 log ("%s: %s",
1452 bool_option_reproducer_strings[opt],
1453 m_bool_options[opt] ? "true" : "false");
1456 /* Write C source code to PATH that attempts to replay the API
1457 calls made to this context (and its parents), for use in
1458 minimizing test cases for libgccjit.
1460 Implements the post-error-checking part of
1461 gcc_jit_context_dump_reproducer_to_file. */
1463 void
1464 recording::context::dump_reproducer_to_file (const char *path)
1466 JIT_LOG_SCOPE (get_logger ());
1467 reproducer r (*this, path);
1469 /* Generate the "ancestry" of this context, as a list. */
1470 auto_vec <context *> ascending_contexts;
1471 for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
1472 ascending_contexts.safe_push (ctxt);
1474 /* Reverse the list, giving a list of contexts from
1475 top-most parent context down through to youngest child context.
1476 We will use this list as the parameters of the functions in
1477 our generated file. */
1478 unsigned num_ctxts = ascending_contexts.length ();
1479 auto_vec <context *> contexts (num_ctxts);
1480 for (unsigned i = 0; i < num_ctxts; i++)
1481 contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
1483 /* contexts[0] should be the top-level context. */
1484 gcc_assert (contexts[0]);
1485 gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
1487 /* The final element in contexts should be "this". */
1488 gcc_assert (contexts[contexts.length () - 1] == this);
1489 gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
1490 == contexts[0]);
1492 r.write ("/* This code was autogenerated by"
1493 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1494 print_version (r.get_file (), " ", false);
1495 r.write ("*/\n");
1496 r.write ("#include <libgccjit.h>\n\n");
1497 r.write ("static void\nset_options (");
1498 r.write_params (contexts);
1499 r.write (");\n\n");
1500 r.write ("static void\ncreate_code (");
1501 r.write_params (contexts);
1502 r.write (");\n\n");
1503 r.write ("int\nmain (int argc, const char **argv)\n");
1504 r.write ("{\n");
1505 for (unsigned i = 0; i < num_ctxts; i++)
1506 r.write (" gcc_jit_context *%s;\n",
1507 r.get_identifier (contexts[i]));
1508 r.write (" gcc_jit_result *result;\n"
1509 "\n");
1511 /* Create the contexts.
1512 The top-level context is acquired from a clean slate, the others as
1513 children of the prior context. */
1514 r.write (" %s = gcc_jit_context_acquire ();\n",
1515 r.get_identifier (contexts[0]));
1516 for (unsigned i = 1; i < num_ctxts; i++)
1517 r.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1518 r.get_identifier (contexts[i]),
1519 r.get_identifier (contexts[i - 1]));
1520 r.write (" set_options (");
1521 r.write_args (contexts);
1522 r.write (");\n");
1523 r.write (" create_code (");
1524 r.write_args (contexts);
1525 r.write (");\n");
1527 r.write (" result = gcc_jit_context_compile (%s);\n",
1528 r.get_identifier (this));
1530 for (unsigned i = num_ctxts; i > 0; i--)
1531 r.write (" gcc_jit_context_release (%s);\n",
1532 r.get_identifier (contexts[i - 1]));
1534 r.write (" gcc_jit_result_release (result);\n"
1535 " return 0;\n"
1536 "}\n\n");
1538 /* Define (char *) variables for use in calls to
1539 gcc_jit_context_enable_dump. */
1540 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1542 if (m_requested_dumps.length ())
1544 r.write ("/* Requested dumps for %s. */\n",
1545 r.get_identifier (contexts[ctxt_idx]));
1546 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1547 r.write ("static char *dump_%p;\n",
1548 (void *)&m_requested_dumps[i]);
1549 r.write ("\n");
1553 /* Write out values of options. */
1554 r.write ("static void\nset_options (");
1555 r.write_params (contexts);
1556 r.write (")\n{\n");
1557 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1559 if (ctxt_idx > 0)
1560 r.write ("\n");
1562 r.write (" /* Set options for %s. */\n",
1563 r.get_identifier (contexts[ctxt_idx]));
1565 r.write (" /* String options. */\n");
1566 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1567 r.write (" gcc_jit_context_set_str_option (%s,\n"
1568 " %s,\n"
1569 " \"%s\");\n",
1570 r.get_identifier (contexts[ctxt_idx]),
1571 str_option_reproducer_strings[opt_idx],
1572 m_str_options[opt_idx] ? m_str_options[opt_idx] : "NULL");
1573 r.write (" /* Int options. */\n");
1574 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1575 r.write (" gcc_jit_context_set_int_option (%s,\n"
1576 " %s,\n"
1577 " %i);\n",
1578 r.get_identifier (contexts[ctxt_idx]),
1579 int_option_reproducer_strings[opt_idx],
1580 m_int_options[opt_idx]);
1581 r.write (" /* Boolean options. */\n");
1582 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1583 r.write (" gcc_jit_context_set_bool_option (%s,\n"
1584 " %s,\n"
1585 " %i);\n",
1586 r.get_identifier (contexts[ctxt_idx]),
1587 bool_option_reproducer_strings[opt_idx],
1588 m_bool_options[opt_idx]);
1590 if (m_requested_dumps.length ())
1592 r.write (" /* Requested dumps. */\n");
1593 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1594 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1596 r.write (" gcc_jit_context_enable_dump (%s,\n"
1597 " \"%s\",\n"
1598 " &dump_%p);\n",
1599 r.get_identifier (contexts[ctxt_idx]),
1600 m_requested_dumps[i].m_dumpname,
1601 (void *)&m_requested_dumps[i]);
1605 r.write ("}\n\n");
1607 r.write ("static void\ncreate_code (");
1608 r.write_params (contexts);
1609 r.write (")\n"
1610 "{\n");
1611 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1613 memento *m;
1614 int i;
1615 if (ctxt_idx > 0)
1616 r.write ("\n\n");
1618 r.write (" /* Replay of API calls for %s. */\n",
1619 r.get_identifier (contexts[ctxt_idx]));
1620 FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
1621 m->write_reproducer (r);
1623 r.write ("}\n");
1626 /* Copy the requested dumps within this context and all ancestors into
1627 OUT. */
1629 void
1630 recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
1632 if (m_parent_ctxt)
1633 m_parent_ctxt->get_all_requested_dumps (out);
1635 out->reserve (m_requested_dumps.length ());
1636 out->splice (m_requested_dumps);
1639 /* This is a pre-compilation check for the context (and any parents).
1641 Detect errors within the context, adding errors if any are found. */
1643 void
1644 recording::context::validate ()
1646 JIT_LOG_SCOPE (get_logger ());
1648 if (m_parent_ctxt)
1649 m_parent_ctxt->validate ();
1651 int i;
1652 function *fn;
1653 FOR_EACH_VEC_ELT (m_functions, i, fn)
1654 fn->validate ();
1657 /* The implementation of class gcc::jit::recording::memento. */
1659 /* Get a (const char *) debug description of the given memento, by
1660 calling the pure-virtual make_debug_string hook, caching the
1661 result.
1663 It is intended that this should only be called in debugging and
1664 error-handling paths, so this doesn't need to be particularly
1665 optimized. */
1667 const char *
1668 recording::memento::get_debug_string ()
1670 if (!m_debug_string)
1671 m_debug_string = make_debug_string ();
1672 return m_debug_string->c_str ();
1675 /* Default implementation of recording::memento::write_to_dump, writing
1676 an indented form of the memento's debug string to the dump. */
1678 void
1679 recording::memento::write_to_dump (dump &d)
1681 d.write(" %s\n", get_debug_string ());
1684 /* The implementation of class gcc::jit::recording::string. */
1686 /* Constructor for gcc::jit::recording::string::string, allocating a
1687 copy of the given text using new char[]. */
1689 recording::string::string (context *ctxt, const char *text)
1690 : memento (ctxt)
1692 m_len = strlen (text);
1693 m_buffer = new char[m_len + 1];
1694 strcpy (m_buffer, text);
1697 /* Destructor for gcc::jit::recording::string::string. */
1699 recording::string::~string ()
1701 delete[] m_buffer;
1704 /* Function for making gcc::jit::recording::string instances on a
1705 context via printf-style formatting.
1707 It is intended that this should only be called in debugging and
1708 error-handling paths, so this doesn't need to be particularly
1709 optimized, hence the double-copy of the string is acceptable. */
1711 recording::string *
1712 recording::string::from_printf (context *ctxt, const char *fmt, ...)
1714 int len;
1715 va_list ap;
1716 char *buf;
1717 recording::string *result;
1719 va_start (ap, fmt);
1720 len = vasprintf (&buf, fmt, ap);
1721 va_end (ap);
1723 if (buf == NULL || len < 0)
1725 ctxt->add_error (NULL, "malloc failure");
1726 return NULL;
1729 result = ctxt->new_string (buf);
1730 free (buf);
1731 return result;
1734 /* Implementation of recording::memento::make_debug_string for strings,
1735 wrapping the given string in quotes and escaping as necessary. */
1737 recording::string *
1738 recording::string::make_debug_string ()
1740 /* Hack to avoid infinite recursion into strings when logging all
1741 mementos: don't re-escape strings: */
1742 if (m_buffer[0] == '"')
1743 return this;
1745 /* Wrap in quotes and do escaping etc */
1747 size_t sz = (1 /* opening quote */
1748 + (m_len * 2) /* each char might get escaped */
1749 + 1 /* closing quote */
1750 + 1); /* nil termintator */
1751 char *tmp = new char[sz];
1752 size_t len = 0;
1754 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1755 APPEND('"'); /* opening quote */
1756 for (size_t i = 0; i < m_len ; i++)
1758 char ch = m_buffer[i];
1759 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
1760 APPEND('\\');
1761 APPEND(ch);
1763 APPEND('"'); /* closing quote */
1764 #undef APPEND
1765 tmp[len] = '\0'; /* nil termintator */
1767 string *result = m_ctxt->new_string (tmp);
1769 delete[] tmp;
1770 return result;
1773 /* Implementation of recording::memento::write_reproducer for strings. */
1775 void
1776 recording::string::write_reproducer (reproducer &)
1778 /* Empty. */
1781 /* The implementation of class gcc::jit::recording::location. */
1783 /* Implementation of recording::memento::replay_into for locations.
1785 Create a new playback::location and store it into the
1786 recording::location's m_playback_obj field. */
1788 void
1789 recording::location::replay_into (replayer *r)
1791 m_playback_obj = r->new_location (this,
1792 m_filename->c_str (),
1793 m_line,
1794 m_column);
1797 /* Implementation of recording::memento::make_debug_string for locations,
1798 turning them into the usual form:
1799 FILENAME:LINE:COLUMN
1800 like we do when emitting diagnostics. */
1802 recording::string *
1803 recording::location::make_debug_string ()
1805 return string::from_printf (m_ctxt,
1806 "%s:%i:%i",
1807 m_filename->c_str (), m_line, m_column);
1810 /* Implementation of recording::memento::write_reproducer for locations. */
1812 void
1813 recording::location::write_reproducer (reproducer &r)
1815 const char *id = r.make_identifier (this, "loc");
1816 r.write (" gcc_jit_location *%s =\n"
1817 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1818 " %s, /* const char *filename */\n"
1819 " %i, /* int line */\n"
1820 " %i);/* int column */\n",
1822 r.get_identifier (get_context ()),
1823 m_filename->get_debug_string (),
1824 m_line, m_column);
1827 /* The implementation of class gcc::jit::recording::type. */
1829 /* Given a type T, get the type T*.
1831 If this doesn't already exist, generate a new memento_of_get_pointer
1832 instance and add it to this type's context's list of mementos.
1834 Otherwise, use the cached type.
1836 Implements the post-error-checking part of
1837 gcc_jit_type_get_pointer. */
1839 recording::type *
1840 recording::type::get_pointer ()
1842 if (!m_pointer_to_this_type)
1844 m_pointer_to_this_type = new memento_of_get_pointer (this);
1845 m_ctxt->record (m_pointer_to_this_type);
1847 return m_pointer_to_this_type;
1850 /* Given a type T, get the type const T.
1852 Implements the post-error-checking part of
1853 gcc_jit_type_get_const. */
1855 recording::type *
1856 recording::type::get_const ()
1858 recording::type *result = new memento_of_get_const (this);
1859 m_ctxt->record (result);
1860 return result;
1863 /* Given a type T, get the type volatile T.
1865 Implements the post-error-checking part of
1866 gcc_jit_type_get_volatile. */
1868 recording::type *
1869 recording::type::get_volatile ()
1871 recording::type *result = new memento_of_get_volatile (this);
1872 m_ctxt->record (result);
1873 return result;
1876 const char *
1877 recording::type::access_as_type (reproducer &r)
1879 return r.get_identifier (this);
1882 /* Implementation of pure virtual hook recording::type::dereference for
1883 recording::memento_of_get_type. */
1885 recording::type *
1886 recording::memento_of_get_type::dereference ()
1888 switch (m_kind)
1890 default: gcc_unreachable ();
1892 case GCC_JIT_TYPE_VOID:
1893 return NULL;
1895 case GCC_JIT_TYPE_VOID_PTR:
1896 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
1898 case GCC_JIT_TYPE_BOOL:
1899 case GCC_JIT_TYPE_CHAR:
1900 case GCC_JIT_TYPE_SIGNED_CHAR:
1901 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1902 case GCC_JIT_TYPE_SHORT:
1903 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1904 case GCC_JIT_TYPE_INT:
1905 case GCC_JIT_TYPE_UNSIGNED_INT:
1906 case GCC_JIT_TYPE_LONG:
1907 case GCC_JIT_TYPE_UNSIGNED_LONG:
1908 case GCC_JIT_TYPE_LONG_LONG:
1909 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1910 case GCC_JIT_TYPE_FLOAT:
1911 case GCC_JIT_TYPE_DOUBLE:
1912 case GCC_JIT_TYPE_LONG_DOUBLE:
1913 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1914 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1915 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
1916 /* Not a pointer: */
1917 return NULL;
1919 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1920 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
1922 case GCC_JIT_TYPE_SIZE_T:
1923 /* Not a pointer: */
1924 return NULL;
1926 case GCC_JIT_TYPE_FILE_PTR:
1927 /* Give the client code back an opaque "struct FILE". */
1928 return m_ctxt->get_opaque_FILE_type ();
1932 /* Implementation of pure virtual hook recording::type::is_int for
1933 recording::memento_of_get_type. */
1935 bool
1936 recording::memento_of_get_type::is_int () const
1938 switch (m_kind)
1940 default: gcc_unreachable ();
1942 case GCC_JIT_TYPE_VOID:
1943 return false;
1945 case GCC_JIT_TYPE_VOID_PTR:
1946 return false;
1948 case GCC_JIT_TYPE_BOOL:
1949 return false;
1951 case GCC_JIT_TYPE_CHAR:
1952 case GCC_JIT_TYPE_SIGNED_CHAR:
1953 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1954 case GCC_JIT_TYPE_SHORT:
1955 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1956 case GCC_JIT_TYPE_INT:
1957 case GCC_JIT_TYPE_UNSIGNED_INT:
1958 case GCC_JIT_TYPE_LONG:
1959 case GCC_JIT_TYPE_UNSIGNED_LONG:
1960 case GCC_JIT_TYPE_LONG_LONG:
1961 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1962 return true;
1964 case GCC_JIT_TYPE_FLOAT:
1965 case GCC_JIT_TYPE_DOUBLE:
1966 case GCC_JIT_TYPE_LONG_DOUBLE:
1967 return false;
1969 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1970 return false;
1972 case GCC_JIT_TYPE_SIZE_T:
1973 return true;
1975 case GCC_JIT_TYPE_FILE_PTR:
1976 return false;
1978 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1979 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1980 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
1981 return false;
1985 /* Implementation of pure virtual hook recording::type::is_float for
1986 recording::memento_of_get_type. */
1988 bool
1989 recording::memento_of_get_type::is_float () const
1991 switch (m_kind)
1993 default: gcc_unreachable ();
1995 case GCC_JIT_TYPE_VOID:
1996 return false;
1998 case GCC_JIT_TYPE_VOID_PTR:
1999 return false;
2001 case GCC_JIT_TYPE_BOOL:
2002 return false;
2004 case GCC_JIT_TYPE_CHAR:
2005 case GCC_JIT_TYPE_SIGNED_CHAR:
2006 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2007 case GCC_JIT_TYPE_SHORT:
2008 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2009 case GCC_JIT_TYPE_INT:
2010 case GCC_JIT_TYPE_UNSIGNED_INT:
2011 case GCC_JIT_TYPE_LONG:
2012 case GCC_JIT_TYPE_UNSIGNED_LONG:
2013 case GCC_JIT_TYPE_LONG_LONG:
2014 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2015 return false;
2017 case GCC_JIT_TYPE_FLOAT:
2018 case GCC_JIT_TYPE_DOUBLE:
2019 case GCC_JIT_TYPE_LONG_DOUBLE:
2020 return true;
2022 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2023 return false;
2025 case GCC_JIT_TYPE_SIZE_T:
2026 return false;
2028 case GCC_JIT_TYPE_FILE_PTR:
2029 return false;
2031 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2032 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2033 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2034 return true;
2038 /* Implementation of pure virtual hook recording::type::is_bool for
2039 recording::memento_of_get_type. */
2041 bool
2042 recording::memento_of_get_type::is_bool () const
2044 switch (m_kind)
2046 default: gcc_unreachable ();
2048 case GCC_JIT_TYPE_VOID:
2049 return false;
2051 case GCC_JIT_TYPE_VOID_PTR:
2052 return false;
2054 case GCC_JIT_TYPE_BOOL:
2055 return true;
2057 case GCC_JIT_TYPE_CHAR:
2058 case GCC_JIT_TYPE_SIGNED_CHAR:
2059 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2060 case GCC_JIT_TYPE_SHORT:
2061 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2062 case GCC_JIT_TYPE_INT:
2063 case GCC_JIT_TYPE_UNSIGNED_INT:
2064 case GCC_JIT_TYPE_LONG:
2065 case GCC_JIT_TYPE_UNSIGNED_LONG:
2066 case GCC_JIT_TYPE_LONG_LONG:
2067 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2068 return false;
2070 case GCC_JIT_TYPE_FLOAT:
2071 case GCC_JIT_TYPE_DOUBLE:
2072 case GCC_JIT_TYPE_LONG_DOUBLE:
2073 return false;
2075 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2076 return false;
2078 case GCC_JIT_TYPE_SIZE_T:
2079 return false;
2081 case GCC_JIT_TYPE_FILE_PTR:
2082 return false;
2084 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2085 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2086 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2087 return false;
2091 /* Implementation of pure virtual hook recording::memento::replay_into
2092 for recording::memento_of_get_type. */
2094 void
2095 recording::memento_of_get_type::replay_into (replayer *r)
2097 set_playback_obj (r->get_type (m_kind));
2100 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2102 /* Descriptive strings for each of enum gcc_jit_types. */
2104 static const char * const get_type_strings[] = {
2105 "void", /* GCC_JIT_TYPE_VOID */
2106 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2108 "bool", /* GCC_JIT_TYPE_BOOL */
2110 "char", /* GCC_JIT_TYPE_CHAR */
2111 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2112 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2114 "short", /* GCC_JIT_TYPE_SHORT */
2115 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2117 "int", /* GCC_JIT_TYPE_INT */
2118 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2120 "long", /* GCC_JIT_TYPE_LONG */
2121 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2123 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2124 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2126 "float", /* GCC_JIT_TYPE_FLOAT */
2127 "double", /* GCC_JIT_TYPE_DOUBLE */
2128 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2130 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2132 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2134 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2136 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2137 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2138 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2142 /* Implementation of recording::memento::make_debug_string for
2143 results of get_type, using a simple table of type names. */
2145 recording::string *
2146 recording::memento_of_get_type::make_debug_string ()
2148 return m_ctxt->new_string (get_type_strings[m_kind]);
2151 static const char * const get_type_enum_strings[] = {
2152 "GCC_JIT_TYPE_VOID",
2153 "GCC_JIT_TYPE_VOID_PTR",
2154 "GCC_JIT_TYPE_BOOL",
2155 "GCC_JIT_TYPE_CHAR",
2156 "GCC_JIT_TYPE_SIGNED_CHAR",
2157 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2158 "GCC_JIT_TYPE_SHORT",
2159 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2160 "GCC_JIT_TYPE_INT",
2161 "GCC_JIT_TYPE_UNSIGNED_INT",
2162 "GCC_JIT_TYPE_LONG",
2163 "GCC_JIT_TYPE_UNSIGNED_LONG",
2164 "GCC_JIT_TYPE_LONG_LONG",
2165 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2166 "GCC_JIT_TYPE_FLOAT",
2167 "GCC_JIT_TYPE_DOUBLE",
2168 "GCC_JIT_TYPE_LONG_DOUBLE",
2169 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2170 "GCC_JIT_TYPE_SIZE_T",
2171 "GCC_JIT_TYPE_FILE_PTR",
2172 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2173 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2174 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2177 void
2178 recording::memento_of_get_type::write_reproducer (reproducer &r)
2180 const char *id = r.make_identifier (this, "type");
2181 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2183 r.get_identifier (get_context ()),
2184 get_type_enum_strings[m_kind]);
2187 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2189 /* Override of default implementation of
2190 recording::type::accepts_writes_from for get_pointer.
2192 Require a pointer type, and allowing writes to
2193 (const T *) from a (T*), but not the other way around. */
2195 bool
2196 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2198 /* Must be a pointer type: */
2199 type *rtype_points_to = rtype->is_pointer ();
2200 if (!rtype_points_to)
2201 return false;
2203 /* It's OK to assign to a (const T *) from a (T *). */
2204 return m_other_type->unqualified ()
2205 ->accepts_writes_from (rtype_points_to);
2208 /* Implementation of pure virtual hook recording::memento::replay_into
2209 for recording::memento_of_get_pointer. */
2211 void
2212 recording::memento_of_get_pointer::replay_into (replayer *)
2214 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2217 /* Implementation of recording::memento::make_debug_string for
2218 results of get_pointer, adding " *" to the underlying type,
2219 with special-casing to handle function pointer types. */
2221 recording::string *
2222 recording::memento_of_get_pointer::make_debug_string ()
2224 /* Special-case function pointer types, to put the "*" in parens between
2225 the return type and the params (for one level of dereferencing, at
2226 least). */
2227 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2228 return fn_type->make_debug_string_with_ptr ();
2230 return string::from_printf (m_ctxt,
2231 "%s *", m_other_type->get_debug_string ());
2234 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2236 void
2237 recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2239 /* We need to special-case function pointer types; see the notes in
2240 recording::function_type::write_deferred_reproducer. */
2241 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2243 fn_type->write_deferred_reproducer (r, this);
2244 return;
2247 const char *id = r.make_identifier (this, "type");
2248 r.write (" gcc_jit_type *%s =\n"
2249 " gcc_jit_type_get_pointer (%s);\n",
2251 r.get_identifier_as_type (m_other_type));
2254 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2256 /* Implementation of pure virtual hook recording::memento::replay_into
2257 for recording::memento_of_get_const. */
2259 void
2260 recording::memento_of_get_const::replay_into (replayer *)
2262 set_playback_obj (m_other_type->playback_type ()->get_const ());
2265 /* Implementation of recording::memento::make_debug_string for
2266 results of get_const, prepending "const ". */
2268 recording::string *
2269 recording::memento_of_get_const::make_debug_string ()
2271 return string::from_printf (m_ctxt,
2272 "const %s", m_other_type->get_debug_string ());
2275 /* Implementation of recording::memento::write_reproducer for const types. */
2277 void
2278 recording::memento_of_get_const::write_reproducer (reproducer &r)
2280 const char *id = r.make_identifier (this, "type");
2281 r.write (" gcc_jit_type *%s =\n"
2282 " gcc_jit_type_get_const (%s);\n",
2284 r.get_identifier_as_type (m_other_type));
2287 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2289 /* Implementation of pure virtual hook recording::memento::replay_into
2290 for recording::memento_of_get_volatile. */
2292 void
2293 recording::memento_of_get_volatile::replay_into (replayer *)
2295 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2298 /* Implementation of recording::memento::make_debug_string for
2299 results of get_volatile, prepending "volatile ". */
2301 recording::string *
2302 recording::memento_of_get_volatile::make_debug_string ()
2304 return string::from_printf (m_ctxt,
2305 "volatile %s", m_other_type->get_debug_string ());
2308 /* Implementation of recording::memento::write_reproducer for volatile
2309 types. */
2311 void
2312 recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2314 const char *id = r.make_identifier (this, "type");
2315 r.write (" gcc_jit_type *%s =\n"
2316 " gcc_jit_type_get_volatile (%s);\n",
2318 r.get_identifier_as_type (m_other_type));
2321 /* The implementation of class gcc::jit::recording::array_type */
2323 /* Implementation of pure virtual hook recording::type::dereference for
2324 recording::array_type. */
2326 recording::type *
2327 recording::array_type::dereference ()
2329 return m_element_type;
2332 /* Implementation of pure virtual hook recording::memento::replay_into
2333 for recording::array_type. */
2335 void
2336 recording::array_type::replay_into (replayer *r)
2338 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
2339 m_element_type->playback_type (),
2340 m_num_elements));
2343 /* Implementation of recording::memento::make_debug_string for
2344 results of new_array_type. */
2346 recording::string *
2347 recording::array_type::make_debug_string ()
2349 return string::from_printf (m_ctxt,
2350 "%s[%d]",
2351 m_element_type->get_debug_string (),
2352 m_num_elements);
2355 /* Implementation of recording::memento::write_reproducer for array
2356 types. */
2358 void
2359 recording::array_type::write_reproducer (reproducer &r)
2361 const char *id = r.make_identifier (this, "array_type");
2362 r.write (" gcc_jit_type *%s =\n"
2363 " gcc_jit_context_new_array_type (%s,\n"
2364 " %s, /* gcc_jit_location *loc */\n"
2365 " %s, /* gcc_jit_type *element_type */\n"
2366 " %i); /* int num_elements */\n",
2368 r.get_identifier (get_context ()),
2369 r.get_identifier (m_loc),
2370 r.get_identifier_as_type (m_element_type),
2371 m_num_elements);
2374 /* The implementation of class gcc::jit::recording::function_type */
2376 /* Constructor for gcc::jit::recording::function_type. */
2378 recording::function_type::function_type (context *ctxt,
2379 type *return_type,
2380 int num_params,
2381 type **param_types,
2382 int is_variadic)
2383 : type (ctxt),
2384 m_return_type (return_type),
2385 m_param_types (),
2386 m_is_variadic (is_variadic)
2388 for (int i = 0; i< num_params; i++)
2389 m_param_types.safe_push (param_types[i]);
2392 /* Implementation of pure virtual hook recording::type::dereference for
2393 recording::function_type. */
2395 recording::type *
2396 recording::function_type::dereference ()
2398 return NULL;
2401 /* Implementation of pure virtual hook recording::memento::replay_into
2402 for recording::function_type. */
2404 void
2405 recording::function_type::replay_into (replayer *r)
2407 /* Convert m_param_types to a vec of playback type. */
2408 auto_vec <playback::type *> param_types;
2409 int i;
2410 recording::type *type;
2411 param_types.create (m_param_types.length ());
2412 FOR_EACH_VEC_ELT (m_param_types, i, type)
2413 param_types.safe_push (type->playback_type ());
2415 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
2416 &param_types,
2417 m_is_variadic));
2420 /* Special-casing for make_debug_string for get_pointer results for
2421 handling (one level) of pointers to functions. */
2423 recording::string *
2424 recording::function_type::make_debug_string_with_ptr ()
2426 return make_debug_string_with ("(*) ");
2429 /* Implementation of recording::memento::make_debug_string for
2430 results of new_function_type. */
2432 recording::string *
2433 recording::function_type::make_debug_string ()
2435 return make_debug_string_with ("");
2438 /* Build a debug string representation of the form:
2440 RESULT_TYPE INSERT (PARAM_TYPES)
2442 for use when handling 0 and 1 level of indirection to this
2443 function type. */
2445 recording::string *
2446 recording::function_type::make_debug_string_with (const char *insert)
2448 /* First, build a buffer for the arguments. */
2449 /* Calculate length of said buffer. */
2450 size_t sz = 1; /* nil terminator */
2451 for (unsigned i = 0; i< m_param_types.length (); i++)
2453 sz += strlen (m_param_types[i]->get_debug_string ());
2454 sz += 2; /* ", " separator */
2456 if (m_is_variadic)
2457 sz += 5; /* ", ..." separator and ellipsis */
2459 /* Now allocate and populate the buffer. */
2460 char *argbuf = new char[sz];
2461 size_t len = 0;
2463 for (unsigned i = 0; i< m_param_types.length (); i++)
2465 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
2466 len += strlen (m_param_types[i]->get_debug_string ());
2467 if (i + 1 < m_param_types.length ())
2469 strcpy (argbuf + len, ", ");
2470 len += 2;
2473 if (m_is_variadic)
2475 if (m_param_types.length ())
2477 strcpy (argbuf + len, ", ");
2478 len += 2;
2480 strcpy (argbuf + len, "...");
2481 len += 3;
2483 argbuf[len] = '\0';
2485 /* ...and use it to get the string for the call as a whole. */
2486 string *result = string::from_printf (m_ctxt,
2487 "%s %s(%s)",
2488 m_return_type->get_debug_string (),
2489 insert,
2490 argbuf);
2492 delete[] argbuf;
2494 return result;
2497 /* Implementation of recording::memento::write_reproducer for function
2498 types. */
2500 void
2501 recording::function_type::write_reproducer (reproducer &)
2503 /* see notes below. */
2506 /* There's a get_pointer within context::new_function_ptr_type:
2507 the type received by client code isn't the memento for the
2508 function_type, but instead the result of get_pointer on it.
2510 Hence we can't directly write a reproducer that gives function_type.
2511 Instead we special-case things within get_pointer, detecting this
2512 case, calling the following function. */
2514 void
2515 recording::function_type::write_deferred_reproducer (reproducer &r,
2516 memento *ptr_type)
2518 gcc_assert (ptr_type);
2519 r.make_identifier (this, "function_type");
2520 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
2521 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
2522 r.write (" gcc_jit_type *%s[%i] = {\n",
2523 param_types_id,
2524 m_param_types.length ());
2525 int i;
2526 type *param_type;
2527 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2528 r.write (" %s,\n", r.get_identifier_as_type (param_type));
2529 r.write (" };\n");
2530 r.write (" gcc_jit_type *%s =\n"
2531 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2532 " %s, /* gcc_jit_location *loc */\n"
2533 " %s, /* gcc_jit_type *return_type */\n"
2534 " %i, /* int num_params */\n"
2535 " %s, /* gcc_jit_type **param_types */\n"
2536 " %i); /* int is_variadic */\n",
2537 ptr_id,
2538 r.get_identifier (get_context ()),
2539 "NULL", /* location is not stored */
2540 r.get_identifier_as_type (m_return_type),
2541 m_param_types.length (),
2542 param_types_id,
2543 m_is_variadic);
2546 /* The implementation of class gcc::jit::recording::field. */
2548 /* Implementation of pure virtual hook recording::memento::replay_into
2549 for recording::field. */
2551 void
2552 recording::field::replay_into (replayer *r)
2554 set_playback_obj (r->new_field (playback_location (r, m_loc),
2555 m_type->playback_type (),
2556 playback_string (m_name)));
2559 /* Override the default implementation of
2560 recording::memento::write_to_dump. Dump each field
2561 by dumping a line of the form:
2562 TYPE NAME;
2563 so that we can build up a struct/union field-byfield. */
2565 void
2566 recording::field::write_to_dump (dump &d)
2568 d.write (" %s %s;\n",
2569 m_type->get_debug_string (),
2570 m_name->c_str ());
2573 /* Implementation of recording::memento::make_debug_string for
2574 results of new_field. */
2576 recording::string *
2577 recording::field::make_debug_string ()
2579 return m_name;
2582 /* Implementation of recording::memento::write_reproducer for fields. */
2584 void
2585 recording::field::write_reproducer (reproducer &r)
2587 const char *id = r.make_identifier (this, "field");
2588 r.write(" gcc_jit_field *%s =\n"
2589 " gcc_jit_context_new_field (%s,\n"
2590 " %s, /* gcc_jit_location *loc */\n"
2591 " %s, /* gcc_jit_type *type, */\n"
2592 " %s); /* const char *name */\n",
2594 r.get_identifier (get_context ()),
2595 r.get_identifier (m_loc),
2596 r.get_identifier_as_type (m_type),
2597 m_name->get_debug_string ());
2600 /* The implementation of class gcc::jit::recording::compound_type */
2602 /* The constructor for gcc::jit::recording::compound_type. */
2604 recording::compound_type::compound_type (context *ctxt,
2605 location *loc,
2606 string *name)
2607 : type (ctxt),
2608 m_loc (loc),
2609 m_name (name),
2610 m_fields (NULL)
2614 /* Set the fields of a compound type.
2616 Implements the post-error-checking part of
2617 gcc_jit_struct_set_fields, and is also used by
2618 gcc_jit_context_new_union_type. */
2620 void
2621 recording::compound_type::set_fields (location *loc,
2622 int num_fields,
2623 field **field_array)
2625 m_loc = loc;
2626 gcc_assert (NULL == m_fields);
2628 m_fields = new fields (this, num_fields, field_array);
2629 m_ctxt->record (m_fields);
2632 /* Implementation of pure virtual hook recording::type::dereference for
2633 recording::compound_type. */
2635 recording::type *
2636 recording::compound_type::dereference ()
2638 return NULL; /* not a pointer */
2641 /* The implementation of class gcc::jit::recording::struct_. */
2643 /* The constructor for gcc::jit::recording::struct_. */
2645 recording::struct_::struct_ (context *ctxt,
2646 location *loc,
2647 string *name)
2648 : compound_type (ctxt, loc, name)
2652 /* Implementation of pure virtual hook recording::memento::replay_into
2653 for recording::struct_. */
2655 void
2656 recording::struct_::replay_into (replayer *r)
2658 set_playback_obj (
2659 r->new_compound_type (playback_location (r, get_loc ()),
2660 get_name ()->c_str (),
2661 true /* is_struct */));
2664 const char *
2665 recording::struct_::access_as_type (reproducer &r)
2667 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2668 r.get_identifier (this));
2671 /* Implementation of recording::memento::make_debug_string for
2672 structs. */
2674 recording::string *
2675 recording::struct_::make_debug_string ()
2677 return string::from_printf (m_ctxt,
2678 "struct %s", get_name ()->c_str ());
2681 void
2682 recording::struct_::write_reproducer (reproducer &r)
2684 const char *id = r.make_identifier (this, "struct");
2685 r.write (" gcc_jit_struct *%s =\n"
2686 " gcc_jit_context_new_opaque_struct (%s,\n"
2687 " %s, /* gcc_jit_location *loc */\n"
2688 " %s); /* const char *name */\n",
2690 r.get_identifier (get_context ()),
2691 r.get_identifier (get_loc ()),
2692 get_name ()->get_debug_string ());
2695 /* The implementation of class gcc::jit::recording::union_. */
2697 /* The constructor for gcc::jit::recording::union_. */
2699 recording::union_::union_ (context *ctxt,
2700 location *loc,
2701 string *name)
2702 : compound_type (ctxt, loc, name)
2706 /* Implementation of pure virtual hook recording::memento::replay_into
2707 for recording::union_. */
2709 void
2710 recording::union_::replay_into (replayer *r)
2712 set_playback_obj (
2713 r->new_compound_type (playback_location (r, get_loc ()),
2714 get_name ()->c_str (),
2715 false /* is_struct */));
2718 /* Implementation of recording::memento::make_debug_string for
2719 unions. */
2721 recording::string *
2722 recording::union_::make_debug_string ()
2724 return string::from_printf (m_ctxt,
2725 "union %s", get_name ()->c_str ());
2728 /* Implementation of recording::memento::write_reproducer for unions. */
2730 void
2731 recording::union_::write_reproducer (reproducer &r)
2733 const char *id = r.make_identifier (this, "union");
2735 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
2736 r.write (" gcc_jit_field *%s[%i] = {\n",
2737 fields_id,
2738 get_fields ()->length ());
2739 for (int i = 0; i < get_fields ()->length (); i++)
2740 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
2741 r.write (" };\n");
2743 r.write (" gcc_jit_type *%s =\n"
2744 " gcc_jit_context_new_union_type (%s,\n"
2745 " %s, /* gcc_jit_location *loc */\n"
2746 " %s, /* const char *name */\n"
2747 " %i, /* int num_fields */\n"
2748 " %s); /* gcc_jit_field **fields */\n",
2750 r.get_identifier (get_context ()),
2751 r.get_identifier (get_loc ()),
2752 get_name ()->get_debug_string (),
2753 get_fields ()->length (),
2754 fields_id);
2757 /* The implementation of class gcc::jit::recording::fields. */
2759 /* The constructor for gcc::jit::recording::fields. */
2761 recording::fields::fields (compound_type *struct_or_union,
2762 int num_fields,
2763 field **fields)
2764 : memento (struct_or_union->m_ctxt),
2765 m_struct_or_union (struct_or_union),
2766 m_fields ()
2768 for (int i = 0; i < num_fields; i++)
2770 gcc_assert (fields[i]->get_container () == NULL);
2771 fields[i]->set_container (m_struct_or_union);
2772 m_fields.safe_push (fields[i]);
2776 /* Implementation of pure virtual hook recording::memento::replay_into
2777 for recording::fields. */
2779 void
2780 recording::fields::replay_into (replayer *)
2782 auto_vec<playback::field *> playback_fields;
2783 playback_fields.create (m_fields.length ());
2784 for (unsigned i = 0; i < m_fields.length (); i++)
2785 playback_fields.safe_push (m_fields[i]->playback_field ());
2786 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
2789 /* Override the default implementation of
2790 recording::memento::write_to_dump by writing a union/struct
2791 declaration of this form:
2793 struct/union NAME {
2794 TYPE_1 NAME_1;
2795 TYPE_2 NAME_2;
2796 ....
2797 TYPE_N NAME_N;
2800 to the dump. */
2802 void
2803 recording::fields::write_to_dump (dump &d)
2805 int i;
2806 field *f;
2808 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
2809 FOR_EACH_VEC_ELT (m_fields, i, f)
2810 f->write_to_dump (d);
2811 d.write ("};\n");
2814 /* Implementation of recording::memento::write_reproducer for the fields
2815 subclass. */
2817 void
2818 recording::fields::write_reproducer (reproducer &r)
2820 if (m_struct_or_union)
2821 if (NULL == m_struct_or_union->dyn_cast_struct ())
2822 /* We have a union; the fields have already been written by
2823 union::write_reproducer. */
2824 return;
2826 const char *fields_id = r.make_identifier (this, "fields");
2827 r.write (" gcc_jit_field *%s[%i] = {\n",
2828 fields_id,
2829 m_fields.length ());
2830 int i;
2831 field *field;
2832 FOR_EACH_VEC_ELT (m_fields, i, field)
2833 r.write (" %s,\n", r.get_identifier (field));
2834 r.write (" };\n");
2836 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
2837 " %s, /* gcc_jit_location *loc */\n"
2838 " %i, /* int num_fields */\n"
2839 " %s); /* gcc_jit_field **fields */\n",
2840 r.get_identifier (m_struct_or_union),
2841 r.get_identifier ((memento *)NULL),
2842 m_fields.length (),
2843 fields_id);
2846 /* Implementation of recording::memento::make_debug_string for
2847 field tables. */
2849 recording::string *
2850 recording::fields::make_debug_string ()
2852 return string::from_printf (m_ctxt,
2853 "fields");
2856 /* The implementation of class gcc::jit::recording::rvalue. */
2858 /* Create a recording::access_field_rvalue instance and add it to
2859 the rvalue's context's list of mementos.
2861 Implements the post-error-checking part of
2862 gcc_jit_rvalue_access_field. */
2864 recording::rvalue *
2865 recording::rvalue::access_field (recording::location *loc,
2866 field *field)
2868 recording::rvalue *result =
2869 new access_field_rvalue (m_ctxt, loc, this, field);
2870 m_ctxt->record (result);
2871 return result;
2874 /* Create a recording::dereference_field_rvalue instance and add it to
2875 the rvalue's context's list of mementos.
2877 Implements the post-error-checking part of
2878 gcc_jit_rvalue_dereference_field. */
2880 recording::lvalue *
2881 recording::rvalue::dereference_field (recording::location *loc,
2882 field *field)
2884 recording::lvalue *result =
2885 new dereference_field_rvalue (m_ctxt, loc, this, field);
2886 m_ctxt->record (result);
2887 return result;
2890 /* Create a recording::dereference_rvalue instance and add it to the
2891 rvalue's context's list of mementos.
2893 Implements the post-error-checking part of
2894 gcc_jit_rvalue_dereference. */
2896 recording::lvalue *
2897 recording::rvalue::dereference (recording::location *loc)
2899 recording::lvalue *result =
2900 new dereference_rvalue (m_ctxt, loc, this);
2901 m_ctxt->record (result);
2902 return result;
2905 /* An rvalue visitor, for validating that every rvalue within an expression
2906 trees within "STMT" has the correct scope (e.g. no access to locals
2907 of a different function). */
2909 class rvalue_usage_validator : public recording::rvalue_visitor
2911 public:
2912 rvalue_usage_validator (const char *api_funcname,
2913 recording::context *ctxt,
2914 recording::statement *stmt);
2916 void
2917 visit (recording::rvalue *rvalue);
2919 private:
2920 const char *m_api_funcname;
2921 recording::context *m_ctxt;
2922 recording::statement *m_stmt;
2925 /* The trivial constructor for rvalue_usage_validator. */
2927 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
2928 recording::context *ctxt,
2929 recording::statement *stmt)
2930 : m_api_funcname (api_funcname),
2931 m_ctxt (ctxt),
2932 m_stmt (stmt)
2936 /* Verify that the given rvalue is in the correct scope. */
2938 void
2939 rvalue_usage_validator::visit (recording::rvalue *rvalue)
2941 gcc_assert (m_stmt->get_block ());
2942 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
2944 /* Most rvalues don't have a scope (only locals and params). */
2945 if (rvalue->get_scope ())
2947 if (rvalue->get_scope () != stmt_scope)
2948 m_ctxt->add_error
2949 (rvalue->get_loc (),
2950 "%s:"
2951 " rvalue %s (type: %s)"
2952 " has scope limited to function %s"
2953 " but was used within function %s"
2954 " (in statement: %s)",
2955 m_api_funcname,
2956 rvalue->get_debug_string (),
2957 rvalue->get_type ()->get_debug_string (),
2958 rvalue->get_scope ()->get_debug_string (),
2959 stmt_scope->get_debug_string (),
2960 m_stmt->get_debug_string ());
2962 else
2964 if (rvalue->dyn_cast_param ())
2965 m_ctxt->add_error
2966 (rvalue->get_loc (),
2967 "%s:"
2968 " param %s (type: %s)"
2969 " was used within function %s"
2970 " (in statement: %s)"
2971 " but is not associated with any function",
2972 m_api_funcname,
2973 rvalue->get_debug_string (),
2974 rvalue->get_type ()->get_debug_string (),
2975 stmt_scope->get_debug_string (),
2976 m_stmt->get_debug_string ());
2980 /* Verify that it's valid to use this rvalue (and all expressions
2981 in the tree below it) within the given statement.
2983 For example, we must reject attempts to use a local from one
2984 function within a different function here, or we'll get
2985 an ICE deep inside toplev::main. */
2987 void
2988 recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
2990 rvalue_usage_validator v (api_funcname,
2991 s->get_context (),
2994 /* Verify that it's OK to use this rvalue within s. */
2995 v.visit (this);
2997 /* Traverse the expression tree below "this", verifying all rvalues
2998 within it. */
2999 visit_children (&v);
3002 /* Set the scope of this rvalue to be the given function. This can only
3003 be done once on a given rvalue. */
3005 void
3006 recording::rvalue::set_scope (function *scope)
3008 gcc_assert (scope);
3009 gcc_assert (NULL == m_scope);
3010 m_scope = scope;
3014 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3015 themselves.
3016 Instances of rvalue don't need an upcast call. */
3018 const char *
3019 recording::rvalue::access_as_rvalue (reproducer &r)
3021 return r.get_identifier (this);
3025 /* The implementation of class gcc::jit::recording::lvalue. */
3027 /* Create a recording::new_access_field_of_lvalue instance and add it to
3028 the lvalue's context's list of mementos.
3030 Implements the post-error-checking part of
3031 gcc_jit_lvalue_access_field. */
3033 recording::lvalue *
3034 recording::lvalue::access_field (recording::location *loc,
3035 field *field)
3037 recording::lvalue *result =
3038 new access_field_of_lvalue (m_ctxt, loc, this, field);
3039 m_ctxt->record (result);
3040 return result;
3043 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3044 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3045 upcast call. */
3047 const char *
3048 recording::lvalue::access_as_rvalue (reproducer &r)
3050 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3051 r.get_identifier (this));
3054 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3055 Instances of lvalue don't need to be upcast. */
3057 const char *
3058 recording::lvalue::access_as_lvalue (reproducer &r)
3060 return r.get_identifier (this);
3063 /* Create a recording::get_address_of_lvalue instance and add it to
3064 the lvalue's context's list of mementos.
3066 Implements the post-error-checking part of
3067 gcc_jit_lvalue_get_address. */
3069 recording::rvalue *
3070 recording::lvalue::get_address (recording::location *loc)
3072 recording::rvalue *result =
3073 new get_address_of_lvalue (m_ctxt, loc, this);
3074 m_ctxt->record (result);
3075 return result;
3078 /* The implementation of class gcc::jit::recording::param. */
3080 /* Implementation of pure virtual hook recording::memento::replay_into
3081 for recording::param. */
3083 void
3084 recording::param::replay_into (replayer *r)
3086 set_playback_obj (r->new_param (playback_location (r, m_loc),
3087 m_type->playback_type (),
3088 m_name->c_str ()));
3091 /* Implementation of recording::rvalue::access_as_rvalue for params.
3092 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3093 upcast call. */
3095 const char *
3096 recording::param::access_as_rvalue (reproducer &r)
3098 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3099 r.get_identifier (this));
3102 /* Implementation of recording::lvalue::access_as_lvalue for params.
3103 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3104 upcast call. */
3106 const char *
3107 recording::param::access_as_lvalue (reproducer &r)
3109 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3110 r.get_identifier (this));
3113 /* Implementation of recording::memento::write_reproducer for params. */
3115 void
3116 recording::param::write_reproducer (reproducer &r)
3118 const char *id = r.make_identifier (this, "param");
3119 r.write (" gcc_jit_param *%s =\n"
3120 " gcc_jit_context_new_param (%s,\n"
3121 " %s, /* gcc_jit_location *loc */\n"
3122 " %s, /*gcc_jit_type *type */\n"
3123 " %s); /* const char *name */\n",
3125 r.get_identifier (get_context ()),
3126 r.get_identifier (m_loc),
3127 r.get_identifier_as_type (m_type),
3128 m_name->get_debug_string ());
3131 /* The implementation of class gcc::jit::recording::function. */
3133 /* gcc::jit::recording::function's constructor. */
3135 recording::function::function (context *ctxt,
3136 recording::location *loc,
3137 enum gcc_jit_function_kind kind,
3138 type *return_type,
3139 recording::string *name,
3140 int num_params,
3141 recording::param **params,
3142 int is_variadic,
3143 enum built_in_function builtin_id)
3144 : memento (ctxt),
3145 m_loc (loc),
3146 m_kind (kind),
3147 m_return_type (return_type),
3148 m_name (name),
3149 m_params (),
3150 m_is_variadic (is_variadic),
3151 m_builtin_id (builtin_id),
3152 m_locals (),
3153 m_blocks ()
3155 for (int i = 0; i< num_params; i++)
3157 param *param = params[i];
3158 gcc_assert (param);
3160 /* Associate each param with this function.
3162 Verify that the param doesn't already have a function. */
3163 if (param->get_scope ())
3165 /* We've already rejected attempts to reuse a param between
3166 different functions (within gcc_jit_context_new_function), so
3167 if the param *does* already have a function, it must be being
3168 reused within the params array for this function. We must
3169 produce an error for this reuse (blocking the compile), since
3170 otherwise we'd have an ICE later on. */
3171 gcc_assert (this == param->get_scope ());
3172 ctxt->add_error
3173 (loc,
3174 "gcc_jit_context_new_function:"
3175 " parameter %s (type: %s)"
3176 " is used more than once when creating function %s",
3177 param->get_debug_string (),
3178 param->get_type ()->get_debug_string (),
3179 name->c_str ());
3181 else
3183 /* The normal, non-error case: associate this function with the
3184 param. */
3185 param->set_scope (this);
3188 m_params.safe_push (param);
3192 /* Implementation of pure virtual hook recording::memento::replay_into
3193 for recording::function. */
3195 void
3196 recording::function::replay_into (replayer *r)
3198 /* Convert m_params to a vec of playback param. */
3199 auto_vec <playback::param *> params;
3200 int i;
3201 recording::param *param;
3202 params.create (m_params.length ());
3203 FOR_EACH_VEC_ELT (m_params, i, param)
3204 params.safe_push (param->playback_param ());
3206 set_playback_obj (r->new_function (playback_location (r, m_loc),
3207 m_kind,
3208 m_return_type->playback_type (),
3209 m_name->c_str (),
3210 &params,
3211 m_is_variadic,
3212 m_builtin_id));
3215 /* Create a recording::local instance and add it to
3216 the functions's context's list of mementos, and to the function's
3217 list of locals.
3219 Implements the post-error-checking part of
3220 gcc_jit_function_new_local. */
3222 recording::lvalue *
3223 recording::function::new_local (recording::location *loc,
3224 type *type,
3225 const char *name)
3227 local *result = new local (this, loc, type, new_string (name));
3228 m_ctxt->record (result);
3229 m_locals.safe_push (result);
3230 return result;
3233 /* Create a recording::block instance and add it to
3234 the functions's context's list of mementos, and to the function's
3235 list of blocks.
3237 Implements the post-error-checking part of
3238 gcc_jit_function_new_block. */
3240 recording::block*
3241 recording::function::new_block (const char *name)
3243 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
3245 recording::block *result =
3246 new recording::block (this, m_blocks.length (), new_string (name));
3247 m_ctxt->record (result);
3248 m_blocks.safe_push (result);
3249 return result;
3252 /* Override the default implementation of
3253 recording::memento::write_to_dump by dumping a C-like
3254 representation of the function; either like a prototype
3255 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3256 all other kinds of function. */
3258 void
3259 recording::function::write_to_dump (dump &d)
3261 switch (m_kind)
3263 default: gcc_unreachable ();
3264 case GCC_JIT_FUNCTION_EXPORTED:
3265 case GCC_JIT_FUNCTION_IMPORTED:
3266 d.write ("extern ");
3267 break;
3268 case GCC_JIT_FUNCTION_INTERNAL:
3269 d.write ("static ");
3270 break;
3271 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
3272 d.write ("static inline ");
3273 break;
3275 d.write ("%s\n", m_return_type->get_debug_string ());
3277 if (d.update_locations ())
3278 m_loc = d.make_location ();
3280 d.write ("%s (", get_debug_string ());
3282 int i;
3283 recording::param *param;
3284 FOR_EACH_VEC_ELT (m_params, i, param)
3286 if (i > 0)
3287 d.write (", ");
3288 d.write ("%s %s",
3289 param->get_type ()->get_debug_string (),
3290 param->get_debug_string ());
3292 d.write (")");
3293 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
3295 d.write ("; /* (imported) */\n\n");
3297 else
3299 int i;
3300 local *var = NULL;
3301 block *b;
3302 d.write ("\n{\n");
3304 /* Write locals: */
3305 FOR_EACH_VEC_ELT (m_locals, i, var)
3306 var->write_to_dump (d);
3307 if (m_locals.length ())
3308 d.write ("\n");
3310 /* Write each block: */
3311 FOR_EACH_VEC_ELT (m_blocks, i, b)
3313 if (i > 0)
3314 d.write ("\n");
3315 b->write_to_dump (d);
3318 d.write ("}\n\n");
3322 /* Pre-compilation validation of a function, for those things we can't
3323 check until the context is (supposedly) fully-populated. */
3325 void
3326 recording::function::validate ()
3328 /* Complain about empty functions with non-void return type. */
3329 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
3330 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
3331 if (0 == m_blocks.length ())
3332 m_ctxt->add_error (m_loc,
3333 "function %s returns non-void (type: %s)"
3334 " but has no blocks",
3335 get_debug_string (),
3336 m_return_type->get_debug_string ());
3338 /* Check that all blocks are terminated. */
3339 int num_invalid_blocks = 0;
3341 int i;
3342 block *b;
3344 FOR_EACH_VEC_ELT (m_blocks, i, b)
3345 if (!b->validate ())
3346 num_invalid_blocks++;
3349 /* Check that all blocks are reachable. */
3350 if (m_blocks.length () > 0 && 0 == num_invalid_blocks)
3352 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3353 flag, starting at the initial block. */
3354 auto_vec<block *> worklist (m_blocks.length ());
3355 worklist.safe_push (m_blocks[0]);
3356 while (worklist.length () > 0)
3358 block *b = worklist.pop ();
3359 b->m_is_reachable = true;
3361 /* Add successor blocks that aren't yet marked to the worklist. */
3362 /* We checked that each block has a terminating statement above . */
3363 block *next1, *next2;
3364 int n = b->get_successor_blocks (&next1, &next2);
3365 switch (n)
3367 default:
3368 gcc_unreachable ();
3369 case 2:
3370 if (!next2->m_is_reachable)
3371 worklist.safe_push (next2);
3372 /* fallthrough */
3373 case 1:
3374 if (!next1->m_is_reachable)
3375 worklist.safe_push (next1);
3376 break;
3377 case 0:
3378 break;
3382 /* Now complain about any blocks that haven't been marked. */
3384 int i;
3385 block *b;
3386 FOR_EACH_VEC_ELT (m_blocks, i, b)
3387 if (!b->m_is_reachable)
3388 m_ctxt->add_error (b->get_loc (),
3389 "unreachable block: %s",
3390 b->get_debug_string ());
3395 /* Implements the post-error-checking part of
3396 gcc_jit_function_dump_to_dot. */
3398 void
3399 recording::function::dump_to_dot (const char *path)
3401 FILE *fp = fopen (path, "w");
3402 if (!fp)
3403 return;
3405 pretty_printer the_pp;
3406 the_pp.buffer->stream = fp;
3408 pretty_printer *pp = &the_pp;
3410 pp_printf (pp,
3411 "digraph %s {\n", get_debug_string ());
3413 /* Blocks: */
3415 int i;
3416 block *b;
3417 FOR_EACH_VEC_ELT (m_blocks, i, b)
3418 b->dump_to_dot (pp);
3421 /* Edges: */
3423 int i;
3424 block *b;
3425 FOR_EACH_VEC_ELT (m_blocks, i, b)
3426 b->dump_edges_to_dot (pp);
3429 pp_printf (pp, "}\n");
3430 pp_flush (pp);
3431 fclose (fp);
3434 /* Implementation of recording::memento::make_debug_string for
3435 functions. */
3437 recording::string *
3438 recording::function::make_debug_string ()
3440 return m_name;
3443 /* A table of enum gcc_jit_function_kind values expressed in string
3444 form. */
3446 static const char * const names_of_function_kinds[] = {
3447 "GCC_JIT_FUNCTION_EXPORTED",
3448 "GCC_JIT_FUNCTION_INTERNAL",
3449 "GCC_JIT_FUNCTION_IMPORTED",
3450 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3453 /* Implementation of recording::memento::write_reproducer for functions. */
3455 void
3456 recording::function::write_reproducer (reproducer &r)
3458 const char *id = r.make_identifier (this, "func");
3460 if (m_builtin_id)
3462 r.write (" gcc_jit_function *%s =\n"
3463 " gcc_jit_context_get_builtin_function (%s,\n"
3464 " %s);\n",
3466 r.get_identifier (get_context ()),
3467 m_name->get_debug_string ());
3468 return;
3470 const char *params_id = r.make_tmp_identifier ("params_for", this);
3471 r.write (" gcc_jit_param *%s[%i] = {\n",
3472 params_id,
3473 m_params.length ());
3474 int i;
3475 param *param;
3476 FOR_EACH_VEC_ELT (m_params, i, param)
3477 r.write (" %s,\n", r.get_identifier (param));
3478 r.write (" };\n");
3479 r.write (" gcc_jit_function *%s =\n"
3480 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3481 " %s, /* gcc_jit_location *loc */\n"
3482 " %s, /* enum gcc_jit_function_kind kind */\n"
3483 " %s, /* gcc_jit_type *return_type */\n"
3484 " %s, /* const char *name */\n"
3485 " %i, /* int num_params */\n"
3486 " %s, /* gcc_jit_param **params */\n"
3487 " %i); /* int is_variadic */\n",
3489 r.get_identifier (get_context ()),
3490 r.get_identifier (m_loc),
3491 names_of_function_kinds[m_kind],
3492 r.get_identifier_as_type (m_return_type),
3493 m_name->get_debug_string (),
3494 m_params.length (),
3495 params_id,
3496 m_is_variadic);
3500 /* The implementation of class gcc::jit::recording::block. */
3502 /* Create a recording::eval instance and add it to
3503 the block's context's list of mementos, and to the block's
3504 list of statements.
3506 Implements the heart of gcc_jit_block_add_eval. */
3508 recording::statement *
3509 recording::block::add_eval (recording::location *loc,
3510 recording::rvalue *rvalue)
3512 statement *result = new eval (this, loc, rvalue);
3513 m_ctxt->record (result);
3514 m_statements.safe_push (result);
3515 return result;
3518 /* Create a recording::assignment instance and add it to
3519 the block's context's list of mementos, and to the block's
3520 list of statements.
3522 Implements the heart of gcc_jit_block_add_assignment. */
3524 recording::statement *
3525 recording::block::add_assignment (recording::location *loc,
3526 recording::lvalue *lvalue,
3527 recording::rvalue *rvalue)
3529 statement *result = new assignment (this, loc, lvalue, rvalue);
3530 m_ctxt->record (result);
3531 m_statements.safe_push (result);
3532 return result;
3535 /* Create a recording::assignment_op instance and add it to
3536 the block's context's list of mementos, and to the block's
3537 list of statements.
3539 Implements the heart of gcc_jit_block_add_assignment_op. */
3541 recording::statement *
3542 recording::block::add_assignment_op (recording::location *loc,
3543 recording::lvalue *lvalue,
3544 enum gcc_jit_binary_op op,
3545 recording::rvalue *rvalue)
3547 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
3548 m_ctxt->record (result);
3549 m_statements.safe_push (result);
3550 return result;
3553 /* Create a recording::comment instance and add it to
3554 the block's context's list of mementos, and to the block's
3555 list of statements.
3557 Implements the heart of gcc_jit_block_add_comment. */
3559 recording::statement *
3560 recording::block::add_comment (recording::location *loc,
3561 const char *text)
3563 statement *result = new comment (this, loc, new_string (text));
3564 m_ctxt->record (result);
3565 m_statements.safe_push (result);
3566 return result;
3569 /* Create a recording::end_with_conditional instance and add it to
3570 the block's context's list of mementos, and to the block's
3571 list of statements.
3573 Implements the heart of gcc_jit_block_end_with_conditional. */
3575 recording::statement *
3576 recording::block::end_with_conditional (recording::location *loc,
3577 recording::rvalue *boolval,
3578 recording::block *on_true,
3579 recording::block *on_false)
3581 statement *result = new conditional (this, loc, boolval, on_true, on_false);
3582 m_ctxt->record (result);
3583 m_statements.safe_push (result);
3584 m_has_been_terminated = true;
3585 return result;
3588 /* Create a recording::end_with_jump instance and add it to
3589 the block's context's list of mementos, and to the block's
3590 list of statements.
3592 Implements the heart of gcc_jit_block_end_with_jump. */
3594 recording::statement *
3595 recording::block::end_with_jump (recording::location *loc,
3596 recording::block *target)
3598 statement *result = new jump (this, loc, target);
3599 m_ctxt->record (result);
3600 m_statements.safe_push (result);
3601 m_has_been_terminated = true;
3602 return result;
3605 /* Create a recording::end_with_return instance and add it to
3606 the block's context's list of mementos, and to the block's
3607 list of statements.
3609 Implements the post-error-checking parts of
3610 gcc_jit_block_end_with_return and
3611 gcc_jit_block_end_with_void_return. */
3613 recording::statement *
3614 recording::block::end_with_return (recording::location *loc,
3615 recording::rvalue *rvalue)
3617 /* This is used by both gcc_jit_function_add_return and
3618 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3619 the former and NULL for the latter. */
3620 statement *result = new return_ (this, loc, rvalue);
3621 m_ctxt->record (result);
3622 m_statements.safe_push (result);
3623 m_has_been_terminated = true;
3624 return result;
3627 /* Override the default implementation of
3628 recording::memento::write_to_dump for blocks by writing
3629 an unindented block name as a label, followed by the indented
3630 statements:
3632 BLOCK_NAME:
3633 STATEMENT_1;
3634 STATEMENT_2;
3636 STATEMENT_N; */
3638 void
3639 recording::block::write_to_dump (dump &d)
3641 d.write ("%s:\n", get_debug_string ());
3643 int i;
3644 statement *s;
3645 FOR_EACH_VEC_ELT (m_statements, i, s)
3646 s->write_to_dump (d);
3649 /* Validate a block by ensuring that it has been terminated. */
3651 bool
3652 recording::block::validate ()
3654 /* Check for termination. */
3655 if (!has_been_terminated ())
3657 statement *stmt = get_last_statement ();
3658 location *loc = stmt ? stmt->get_loc () : NULL;
3659 m_func->get_context ()->add_error (loc,
3660 "unterminated block in %s: %s",
3661 m_func->get_debug_string (),
3662 get_debug_string ());
3663 return false;
3666 return true;
3669 /* Get the source-location of a block by using that of the first
3670 statement within it, if any. */
3672 recording::location *
3673 recording::block::get_loc () const
3675 recording::statement *stmt = get_first_statement ();
3676 if (stmt)
3677 return stmt->get_loc ();
3678 else
3679 return NULL;
3682 /* Get the first statement within a block, if any. */
3684 recording::statement *
3685 recording::block::get_first_statement () const
3687 if (m_statements.length ())
3688 return m_statements[0];
3689 else
3690 return NULL;
3693 /* Get the last statement within a block, if any. */
3695 recording::statement *
3696 recording::block::get_last_statement () const
3698 if (m_statements.length ())
3699 return m_statements[m_statements.length () - 1];
3700 else
3701 return NULL;
3704 /* Assuming that this block has been terminated, get the number of
3705 successor blocks, which will be 0, 1 or 2, for return, unconditional
3706 jump, and conditional jump respectively.
3707 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
3708 is written to NEXT1, and the second (if any) to NEXT2.
3710 Used when validating functions, and when dumping dot representations
3711 of them. */
3714 recording::block::get_successor_blocks (block **next1, block **next2) const
3716 gcc_assert (m_has_been_terminated);
3717 gcc_assert (next1);
3718 gcc_assert (next2);
3719 statement *last_statement = get_last_statement ();
3720 gcc_assert (last_statement);
3721 return last_statement->get_successor_blocks (next1, next2);
3724 /* Implementation of pure virtual hook recording::memento::replay_into
3725 for recording::block. */
3727 void
3728 recording::block::replay_into (replayer *)
3730 set_playback_obj (m_func->playback_function ()
3731 ->new_block (playback_string (m_name)));
3734 /* Implementation of recording::memento::make_debug_string for
3735 blocks. */
3737 recording::string *
3738 recording::block::make_debug_string ()
3740 if (m_name)
3741 return m_name;
3742 else
3743 return string::from_printf (m_ctxt,
3744 "<UNNAMED BLOCK %p>",
3745 (void *)this);
3748 /* Implementation of recording::memento::write_reproducer for blocks. */
3750 void
3751 recording::block::write_reproducer (reproducer &r)
3753 const char *id = r.make_identifier (this, "block");
3754 r.write (" gcc_jit_block *%s =\n"
3755 " gcc_jit_function_new_block (%s, %s);\n",
3757 r.get_identifier (m_func),
3758 m_name ? m_name->get_debug_string () : "NULL");
3761 /* Dump a block in graphviz form into PP, capturing the block name (if
3762 any) and the statements. */
3764 void
3765 recording::block::dump_to_dot (pretty_printer *pp)
3767 pp_printf (pp,
3768 ("\tblock_%d "
3769 "[shape=record,style=filled,fillcolor=white,label=\"{"),
3770 m_index);
3771 pp_write_text_to_stream (pp);
3772 if (m_name)
3774 pp_string (pp, m_name->c_str ());
3775 pp_string (pp, ":");
3776 pp_newline (pp);
3777 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3780 int i;
3781 statement *s;
3782 FOR_EACH_VEC_ELT (m_statements, i, s)
3784 pp_string (pp, s->get_debug_string ());
3785 pp_newline (pp);
3786 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3789 pp_printf (pp,
3790 "}\"];\n\n");
3791 pp_flush (pp);
3794 /* Dump the out-edges of the block in graphviz form into PP. */
3796 void
3797 recording::block::dump_edges_to_dot (pretty_printer *pp)
3799 block *next[2];
3800 int num_succs = get_successor_blocks (&next[0], &next[1]);
3801 for (int i = 0; i < num_succs; i++)
3802 pp_printf (pp,
3803 "\tblock_%d:s -> block_%d:n;\n",
3804 m_index, next[i]->m_index);
3807 /* The implementation of class gcc::jit::recording::global. */
3809 /* Implementation of pure virtual hook recording::memento::replay_into
3810 for recording::global. */
3812 void
3813 recording::global::replay_into (replayer *r)
3815 set_playback_obj (r->new_global (playback_location (r, m_loc),
3816 m_kind,
3817 m_type->playback_type (),
3818 playback_string (m_name)));
3821 /* Override the default implementation of
3822 recording::memento::write_to_dump for globals.
3823 This will be of the form:
3825 GCC_JIT_GLOBAL_EXPORTED:
3826 "TYPE NAME;"
3827 e.g. "int foo;"
3829 GCC_JIT_GLOBAL_INTERNAL:
3830 "static TYPE NAME;"
3831 e.g. "static int foo;"
3833 GCC_JIT_GLOBAL_IMPORTED:
3834 "extern TYPE NAME;"
3835 e.g. "extern int foo;"
3837 These are written to the top of the dump by
3838 recording::context::dump_to_file. */
3840 void
3841 recording::global::write_to_dump (dump &d)
3843 if (d.update_locations ())
3844 m_loc = d.make_location ();
3846 switch (m_kind)
3848 default:
3849 gcc_unreachable ();
3851 case GCC_JIT_GLOBAL_EXPORTED:
3852 break;
3854 case GCC_JIT_GLOBAL_INTERNAL:
3855 d.write ("static ");
3856 break;
3858 case GCC_JIT_GLOBAL_IMPORTED:
3859 d.write ("extern ");
3860 break;
3862 d.write ("%s %s;\n",
3863 m_type->get_debug_string (),
3864 get_debug_string ());
3867 /* A table of enum gcc_jit_global_kind values expressed in string
3868 form. */
3870 static const char * const global_kind_reproducer_strings[] = {
3871 "GCC_JIT_GLOBAL_EXPORTED",
3872 "GCC_JIT_GLOBAL_INTERNAL",
3873 "GCC_JIT_GLOBAL_IMPORTED"
3876 /* Implementation of recording::memento::write_reproducer for globals. */
3878 void
3879 recording::global::write_reproducer (reproducer &r)
3881 const char *id = r.make_identifier (this, "block");
3882 r.write (" gcc_jit_lvalue *%s =\n"
3883 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
3884 " %s, /* gcc_jit_location *loc */\n"
3885 " %s, /* enum gcc_jit_global_kind kind */\n"
3886 " %s, /* gcc_jit_type *type */\n"
3887 " %s); /* const char *name */\n",
3889 r.get_identifier (get_context ()),
3890 r.get_identifier (m_loc),
3891 global_kind_reproducer_strings[m_kind],
3892 r.get_identifier_as_type (get_type ()),
3893 m_name->get_debug_string ());
3896 /* The implementation of the various const-handling classes:
3897 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
3899 /* Explicit specialization of the various mementos we're interested in. */
3900 template class recording::memento_of_new_rvalue_from_const <int>;
3901 template class recording::memento_of_new_rvalue_from_const <long>;
3902 template class recording::memento_of_new_rvalue_from_const <double>;
3903 template class recording::memento_of_new_rvalue_from_const <void *>;
3905 /* Implementation of the pure virtual hook recording::memento::replay_into
3906 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
3908 template <typename HOST_TYPE>
3909 void
3910 recording::
3911 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
3913 set_playback_obj
3914 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
3915 m_value));
3918 /* The make_debug_string and write_reproducer methods vary between the
3919 various
3920 memento_of_new_rvalue_from_const <HOST_TYPE>
3921 classes, so we explicitly write specializations of them.
3923 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
3924 namespaces are written out explicitly, which is why most of this file
3925 doesn't abbreviate things by entering the "recording" namespace.
3927 However, these specializations are required to be in the same namespace
3928 as the template, hence we now have to enter the gcc::jit::recording
3929 namespace. */
3931 namespace recording
3934 /* The make_debug_string specialization for <int>, which renders it as
3935 (TARGET_TYPE)LITERAL
3936 e.g.
3937 "(int)42". */
3939 template <>
3940 string *
3941 memento_of_new_rvalue_from_const <int>::make_debug_string ()
3943 return string::from_printf (m_ctxt,
3944 "(%s)%i",
3945 m_type->get_debug_string (),
3946 m_value);
3949 /* The write_reproducer specialization for <int>. */
3951 template <>
3952 void
3953 memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
3955 const char *id = r.make_identifier (this, "rvalue");
3956 r.write (" gcc_jit_rvalue *%s =\n"
3957 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
3958 " %s, /* gcc_jit_type *numeric_type */\n"
3959 " %i); /* int value */\n",
3961 r.get_identifier (get_context ()),
3962 r.get_identifier_as_type (m_type),
3963 m_value);
3966 /* The make_debug_string specialization for <long>, rendering it as
3967 (TARGET_TYPE)LITERAL
3968 e.g.
3969 "(long)42". */
3971 template <>
3972 string *
3973 memento_of_new_rvalue_from_const <long>::make_debug_string ()
3975 return string::from_printf (m_ctxt,
3976 "(%s)%li",
3977 m_type->get_debug_string (),
3978 m_value);
3981 /* The write_reproducer specialization for <long>. */
3983 template <>
3984 void
3985 recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
3987 const char *id = r.make_identifier (this, "rvalue");
3989 /* We have to special-case LONG_MIN, since e.g.
3990 -9223372036854775808L
3991 is parsed as
3992 -(9223372036854775808L)
3993 and hence we'd get:
3994 error: integer constant is so large that it is unsigned [-Werror]
3995 Workaround this by writing (LONG_MIN + 1) - 1. */
3996 if (m_value == LONG_MIN)
3998 r.write (" gcc_jit_rvalue *%s =\n"
3999 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4000 " %s, /* gcc_jit_type *numeric_type */\n"
4001 " %ldL - 1); /* long value */\n",
4003 r.get_identifier (get_context ()),
4004 r.get_identifier_as_type (m_type),
4005 m_value + 1);;
4006 return;
4009 r.write (" gcc_jit_rvalue *%s =\n"
4010 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4011 " %s, /* gcc_jit_type *numeric_type */\n"
4012 " %ldL); /* long value */\n",
4014 r.get_identifier (get_context ()),
4015 r.get_identifier_as_type (m_type),
4016 m_value);
4019 /* The make_debug_string specialization for <double>, rendering it as
4020 (TARGET_TYPE)LITERAL
4021 e.g.
4022 "(float)42.0". */
4024 template <>
4025 string *
4026 memento_of_new_rvalue_from_const <double>::make_debug_string ()
4028 return string::from_printf (m_ctxt,
4029 "(%s)%f",
4030 m_type->get_debug_string (),
4031 m_value);
4034 /* The write_reproducer specialization for <double>. */
4036 template <>
4037 void
4038 recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
4040 const char *id = r.make_identifier (this, "rvalue");
4041 r.write (" gcc_jit_rvalue *%s =\n"
4042 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4043 " %s, /* gcc_jit_type *numeric_type */\n"
4044 " %f); /* double value */\n",
4046 r.get_identifier (get_context ()),
4047 r.get_identifier_as_type (m_type),
4048 m_value);
4051 /* The make_debug_string specialization for <void *>, rendering it as
4052 (TARGET_TYPE)HEX
4053 e.g.
4054 "(int *)0xdeadbeef"
4056 Zero is rendered as NULL e.g.
4057 "(int *)NULL". */
4059 template <>
4060 string *
4061 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
4063 if (m_value != NULL)
4064 return string::from_printf (m_ctxt,
4065 "(%s)%p",
4066 m_type->get_debug_string (), m_value);
4067 else
4068 return string::from_printf (m_ctxt,
4069 "(%s)NULL",
4070 m_type->get_debug_string ());
4073 /* Implementation of recording::memento::write_reproducer for <void *>
4074 values. */
4076 template <>
4077 void
4078 memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
4080 const char *id = r.make_identifier (this, "rvalue");
4081 if (m_value)
4082 r.write (" gcc_jit_rvalue *%s =\n"
4083 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4084 " %s, /* gcc_jit_type *pointer_type */\n"
4085 " (void *)%p); /* void *value */\n",
4087 r.get_identifier (get_context ()),
4088 r.get_identifier_as_type (m_type),
4089 m_value);
4090 else
4091 r.write (" gcc_jit_rvalue *%s =\n"
4092 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4093 " %s); /* gcc_jit_type *pointer_type */\n",
4095 r.get_identifier (get_context ()),
4096 r.get_identifier_as_type (m_type));
4099 /* We're done specializing make_debug_string and write_reproducer, so we
4100 can exit the gcc::jit::recording namespace. */
4102 } // namespace recording
4104 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4106 /* Implementation of pure virtual hook recording::memento::replay_into
4107 for recording::memento_of_new_string_literal. */
4109 void
4110 recording::memento_of_new_string_literal::replay_into (replayer *r)
4112 set_playback_obj (r->new_string_literal (m_value->c_str ()));
4115 /* Implementation of recording::memento::make_debug_string for
4116 string literals. */
4118 recording::string *
4119 recording::memento_of_new_string_literal::make_debug_string ()
4121 return string::from_printf (m_ctxt,
4122 "%s",
4123 m_value->get_debug_string ());
4126 /* Implementation of recording::memento::write_reproducer for string literal
4127 values. */
4129 void
4130 recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
4132 const char *id = r.make_identifier (this, "rvalue");
4133 r.write (" gcc_jit_rvalue *%s =\n"
4134 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4135 " %s); /* const char *value */\n",
4137 r.get_identifier (get_context ()),
4138 m_value->get_debug_string ());
4141 /* The implementation of class gcc::jit::recording::unary_op. */
4143 /* Implementation of pure virtual hook recording::memento::replay_into
4144 for recording::unary_op. */
4146 void
4147 recording::unary_op::replay_into (replayer *r)
4149 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
4150 m_op,
4151 get_type ()->playback_type (),
4152 m_a->playback_rvalue ()));
4155 /* Implementation of pure virtual hook recording::rvalue::visit_children
4156 for recording::unary_op. */
4157 void
4158 recording::unary_op::visit_children (rvalue_visitor *v)
4160 v->visit (m_a);
4163 /* Implementation of recording::memento::make_debug_string for
4164 unary ops. */
4166 static const char * const unary_op_strings[] = {
4167 "-", /* GCC_JIT_UNARY_OP_MINUS */
4168 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4169 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4170 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4173 recording::string *
4174 recording::unary_op::make_debug_string ()
4176 return string::from_printf (m_ctxt,
4177 "%s(%s)",
4178 unary_op_strings[m_op],
4179 m_a->get_debug_string ());
4182 static const char * const unary_op_reproducer_strings[] = {
4183 "GCC_JIT_UNARY_OP_MINUS",
4184 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4185 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4186 "GCC_JIT_UNARY_OP_ABS"
4189 /* Implementation of recording::memento::write_reproducer for unary ops. */
4191 void
4192 recording::unary_op::write_reproducer (reproducer &r)
4194 const char *id = r.make_identifier (this, "rvalue");
4195 r.write (" gcc_jit_rvalue *%s =\n"
4196 " gcc_jit_context_new_unary_op (%s,\n"
4197 " %s, /* gcc_jit_location *loc */\n"
4198 " %s, /* enum gcc_jit_unary_op op */\n"
4199 " %s, /* gcc_jit_type *result_type */\n"
4200 " %s); /* gcc_jit_rvalue *a */\n",
4202 r.get_identifier (get_context ()),
4203 r.get_identifier (m_loc),
4204 unary_op_reproducer_strings[m_op],
4205 r.get_identifier_as_type (get_type ()),
4206 r.get_identifier_as_rvalue (m_a));
4209 /* The implementation of class gcc::jit::recording::binary_op. */
4211 /* Implementation of pure virtual hook recording::memento::replay_into
4212 for recording::binary_op. */
4214 void
4215 recording::binary_op::replay_into (replayer *r)
4217 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
4218 m_op,
4219 get_type ()->playback_type (),
4220 m_a->playback_rvalue (),
4221 m_b->playback_rvalue ()));
4224 /* Implementation of pure virtual hook recording::rvalue::visit_children
4225 for recording::binary_op. */
4226 void
4227 recording::binary_op::visit_children (rvalue_visitor *v)
4229 v->visit (m_a);
4230 v->visit (m_b);
4233 /* Implementation of recording::memento::make_debug_string for
4234 binary ops. */
4236 static const char * const binary_op_strings[] = {
4237 "+", /* GCC_JIT_BINARY_OP_PLUS */
4238 "-", /* GCC_JIT_BINARY_OP_MINUS */
4239 "*", /* GCC_JIT_BINARY_OP_MULT */
4240 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4241 "%", /* GCC_JIT_BINARY_OP_MODULO */
4242 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4243 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4244 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4245 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4246 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4247 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4248 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4251 recording::string *
4252 recording::binary_op::make_debug_string ()
4254 return string::from_printf (m_ctxt,
4255 "%s %s %s",
4256 m_a->get_debug_string (),
4257 binary_op_strings[m_op],
4258 m_b->get_debug_string ());
4261 static const char * const binary_op_reproducer_strings[] = {
4262 "GCC_JIT_BINARY_OP_PLUS",
4263 "GCC_JIT_BINARY_OP_MINUS",
4264 "GCC_JIT_BINARY_OP_MULT",
4265 "GCC_JIT_BINARY_OP_DIVIDE",
4266 "GCC_JIT_BINARY_OP_MODULO",
4267 "GCC_JIT_BINARY_OP_BITWISE_AND",
4268 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4269 "GCC_JIT_BINARY_OP_BITWISE_OR",
4270 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4271 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4272 "GCC_JIT_BINARY_OP_LSHIFT",
4273 "GCC_JIT_BINARY_OP_RSHIFT"
4276 /* Implementation of recording::memento::write_reproducer for binary ops. */
4278 void
4279 recording::binary_op::write_reproducer (reproducer &r)
4281 const char *id = r.make_identifier (this, "rvalue");
4282 r.write (" gcc_jit_rvalue *%s =\n"
4283 " gcc_jit_context_new_binary_op (%s,\n"
4284 " %s, /* gcc_jit_location *loc */\n"
4285 " %s, /* enum gcc_jit_binary_op op */\n"
4286 " %s, /* gcc_jit_type *result_type */\n"
4287 " %s, /* gcc_jit_rvalue *a */\n"
4288 " %s); /* gcc_jit_rvalue *b */\n",
4290 r.get_identifier (get_context ()),
4291 r.get_identifier (m_loc),
4292 binary_op_reproducer_strings[m_op],
4293 r.get_identifier_as_type (get_type ()),
4294 r.get_identifier_as_rvalue (m_a),
4295 r.get_identifier_as_rvalue (m_b));
4298 /* The implementation of class gcc::jit::recording::comparison. */
4300 /* Implementation of recording::memento::make_debug_string for
4301 comparisons. */
4303 static const char * const comparison_strings[] =
4305 "==", /* GCC_JIT_COMPARISON_EQ */
4306 "!=", /* GCC_JIT_COMPARISON_NE */
4307 "<", /* GCC_JIT_COMPARISON_LT */
4308 "<=", /* GCC_JIT_COMPARISON_LE */
4309 ">", /* GCC_JIT_COMPARISON_GT */
4310 ">=", /* GCC_JIT_COMPARISON_GE */
4313 recording::string *
4314 recording::comparison::make_debug_string ()
4316 return string::from_printf (m_ctxt,
4317 "%s %s %s",
4318 m_a->get_debug_string (),
4319 comparison_strings[m_op],
4320 m_b->get_debug_string ());
4323 /* A table of enum gcc_jit_comparison values expressed in string
4324 form. */
4326 static const char * const comparison_reproducer_strings[] =
4328 "GCC_JIT_COMPARISON_EQ",
4329 "GCC_JIT_COMPARISON_NE",
4330 "GCC_JIT_COMPARISON_LT",
4331 "GCC_JIT_COMPARISON_LE",
4332 "GCC_JIT_COMPARISON_GT",
4333 "GCC_JIT_COMPARISON_GE"
4336 /* Implementation of recording::memento::write_reproducer for comparisons. */
4338 void
4339 recording::comparison::write_reproducer (reproducer &r)
4341 const char *id = r.make_identifier (this, "rvalue");
4342 r.write (" gcc_jit_rvalue *%s =\n"
4343 " gcc_jit_context_new_comparison (%s,\n"
4344 " %s, /* gcc_jit_location *loc */\n"
4345 " %s, /* enum gcc_jit_comparison op */\n"
4346 " %s, /* gcc_jit_rvalue *a */\n"
4347 " %s); /* gcc_jit_rvalue *b */\n",
4349 r.get_identifier (get_context ()),
4350 r.get_identifier (m_loc),
4351 comparison_reproducer_strings[m_op],
4352 r.get_identifier_as_rvalue (m_a),
4353 r.get_identifier_as_rvalue (m_b));
4356 /* Implementation of pure virtual hook recording::memento::replay_into
4357 for recording::comparison. */
4359 void
4360 recording::comparison::replay_into (replayer *r)
4362 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
4363 m_op,
4364 m_a->playback_rvalue (),
4365 m_b->playback_rvalue ()));
4368 /* Implementation of pure virtual hook recording::rvalue::visit_children
4369 for recording::comparison. */
4371 void
4372 recording::comparison::visit_children (rvalue_visitor *v)
4374 v->visit (m_a);
4375 v->visit (m_b);
4378 /* Implementation of pure virtual hook recording::memento::replay_into
4379 for recording::cast. */
4381 void
4382 recording::cast::replay_into (replayer *r)
4384 set_playback_obj (r->new_cast (playback_location (r, m_loc),
4385 m_rvalue->playback_rvalue (),
4386 get_type ()->playback_type ()));
4389 /* Implementation of pure virtual hook recording::rvalue::visit_children
4390 for recording::cast. */
4391 void
4392 recording::cast::visit_children (rvalue_visitor *v)
4394 v->visit (m_rvalue);
4397 /* Implementation of recording::memento::make_debug_string for
4398 casts. */
4400 recording::string *
4401 recording::cast::make_debug_string ()
4403 return string::from_printf (m_ctxt,
4404 "(%s)%s",
4405 get_type ()->get_debug_string (),
4406 m_rvalue->get_debug_string ());
4409 /* Implementation of recording::memento::write_reproducer for casts. */
4411 void
4412 recording::cast::write_reproducer (reproducer &r)
4414 const char *id = r.make_identifier (this, "rvalue");
4415 r.write (" gcc_jit_rvalue *%s =\n"
4416 " gcc_jit_context_new_cast (%s,\n"
4417 " %s, /* gcc_jit_location *loc */\n"
4418 " %s, /* gcc_jit_rvalue *rvalue */\n"
4419 " %s); /* gcc_jit_type *type */\n",
4421 r.get_identifier (get_context ()),
4422 r.get_identifier (m_loc),
4423 r.get_identifier_as_rvalue (m_rvalue),
4424 r.get_identifier_as_type (get_type ()));
4427 /* The implementation of class gcc::jit::recording::call. */
4429 /* The constructor for gcc::jit::recording::call. */
4431 recording::call::call (recording::context *ctxt,
4432 recording::location *loc,
4433 recording::function *func,
4434 int numargs,
4435 rvalue **args)
4436 : rvalue (ctxt, loc, func->get_return_type ()),
4437 m_func (func),
4438 m_args ()
4440 for (int i = 0; i< numargs; i++)
4441 m_args.safe_push (args[i]);
4444 /* Implementation of pure virtual hook recording::memento::replay_into
4445 for recording::call. */
4447 void
4448 recording::call::replay_into (replayer *r)
4450 auto_vec<playback::rvalue *> playback_args;
4451 playback_args.create (m_args.length ());
4452 for (unsigned i = 0; i< m_args.length (); i++)
4453 playback_args.safe_push (m_args[i]->playback_rvalue ());
4455 set_playback_obj (r->new_call (playback_location (r, m_loc),
4456 m_func->playback_function (),
4457 &playback_args));
4460 /* Implementation of pure virtual hook recording::rvalue::visit_children
4461 for recording::call. */
4463 void
4464 recording::call::visit_children (rvalue_visitor *v)
4466 for (unsigned i = 0; i< m_args.length (); i++)
4467 v->visit (m_args[i]);
4470 /* Implementation of recording::memento::make_debug_string for
4471 function calls. */
4473 recording::string *
4474 recording::call::make_debug_string ()
4476 /* First, build a buffer for the arguments. */
4477 /* Calculate length of said buffer. */
4478 size_t sz = 1; /* nil terminator */
4479 for (unsigned i = 0; i< m_args.length (); i++)
4481 sz += strlen (m_args[i]->get_debug_string ());
4482 sz += 2; /* ", " separator */
4485 /* Now allocate and populate the buffer. */
4486 char *argbuf = new char[sz];
4487 size_t len = 0;
4489 for (unsigned i = 0; i< m_args.length (); i++)
4491 strcpy (argbuf + len, m_args[i]->get_debug_string ());
4492 len += strlen (m_args[i]->get_debug_string ());
4493 if (i + 1 < m_args.length ())
4495 strcpy (argbuf + len, ", ");
4496 len += 2;
4499 argbuf[len] = '\0';
4501 /* ...and use it to get the string for the call as a whole. */
4502 string *result = string::from_printf (m_ctxt,
4503 "%s (%s)",
4504 m_func->get_debug_string (),
4505 argbuf);
4507 delete[] argbuf;
4509 return result;
4512 void
4513 recording::call::write_reproducer (reproducer &r)
4515 const char *id = r.make_identifier (this, "call");
4516 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4517 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4518 args_id,
4519 m_args.length ());
4520 for (unsigned i = 0; i< m_args.length (); i++)
4521 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4522 r.write (" };\n");
4523 r.write (" gcc_jit_rvalue *%s =\n"
4524 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4525 " %s, /* gcc_jit_location *loc */\n"
4526 " %s, /* gcc_jit_function *func */\n"
4527 " %i, /* int numargs */ \n"
4528 " %s); /* gcc_jit_rvalue **args*/\n",
4530 r.get_identifier (get_context ()),
4531 r.get_identifier (m_loc),
4532 r.get_identifier (m_func),
4533 m_args.length (),
4534 args_id);
4537 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4539 /* The constructor for recording::call_through_ptr. */
4541 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
4542 recording::location *loc,
4543 recording::rvalue *fn_ptr,
4544 int numargs,
4545 rvalue **args)
4546 : rvalue (ctxt, loc,
4547 fn_ptr->get_type ()->dereference ()
4548 ->as_a_function_type ()->get_return_type ()),
4549 m_fn_ptr (fn_ptr),
4550 m_args ()
4552 for (int i = 0; i< numargs; i++)
4553 m_args.safe_push (args[i]);
4556 /* Implementation of pure virtual hook recording::memento::replay_into
4557 for recording::call_through_ptr. */
4559 void
4560 recording::call_through_ptr::replay_into (replayer *r)
4562 auto_vec<playback::rvalue *> playback_args;
4563 playback_args.create (m_args.length ());
4564 for (unsigned i = 0; i< m_args.length (); i++)
4565 playback_args.safe_push (m_args[i]->playback_rvalue ());
4567 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
4568 m_fn_ptr->playback_rvalue (),
4569 &playback_args));
4572 /* Implementation of pure virtual hook recording::rvalue::visit_children
4573 for recording::call_through_ptr. */
4575 void
4576 recording::call_through_ptr::visit_children (rvalue_visitor *v)
4578 v->visit (m_fn_ptr);
4579 for (unsigned i = 0; i< m_args.length (); i++)
4580 v->visit (m_args[i]);
4583 /* Implementation of recording::memento::make_debug_string for
4584 calls through function ptrs. */
4586 recording::string *
4587 recording::call_through_ptr::make_debug_string ()
4589 /* First, build a buffer for the arguments. */
4590 /* Calculate length of said buffer. */
4591 size_t sz = 1; /* nil terminator */
4592 for (unsigned i = 0; i< m_args.length (); i++)
4594 sz += strlen (m_args[i]->get_debug_string ());
4595 sz += 2; /* ", " separator */
4598 /* Now allocate and populate the buffer. */
4599 char *argbuf = new char[sz];
4600 size_t len = 0;
4602 for (unsigned i = 0; i< m_args.length (); i++)
4604 strcpy (argbuf + len, m_args[i]->get_debug_string ());
4605 len += strlen (m_args[i]->get_debug_string ());
4606 if (i + 1 < m_args.length ())
4608 strcpy (argbuf + len, ", ");
4609 len += 2;
4612 argbuf[len] = '\0';
4614 /* ...and use it to get the string for the call as a whole. */
4615 string *result = string::from_printf (m_ctxt,
4616 "%s (%s)",
4617 m_fn_ptr->get_debug_string (),
4618 argbuf);
4620 delete[] argbuf;
4622 return result;
4625 /* Implementation of recording::memento::write_reproducer for
4626 call_through_ptr. */
4628 void
4629 recording::call_through_ptr::write_reproducer (reproducer &r)
4631 const char *id = r.make_identifier (this, "call");
4632 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4633 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4634 args_id,
4635 m_args.length ());
4636 for (unsigned i = 0; i< m_args.length (); i++)
4637 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4638 r.write (" };\n");
4639 r.write (" gcc_jit_rvalue *%s =\n"
4640 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
4641 " %s, /* gcc_jit_location *loc */\n"
4642 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
4643 " %i, /* int numargs */ \n"
4644 " %s); /* gcc_jit_rvalue **args*/\n",
4646 r.get_identifier (get_context ()),
4647 r.get_identifier (m_loc),
4648 r.get_identifier_as_rvalue (m_fn_ptr),
4649 m_args.length (),
4650 args_id);
4653 /* The implementation of class gcc::jit::recording::array_access. */
4655 /* Implementation of pure virtual hook recording::memento::replay_into
4656 for recording::array_access. */
4658 void
4659 recording::array_access::replay_into (replayer *r)
4661 set_playback_obj (
4662 r->new_array_access (playback_location (r, m_loc),
4663 m_ptr->playback_rvalue (),
4664 m_index->playback_rvalue ()));
4667 /* Implementation of pure virtual hook recording::rvalue::visit_children
4668 for recording::array_access. */
4670 void
4671 recording::array_access::visit_children (rvalue_visitor *v)
4673 v->visit (m_ptr);
4674 v->visit (m_index);
4677 /* Implementation of recording::memento::make_debug_string for
4678 array accesses. */
4680 recording::string *
4681 recording::array_access::make_debug_string ()
4683 return string::from_printf (m_ctxt,
4684 "%s[%s]",
4685 m_ptr->get_debug_string (),
4686 m_index->get_debug_string ());
4689 /* Implementation of recording::memento::write_reproducer for
4690 array_access. */
4692 void
4693 recording::array_access::write_reproducer (reproducer &r)
4695 const char *id = r.make_identifier (this, "lvalue");
4696 r.write (" gcc_jit_lvalue *%s = \n"
4697 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
4698 " %s, /*gcc_jit_location *loc */\n"
4699 " %s, /* gcc_jit_rvalue *ptr */\n"
4700 " %s); /* gcc_jit_rvalue *index */\n",
4702 r.get_identifier (get_context ()),
4703 r.get_identifier (m_loc),
4704 r.get_identifier_as_rvalue (m_ptr),
4705 r.get_identifier_as_rvalue (m_index));
4708 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
4710 /* Implementation of pure virtual hook recording::memento::replay_into
4711 for recording::access_field_of_lvalue. */
4713 void
4714 recording::access_field_of_lvalue::replay_into (replayer *r)
4716 set_playback_obj (
4717 m_lvalue->playback_lvalue ()
4718 ->access_field (playback_location (r, m_loc),
4719 m_field->playback_field ()));
4723 /* Implementation of pure virtual hook recording::rvalue::visit_children
4724 for recording::access_field_of_lvalue. */
4726 void
4727 recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
4729 v->visit (m_lvalue);
4732 /* Implementation of recording::memento::make_debug_string for
4733 accessing a field of an lvalue. */
4735 recording::string *
4736 recording::access_field_of_lvalue::make_debug_string ()
4738 return string::from_printf (m_ctxt,
4739 "%s.%s",
4740 m_lvalue->get_debug_string (),
4741 m_field->get_debug_string ());
4744 /* Implementation of recording::memento::write_reproducer for
4745 access_field_of_lvalue. */
4747 void
4748 recording::access_field_of_lvalue::write_reproducer (reproducer &r)
4750 const char *id = r.make_identifier (this, "lvalue");
4751 r.write (" gcc_jit_lvalue *%s = \n"
4752 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
4753 " %s, /*gcc_jit_location *loc */\n"
4754 " %s);\n",
4756 r.get_identifier_as_lvalue (m_lvalue),
4757 r.get_identifier (m_loc),
4758 r.get_identifier (m_field));
4761 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
4763 /* Implementation of pure virtual hook recording::memento::replay_into
4764 for recording::access_field_rvalue. */
4766 void
4767 recording::access_field_rvalue::replay_into (replayer *r)
4769 set_playback_obj (
4770 m_rvalue->playback_rvalue ()
4771 ->access_field (playback_location (r, m_loc),
4772 m_field->playback_field ()));
4775 /* Implementation of pure virtual hook recording::rvalue::visit_children
4776 for recording::access_field_rvalue. */
4778 void
4779 recording::access_field_rvalue::visit_children (rvalue_visitor *v)
4781 v->visit (m_rvalue);
4784 /* Implementation of recording::memento::make_debug_string for
4785 accessing a field of an rvalue. */
4787 recording::string *
4788 recording::access_field_rvalue::make_debug_string ()
4790 return string::from_printf (m_ctxt,
4791 "%s.%s",
4792 m_rvalue->get_debug_string (),
4793 m_field->get_debug_string ());
4796 /* Implementation of recording::memento::write_reproducer for
4797 access_field_rvalue. */
4799 void
4800 recording::access_field_rvalue::write_reproducer (reproducer &r)
4802 const char *id = r.make_identifier (this, "rvalue");
4803 r.write (" gcc_jit_rvalue *%s = \n"
4804 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
4805 " %s, /*gcc_jit_location *loc */\n"
4806 " %s);\n",
4808 r.get_identifier_as_rvalue (m_rvalue),
4809 r.get_identifier (m_loc),
4810 r.get_identifier (m_field));
4813 /* The implementation of class
4814 gcc::jit::recording::dereference_field_rvalue. */
4816 /* Implementation of pure virtual hook recording::memento::replay_into
4817 for recording::dereference_field_rvalue. */
4819 void
4820 recording::dereference_field_rvalue::replay_into (replayer *r)
4822 set_playback_obj (
4823 m_rvalue->playback_rvalue ()->
4824 dereference_field (playback_location (r, m_loc),
4825 m_field->playback_field ()));
4828 /* Implementation of pure virtual hook recording::rvalue::visit_children
4829 for recording::dereference_field_rvalue. */
4831 void
4832 recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
4834 v->visit (m_rvalue);
4837 /* Implementation of recording::memento::make_debug_string for
4838 dereferencing a field of an rvalue. */
4840 recording::string *
4841 recording::dereference_field_rvalue::make_debug_string ()
4843 return string::from_printf (m_ctxt,
4844 "%s->%s",
4845 m_rvalue->get_debug_string (),
4846 m_field->get_debug_string ());
4849 /* Implementation of recording::memento::write_reproducer for
4850 dereference_field_rvalue. */
4852 void
4853 recording::dereference_field_rvalue::write_reproducer (reproducer &r)
4855 const char *id = r.make_identifier (this, "lvalue");
4856 r.write (" gcc_jit_lvalue *%s=\n"
4857 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
4858 " %s, /* gcc_jit_location *loc */\n"
4859 " %s); /* gcc_jit_field *field */\n",
4861 r.get_identifier_as_rvalue (m_rvalue),
4862 r.get_identifier (m_loc),
4863 r.get_identifier (m_field));
4866 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
4868 /* Implementation of pure virtual hook recording::memento::replay_into
4869 for recording::dereference_rvalue. */
4871 void
4872 recording::dereference_rvalue::replay_into (replayer *r)
4874 set_playback_obj (
4875 m_rvalue->playback_rvalue ()->
4876 dereference (playback_location (r, m_loc)));
4879 /* Implementation of pure virtual hook recording::rvalue::visit_children
4880 for recording::dereference_rvalue. */
4882 void
4883 recording::dereference_rvalue::visit_children (rvalue_visitor *v)
4885 v->visit (m_rvalue);
4888 /* Implementation of recording::memento::make_debug_string for
4889 dereferencing an rvalue. */
4891 recording::string *
4892 recording::dereference_rvalue::make_debug_string ()
4894 return string::from_printf (m_ctxt,
4895 "*%s",
4896 m_rvalue->get_debug_string ());
4899 /* Implementation of recording::memento::write_reproducer for
4900 dereference_rvalue. */
4902 void
4903 recording::dereference_rvalue::write_reproducer (reproducer &r)
4905 const char *id = r.make_identifier (this, "dereference");
4906 r.write (" gcc_jit_lvalue *%s =\n"
4907 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
4908 " %s); /* gcc_jit_location *loc */\n",
4910 r.get_identifier_as_rvalue (m_rvalue),
4911 r.get_identifier (m_loc));
4914 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
4916 /* Implementation of pure virtual hook recording::memento::replay_into
4917 for recording::get_address_of_lvalue. */
4919 void
4920 recording::get_address_of_lvalue::replay_into (replayer *r)
4922 set_playback_obj (
4923 m_lvalue->playback_lvalue ()->
4924 get_address (playback_location (r, m_loc)));
4927 /* Implementation of pure virtual hook recording::rvalue::visit_children
4928 for recording::get_address_of_lvalue. */
4930 void
4931 recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
4933 v->visit (m_lvalue);
4936 /* Implementation of recording::memento::make_debug_string for
4937 getting the address of an lvalue. */
4939 recording::string *
4940 recording::get_address_of_lvalue::make_debug_string ()
4942 return string::from_printf (m_ctxt,
4943 "&%s",
4944 m_lvalue->get_debug_string ());
4947 /* Implementation of recording::memento::write_reproducer for
4948 get_address_of_lvalue. */
4950 void
4951 recording::get_address_of_lvalue::write_reproducer (reproducer &r)
4953 const char *id = r.make_identifier (this, "address_of");
4954 r.write (" gcc_jit_rvalue *%s =\n"
4955 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
4956 " %s); /* gcc_jit_location *loc */\n",
4958 r.get_identifier_as_lvalue (m_lvalue),
4959 r.get_identifier (m_loc));
4962 /* The implementation of class gcc::jit::recording::local. */
4964 /* Implementation of pure virtual hook recording::memento::replay_into
4965 for recording::local. */
4967 void
4968 recording::local::replay_into (replayer *r)
4970 set_playback_obj (
4971 m_func->playback_function ()
4972 ->new_local (playback_location (r, m_loc),
4973 m_type->playback_type (),
4974 playback_string (m_name)));
4977 /* Override the default implementation of
4978 recording::memento::write_to_dump for locals by writing
4979 TYPE NAME;
4980 for use at the top of the function body as if it were a
4981 declaration. */
4983 void
4984 recording::local::write_to_dump (dump &d)
4986 if (d.update_locations ())
4987 m_loc = d.make_location ();
4988 d.write(" %s %s;\n",
4989 m_type->get_debug_string (),
4990 get_debug_string ());
4993 void
4994 recording::local::write_reproducer (reproducer &r)
4996 const char *id = r.make_identifier (this, "local");
4997 r.write (" gcc_jit_lvalue *%s =\n"
4998 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
4999 " %s, /* gcc_jit_location *loc */\n"
5000 " %s, /* gcc_jit_type *type */\n"
5001 " %s); /* const char *name */\n",
5003 r.get_identifier (m_func),
5004 r.get_identifier (m_loc),
5005 r.get_identifier_as_type (m_type),
5006 m_name->get_debug_string ());
5009 /* The implementation of class gcc::jit::recording::statement. */
5011 /* We poison the default implementation of
5012 gcc::jit::recording::statement::get_successor_blocks
5013 since this vfunc must only ever be called on terminator
5014 statements. */
5017 recording::statement::get_successor_blocks (block **/*out_next1*/,
5018 block **/*out_next2*/) const
5020 /* The base class implementation is for non-terminating statements,
5021 and thus should never be called. */
5022 gcc_unreachable ();
5023 return 0;
5026 /* Extend the default implementation of
5027 recording::memento::write_to_dump for statements by (if requested)
5028 updating the location of the statement to the current location in
5029 the dumpfile. */
5031 void
5032 recording::statement::write_to_dump (dump &d)
5034 memento::write_to_dump (d);
5035 if (d.update_locations ())
5036 m_loc = d.make_location ();
5039 /* The implementation of class gcc::jit::recording::eval. */
5041 /* Implementation of pure virtual hook recording::memento::replay_into
5042 for recording::eval. */
5044 void
5045 recording::eval::replay_into (replayer *r)
5047 playback_block (get_block ())
5048 ->add_eval (playback_location (r),
5049 m_rvalue->playback_rvalue ());
5052 /* Implementation of recording::memento::make_debug_string for
5053 an eval statement. */
5055 recording::string *
5056 recording::eval::make_debug_string ()
5058 return string::from_printf (m_ctxt,
5059 "(void)%s;",
5060 m_rvalue->get_debug_string ());
5063 /* Implementation of recording::memento::write_reproducer for
5064 eval statements. */
5066 void
5067 recording::eval::write_reproducer (reproducer &r)
5069 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5070 " %s, /* gcc_jit_location *loc */\n"
5071 " %s); /* gcc_jit_rvalue *rvalue */\n",
5072 r.get_identifier (get_block ()),
5073 r.get_identifier (get_loc ()),
5074 r.get_identifier_as_rvalue (m_rvalue));
5077 /* The implementation of class gcc::jit::recording::assignment. */
5079 /* Implementation of pure virtual hook recording::memento::replay_into
5080 for recording::assignment. */
5082 void
5083 recording::assignment::replay_into (replayer *r)
5085 playback_block (get_block ())
5086 ->add_assignment (playback_location (r),
5087 m_lvalue->playback_lvalue (),
5088 m_rvalue->playback_rvalue ());
5091 /* Implementation of recording::memento::make_debug_string for
5092 an assignment statement. */
5094 recording::string *
5095 recording::assignment::make_debug_string ()
5097 return string::from_printf (m_ctxt,
5098 "%s = %s;",
5099 m_lvalue->get_debug_string (),
5100 m_rvalue->get_debug_string ());
5103 /* Implementation of recording::memento::write_reproducer for
5104 assignment statements. */
5106 void
5107 recording::assignment::write_reproducer (reproducer &r)
5109 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5110 " %s, /* gcc_jit_location *loc */\n"
5111 " %s, /* gcc_jit_lvalue *lvalue */\n"
5112 " %s); /* gcc_jit_rvalue *rvalue */\n",
5113 r.get_identifier (get_block ()),
5114 r.get_identifier (get_loc ()),
5115 r.get_identifier_as_lvalue (m_lvalue),
5116 r.get_identifier_as_rvalue (m_rvalue));
5119 /* The implementation of class gcc::jit::recording::assignment_op. */
5121 /* Implementation of pure virtual hook recording::memento::replay_into
5122 for recording::assignment_op. */
5124 void
5125 recording::assignment_op::replay_into (replayer *r)
5127 playback::type *result_type =
5128 m_lvalue->playback_lvalue ()->get_type ();
5130 playback::rvalue *binary_op =
5131 r->new_binary_op (playback_location (r),
5132 m_op,
5133 result_type,
5134 m_lvalue->playback_rvalue (),
5135 m_rvalue->playback_rvalue ());
5137 playback_block (get_block ())
5138 ->add_assignment (playback_location (r),
5139 m_lvalue->playback_lvalue (),
5140 binary_op);
5143 /* Implementation of recording::memento::make_debug_string for
5144 an assignment_op statement. */
5146 recording::string *
5147 recording::assignment_op::make_debug_string ()
5149 return string::from_printf (m_ctxt,
5150 "%s %s= %s;",
5151 m_lvalue->get_debug_string (),
5152 binary_op_strings[m_op],
5153 m_rvalue->get_debug_string ());
5156 /* Implementation of recording::memento::write_reproducer for
5157 assignment_op statements. */
5159 void
5160 recording::assignment_op::write_reproducer (reproducer &r)
5162 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5163 " %s, /* gcc_jit_location *loc */\n"
5164 " %s, /* gcc_jit_lvalue *lvalue */\n"
5165 " %s, /* enum gcc_jit_binary_op op */\n"
5166 " %s); /* gcc_jit_rvalue *rvalue */\n",
5167 r.get_identifier (get_block ()),
5168 r.get_identifier (get_loc ()),
5169 r.get_identifier_as_lvalue (m_lvalue),
5170 binary_op_reproducer_strings[m_op],
5171 r.get_identifier_as_rvalue (m_rvalue));
5174 /* The implementation of class gcc::jit::recording::comment. */
5176 /* Implementation of pure virtual hook recording::memento::replay_into
5177 for recording::comment. */
5179 void
5180 recording::comment::replay_into (replayer *r)
5182 playback_block (get_block ())
5183 ->add_comment (playback_location (r),
5184 m_text->c_str ());
5187 /* Implementation of recording::memento::make_debug_string for
5188 a comment "statement". */
5190 recording::string *
5191 recording::comment::make_debug_string ()
5193 return string::from_printf (m_ctxt,
5194 "/* %s */",
5195 m_text->c_str ());
5198 /* Implementation of recording::memento::write_reproducer for
5199 comments. */
5201 void
5202 recording::comment::write_reproducer (reproducer &r)
5204 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5205 " %s, /* gcc_jit_location *loc */\n"
5206 " %s); /* const char *text */\n",
5207 r.get_identifier (get_block ()),
5208 r.get_identifier (get_loc ()),
5209 m_text->get_debug_string ());
5212 /* The implementation of class gcc::jit::recording::conditional. */
5214 /* Implementation of pure virtual hook recording::memento::replay_into
5215 for recording::conditional. */
5217 void
5218 recording::conditional::replay_into (replayer *r)
5220 playback_block (get_block ())
5221 ->add_conditional (playback_location (r),
5222 m_boolval->playback_rvalue (),
5223 playback_block (m_on_true),
5224 playback_block (m_on_false));
5227 /* Override the poisoned default implementation of
5228 gcc::jit::recording::statement::get_successor_blocks
5230 A conditional jump has 2 successor blocks. */
5233 recording::conditional::get_successor_blocks (block **out_next1,
5234 block **out_next2) const
5236 *out_next1 = m_on_true;
5237 *out_next2 = m_on_false;
5238 return 2;
5241 /* Implementation of recording::memento::make_debug_string for
5242 a conditional jump statement. */
5244 recording::string *
5245 recording::conditional::make_debug_string ()
5247 if (m_on_false)
5248 return string::from_printf (m_ctxt,
5249 "if (%s) goto %s; else goto %s;",
5250 m_boolval->get_debug_string (),
5251 m_on_true->get_debug_string (),
5252 m_on_false->get_debug_string ());
5253 else
5254 return string::from_printf (m_ctxt,
5255 "if (%s) goto %s;",
5256 m_boolval->get_debug_string (),
5257 m_on_true->get_debug_string ());
5260 /* Implementation of recording::memento::write_reproducer for
5261 conditional statements. */
5263 void
5264 recording::conditional::write_reproducer (reproducer &r)
5266 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5267 " %s, /* gcc_jit_location *loc */\n"
5268 " %s, /* gcc_jit_rvalue *boolval */\n"
5269 " %s, /* gcc_jit_block *on_true */\n"
5270 " %s); /* gcc_jit_block *on_false */\n",
5271 r.get_identifier (get_block ()),
5272 r.get_identifier (get_loc ()),
5273 r.get_identifier_as_rvalue (m_boolval),
5274 r.get_identifier (m_on_true),
5275 r.get_identifier (m_on_false));
5278 /* The implementation of class gcc::jit::recording::jump. */
5280 /* Implementation of pure virtual hook recording::memento::replay_into
5281 for recording::jump. */
5283 void
5284 recording::jump::replay_into (replayer *r)
5286 playback_block (get_block ())
5287 ->add_jump (playback_location (r),
5288 m_target->playback_block ());
5291 /* Override the poisoned default implementation of
5292 gcc::jit::recording::statement::get_successor_blocks
5294 An unconditional jump has 1 successor block. */
5297 recording::jump::get_successor_blocks (block **out_next1,
5298 block **/*out_next2*/) const
5300 *out_next1 = m_target;
5301 return 1;
5304 /* Implementation of recording::memento::make_debug_string for
5305 a unconditional jump statement. */
5307 recording::string *
5308 recording::jump::make_debug_string ()
5310 return string::from_printf (m_ctxt,
5311 "goto %s;",
5312 m_target->get_debug_string ());
5315 /* Implementation of recording::memento::write_reproducer for
5316 jump statements. */
5318 void
5319 recording::jump::write_reproducer (reproducer &r)
5321 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5322 " %s, /* gcc_jit_location *loc */\n"
5323 " %s); /* gcc_jit_block *target */\n",
5324 r.get_identifier (get_block ()),
5325 r.get_identifier (get_loc ()),
5326 r.get_identifier (m_target));
5329 /* The implementation of class gcc::jit::recording::return_. */
5331 /* Implementation of pure virtual hook recording::memento::replay_into
5332 for recording::return_. */
5334 void
5335 recording::return_::replay_into (replayer *r)
5337 playback_block (get_block ())
5338 ->add_return (playback_location (r),
5339 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
5342 /* Override the poisoned default implementation of
5343 gcc::jit::recording::statement::get_successor_blocks
5345 A return statement has no successor block. */
5348 recording::return_::get_successor_blocks (block **/*out_next1*/,
5349 block **/*out_next2*/) const
5351 return 0;
5354 /* Implementation of recording::memento::make_debug_string for
5355 a return statement (covers both those with and without rvalues). */
5357 recording::string *
5358 recording::return_::make_debug_string ()
5360 if (m_rvalue)
5361 return string::from_printf (m_ctxt,
5362 "return %s;",
5363 m_rvalue->get_debug_string ());
5364 else
5365 return string::from_printf (m_ctxt,
5366 "return;");
5369 /* Implementation of recording::memento::write_reproducer for
5370 return statements. */
5372 void
5373 recording::return_::write_reproducer (reproducer &r)
5375 if (m_rvalue)
5376 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5377 " %s, /* gcc_jit_location *loc */\n"
5378 " %s); /* gcc_jit_rvalue *rvalue */\n",
5379 r.get_identifier (get_block ()),
5380 r.get_identifier (get_loc ()),
5381 r.get_identifier_as_rvalue (m_rvalue));
5382 else
5383 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5384 " %s); /* gcc_jit_location *loc */\n",
5385 r.get_identifier (get_block ()),
5386 r.get_identifier (get_loc ()));
5389 } // namespace gcc::jit
5391 } // namespace gcc