PR jit/66546: Add gcc_jit_context_set_bool_allow_unreachable_blocks
[official-gcc.git] / gcc / jit / jit-recording.c
blobad13aaa498b0bc73e0ec1320fdb2d735a4b81220
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 memcpy (m_inner_bool_options,
493 parent_ctxt->m_inner_bool_options,
494 sizeof (m_inner_bool_options));
495 set_logger (parent_ctxt->get_logger ());
497 else
499 memset (m_str_options, 0, sizeof (m_str_options));
500 memset (m_int_options, 0, sizeof (m_int_options));
501 memset (m_bool_options, 0, sizeof (m_bool_options));
502 memset (m_inner_bool_options, 0, sizeof (m_inner_bool_options));
505 memset (m_basic_types, 0, sizeof (m_basic_types));
508 /* The destructor for gcc::jit::recording::context, implicitly used by
509 gcc_jit_context_release. */
511 recording::context::~context ()
513 JIT_LOG_SCOPE (get_logger ());
514 int i;
515 memento *m;
516 FOR_EACH_VEC_ELT (m_mementos, i, m)
518 delete m;
521 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
522 free (m_str_options[i]);
524 char *optname;
525 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
526 free (optname);
528 if (m_builtins_manager)
529 delete m_builtins_manager;
531 if (m_owns_first_error_str)
532 free (m_first_error_str);
534 if (m_owns_last_error_str)
535 if (m_last_error_str != m_first_error_str)
536 free (m_last_error_str);
539 /* Add the given mememto to the list of those tracked by this
540 gcc::jit::recording::context, so that e.g. it can be deleted
541 when this context is released. */
543 void
544 recording::context::record (memento *m)
546 gcc_assert (m);
548 m_mementos.safe_push (m);
551 /* Replay this context (and any parents) into the given replayer. */
553 void
554 recording::context::replay_into (replayer *r)
556 JIT_LOG_SCOPE (get_logger ());
557 int i;
558 memento *m;
560 /* If we have a parent context, we must replay it. This will
561 recursively walk backwards up the historical tree, then replay things
562 forwards "in historical order", starting with the ultimate parent
563 context, until we reach the "this" context.
565 Note that we fully replay the parent, then fully replay the child,
566 which means that inter-context references can only exist from child
567 to parent, not the other way around.
569 All of this replaying is suboptimal - it would be better to do the
570 work for the parent context *once*, rather than replaying the parent
571 every time we replay each child. However, fixing this requires deep
572 surgery to lifetime-management: we'd need every context family tree
573 to have its own GC heap, and to initialize the GCC code to use that
574 heap (with a mutex on such a heap). */
575 if (m_parent_ctxt)
576 m_parent_ctxt->replay_into (r);
578 if (r->errors_occurred ())
579 return;
581 /* Replay this context's saved operations into r. */
582 FOR_EACH_VEC_ELT (m_mementos, i, m)
584 /* Disabled low-level debugging, here if we need it: print what
585 we're replaying.
586 Note that the calls to get_debug_string might lead to more
587 mementos being created for the strings.
588 This can also be used to exercise the debug_string
589 machinery. */
590 if (0)
591 printf ("context %p replaying (%p): %s\n",
592 (void *)this, (void *)m, m->get_debug_string ());
594 m->replay_into (r);
596 if (r->errors_occurred ())
597 return;
601 /* During a playback, we associate objects from the recording with
602 their counterparts during this playback.
604 For simplicity, we store this within the recording objects.
606 The following method cleans away these associations, to ensure that
607 we never have out-of-date associations lingering on subsequent
608 playbacks (the objects pointed to are GC-managed, but the
609 recording objects don't own refs to them). */
611 void
612 recording::context::disassociate_from_playback ()
614 JIT_LOG_SCOPE (get_logger ());
615 int i;
616 memento *m;
618 if (m_parent_ctxt)
619 m_parent_ctxt->disassociate_from_playback ();
621 FOR_EACH_VEC_ELT (m_mementos, i, m)
623 m->set_playback_obj (NULL);
627 /* Create a recording::string instance and add it to this context's list
628 of mementos.
630 This creates a fresh copy of the given 0-terminated buffer. */
632 recording::string *
633 recording::context::new_string (const char *text)
635 if (!text)
636 return NULL;
638 recording::string *result = new string (this, text);
639 record (result);
640 return result;
643 /* Create a recording::location instance and add it to this context's
644 list of mementos.
646 Implements the post-error-checking part of
647 gcc_jit_context_new_location. */
649 recording::location *
650 recording::context::new_location (const char *filename,
651 int line,
652 int column,
653 bool created_by_user)
655 recording::location *result =
656 new recording::location (this,
657 new_string (filename),
658 line, column,
659 created_by_user);
660 record (result);
661 return result;
664 /* If we haven't seen this enum value yet, create a recording::type
665 instance and add it to this context's list of mementos.
667 If we have seen it before, reuse our cached value, so that repeated
668 calls on the context give the same object.
670 If we have a parent context, the cache is within the ultimate
671 ancestor context.
673 Implements the post-error-checking part of
674 gcc_jit_context_get_type. */
676 recording::type *
677 recording::context::get_type (enum gcc_jit_types kind)
679 if (!m_basic_types[kind])
681 if (m_parent_ctxt)
682 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
683 else
685 recording::type *result = new memento_of_get_type (this, kind);
686 record (result);
687 m_basic_types[kind] = result;
691 return m_basic_types[kind];
694 /* Get a recording::type instance for the given size and signedness.
695 This is implemented in terms of recording::context::get_type
696 above.
698 Implements the post-error-checking part of
699 gcc_jit_context_get_int_type. */
701 recording::type *
702 recording::context::get_int_type (int num_bytes, int is_signed)
704 /* We can't use a switch here since some of the values are macros affected
705 by options; e.g. i386.h has
706 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
707 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
708 are in bits, rather than bytes.
710 const int num_bits = num_bytes * 8;
711 if (num_bits == INT_TYPE_SIZE)
712 return get_type (is_signed
713 ? GCC_JIT_TYPE_INT
714 : GCC_JIT_TYPE_UNSIGNED_INT);
715 if (num_bits == CHAR_TYPE_SIZE)
716 return get_type (is_signed
717 ? GCC_JIT_TYPE_SIGNED_CHAR
718 : GCC_JIT_TYPE_UNSIGNED_CHAR);
719 if (num_bits == SHORT_TYPE_SIZE)
720 return get_type (is_signed
721 ? GCC_JIT_TYPE_SHORT
722 : GCC_JIT_TYPE_UNSIGNED_SHORT);
723 if (num_bits == LONG_TYPE_SIZE)
724 return get_type (is_signed
725 ? GCC_JIT_TYPE_LONG
726 : GCC_JIT_TYPE_UNSIGNED_LONG);
727 if (num_bits == LONG_LONG_TYPE_SIZE)
728 return get_type (is_signed
729 ? GCC_JIT_TYPE_LONG_LONG
730 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
732 /* Some other size, not corresponding to the C int types. */
733 /* To be written: support arbitrary other sizes, sharing by
734 memoizing at the recording::context level? */
735 gcc_unreachable ();
738 /* Create a recording::type instance and add it to this context's list
739 of mementos.
741 Implements the post-error-checking part of
742 gcc_jit_context_new_array_type. */
744 recording::type *
745 recording::context::new_array_type (recording::location *loc,
746 recording::type *element_type,
747 int num_elements)
749 if (struct_ *s = element_type->dyn_cast_struct ())
750 if (!s->get_fields ())
752 add_error (NULL,
753 "cannot create an array of type %s"
754 " until the fields have been set",
755 s->get_name ()->c_str ());
756 return NULL;
758 recording::type *result =
759 new recording::array_type (this, loc, element_type, num_elements);
760 record (result);
761 return result;
764 /* Create a recording::field instance and add it to this context's list
765 of mementos.
767 Implements the post-error-checking part of
768 gcc_jit_context_new_field. */
770 recording::field *
771 recording::context::new_field (recording::location *loc,
772 recording::type *type,
773 const char *name)
775 recording::field *result =
776 new recording::field (this, loc, type, new_string (name));
777 record (result);
778 return result;
781 /* Create a recording::struct_ instance and add it to this context's
782 list of mementos and list of compound types.
784 Implements the post-error-checking part of
785 gcc_jit_context_new_struct_type. */
787 recording::struct_ *
788 recording::context::new_struct_type (recording::location *loc,
789 const char *name)
791 recording::struct_ *result = new struct_ (this, loc, new_string (name));
792 record (result);
793 m_compound_types.safe_push (result);
794 return result;
797 /* Create a recording::union_ instance and add it to this context's
798 list of mementos and list of compound types.
800 Implements the first post-error-checking part of
801 gcc_jit_context_new_union_type. */
803 recording::union_ *
804 recording::context::new_union_type (recording::location *loc,
805 const char *name)
807 recording::union_ *result = new union_ (this, loc, new_string (name));
808 record (result);
809 m_compound_types.safe_push (result);
810 return result;
813 /* Create a recording::function_type instance and add it to this context's
814 list of mementos.
816 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
818 recording::function_type *
819 recording::context::new_function_type (recording::type *return_type,
820 int num_params,
821 recording::type **param_types,
822 int is_variadic)
824 recording::function_type *fn_type
825 = new function_type (this,
826 return_type,
827 num_params,
828 param_types,
829 is_variadic);
830 record (fn_type);
831 return fn_type;
834 /* Create a recording::type instance and add it to this context's list
835 of mementos.
837 Implements the post-error-checking part of
838 gcc_jit_context_new_function_ptr_type. */
840 recording::type *
841 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
842 recording::type *return_type,
843 int num_params,
844 recording::type **param_types,
845 int is_variadic)
847 recording::function_type *fn_type
848 = new_function_type (return_type,
849 num_params,
850 param_types,
851 is_variadic);
853 /* Return a pointer-type to the the function type. */
854 return fn_type->get_pointer ();
857 /* Create a recording::param instance and add it to this context's list
858 of mementos.
860 Implements the post-error-checking part of
861 gcc_jit_context_new_param. */
863 recording::param *
864 recording::context::new_param (recording::location *loc,
865 recording::type *type,
866 const char *name)
868 recording::param *result = new recording::param (this, loc, type, new_string (name));
869 record (result);
870 return result;
873 /* Create a recording::function instance and add it to this context's list
874 of mementos and list of functions.
876 Implements the post-error-checking part of
877 gcc_jit_context_new_function. */
879 recording::function *
880 recording::context::new_function (recording::location *loc,
881 enum gcc_jit_function_kind kind,
882 recording::type *return_type,
883 const char *name,
884 int num_params,
885 recording::param **params,
886 int is_variadic,
887 enum built_in_function builtin_id)
889 recording::function *result =
890 new recording::function (this,
891 loc, kind, return_type,
892 new_string (name),
893 num_params, params, is_variadic,
894 builtin_id);
895 record (result);
896 m_functions.safe_push (result);
898 return result;
901 /* Locate the builtins_manager (if any) for this family of contexts,
902 creating it if it doesn't exist already.
904 All of the recording contexts in a family share one builtins_manager:
905 if we have a child context, follow the parent links to get the
906 ultimate ancestor context, and look for it/store it there. */
908 builtins_manager *
909 recording::context::get_builtins_manager ()
911 if (m_parent_ctxt)
912 return m_parent_ctxt->get_builtins_manager ();
914 if (!m_builtins_manager)
915 m_builtins_manager = new builtins_manager (this);
917 return m_builtins_manager;
920 /* Get a recording::function instance, which is lazily-created and added
921 to the context's lists of mementos.
923 Implements the post-error-checking part of
924 gcc_jit_context_get_builtin_function. */
926 recording::function *
927 recording::context::get_builtin_function (const char *name)
929 builtins_manager *bm = get_builtins_manager ();
930 return bm->get_builtin_function (name);
933 /* Create a recording::global instance and add it to this context's list
934 of mementos.
936 Implements the post-error-checking part of
937 gcc_jit_context_new_global. */
939 recording::lvalue *
940 recording::context::new_global (recording::location *loc,
941 enum gcc_jit_global_kind kind,
942 recording::type *type,
943 const char *name)
945 recording::global *result =
946 new recording::global (this, loc, kind, type, new_string (name));
947 record (result);
948 m_globals.safe_push (result);
950 return result;
953 /* Create a recording::memento_of_new_string_literal instance and add it
954 to this context's list of mementos.
956 Implements the post-error-checking part of
957 gcc_jit_context_new_string_literal. */
959 recording::rvalue *
960 recording::context::new_string_literal (const char *value)
962 recording::rvalue *result =
963 new memento_of_new_string_literal (this, NULL, new_string (value));
964 record (result);
965 return result;
968 /* Create a recording::unary_op instance and add it to this context's
969 list of mementos.
971 Implements the post-error-checking part of
972 gcc_jit_context_new_unary_op. */
974 recording::rvalue *
975 recording::context::new_unary_op (recording::location *loc,
976 enum gcc_jit_unary_op op,
977 recording::type *result_type,
978 recording::rvalue *a)
980 recording::rvalue *result =
981 new unary_op (this, loc, op, result_type, a);
982 record (result);
983 return result;
986 /* Create a recording::binary_op instance and add it to this context's
987 list of mementos.
989 Implements the post-error-checking part of
990 gcc_jit_context_new_binary_op. */
992 recording::rvalue *
993 recording::context::new_binary_op (recording::location *loc,
994 enum gcc_jit_binary_op op,
995 recording::type *result_type,
996 recording::rvalue *a,
997 recording::rvalue *b)
999 recording::rvalue *result =
1000 new binary_op (this, loc, op, result_type, a, b);
1001 record (result);
1002 return result;
1005 /* Create a recording::comparison instance and add it to this context's
1006 list of mementos.
1008 Implements the post-error-checking part of
1009 gcc_jit_context_new_comparison. */
1011 recording::rvalue *
1012 recording::context::new_comparison (recording::location *loc,
1013 enum gcc_jit_comparison op,
1014 recording::rvalue *a,
1015 recording::rvalue *b)
1017 recording::rvalue *result = new comparison (this, loc, op, a, b);
1018 record (result);
1019 return result;
1022 /* Create a recording::cast instance and add it to this context's list
1023 of mementos.
1025 Implements the post-error-checking part of
1026 gcc_jit_context_new_cast. */
1028 recording::rvalue *
1029 recording::context::new_cast (recording::location *loc,
1030 recording::rvalue *expr,
1031 recording::type *type_)
1033 recording::rvalue *result = new cast (this, loc, expr, type_);
1034 record (result);
1035 return result;
1038 /* Create a recording::call instance and add it to this context's list
1039 of mementos.
1041 Implements the post-error-checking part of
1042 gcc_jit_context_new_call. */
1044 recording::rvalue *
1045 recording::context::new_call (recording::location *loc,
1046 function *func,
1047 int numargs , recording::rvalue **args)
1049 recording::rvalue *result = new call (this, loc, func, numargs, args);
1050 record (result);
1051 return result;
1054 /* Create a recording::call_through_ptr instance and add it to this
1055 context's list of mementos.
1057 Implements the post-error-checking part of
1058 gcc_jit_context_new_call_through_ptr. */
1060 recording::rvalue *
1061 recording::context::new_call_through_ptr (recording::location *loc,
1062 recording::rvalue *fn_ptr,
1063 int numargs,
1064 recording::rvalue **args)
1066 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
1067 record (result);
1068 return result;
1071 /* Create a recording::array_access instance and add it to this context's list
1072 of mementos.
1074 Implements the post-error-checking part of
1075 gcc_jit_context_new_array_access. */
1077 recording::lvalue *
1078 recording::context::new_array_access (recording::location *loc,
1079 recording::rvalue *ptr,
1080 recording::rvalue *index)
1082 recording::lvalue *result = new array_access (this, loc, ptr, index);
1083 record (result);
1084 return result;
1087 /* Set the given string option for this context, or add an error if
1088 it's not recognized.
1090 Implements the post-error-checking part of
1091 gcc_jit_context_set_str_option. */
1093 void
1094 recording::context::set_str_option (enum gcc_jit_str_option opt,
1095 const char *value)
1097 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
1099 add_error (NULL,
1100 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
1101 return;
1103 free (m_str_options[opt]);
1104 m_str_options[opt] = value ? xstrdup (value) : NULL;
1105 log_str_option (opt);
1108 /* Set the given integer option for this context, or add an error if
1109 it's not recognized.
1111 Implements the post-error-checking part of
1112 gcc_jit_context_set_int_option. */
1114 void
1115 recording::context::set_int_option (enum gcc_jit_int_option opt,
1116 int value)
1118 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
1120 add_error (NULL,
1121 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
1122 return;
1124 m_int_options[opt] = value;
1125 log_int_option (opt);
1128 /* Set the given boolean option for this context, or add an error if
1129 it's not recognized.
1131 Implements the post-error-checking part of
1132 gcc_jit_context_set_bool_option. */
1134 void
1135 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
1136 int value)
1138 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
1140 add_error (NULL,
1141 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
1142 return;
1144 m_bool_options[opt] = value ? true : false;
1145 log_bool_option (opt);
1148 void
1149 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt,
1150 int value)
1152 gcc_assert (inner_opt >= 0 && inner_opt < NUM_INNER_BOOL_OPTIONS);
1153 m_inner_bool_options[inner_opt] = value ? true : false;
1154 log_inner_bool_option (inner_opt);
1158 /* Add the given optname to this context's list of extra options.
1160 Implements the post-error-checking part of
1161 gcc_jit_context_add_command_line_option. */
1163 void
1164 recording::context::add_command_line_option (const char *optname)
1166 m_command_line_options.safe_push (xstrdup (optname));
1169 /* Add any user-provided extra options, starting with any from
1170 parent contexts.
1171 Called by playback::context::make_fake_args. */
1173 void
1174 recording::context::append_command_line_options (vec <char *> *argvec)
1176 if (m_parent_ctxt)
1177 m_parent_ctxt->append_command_line_options (argvec);
1179 int i;
1180 char *optname;
1181 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1182 argvec->safe_push (xstrdup (optname));
1185 /* Add the given dumpname/out_ptr pair to this context's list of requested
1186 dumps.
1188 Implements the post-error-checking part of
1189 gcc_jit_context_enable_dump. */
1191 void
1192 recording::context::enable_dump (const char *dumpname,
1193 char **out_ptr)
1195 requested_dump d;
1196 gcc_assert (dumpname);
1197 gcc_assert (out_ptr);
1199 d.m_dumpname = dumpname;
1200 d.m_out_ptr = out_ptr;
1201 *out_ptr = NULL;
1202 m_requested_dumps.safe_push (d);
1205 /* Validate this context, and if it passes, compile it to memory
1206 (within a mutex).
1208 Implements the post-error-checking part of
1209 gcc_jit_context_compile. */
1211 result *
1212 recording::context::compile ()
1214 JIT_LOG_SCOPE (get_logger ());
1216 log_all_options ();
1218 validate ();
1220 if (errors_occurred ())
1221 return NULL;
1223 /* Set up a compile_to_memory playback context. */
1224 ::gcc::jit::playback::compile_to_memory replayer (this);
1226 /* Use it. */
1227 replayer.compile ();
1229 /* Get the jit::result (or NULL) from the
1230 compile_to_memory playback context. */
1231 return replayer.get_result_obj ();
1234 /* Validate this context, and if it passes, compile it to a file
1235 (within a mutex).
1237 Implements the post-error-checking part of
1238 gcc_jit_context_compile_to_file. */
1240 void
1241 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
1242 const char *output_path)
1244 JIT_LOG_SCOPE (get_logger ());
1246 log_all_options ();
1248 validate ();
1250 if (errors_occurred ())
1251 return;
1253 /* Set up a compile_to_file playback context. */
1254 ::gcc::jit::playback::compile_to_file replayer (this,
1255 output_kind,
1256 output_path);
1258 /* Use it. */
1259 replayer.compile ();
1262 /* Format the given error using printf's conventions, print
1263 it to stderr, and add it to the context. */
1265 void
1266 recording::context::add_error (location *loc, const char *fmt, ...)
1268 va_list ap;
1269 va_start (ap, fmt);
1270 add_error_va (loc, fmt, ap);
1271 va_end (ap);
1274 /* Format the given error using printf's conventions, print
1275 it to stderr, and add it to the context. */
1277 void
1278 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
1280 int len;
1281 char *malloced_msg;
1282 const char *errmsg;
1283 bool has_ownership;
1285 JIT_LOG_SCOPE (get_logger ());
1287 len = vasprintf (&malloced_msg, fmt, ap);
1288 if (malloced_msg == NULL || len < 0)
1290 errmsg = "out of memory generating error message";
1291 has_ownership = false;
1293 else
1295 errmsg = malloced_msg;
1296 has_ownership = true;
1298 if (get_logger ())
1299 get_logger ()->log ("error %i: %s", m_error_count, errmsg);
1301 const char *ctxt_progname =
1302 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
1303 if (!ctxt_progname)
1304 ctxt_progname = "libgccjit.so";
1306 if (loc)
1307 fprintf (stderr, "%s: %s: error: %s\n",
1308 ctxt_progname,
1309 loc->get_debug_string (),
1310 errmsg);
1311 else
1312 fprintf (stderr, "%s: error: %s\n",
1313 ctxt_progname,
1314 errmsg);
1316 if (!m_error_count)
1318 m_first_error_str = const_cast <char *> (errmsg);
1319 m_owns_first_error_str = has_ownership;
1322 if (m_owns_last_error_str)
1323 if (m_last_error_str != m_first_error_str)
1324 free (m_last_error_str);
1325 m_last_error_str = const_cast <char *> (errmsg);
1326 m_owns_last_error_str = has_ownership;
1328 m_error_count++;
1331 /* Get the message for the first error that occurred on this context, or
1332 NULL if no errors have occurred on it.
1334 Implements the post-error-checking part of
1335 gcc_jit_context_get_first_error. */
1337 const char *
1338 recording::context::get_first_error () const
1340 return m_first_error_str;
1343 /* Get the message for the last error that occurred on this context, or
1344 NULL if no errors have occurred on it.
1346 Implements the post-error-checking part of
1347 gcc_jit_context_get_last_error. */
1349 const char *
1350 recording::context::get_last_error () const
1352 return m_last_error_str;
1355 /* Lazily generate and record a recording::type representing an opaque
1356 struct named "FILE".
1358 For use if client code tries to dereference the result of
1359 get_type (GCC_JIT_TYPE_FILE_PTR). */
1361 recording::type *
1362 recording::context::get_opaque_FILE_type ()
1364 if (!m_FILE_type)
1365 m_FILE_type = new_struct_type (NULL, "FILE");
1366 return m_FILE_type;
1369 /* Dump a C-like representation of the given context to the given path.
1370 If UPDATE_LOCATIONS is true, update the locations within the
1371 context's mementos to point to the dumpfile.
1373 Implements the post-error-checking part of
1374 gcc_jit_context_dump_to_file. */
1376 void
1377 recording::context::dump_to_file (const char *path, bool update_locations)
1379 int i;
1380 dump d (*this, path, update_locations);
1382 /* Forward declaration of structs and unions. */
1383 compound_type *st;
1384 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1386 d.write ("%s;\n\n", st->get_debug_string ());
1389 /* Content of structs, where set. */
1390 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1391 if (st->get_fields ())
1393 st->get_fields ()->write_to_dump (d);
1394 d.write ("\n");
1397 /* Globals. */
1398 global *g;
1399 FOR_EACH_VEC_ELT (m_globals, i, g)
1401 g->write_to_dump (d);
1403 if (!m_globals.is_empty ())
1404 d.write ("\n");
1406 function *fn;
1407 FOR_EACH_VEC_ELT (m_functions, i, fn)
1409 fn->write_to_dump (d);
1413 static const char * const
1414 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
1415 "GCC_JIT_STR_OPTION_PROGNAME"
1418 static const char * const
1419 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
1420 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1423 static const char * const
1424 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
1425 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1426 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1427 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1428 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1429 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1430 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1431 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1432 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1435 static const char * const
1436 inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = {
1437 "gcc_jit_context_set_bool_allow_unreachable_blocks"
1440 /* Write the current value of all options to the log file (if any). */
1442 void
1443 recording::context::log_all_options () const
1445 int opt_idx;
1447 if (!get_logger ())
1448 return;
1450 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1451 log_str_option ((enum gcc_jit_str_option)opt_idx);
1453 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1454 log_int_option ((enum gcc_jit_int_option)opt_idx);
1456 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1457 log_bool_option ((enum gcc_jit_bool_option)opt_idx);
1458 for (opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1459 log_inner_bool_option ((enum inner_bool_option)opt_idx);
1462 /* Write the current value of the given string option to the
1463 log file (if any). */
1465 void
1466 recording::context::log_str_option (enum gcc_jit_str_option opt) const
1468 gcc_assert (opt < GCC_JIT_NUM_STR_OPTIONS);
1469 if (get_logger ())
1471 if (m_str_options[opt])
1472 log ("%s: \"%s\"",
1473 str_option_reproducer_strings[opt],
1474 m_str_options[opt]);
1475 else
1476 log ("%s: NULL",
1477 str_option_reproducer_strings[opt]);
1481 /* Write the current value of the given int option to the
1482 log file (if any). */
1484 void
1485 recording::context::log_int_option (enum gcc_jit_int_option opt) const
1487 gcc_assert (opt < GCC_JIT_NUM_INT_OPTIONS);
1488 if (get_logger ())
1489 log ("%s: %i",
1490 int_option_reproducer_strings[opt],
1491 m_int_options[opt]);
1494 /* Write the current value of the given bool option to the
1495 log file (if any). */
1497 void
1498 recording::context::log_bool_option (enum gcc_jit_bool_option opt) const
1500 gcc_assert (opt < GCC_JIT_NUM_BOOL_OPTIONS);
1501 if (get_logger ())
1502 log ("%s: %s",
1503 bool_option_reproducer_strings[opt],
1504 m_bool_options[opt] ? "true" : "false");
1507 /* Write the current value of the given "inner" bool option to the
1508 log file (if any). */
1510 void
1511 recording::context::log_inner_bool_option (enum inner_bool_option opt) const
1513 gcc_assert (opt < NUM_INNER_BOOL_OPTIONS);
1514 if (get_logger ())
1515 log ("%s: %s",
1516 inner_bool_option_reproducer_strings[opt],
1517 m_inner_bool_options[opt] ? "true" : "false");
1520 /* Write C source code to PATH that attempts to replay the API
1521 calls made to this context (and its parents), for use in
1522 minimizing test cases for libgccjit.
1524 Implements the post-error-checking part of
1525 gcc_jit_context_dump_reproducer_to_file. */
1527 void
1528 recording::context::dump_reproducer_to_file (const char *path)
1530 JIT_LOG_SCOPE (get_logger ());
1531 reproducer r (*this, path);
1533 /* Generate the "ancestry" of this context, as a list. */
1534 auto_vec <context *> ascending_contexts;
1535 for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
1536 ascending_contexts.safe_push (ctxt);
1538 /* Reverse the list, giving a list of contexts from
1539 top-most parent context down through to youngest child context.
1540 We will use this list as the parameters of the functions in
1541 our generated file. */
1542 unsigned num_ctxts = ascending_contexts.length ();
1543 auto_vec <context *> contexts (num_ctxts);
1544 for (unsigned i = 0; i < num_ctxts; i++)
1545 contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
1547 /* contexts[0] should be the top-level context. */
1548 gcc_assert (contexts[0]);
1549 gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
1551 /* The final element in contexts should be "this". */
1552 gcc_assert (contexts[contexts.length () - 1] == this);
1553 gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
1554 == contexts[0]);
1556 r.write ("/* This code was autogenerated by"
1557 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1558 print_version (r.get_file (), " ", false);
1559 r.write ("*/\n");
1560 r.write ("#include <libgccjit.h>\n\n");
1561 r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1562 r.write ("static void\nset_options (");
1563 r.write_params (contexts);
1564 r.write (");\n\n");
1565 r.write ("static void\ncreate_code (");
1566 r.write_params (contexts);
1567 r.write (");\n\n");
1568 r.write ("int\nmain (int argc, const char **argv)\n");
1569 r.write ("{\n");
1570 for (unsigned i = 0; i < num_ctxts; i++)
1571 r.write (" gcc_jit_context *%s;\n",
1572 r.get_identifier (contexts[i]));
1573 r.write (" gcc_jit_result *result;\n"
1574 "\n");
1576 /* Create the contexts.
1577 The top-level context is acquired from a clean slate, the others as
1578 children of the prior context. */
1579 r.write (" %s = gcc_jit_context_acquire ();\n",
1580 r.get_identifier (contexts[0]));
1581 for (unsigned i = 1; i < num_ctxts; i++)
1582 r.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1583 r.get_identifier (contexts[i]),
1584 r.get_identifier (contexts[i - 1]));
1585 r.write (" set_options (");
1586 r.write_args (contexts);
1587 r.write (");\n");
1588 r.write (" create_code (");
1589 r.write_args (contexts);
1590 r.write (");\n");
1592 r.write (" result = gcc_jit_context_compile (%s);\n",
1593 r.get_identifier (this));
1595 for (unsigned i = num_ctxts; i > 0; i--)
1596 r.write (" gcc_jit_context_release (%s);\n",
1597 r.get_identifier (contexts[i - 1]));
1599 r.write (" gcc_jit_result_release (result);\n"
1600 " return 0;\n"
1601 "}\n\n");
1603 /* Define (char *) variables for use in calls to
1604 gcc_jit_context_enable_dump. */
1605 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1607 if (m_requested_dumps.length ())
1609 r.write ("/* Requested dumps for %s. */\n",
1610 r.get_identifier (contexts[ctxt_idx]));
1611 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1612 r.write ("static char *dump_%p;\n",
1613 (void *)&m_requested_dumps[i]);
1614 r.write ("\n");
1618 /* Write out values of options. */
1619 r.write ("static void\nset_options (");
1620 r.write_params (contexts);
1621 r.write (")\n{\n");
1622 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1624 if (ctxt_idx > 0)
1625 r.write ("\n");
1627 r.write (" /* Set options for %s. */\n",
1628 r.get_identifier (contexts[ctxt_idx]));
1630 r.write (" /* String options. */\n");
1631 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1633 r.write (" gcc_jit_context_set_str_option (%s,\n"
1634 " %s,\n",
1635 r.get_identifier (contexts[ctxt_idx]),
1636 str_option_reproducer_strings[opt_idx]);
1637 if (m_str_options[opt_idx])
1638 r.write (" \"%s\");\n",
1639 m_str_options[opt_idx]);
1640 else
1641 r.write (" NULL);\n");
1643 r.write (" /* Int options. */\n");
1644 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1645 r.write (" gcc_jit_context_set_int_option (%s,\n"
1646 " %s,\n"
1647 " %i);\n",
1648 r.get_identifier (contexts[ctxt_idx]),
1649 int_option_reproducer_strings[opt_idx],
1650 m_int_options[opt_idx]);
1651 r.write (" /* Boolean options. */\n");
1652 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1653 r.write (" gcc_jit_context_set_bool_option (%s,\n"
1654 " %s,\n"
1655 " %i);\n",
1656 r.get_identifier (contexts[ctxt_idx]),
1657 bool_option_reproducer_strings[opt_idx],
1658 m_bool_options[opt_idx]);
1659 for (int opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1660 r.write (" %s (%s, %i);\n",
1661 inner_bool_option_reproducer_strings[opt_idx],
1662 r.get_identifier (contexts[ctxt_idx]),
1663 m_inner_bool_options[opt_idx]);
1665 if (!m_command_line_options.is_empty ())
1667 int i;
1668 char *optname;
1669 r.write (" /* User-provided command-line options. */\n");
1670 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1671 r.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1672 r.get_identifier (contexts[ctxt_idx]),
1673 optname);
1676 if (m_requested_dumps.length ())
1678 r.write (" /* Requested dumps. */\n");
1679 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1680 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1682 r.write (" gcc_jit_context_enable_dump (%s,\n"
1683 " \"%s\",\n"
1684 " &dump_%p);\n",
1685 r.get_identifier (contexts[ctxt_idx]),
1686 m_requested_dumps[i].m_dumpname,
1687 (void *)&m_requested_dumps[i]);
1691 r.write ("}\n\n");
1693 r.write ("static void\ncreate_code (");
1694 r.write_params (contexts);
1695 r.write (")\n"
1696 "{\n");
1697 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1699 memento *m;
1700 int i;
1701 if (ctxt_idx > 0)
1702 r.write ("\n\n");
1704 r.write (" /* Replay of API calls for %s. */\n",
1705 r.get_identifier (contexts[ctxt_idx]));
1706 FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
1707 m->write_reproducer (r);
1709 r.write ("}\n");
1712 /* Copy the requested dumps within this context and all ancestors into
1713 OUT. */
1715 void
1716 recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
1718 if (m_parent_ctxt)
1719 m_parent_ctxt->get_all_requested_dumps (out);
1721 out->reserve (m_requested_dumps.length ());
1722 out->splice (m_requested_dumps);
1725 /* This is a pre-compilation check for the context (and any parents).
1727 Detect errors within the context, adding errors if any are found. */
1729 void
1730 recording::context::validate ()
1732 JIT_LOG_SCOPE (get_logger ());
1734 if (m_parent_ctxt)
1735 m_parent_ctxt->validate ();
1737 int i;
1738 function *fn;
1739 FOR_EACH_VEC_ELT (m_functions, i, fn)
1740 fn->validate ();
1743 /* The implementation of class gcc::jit::recording::memento. */
1745 /* Get a (const char *) debug description of the given memento, by
1746 calling the pure-virtual make_debug_string hook, caching the
1747 result.
1749 It is intended that this should only be called in debugging and
1750 error-handling paths, so this doesn't need to be particularly
1751 optimized. */
1753 const char *
1754 recording::memento::get_debug_string ()
1756 if (!m_debug_string)
1757 m_debug_string = make_debug_string ();
1758 return m_debug_string->c_str ();
1761 /* Default implementation of recording::memento::write_to_dump, writing
1762 an indented form of the memento's debug string to the dump. */
1764 void
1765 recording::memento::write_to_dump (dump &d)
1767 d.write(" %s\n", get_debug_string ());
1770 /* The implementation of class gcc::jit::recording::string. */
1772 /* Constructor for gcc::jit::recording::string::string, allocating a
1773 copy of the given text using new char[]. */
1775 recording::string::string (context *ctxt, const char *text)
1776 : memento (ctxt)
1778 m_len = strlen (text);
1779 m_buffer = new char[m_len + 1];
1780 strcpy (m_buffer, text);
1783 /* Destructor for gcc::jit::recording::string::string. */
1785 recording::string::~string ()
1787 delete[] m_buffer;
1790 /* Function for making gcc::jit::recording::string instances on a
1791 context via printf-style formatting.
1793 It is intended that this should only be called in debugging and
1794 error-handling paths, so this doesn't need to be particularly
1795 optimized, hence the double-copy of the string is acceptable. */
1797 recording::string *
1798 recording::string::from_printf (context *ctxt, const char *fmt, ...)
1800 int len;
1801 va_list ap;
1802 char *buf;
1803 recording::string *result;
1805 va_start (ap, fmt);
1806 len = vasprintf (&buf, fmt, ap);
1807 va_end (ap);
1809 if (buf == NULL || len < 0)
1811 ctxt->add_error (NULL, "malloc failure");
1812 return NULL;
1815 result = ctxt->new_string (buf);
1816 free (buf);
1817 return result;
1820 /* Implementation of recording::memento::make_debug_string for strings,
1821 wrapping the given string in quotes and escaping as necessary. */
1823 recording::string *
1824 recording::string::make_debug_string ()
1826 /* Hack to avoid infinite recursion into strings when logging all
1827 mementos: don't re-escape strings: */
1828 if (m_buffer[0] == '"')
1829 return this;
1831 /* Wrap in quotes and do escaping etc */
1833 size_t sz = (1 /* opening quote */
1834 + (m_len * 2) /* each char might get escaped */
1835 + 1 /* closing quote */
1836 + 1); /* nil termintator */
1837 char *tmp = new char[sz];
1838 size_t len = 0;
1840 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1841 APPEND('"'); /* opening quote */
1842 for (size_t i = 0; i < m_len ; i++)
1844 char ch = m_buffer[i];
1845 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
1846 APPEND('\\');
1847 APPEND(ch);
1849 APPEND('"'); /* closing quote */
1850 #undef APPEND
1851 tmp[len] = '\0'; /* nil termintator */
1853 string *result = m_ctxt->new_string (tmp);
1855 delete[] tmp;
1856 return result;
1859 /* Implementation of recording::memento::write_reproducer for strings. */
1861 void
1862 recording::string::write_reproducer (reproducer &)
1864 /* Empty. */
1867 /* The implementation of class gcc::jit::recording::location. */
1869 /* Implementation of recording::memento::replay_into for locations.
1871 Create a new playback::location and store it into the
1872 recording::location's m_playback_obj field. */
1874 void
1875 recording::location::replay_into (replayer *r)
1877 m_playback_obj = r->new_location (this,
1878 m_filename->c_str (),
1879 m_line,
1880 m_column);
1883 /* Implementation of recording::memento::make_debug_string for locations,
1884 turning them into the usual form:
1885 FILENAME:LINE:COLUMN
1886 like we do when emitting diagnostics. */
1888 recording::string *
1889 recording::location::make_debug_string ()
1891 return string::from_printf (m_ctxt,
1892 "%s:%i:%i",
1893 m_filename->c_str (), m_line, m_column);
1896 /* Implementation of recording::memento::write_reproducer for locations. */
1898 void
1899 recording::location::write_reproducer (reproducer &r)
1901 const char *id = r.make_identifier (this, "loc");
1902 r.write (" gcc_jit_location *%s =\n"
1903 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1904 " %s, /* const char *filename */\n"
1905 " %i, /* int line */\n"
1906 " %i);/* int column */\n",
1908 r.get_identifier (get_context ()),
1909 m_filename->get_debug_string (),
1910 m_line, m_column);
1913 /* The implementation of class gcc::jit::recording::type. */
1915 /* Given a type T, get the type T*.
1917 If this doesn't already exist, generate a new memento_of_get_pointer
1918 instance and add it to this type's context's list of mementos.
1920 Otherwise, use the cached type.
1922 Implements the post-error-checking part of
1923 gcc_jit_type_get_pointer. */
1925 recording::type *
1926 recording::type::get_pointer ()
1928 if (!m_pointer_to_this_type)
1930 m_pointer_to_this_type = new memento_of_get_pointer (this);
1931 m_ctxt->record (m_pointer_to_this_type);
1933 return m_pointer_to_this_type;
1936 /* Given a type T, get the type const T.
1938 Implements the post-error-checking part of
1939 gcc_jit_type_get_const. */
1941 recording::type *
1942 recording::type::get_const ()
1944 recording::type *result = new memento_of_get_const (this);
1945 m_ctxt->record (result);
1946 return result;
1949 /* Given a type T, get the type volatile T.
1951 Implements the post-error-checking part of
1952 gcc_jit_type_get_volatile. */
1954 recording::type *
1955 recording::type::get_volatile ()
1957 recording::type *result = new memento_of_get_volatile (this);
1958 m_ctxt->record (result);
1959 return result;
1962 const char *
1963 recording::type::access_as_type (reproducer &r)
1965 return r.get_identifier (this);
1968 /* Implementation of pure virtual hook recording::type::dereference for
1969 recording::memento_of_get_type. */
1971 recording::type *
1972 recording::memento_of_get_type::dereference ()
1974 switch (m_kind)
1976 default: gcc_unreachable ();
1978 case GCC_JIT_TYPE_VOID:
1979 return NULL;
1981 case GCC_JIT_TYPE_VOID_PTR:
1982 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
1984 case GCC_JIT_TYPE_BOOL:
1985 case GCC_JIT_TYPE_CHAR:
1986 case GCC_JIT_TYPE_SIGNED_CHAR:
1987 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1988 case GCC_JIT_TYPE_SHORT:
1989 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1990 case GCC_JIT_TYPE_INT:
1991 case GCC_JIT_TYPE_UNSIGNED_INT:
1992 case GCC_JIT_TYPE_LONG:
1993 case GCC_JIT_TYPE_UNSIGNED_LONG:
1994 case GCC_JIT_TYPE_LONG_LONG:
1995 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1996 case GCC_JIT_TYPE_FLOAT:
1997 case GCC_JIT_TYPE_DOUBLE:
1998 case GCC_JIT_TYPE_LONG_DOUBLE:
1999 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2000 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2001 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2002 /* Not a pointer: */
2003 return NULL;
2005 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2006 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
2008 case GCC_JIT_TYPE_SIZE_T:
2009 /* Not a pointer: */
2010 return NULL;
2012 case GCC_JIT_TYPE_FILE_PTR:
2013 /* Give the client code back an opaque "struct FILE". */
2014 return m_ctxt->get_opaque_FILE_type ();
2018 /* Implementation of pure virtual hook recording::type::is_int for
2019 recording::memento_of_get_type. */
2021 bool
2022 recording::memento_of_get_type::is_int () const
2024 switch (m_kind)
2026 default: gcc_unreachable ();
2028 case GCC_JIT_TYPE_VOID:
2029 return false;
2031 case GCC_JIT_TYPE_VOID_PTR:
2032 return false;
2034 case GCC_JIT_TYPE_BOOL:
2035 return false;
2037 case GCC_JIT_TYPE_CHAR:
2038 case GCC_JIT_TYPE_SIGNED_CHAR:
2039 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2040 case GCC_JIT_TYPE_SHORT:
2041 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2042 case GCC_JIT_TYPE_INT:
2043 case GCC_JIT_TYPE_UNSIGNED_INT:
2044 case GCC_JIT_TYPE_LONG:
2045 case GCC_JIT_TYPE_UNSIGNED_LONG:
2046 case GCC_JIT_TYPE_LONG_LONG:
2047 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2048 return true;
2050 case GCC_JIT_TYPE_FLOAT:
2051 case GCC_JIT_TYPE_DOUBLE:
2052 case GCC_JIT_TYPE_LONG_DOUBLE:
2053 return false;
2055 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2056 return false;
2058 case GCC_JIT_TYPE_SIZE_T:
2059 return true;
2061 case GCC_JIT_TYPE_FILE_PTR:
2062 return false;
2064 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2065 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2066 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2067 return false;
2071 /* Implementation of pure virtual hook recording::type::is_float for
2072 recording::memento_of_get_type. */
2074 bool
2075 recording::memento_of_get_type::is_float () const
2077 switch (m_kind)
2079 default: gcc_unreachable ();
2081 case GCC_JIT_TYPE_VOID:
2082 return false;
2084 case GCC_JIT_TYPE_VOID_PTR:
2085 return false;
2087 case GCC_JIT_TYPE_BOOL:
2088 return false;
2090 case GCC_JIT_TYPE_CHAR:
2091 case GCC_JIT_TYPE_SIGNED_CHAR:
2092 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2093 case GCC_JIT_TYPE_SHORT:
2094 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2095 case GCC_JIT_TYPE_INT:
2096 case GCC_JIT_TYPE_UNSIGNED_INT:
2097 case GCC_JIT_TYPE_LONG:
2098 case GCC_JIT_TYPE_UNSIGNED_LONG:
2099 case GCC_JIT_TYPE_LONG_LONG:
2100 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2101 return false;
2103 case GCC_JIT_TYPE_FLOAT:
2104 case GCC_JIT_TYPE_DOUBLE:
2105 case GCC_JIT_TYPE_LONG_DOUBLE:
2106 return true;
2108 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2109 return false;
2111 case GCC_JIT_TYPE_SIZE_T:
2112 return false;
2114 case GCC_JIT_TYPE_FILE_PTR:
2115 return false;
2117 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2118 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2119 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2120 return true;
2124 /* Implementation of pure virtual hook recording::type::is_bool for
2125 recording::memento_of_get_type. */
2127 bool
2128 recording::memento_of_get_type::is_bool () const
2130 switch (m_kind)
2132 default: gcc_unreachable ();
2134 case GCC_JIT_TYPE_VOID:
2135 return false;
2137 case GCC_JIT_TYPE_VOID_PTR:
2138 return false;
2140 case GCC_JIT_TYPE_BOOL:
2141 return true;
2143 case GCC_JIT_TYPE_CHAR:
2144 case GCC_JIT_TYPE_SIGNED_CHAR:
2145 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2146 case GCC_JIT_TYPE_SHORT:
2147 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2148 case GCC_JIT_TYPE_INT:
2149 case GCC_JIT_TYPE_UNSIGNED_INT:
2150 case GCC_JIT_TYPE_LONG:
2151 case GCC_JIT_TYPE_UNSIGNED_LONG:
2152 case GCC_JIT_TYPE_LONG_LONG:
2153 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2154 return false;
2156 case GCC_JIT_TYPE_FLOAT:
2157 case GCC_JIT_TYPE_DOUBLE:
2158 case GCC_JIT_TYPE_LONG_DOUBLE:
2159 return false;
2161 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2162 return false;
2164 case GCC_JIT_TYPE_SIZE_T:
2165 return false;
2167 case GCC_JIT_TYPE_FILE_PTR:
2168 return false;
2170 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2171 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2172 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2173 return false;
2177 /* Implementation of pure virtual hook recording::memento::replay_into
2178 for recording::memento_of_get_type. */
2180 void
2181 recording::memento_of_get_type::replay_into (replayer *r)
2183 set_playback_obj (r->get_type (m_kind));
2186 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2188 /* Descriptive strings for each of enum gcc_jit_types. */
2190 static const char * const get_type_strings[] = {
2191 "void", /* GCC_JIT_TYPE_VOID */
2192 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2194 "bool", /* GCC_JIT_TYPE_BOOL */
2196 "char", /* GCC_JIT_TYPE_CHAR */
2197 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2198 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2200 "short", /* GCC_JIT_TYPE_SHORT */
2201 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2203 "int", /* GCC_JIT_TYPE_INT */
2204 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2206 "long", /* GCC_JIT_TYPE_LONG */
2207 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2209 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2210 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2212 "float", /* GCC_JIT_TYPE_FLOAT */
2213 "double", /* GCC_JIT_TYPE_DOUBLE */
2214 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2216 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2218 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2220 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2222 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2223 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2224 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2228 /* Implementation of recording::memento::make_debug_string for
2229 results of get_type, using a simple table of type names. */
2231 recording::string *
2232 recording::memento_of_get_type::make_debug_string ()
2234 return m_ctxt->new_string (get_type_strings[m_kind]);
2237 static const char * const get_type_enum_strings[] = {
2238 "GCC_JIT_TYPE_VOID",
2239 "GCC_JIT_TYPE_VOID_PTR",
2240 "GCC_JIT_TYPE_BOOL",
2241 "GCC_JIT_TYPE_CHAR",
2242 "GCC_JIT_TYPE_SIGNED_CHAR",
2243 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2244 "GCC_JIT_TYPE_SHORT",
2245 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2246 "GCC_JIT_TYPE_INT",
2247 "GCC_JIT_TYPE_UNSIGNED_INT",
2248 "GCC_JIT_TYPE_LONG",
2249 "GCC_JIT_TYPE_UNSIGNED_LONG",
2250 "GCC_JIT_TYPE_LONG_LONG",
2251 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2252 "GCC_JIT_TYPE_FLOAT",
2253 "GCC_JIT_TYPE_DOUBLE",
2254 "GCC_JIT_TYPE_LONG_DOUBLE",
2255 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2256 "GCC_JIT_TYPE_SIZE_T",
2257 "GCC_JIT_TYPE_FILE_PTR",
2258 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2259 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2260 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2263 void
2264 recording::memento_of_get_type::write_reproducer (reproducer &r)
2266 const char *id = r.make_identifier (this, "type");
2267 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2269 r.get_identifier (get_context ()),
2270 get_type_enum_strings[m_kind]);
2273 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2275 /* Override of default implementation of
2276 recording::type::accepts_writes_from for get_pointer.
2278 Require a pointer type, and allowing writes to
2279 (const T *) from a (T*), but not the other way around. */
2281 bool
2282 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2284 /* Must be a pointer type: */
2285 type *rtype_points_to = rtype->is_pointer ();
2286 if (!rtype_points_to)
2287 return false;
2289 /* It's OK to assign to a (const T *) from a (T *). */
2290 return m_other_type->unqualified ()
2291 ->accepts_writes_from (rtype_points_to);
2294 /* Implementation of pure virtual hook recording::memento::replay_into
2295 for recording::memento_of_get_pointer. */
2297 void
2298 recording::memento_of_get_pointer::replay_into (replayer *)
2300 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2303 /* Implementation of recording::memento::make_debug_string for
2304 results of get_pointer, adding " *" to the underlying type,
2305 with special-casing to handle function pointer types. */
2307 recording::string *
2308 recording::memento_of_get_pointer::make_debug_string ()
2310 /* Special-case function pointer types, to put the "*" in parens between
2311 the return type and the params (for one level of dereferencing, at
2312 least). */
2313 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2314 return fn_type->make_debug_string_with_ptr ();
2316 return string::from_printf (m_ctxt,
2317 "%s *", m_other_type->get_debug_string ());
2320 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2322 void
2323 recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2325 /* We need to special-case function pointer types; see the notes in
2326 recording::function_type::write_deferred_reproducer. */
2327 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2329 fn_type->write_deferred_reproducer (r, this);
2330 return;
2333 const char *id = r.make_identifier (this, "type");
2334 r.write (" gcc_jit_type *%s =\n"
2335 " gcc_jit_type_get_pointer (%s);\n",
2337 r.get_identifier_as_type (m_other_type));
2340 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2342 /* Implementation of pure virtual hook recording::memento::replay_into
2343 for recording::memento_of_get_const. */
2345 void
2346 recording::memento_of_get_const::replay_into (replayer *)
2348 set_playback_obj (m_other_type->playback_type ()->get_const ());
2351 /* Implementation of recording::memento::make_debug_string for
2352 results of get_const, prepending "const ". */
2354 recording::string *
2355 recording::memento_of_get_const::make_debug_string ()
2357 return string::from_printf (m_ctxt,
2358 "const %s", m_other_type->get_debug_string ());
2361 /* Implementation of recording::memento::write_reproducer for const types. */
2363 void
2364 recording::memento_of_get_const::write_reproducer (reproducer &r)
2366 const char *id = r.make_identifier (this, "type");
2367 r.write (" gcc_jit_type *%s =\n"
2368 " gcc_jit_type_get_const (%s);\n",
2370 r.get_identifier_as_type (m_other_type));
2373 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2375 /* Implementation of pure virtual hook recording::memento::replay_into
2376 for recording::memento_of_get_volatile. */
2378 void
2379 recording::memento_of_get_volatile::replay_into (replayer *)
2381 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2384 /* Implementation of recording::memento::make_debug_string for
2385 results of get_volatile, prepending "volatile ". */
2387 recording::string *
2388 recording::memento_of_get_volatile::make_debug_string ()
2390 return string::from_printf (m_ctxt,
2391 "volatile %s", m_other_type->get_debug_string ());
2394 /* Implementation of recording::memento::write_reproducer for volatile
2395 types. */
2397 void
2398 recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2400 const char *id = r.make_identifier (this, "type");
2401 r.write (" gcc_jit_type *%s =\n"
2402 " gcc_jit_type_get_volatile (%s);\n",
2404 r.get_identifier_as_type (m_other_type));
2407 /* The implementation of class gcc::jit::recording::array_type */
2409 /* Implementation of pure virtual hook recording::type::dereference for
2410 recording::array_type. */
2412 recording::type *
2413 recording::array_type::dereference ()
2415 return m_element_type;
2418 /* Implementation of pure virtual hook recording::memento::replay_into
2419 for recording::array_type. */
2421 void
2422 recording::array_type::replay_into (replayer *r)
2424 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
2425 m_element_type->playback_type (),
2426 m_num_elements));
2429 /* Implementation of recording::memento::make_debug_string for
2430 results of new_array_type. */
2432 recording::string *
2433 recording::array_type::make_debug_string ()
2435 return string::from_printf (m_ctxt,
2436 "%s[%d]",
2437 m_element_type->get_debug_string (),
2438 m_num_elements);
2441 /* Implementation of recording::memento::write_reproducer for array
2442 types. */
2444 void
2445 recording::array_type::write_reproducer (reproducer &r)
2447 const char *id = r.make_identifier (this, "array_type");
2448 r.write (" gcc_jit_type *%s =\n"
2449 " gcc_jit_context_new_array_type (%s,\n"
2450 " %s, /* gcc_jit_location *loc */\n"
2451 " %s, /* gcc_jit_type *element_type */\n"
2452 " %i); /* int num_elements */\n",
2454 r.get_identifier (get_context ()),
2455 r.get_identifier (m_loc),
2456 r.get_identifier_as_type (m_element_type),
2457 m_num_elements);
2460 /* The implementation of class gcc::jit::recording::function_type */
2462 /* Constructor for gcc::jit::recording::function_type. */
2464 recording::function_type::function_type (context *ctxt,
2465 type *return_type,
2466 int num_params,
2467 type **param_types,
2468 int is_variadic)
2469 : type (ctxt),
2470 m_return_type (return_type),
2471 m_param_types (),
2472 m_is_variadic (is_variadic)
2474 for (int i = 0; i< num_params; i++)
2475 m_param_types.safe_push (param_types[i]);
2478 /* Implementation of pure virtual hook recording::type::dereference for
2479 recording::function_type. */
2481 recording::type *
2482 recording::function_type::dereference ()
2484 return NULL;
2487 /* Implementation of pure virtual hook recording::memento::replay_into
2488 for recording::function_type. */
2490 void
2491 recording::function_type::replay_into (replayer *r)
2493 /* Convert m_param_types to a vec of playback type. */
2494 auto_vec <playback::type *> param_types;
2495 int i;
2496 recording::type *type;
2497 param_types.create (m_param_types.length ());
2498 FOR_EACH_VEC_ELT (m_param_types, i, type)
2499 param_types.safe_push (type->playback_type ());
2501 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
2502 &param_types,
2503 m_is_variadic));
2506 /* Special-casing for make_debug_string for get_pointer results for
2507 handling (one level) of pointers to functions. */
2509 recording::string *
2510 recording::function_type::make_debug_string_with_ptr ()
2512 return make_debug_string_with ("(*) ");
2515 /* Implementation of recording::memento::make_debug_string for
2516 results of new_function_type. */
2518 recording::string *
2519 recording::function_type::make_debug_string ()
2521 return make_debug_string_with ("");
2524 /* Build a debug string representation of the form:
2526 RESULT_TYPE INSERT (PARAM_TYPES)
2528 for use when handling 0 and 1 level of indirection to this
2529 function type. */
2531 recording::string *
2532 recording::function_type::make_debug_string_with (const char *insert)
2534 /* First, build a buffer for the arguments. */
2535 /* Calculate length of said buffer. */
2536 size_t sz = 1; /* nil terminator */
2537 for (unsigned i = 0; i< m_param_types.length (); i++)
2539 sz += strlen (m_param_types[i]->get_debug_string ());
2540 sz += 2; /* ", " separator */
2542 if (m_is_variadic)
2543 sz += 5; /* ", ..." separator and ellipsis */
2545 /* Now allocate and populate the buffer. */
2546 char *argbuf = new char[sz];
2547 size_t len = 0;
2549 for (unsigned i = 0; i< m_param_types.length (); i++)
2551 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
2552 len += strlen (m_param_types[i]->get_debug_string ());
2553 if (i + 1 < m_param_types.length ())
2555 strcpy (argbuf + len, ", ");
2556 len += 2;
2559 if (m_is_variadic)
2561 if (m_param_types.length ())
2563 strcpy (argbuf + len, ", ");
2564 len += 2;
2566 strcpy (argbuf + len, "...");
2567 len += 3;
2569 argbuf[len] = '\0';
2571 /* ...and use it to get the string for the call as a whole. */
2572 string *result = string::from_printf (m_ctxt,
2573 "%s %s(%s)",
2574 m_return_type->get_debug_string (),
2575 insert,
2576 argbuf);
2578 delete[] argbuf;
2580 return result;
2583 /* Implementation of recording::memento::write_reproducer for function
2584 types. */
2586 void
2587 recording::function_type::write_reproducer (reproducer &)
2589 /* see notes below. */
2592 /* There's a get_pointer within context::new_function_ptr_type:
2593 the type received by client code isn't the memento for the
2594 function_type, but instead the result of get_pointer on it.
2596 Hence we can't directly write a reproducer that gives function_type.
2597 Instead we special-case things within get_pointer, detecting this
2598 case, calling the following function. */
2600 void
2601 recording::function_type::write_deferred_reproducer (reproducer &r,
2602 memento *ptr_type)
2604 gcc_assert (ptr_type);
2605 r.make_identifier (this, "function_type");
2606 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
2607 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
2608 r.write (" gcc_jit_type *%s[%i] = {\n",
2609 param_types_id,
2610 m_param_types.length ());
2611 int i;
2612 type *param_type;
2613 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2614 r.write (" %s,\n", r.get_identifier_as_type (param_type));
2615 r.write (" };\n");
2616 r.write (" gcc_jit_type *%s =\n"
2617 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2618 " %s, /* gcc_jit_location *loc */\n"
2619 " %s, /* gcc_jit_type *return_type */\n"
2620 " %i, /* int num_params */\n"
2621 " %s, /* gcc_jit_type **param_types */\n"
2622 " %i); /* int is_variadic */\n",
2623 ptr_id,
2624 r.get_identifier (get_context ()),
2625 "NULL", /* location is not stored */
2626 r.get_identifier_as_type (m_return_type),
2627 m_param_types.length (),
2628 param_types_id,
2629 m_is_variadic);
2632 /* The implementation of class gcc::jit::recording::field. */
2634 /* Implementation of pure virtual hook recording::memento::replay_into
2635 for recording::field. */
2637 void
2638 recording::field::replay_into (replayer *r)
2640 set_playback_obj (r->new_field (playback_location (r, m_loc),
2641 m_type->playback_type (),
2642 playback_string (m_name)));
2645 /* Override the default implementation of
2646 recording::memento::write_to_dump. Dump each field
2647 by dumping a line of the form:
2648 TYPE NAME;
2649 so that we can build up a struct/union field-byfield. */
2651 void
2652 recording::field::write_to_dump (dump &d)
2654 d.write (" %s %s;\n",
2655 m_type->get_debug_string (),
2656 m_name->c_str ());
2659 /* Implementation of recording::memento::make_debug_string for
2660 results of new_field. */
2662 recording::string *
2663 recording::field::make_debug_string ()
2665 return m_name;
2668 /* Implementation of recording::memento::write_reproducer for fields. */
2670 void
2671 recording::field::write_reproducer (reproducer &r)
2673 const char *id = r.make_identifier (this, "field");
2674 r.write(" gcc_jit_field *%s =\n"
2675 " gcc_jit_context_new_field (%s,\n"
2676 " %s, /* gcc_jit_location *loc */\n"
2677 " %s, /* gcc_jit_type *type, */\n"
2678 " %s); /* const char *name */\n",
2680 r.get_identifier (get_context ()),
2681 r.get_identifier (m_loc),
2682 r.get_identifier_as_type (m_type),
2683 m_name->get_debug_string ());
2686 /* The implementation of class gcc::jit::recording::compound_type */
2688 /* The constructor for gcc::jit::recording::compound_type. */
2690 recording::compound_type::compound_type (context *ctxt,
2691 location *loc,
2692 string *name)
2693 : type (ctxt),
2694 m_loc (loc),
2695 m_name (name),
2696 m_fields (NULL)
2700 /* Set the fields of a compound type.
2702 Implements the post-error-checking part of
2703 gcc_jit_struct_set_fields, and is also used by
2704 gcc_jit_context_new_union_type. */
2706 void
2707 recording::compound_type::set_fields (location *loc,
2708 int num_fields,
2709 field **field_array)
2711 m_loc = loc;
2712 gcc_assert (NULL == m_fields);
2714 m_fields = new fields (this, num_fields, field_array);
2715 m_ctxt->record (m_fields);
2718 /* Implementation of pure virtual hook recording::type::dereference for
2719 recording::compound_type. */
2721 recording::type *
2722 recording::compound_type::dereference ()
2724 return NULL; /* not a pointer */
2727 /* The implementation of class gcc::jit::recording::struct_. */
2729 /* The constructor for gcc::jit::recording::struct_. */
2731 recording::struct_::struct_ (context *ctxt,
2732 location *loc,
2733 string *name)
2734 : compound_type (ctxt, loc, name)
2738 /* Implementation of pure virtual hook recording::memento::replay_into
2739 for recording::struct_. */
2741 void
2742 recording::struct_::replay_into (replayer *r)
2744 set_playback_obj (
2745 r->new_compound_type (playback_location (r, get_loc ()),
2746 get_name ()->c_str (),
2747 true /* is_struct */));
2750 const char *
2751 recording::struct_::access_as_type (reproducer &r)
2753 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2754 r.get_identifier (this));
2757 /* Implementation of recording::memento::make_debug_string for
2758 structs. */
2760 recording::string *
2761 recording::struct_::make_debug_string ()
2763 return string::from_printf (m_ctxt,
2764 "struct %s", get_name ()->c_str ());
2767 void
2768 recording::struct_::write_reproducer (reproducer &r)
2770 const char *id = r.make_identifier (this, "struct");
2771 r.write (" gcc_jit_struct *%s =\n"
2772 " gcc_jit_context_new_opaque_struct (%s,\n"
2773 " %s, /* gcc_jit_location *loc */\n"
2774 " %s); /* const char *name */\n",
2776 r.get_identifier (get_context ()),
2777 r.get_identifier (get_loc ()),
2778 get_name ()->get_debug_string ());
2781 /* The implementation of class gcc::jit::recording::union_. */
2783 /* The constructor for gcc::jit::recording::union_. */
2785 recording::union_::union_ (context *ctxt,
2786 location *loc,
2787 string *name)
2788 : compound_type (ctxt, loc, name)
2792 /* Implementation of pure virtual hook recording::memento::replay_into
2793 for recording::union_. */
2795 void
2796 recording::union_::replay_into (replayer *r)
2798 set_playback_obj (
2799 r->new_compound_type (playback_location (r, get_loc ()),
2800 get_name ()->c_str (),
2801 false /* is_struct */));
2804 /* Implementation of recording::memento::make_debug_string for
2805 unions. */
2807 recording::string *
2808 recording::union_::make_debug_string ()
2810 return string::from_printf (m_ctxt,
2811 "union %s", get_name ()->c_str ());
2814 /* Implementation of recording::memento::write_reproducer for unions. */
2816 void
2817 recording::union_::write_reproducer (reproducer &r)
2819 const char *id = r.make_identifier (this, "union");
2821 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
2822 r.write (" gcc_jit_field *%s[%i] = {\n",
2823 fields_id,
2824 get_fields ()->length ());
2825 for (int i = 0; i < get_fields ()->length (); i++)
2826 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
2827 r.write (" };\n");
2829 r.write (" gcc_jit_type *%s =\n"
2830 " gcc_jit_context_new_union_type (%s,\n"
2831 " %s, /* gcc_jit_location *loc */\n"
2832 " %s, /* const char *name */\n"
2833 " %i, /* int num_fields */\n"
2834 " %s); /* gcc_jit_field **fields */\n",
2836 r.get_identifier (get_context ()),
2837 r.get_identifier (get_loc ()),
2838 get_name ()->get_debug_string (),
2839 get_fields ()->length (),
2840 fields_id);
2843 /* The implementation of class gcc::jit::recording::fields. */
2845 /* The constructor for gcc::jit::recording::fields. */
2847 recording::fields::fields (compound_type *struct_or_union,
2848 int num_fields,
2849 field **fields)
2850 : memento (struct_or_union->m_ctxt),
2851 m_struct_or_union (struct_or_union),
2852 m_fields ()
2854 for (int i = 0; i < num_fields; i++)
2856 gcc_assert (fields[i]->get_container () == NULL);
2857 fields[i]->set_container (m_struct_or_union);
2858 m_fields.safe_push (fields[i]);
2862 /* Implementation of pure virtual hook recording::memento::replay_into
2863 for recording::fields. */
2865 void
2866 recording::fields::replay_into (replayer *)
2868 auto_vec<playback::field *> playback_fields;
2869 playback_fields.create (m_fields.length ());
2870 for (unsigned i = 0; i < m_fields.length (); i++)
2871 playback_fields.safe_push (m_fields[i]->playback_field ());
2872 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
2875 /* Override the default implementation of
2876 recording::memento::write_to_dump by writing a union/struct
2877 declaration of this form:
2879 struct/union NAME {
2880 TYPE_1 NAME_1;
2881 TYPE_2 NAME_2;
2882 ....
2883 TYPE_N NAME_N;
2886 to the dump. */
2888 void
2889 recording::fields::write_to_dump (dump &d)
2891 int i;
2892 field *f;
2894 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
2895 FOR_EACH_VEC_ELT (m_fields, i, f)
2896 f->write_to_dump (d);
2897 d.write ("};\n");
2900 /* Implementation of recording::memento::write_reproducer for the fields
2901 subclass. */
2903 void
2904 recording::fields::write_reproducer (reproducer &r)
2906 if (m_struct_or_union)
2907 if (NULL == m_struct_or_union->dyn_cast_struct ())
2908 /* We have a union; the fields have already been written by
2909 union::write_reproducer. */
2910 return;
2912 const char *fields_id = r.make_identifier (this, "fields");
2913 r.write (" gcc_jit_field *%s[%i] = {\n",
2914 fields_id,
2915 m_fields.length ());
2916 int i;
2917 field *field;
2918 FOR_EACH_VEC_ELT (m_fields, i, field)
2919 r.write (" %s,\n", r.get_identifier (field));
2920 r.write (" };\n");
2922 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
2923 " %s, /* gcc_jit_location *loc */\n"
2924 " %i, /* int num_fields */\n"
2925 " %s); /* gcc_jit_field **fields */\n",
2926 r.get_identifier (m_struct_or_union),
2927 r.get_identifier ((memento *)NULL),
2928 m_fields.length (),
2929 fields_id);
2932 /* Implementation of recording::memento::make_debug_string for
2933 field tables. */
2935 recording::string *
2936 recording::fields::make_debug_string ()
2938 return string::from_printf (m_ctxt,
2939 "fields");
2942 /* The implementation of class gcc::jit::recording::rvalue. */
2944 /* Create a recording::access_field_rvalue instance and add it to
2945 the rvalue's context's list of mementos.
2947 Implements the post-error-checking part of
2948 gcc_jit_rvalue_access_field. */
2950 recording::rvalue *
2951 recording::rvalue::access_field (recording::location *loc,
2952 field *field)
2954 recording::rvalue *result =
2955 new access_field_rvalue (m_ctxt, loc, this, field);
2956 m_ctxt->record (result);
2957 return result;
2960 /* Create a recording::dereference_field_rvalue instance and add it to
2961 the rvalue's context's list of mementos.
2963 Implements the post-error-checking part of
2964 gcc_jit_rvalue_dereference_field. */
2966 recording::lvalue *
2967 recording::rvalue::dereference_field (recording::location *loc,
2968 field *field)
2970 recording::lvalue *result =
2971 new dereference_field_rvalue (m_ctxt, loc, this, field);
2972 m_ctxt->record (result);
2973 return result;
2976 /* Create a recording::dereference_rvalue instance and add it to the
2977 rvalue's context's list of mementos.
2979 Implements the post-error-checking part of
2980 gcc_jit_rvalue_dereference. */
2982 recording::lvalue *
2983 recording::rvalue::dereference (recording::location *loc)
2985 recording::lvalue *result =
2986 new dereference_rvalue (m_ctxt, loc, this);
2987 m_ctxt->record (result);
2988 return result;
2991 /* An rvalue visitor, for validating that every rvalue within an expression
2992 trees within "STMT" has the correct scope (e.g. no access to locals
2993 of a different function). */
2995 class rvalue_usage_validator : public recording::rvalue_visitor
2997 public:
2998 rvalue_usage_validator (const char *api_funcname,
2999 recording::context *ctxt,
3000 recording::statement *stmt);
3002 void
3003 visit (recording::rvalue *rvalue);
3005 private:
3006 const char *m_api_funcname;
3007 recording::context *m_ctxt;
3008 recording::statement *m_stmt;
3011 /* The trivial constructor for rvalue_usage_validator. */
3013 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
3014 recording::context *ctxt,
3015 recording::statement *stmt)
3016 : m_api_funcname (api_funcname),
3017 m_ctxt (ctxt),
3018 m_stmt (stmt)
3022 /* Verify that the given rvalue is in the correct scope. */
3024 void
3025 rvalue_usage_validator::visit (recording::rvalue *rvalue)
3027 gcc_assert (m_stmt->get_block ());
3028 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
3030 /* Most rvalues don't have a scope (only locals and params). */
3031 if (rvalue->get_scope ())
3033 if (rvalue->get_scope () != stmt_scope)
3034 m_ctxt->add_error
3035 (rvalue->get_loc (),
3036 "%s:"
3037 " rvalue %s (type: %s)"
3038 " has scope limited to function %s"
3039 " but was used within function %s"
3040 " (in statement: %s)",
3041 m_api_funcname,
3042 rvalue->get_debug_string (),
3043 rvalue->get_type ()->get_debug_string (),
3044 rvalue->get_scope ()->get_debug_string (),
3045 stmt_scope->get_debug_string (),
3046 m_stmt->get_debug_string ());
3048 else
3050 if (rvalue->dyn_cast_param ())
3051 m_ctxt->add_error
3052 (rvalue->get_loc (),
3053 "%s:"
3054 " param %s (type: %s)"
3055 " was used within function %s"
3056 " (in statement: %s)"
3057 " but is not associated with any function",
3058 m_api_funcname,
3059 rvalue->get_debug_string (),
3060 rvalue->get_type ()->get_debug_string (),
3061 stmt_scope->get_debug_string (),
3062 m_stmt->get_debug_string ());
3066 /* Verify that it's valid to use this rvalue (and all expressions
3067 in the tree below it) within the given statement.
3069 For example, we must reject attempts to use a local from one
3070 function within a different function here, or we'll get
3071 an ICE deep inside toplev::main. */
3073 void
3074 recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
3076 rvalue_usage_validator v (api_funcname,
3077 s->get_context (),
3080 /* Verify that it's OK to use this rvalue within s. */
3081 v.visit (this);
3083 /* Traverse the expression tree below "this", verifying all rvalues
3084 within it. */
3085 visit_children (&v);
3088 /* Set the scope of this rvalue to be the given function. This can only
3089 be done once on a given rvalue. */
3091 void
3092 recording::rvalue::set_scope (function *scope)
3094 gcc_assert (scope);
3095 gcc_assert (NULL == m_scope);
3096 m_scope = scope;
3100 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3101 themselves.
3102 Instances of rvalue don't need an upcast call. */
3104 const char *
3105 recording::rvalue::access_as_rvalue (reproducer &r)
3107 return r.get_identifier (this);
3110 /* Return a debug string for the given rvalue, wrapping it in parentheses
3111 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3112 stronger precedence that this rvalue's precedence.
3114 For example, given:
3116 MULT
3118 PLUS MINUS
3119 / \ / \
3120 A B C D
3122 we want to emit:
3124 (A + B) * (C - D)
3126 since MULT has strong precedence than PLUS and MINUS, whereas for:
3128 PLUS
3130 MULT DIVIDE
3131 / \ / \
3132 A B C D
3134 we can simply emit:
3136 A * B + C / D
3138 since PLUS has weaker precedence than MULT and DIVIDE. */
3140 const char *
3141 recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
3143 enum precedence this_prec = get_precedence ();
3145 /* If this_prec has stronger precedence than outer_prec, we don't
3146 need to wrap this in parens within the outer debug string.
3147 Stronger precedences occur earlier than weaker within the enum,
3148 so this is a less than test. Equal precedences don't need
3149 parentheses. */
3150 if (this_prec <= outer_prec)
3151 return get_debug_string();
3153 /* Otherwise, we need parentheses. */
3155 /* Lazily-build and cache m_parenthesized_string. */
3156 if (!m_parenthesized_string)
3158 const char *debug_string = get_debug_string ();
3159 m_parenthesized_string = string::from_printf (get_context (),
3160 "(%s)",
3161 debug_string);
3163 gcc_assert (m_parenthesized_string);
3164 return m_parenthesized_string->c_str ();
3168 /* The implementation of class gcc::jit::recording::lvalue. */
3170 /* Create a recording::new_access_field_of_lvalue instance and add it to
3171 the lvalue's context's list of mementos.
3173 Implements the post-error-checking part of
3174 gcc_jit_lvalue_access_field. */
3176 recording::lvalue *
3177 recording::lvalue::access_field (recording::location *loc,
3178 field *field)
3180 recording::lvalue *result =
3181 new access_field_of_lvalue (m_ctxt, loc, this, field);
3182 m_ctxt->record (result);
3183 return result;
3186 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3187 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3188 upcast call. */
3190 const char *
3191 recording::lvalue::access_as_rvalue (reproducer &r)
3193 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3194 r.get_identifier (this));
3197 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3198 Instances of lvalue don't need to be upcast. */
3200 const char *
3201 recording::lvalue::access_as_lvalue (reproducer &r)
3203 return r.get_identifier (this);
3206 /* Create a recording::get_address_of_lvalue instance and add it to
3207 the lvalue's context's list of mementos.
3209 Implements the post-error-checking part of
3210 gcc_jit_lvalue_get_address. */
3212 recording::rvalue *
3213 recording::lvalue::get_address (recording::location *loc)
3215 recording::rvalue *result =
3216 new get_address_of_lvalue (m_ctxt, loc, this);
3217 m_ctxt->record (result);
3218 return result;
3221 /* The implementation of class gcc::jit::recording::param. */
3223 /* Implementation of pure virtual hook recording::memento::replay_into
3224 for recording::param. */
3226 void
3227 recording::param::replay_into (replayer *r)
3229 set_playback_obj (r->new_param (playback_location (r, m_loc),
3230 m_type->playback_type (),
3231 m_name->c_str ()));
3234 /* Implementation of recording::rvalue::access_as_rvalue for params.
3235 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3236 upcast call. */
3238 const char *
3239 recording::param::access_as_rvalue (reproducer &r)
3241 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3242 r.get_identifier (this));
3245 /* Implementation of recording::lvalue::access_as_lvalue for params.
3246 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3247 upcast call. */
3249 const char *
3250 recording::param::access_as_lvalue (reproducer &r)
3252 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3253 r.get_identifier (this));
3256 /* Implementation of recording::memento::write_reproducer for params. */
3258 void
3259 recording::param::write_reproducer (reproducer &r)
3261 const char *id = r.make_identifier (this, "param");
3262 r.write (" gcc_jit_param *%s =\n"
3263 " gcc_jit_context_new_param (%s,\n"
3264 " %s, /* gcc_jit_location *loc */\n"
3265 " %s, /*gcc_jit_type *type */\n"
3266 " %s); /* const char *name */\n",
3268 r.get_identifier (get_context ()),
3269 r.get_identifier (m_loc),
3270 r.get_identifier_as_type (m_type),
3271 m_name->get_debug_string ());
3274 /* The implementation of class gcc::jit::recording::function. */
3276 /* gcc::jit::recording::function's constructor. */
3278 recording::function::function (context *ctxt,
3279 recording::location *loc,
3280 enum gcc_jit_function_kind kind,
3281 type *return_type,
3282 recording::string *name,
3283 int num_params,
3284 recording::param **params,
3285 int is_variadic,
3286 enum built_in_function builtin_id)
3287 : memento (ctxt),
3288 m_loc (loc),
3289 m_kind (kind),
3290 m_return_type (return_type),
3291 m_name (name),
3292 m_params (),
3293 m_is_variadic (is_variadic),
3294 m_builtin_id (builtin_id),
3295 m_locals (),
3296 m_blocks ()
3298 for (int i = 0; i< num_params; i++)
3300 param *param = params[i];
3301 gcc_assert (param);
3303 /* Associate each param with this function.
3305 Verify that the param doesn't already have a function. */
3306 if (param->get_scope ())
3308 /* We've already rejected attempts to reuse a param between
3309 different functions (within gcc_jit_context_new_function), so
3310 if the param *does* already have a function, it must be being
3311 reused within the params array for this function. We must
3312 produce an error for this reuse (blocking the compile), since
3313 otherwise we'd have an ICE later on. */
3314 gcc_assert (this == param->get_scope ());
3315 ctxt->add_error
3316 (loc,
3317 "gcc_jit_context_new_function:"
3318 " parameter %s (type: %s)"
3319 " is used more than once when creating function %s",
3320 param->get_debug_string (),
3321 param->get_type ()->get_debug_string (),
3322 name->c_str ());
3324 else
3326 /* The normal, non-error case: associate this function with the
3327 param. */
3328 param->set_scope (this);
3331 m_params.safe_push (param);
3335 /* Implementation of pure virtual hook recording::memento::replay_into
3336 for recording::function. */
3338 void
3339 recording::function::replay_into (replayer *r)
3341 /* Convert m_params to a vec of playback param. */
3342 auto_vec <playback::param *> params;
3343 int i;
3344 recording::param *param;
3345 params.create (m_params.length ());
3346 FOR_EACH_VEC_ELT (m_params, i, param)
3347 params.safe_push (param->playback_param ());
3349 set_playback_obj (r->new_function (playback_location (r, m_loc),
3350 m_kind,
3351 m_return_type->playback_type (),
3352 m_name->c_str (),
3353 &params,
3354 m_is_variadic,
3355 m_builtin_id));
3358 /* Create a recording::local instance and add it to
3359 the functions's context's list of mementos, and to the function's
3360 list of locals.
3362 Implements the post-error-checking part of
3363 gcc_jit_function_new_local. */
3365 recording::lvalue *
3366 recording::function::new_local (recording::location *loc,
3367 type *type,
3368 const char *name)
3370 local *result = new local (this, loc, type, new_string (name));
3371 m_ctxt->record (result);
3372 m_locals.safe_push (result);
3373 return result;
3376 /* Create a recording::block instance and add it to
3377 the functions's context's list of mementos, and to the function's
3378 list of blocks.
3380 Implements the post-error-checking part of
3381 gcc_jit_function_new_block. */
3383 recording::block*
3384 recording::function::new_block (const char *name)
3386 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
3388 recording::block *result =
3389 new recording::block (this, m_blocks.length (), new_string (name));
3390 m_ctxt->record (result);
3391 m_blocks.safe_push (result);
3392 return result;
3395 /* Override the default implementation of
3396 recording::memento::write_to_dump by dumping a C-like
3397 representation of the function; either like a prototype
3398 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3399 all other kinds of function. */
3401 void
3402 recording::function::write_to_dump (dump &d)
3404 switch (m_kind)
3406 default: gcc_unreachable ();
3407 case GCC_JIT_FUNCTION_EXPORTED:
3408 case GCC_JIT_FUNCTION_IMPORTED:
3409 d.write ("extern ");
3410 break;
3411 case GCC_JIT_FUNCTION_INTERNAL:
3412 d.write ("static ");
3413 break;
3414 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
3415 d.write ("static inline ");
3416 break;
3418 d.write ("%s\n", m_return_type->get_debug_string ());
3420 if (d.update_locations ())
3421 m_loc = d.make_location ();
3423 d.write ("%s (", get_debug_string ());
3425 int i;
3426 recording::param *param;
3427 FOR_EACH_VEC_ELT (m_params, i, param)
3429 if (i > 0)
3430 d.write (", ");
3431 d.write ("%s %s",
3432 param->get_type ()->get_debug_string (),
3433 param->get_debug_string ());
3435 d.write (")");
3436 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
3438 d.write ("; /* (imported) */\n\n");
3440 else
3442 int i;
3443 local *var = NULL;
3444 block *b;
3445 d.write ("\n{\n");
3447 /* Write locals: */
3448 FOR_EACH_VEC_ELT (m_locals, i, var)
3449 var->write_to_dump (d);
3450 if (m_locals.length ())
3451 d.write ("\n");
3453 /* Write each block: */
3454 FOR_EACH_VEC_ELT (m_blocks, i, b)
3456 if (i > 0)
3457 d.write ("\n");
3458 b->write_to_dump (d);
3461 d.write ("}\n\n");
3465 /* Pre-compilation validation of a function, for those things we can't
3466 check until the context is (supposedly) fully-populated. */
3468 void
3469 recording::function::validate ()
3471 /* Complain about empty functions with non-void return type. */
3472 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
3473 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
3474 if (0 == m_blocks.length ())
3475 m_ctxt->add_error (m_loc,
3476 "function %s returns non-void (type: %s)"
3477 " but has no blocks",
3478 get_debug_string (),
3479 m_return_type->get_debug_string ());
3481 /* Check that all blocks are terminated. */
3482 int num_invalid_blocks = 0;
3484 int i;
3485 block *b;
3487 FOR_EACH_VEC_ELT (m_blocks, i, b)
3488 if (!b->validate ())
3489 num_invalid_blocks++;
3492 /* Check that all blocks are reachable. */
3493 if (!m_ctxt->get_inner_bool_option
3494 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
3495 && m_blocks.length () > 0 && 0 == num_invalid_blocks)
3497 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3498 flag, starting at the initial block. */
3499 auto_vec<block *> worklist (m_blocks.length ());
3500 worklist.safe_push (m_blocks[0]);
3501 while (worklist.length () > 0)
3503 block *b = worklist.pop ();
3504 b->m_is_reachable = true;
3506 /* Add successor blocks that aren't yet marked to the worklist. */
3507 /* We checked that each block has a terminating statement above . */
3508 block *next1, *next2;
3509 int n = b->get_successor_blocks (&next1, &next2);
3510 switch (n)
3512 default:
3513 gcc_unreachable ();
3514 case 2:
3515 if (!next2->m_is_reachable)
3516 worklist.safe_push (next2);
3517 /* fallthrough */
3518 case 1:
3519 if (!next1->m_is_reachable)
3520 worklist.safe_push (next1);
3521 break;
3522 case 0:
3523 break;
3527 /* Now complain about any blocks that haven't been marked. */
3529 int i;
3530 block *b;
3531 FOR_EACH_VEC_ELT (m_blocks, i, b)
3532 if (!b->m_is_reachable)
3533 m_ctxt->add_error (b->get_loc (),
3534 "unreachable block: %s",
3535 b->get_debug_string ());
3540 /* Implements the post-error-checking part of
3541 gcc_jit_function_dump_to_dot. */
3543 void
3544 recording::function::dump_to_dot (const char *path)
3546 FILE *fp = fopen (path, "w");
3547 if (!fp)
3548 return;
3550 pretty_printer the_pp;
3551 the_pp.buffer->stream = fp;
3553 pretty_printer *pp = &the_pp;
3555 pp_printf (pp,
3556 "digraph %s {\n", get_debug_string ());
3558 /* Blocks: */
3560 int i;
3561 block *b;
3562 FOR_EACH_VEC_ELT (m_blocks, i, b)
3563 b->dump_to_dot (pp);
3566 /* Edges: */
3568 int i;
3569 block *b;
3570 FOR_EACH_VEC_ELT (m_blocks, i, b)
3571 b->dump_edges_to_dot (pp);
3574 pp_printf (pp, "}\n");
3575 pp_flush (pp);
3576 fclose (fp);
3579 /* Implementation of recording::memento::make_debug_string for
3580 functions. */
3582 recording::string *
3583 recording::function::make_debug_string ()
3585 return m_name;
3588 /* A table of enum gcc_jit_function_kind values expressed in string
3589 form. */
3591 static const char * const names_of_function_kinds[] = {
3592 "GCC_JIT_FUNCTION_EXPORTED",
3593 "GCC_JIT_FUNCTION_INTERNAL",
3594 "GCC_JIT_FUNCTION_IMPORTED",
3595 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3598 /* Implementation of recording::memento::write_reproducer for functions. */
3600 void
3601 recording::function::write_reproducer (reproducer &r)
3603 const char *id = r.make_identifier (this, "func");
3605 if (m_builtin_id)
3607 r.write (" gcc_jit_function *%s =\n"
3608 " gcc_jit_context_get_builtin_function (%s,\n"
3609 " %s);\n",
3611 r.get_identifier (get_context ()),
3612 m_name->get_debug_string ());
3613 return;
3615 const char *params_id = r.make_tmp_identifier ("params_for", this);
3616 r.write (" gcc_jit_param *%s[%i] = {\n",
3617 params_id,
3618 m_params.length ());
3619 int i;
3620 param *param;
3621 FOR_EACH_VEC_ELT (m_params, i, param)
3622 r.write (" %s,\n", r.get_identifier (param));
3623 r.write (" };\n");
3624 r.write (" gcc_jit_function *%s =\n"
3625 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3626 " %s, /* gcc_jit_location *loc */\n"
3627 " %s, /* enum gcc_jit_function_kind kind */\n"
3628 " %s, /* gcc_jit_type *return_type */\n"
3629 " %s, /* const char *name */\n"
3630 " %i, /* int num_params */\n"
3631 " %s, /* gcc_jit_param **params */\n"
3632 " %i); /* int is_variadic */\n",
3634 r.get_identifier (get_context ()),
3635 r.get_identifier (m_loc),
3636 names_of_function_kinds[m_kind],
3637 r.get_identifier_as_type (m_return_type),
3638 m_name->get_debug_string (),
3639 m_params.length (),
3640 params_id,
3641 m_is_variadic);
3645 /* The implementation of class gcc::jit::recording::block. */
3647 /* Create a recording::eval instance and add it to
3648 the block's context's list of mementos, and to the block's
3649 list of statements.
3651 Implements the heart of gcc_jit_block_add_eval. */
3653 recording::statement *
3654 recording::block::add_eval (recording::location *loc,
3655 recording::rvalue *rvalue)
3657 statement *result = new eval (this, loc, rvalue);
3658 m_ctxt->record (result);
3659 m_statements.safe_push (result);
3660 return result;
3663 /* Create a recording::assignment instance and add it to
3664 the block's context's list of mementos, and to the block's
3665 list of statements.
3667 Implements the heart of gcc_jit_block_add_assignment. */
3669 recording::statement *
3670 recording::block::add_assignment (recording::location *loc,
3671 recording::lvalue *lvalue,
3672 recording::rvalue *rvalue)
3674 statement *result = new assignment (this, loc, lvalue, rvalue);
3675 m_ctxt->record (result);
3676 m_statements.safe_push (result);
3677 return result;
3680 /* Create a recording::assignment_op instance and add it to
3681 the block's context's list of mementos, and to the block's
3682 list of statements.
3684 Implements the heart of gcc_jit_block_add_assignment_op. */
3686 recording::statement *
3687 recording::block::add_assignment_op (recording::location *loc,
3688 recording::lvalue *lvalue,
3689 enum gcc_jit_binary_op op,
3690 recording::rvalue *rvalue)
3692 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
3693 m_ctxt->record (result);
3694 m_statements.safe_push (result);
3695 return result;
3698 /* Create a recording::comment instance and add it to
3699 the block's context's list of mementos, and to the block's
3700 list of statements.
3702 Implements the heart of gcc_jit_block_add_comment. */
3704 recording::statement *
3705 recording::block::add_comment (recording::location *loc,
3706 const char *text)
3708 statement *result = new comment (this, loc, new_string (text));
3709 m_ctxt->record (result);
3710 m_statements.safe_push (result);
3711 return result;
3714 /* Create a recording::end_with_conditional instance and add it to
3715 the block's context's list of mementos, and to the block's
3716 list of statements.
3718 Implements the heart of gcc_jit_block_end_with_conditional. */
3720 recording::statement *
3721 recording::block::end_with_conditional (recording::location *loc,
3722 recording::rvalue *boolval,
3723 recording::block *on_true,
3724 recording::block *on_false)
3726 statement *result = new conditional (this, loc, boolval, on_true, on_false);
3727 m_ctxt->record (result);
3728 m_statements.safe_push (result);
3729 m_has_been_terminated = true;
3730 return result;
3733 /* Create a recording::end_with_jump instance and add it to
3734 the block's context's list of mementos, and to the block's
3735 list of statements.
3737 Implements the heart of gcc_jit_block_end_with_jump. */
3739 recording::statement *
3740 recording::block::end_with_jump (recording::location *loc,
3741 recording::block *target)
3743 statement *result = new jump (this, loc, target);
3744 m_ctxt->record (result);
3745 m_statements.safe_push (result);
3746 m_has_been_terminated = true;
3747 return result;
3750 /* Create a recording::end_with_return instance and add it to
3751 the block's context's list of mementos, and to the block's
3752 list of statements.
3754 Implements the post-error-checking parts of
3755 gcc_jit_block_end_with_return and
3756 gcc_jit_block_end_with_void_return. */
3758 recording::statement *
3759 recording::block::end_with_return (recording::location *loc,
3760 recording::rvalue *rvalue)
3762 /* This is used by both gcc_jit_function_add_return and
3763 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3764 the former and NULL for the latter. */
3765 statement *result = new return_ (this, loc, rvalue);
3766 m_ctxt->record (result);
3767 m_statements.safe_push (result);
3768 m_has_been_terminated = true;
3769 return result;
3772 /* Override the default implementation of
3773 recording::memento::write_to_dump for blocks by writing
3774 an unindented block name as a label, followed by the indented
3775 statements:
3777 BLOCK_NAME:
3778 STATEMENT_1;
3779 STATEMENT_2;
3781 STATEMENT_N; */
3783 void
3784 recording::block::write_to_dump (dump &d)
3786 d.write ("%s:\n", get_debug_string ());
3788 int i;
3789 statement *s;
3790 FOR_EACH_VEC_ELT (m_statements, i, s)
3791 s->write_to_dump (d);
3794 /* Validate a block by ensuring that it has been terminated. */
3796 bool
3797 recording::block::validate ()
3799 /* Check for termination. */
3800 if (!has_been_terminated ())
3802 statement *stmt = get_last_statement ();
3803 location *loc = stmt ? stmt->get_loc () : NULL;
3804 m_func->get_context ()->add_error (loc,
3805 "unterminated block in %s: %s",
3806 m_func->get_debug_string (),
3807 get_debug_string ());
3808 return false;
3811 return true;
3814 /* Get the source-location of a block by using that of the first
3815 statement within it, if any. */
3817 recording::location *
3818 recording::block::get_loc () const
3820 recording::statement *stmt = get_first_statement ();
3821 if (stmt)
3822 return stmt->get_loc ();
3823 else
3824 return NULL;
3827 /* Get the first statement within a block, if any. */
3829 recording::statement *
3830 recording::block::get_first_statement () const
3832 if (m_statements.length ())
3833 return m_statements[0];
3834 else
3835 return NULL;
3838 /* Get the last statement within a block, if any. */
3840 recording::statement *
3841 recording::block::get_last_statement () const
3843 if (m_statements.length ())
3844 return m_statements[m_statements.length () - 1];
3845 else
3846 return NULL;
3849 /* Assuming that this block has been terminated, get the number of
3850 successor blocks, which will be 0, 1 or 2, for return, unconditional
3851 jump, and conditional jump respectively.
3852 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
3853 is written to NEXT1, and the second (if any) to NEXT2.
3855 Used when validating functions, and when dumping dot representations
3856 of them. */
3859 recording::block::get_successor_blocks (block **next1, block **next2) const
3861 gcc_assert (m_has_been_terminated);
3862 gcc_assert (next1);
3863 gcc_assert (next2);
3864 statement *last_statement = get_last_statement ();
3865 gcc_assert (last_statement);
3866 return last_statement->get_successor_blocks (next1, next2);
3869 /* Implementation of pure virtual hook recording::memento::replay_into
3870 for recording::block. */
3872 void
3873 recording::block::replay_into (replayer *)
3875 set_playback_obj (m_func->playback_function ()
3876 ->new_block (playback_string (m_name)));
3879 /* Implementation of recording::memento::make_debug_string for
3880 blocks. */
3882 recording::string *
3883 recording::block::make_debug_string ()
3885 if (m_name)
3886 return m_name;
3887 else
3888 return string::from_printf (m_ctxt,
3889 "<UNNAMED BLOCK %p>",
3890 (void *)this);
3893 /* Implementation of recording::memento::write_reproducer for blocks. */
3895 void
3896 recording::block::write_reproducer (reproducer &r)
3898 const char *id = r.make_identifier (this, "block");
3899 r.write (" gcc_jit_block *%s =\n"
3900 " gcc_jit_function_new_block (%s, %s);\n",
3902 r.get_identifier (m_func),
3903 m_name ? m_name->get_debug_string () : "NULL");
3906 /* Dump a block in graphviz form into PP, capturing the block name (if
3907 any) and the statements. */
3909 void
3910 recording::block::dump_to_dot (pretty_printer *pp)
3912 pp_printf (pp,
3913 ("\tblock_%d "
3914 "[shape=record,style=filled,fillcolor=white,label=\"{"),
3915 m_index);
3916 pp_write_text_to_stream (pp);
3917 if (m_name)
3919 pp_string (pp, m_name->c_str ());
3920 pp_string (pp, ":");
3921 pp_newline (pp);
3922 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3925 int i;
3926 statement *s;
3927 FOR_EACH_VEC_ELT (m_statements, i, s)
3929 pp_string (pp, s->get_debug_string ());
3930 pp_newline (pp);
3931 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3934 pp_printf (pp,
3935 "}\"];\n\n");
3936 pp_flush (pp);
3939 /* Dump the out-edges of the block in graphviz form into PP. */
3941 void
3942 recording::block::dump_edges_to_dot (pretty_printer *pp)
3944 block *next[2];
3945 int num_succs = get_successor_blocks (&next[0], &next[1]);
3946 for (int i = 0; i < num_succs; i++)
3947 pp_printf (pp,
3948 "\tblock_%d:s -> block_%d:n;\n",
3949 m_index, next[i]->m_index);
3952 /* The implementation of class gcc::jit::recording::global. */
3954 /* Implementation of pure virtual hook recording::memento::replay_into
3955 for recording::global. */
3957 void
3958 recording::global::replay_into (replayer *r)
3960 set_playback_obj (r->new_global (playback_location (r, m_loc),
3961 m_kind,
3962 m_type->playback_type (),
3963 playback_string (m_name)));
3966 /* Override the default implementation of
3967 recording::memento::write_to_dump for globals.
3968 This will be of the form:
3970 GCC_JIT_GLOBAL_EXPORTED:
3971 "TYPE NAME;"
3972 e.g. "int foo;"
3974 GCC_JIT_GLOBAL_INTERNAL:
3975 "static TYPE NAME;"
3976 e.g. "static int foo;"
3978 GCC_JIT_GLOBAL_IMPORTED:
3979 "extern TYPE NAME;"
3980 e.g. "extern int foo;"
3982 These are written to the top of the dump by
3983 recording::context::dump_to_file. */
3985 void
3986 recording::global::write_to_dump (dump &d)
3988 if (d.update_locations ())
3989 m_loc = d.make_location ();
3991 switch (m_kind)
3993 default:
3994 gcc_unreachable ();
3996 case GCC_JIT_GLOBAL_EXPORTED:
3997 break;
3999 case GCC_JIT_GLOBAL_INTERNAL:
4000 d.write ("static ");
4001 break;
4003 case GCC_JIT_GLOBAL_IMPORTED:
4004 d.write ("extern ");
4005 break;
4007 d.write ("%s %s;\n",
4008 m_type->get_debug_string (),
4009 get_debug_string ());
4012 /* A table of enum gcc_jit_global_kind values expressed in string
4013 form. */
4015 static const char * const global_kind_reproducer_strings[] = {
4016 "GCC_JIT_GLOBAL_EXPORTED",
4017 "GCC_JIT_GLOBAL_INTERNAL",
4018 "GCC_JIT_GLOBAL_IMPORTED"
4021 /* Implementation of recording::memento::write_reproducer for globals. */
4023 void
4024 recording::global::write_reproducer (reproducer &r)
4026 const char *id = r.make_identifier (this, "block");
4027 r.write (" gcc_jit_lvalue *%s =\n"
4028 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4029 " %s, /* gcc_jit_location *loc */\n"
4030 " %s, /* enum gcc_jit_global_kind kind */\n"
4031 " %s, /* gcc_jit_type *type */\n"
4032 " %s); /* const char *name */\n",
4034 r.get_identifier (get_context ()),
4035 r.get_identifier (m_loc),
4036 global_kind_reproducer_strings[m_kind],
4037 r.get_identifier_as_type (get_type ()),
4038 m_name->get_debug_string ());
4041 /* The implementation of the various const-handling classes:
4042 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4044 /* Explicit specialization of the various mementos we're interested in. */
4045 template class recording::memento_of_new_rvalue_from_const <int>;
4046 template class recording::memento_of_new_rvalue_from_const <long>;
4047 template class recording::memento_of_new_rvalue_from_const <double>;
4048 template class recording::memento_of_new_rvalue_from_const <void *>;
4050 /* Implementation of the pure virtual hook recording::memento::replay_into
4051 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4053 template <typename HOST_TYPE>
4054 void
4055 recording::
4056 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
4058 set_playback_obj
4059 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
4060 m_value));
4063 /* The make_debug_string and write_reproducer methods vary between the
4064 various
4065 memento_of_new_rvalue_from_const <HOST_TYPE>
4066 classes, so we explicitly write specializations of them.
4068 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4069 namespaces are written out explicitly, which is why most of this file
4070 doesn't abbreviate things by entering the "recording" namespace.
4072 However, these specializations are required to be in the same namespace
4073 as the template, hence we now have to enter the gcc::jit::recording
4074 namespace. */
4076 namespace recording
4079 /* The make_debug_string specialization for <int>, which renders it as
4080 (TARGET_TYPE)LITERAL
4081 e.g.
4082 "(int)42". */
4084 template <>
4085 string *
4086 memento_of_new_rvalue_from_const <int>::make_debug_string ()
4088 return string::from_printf (m_ctxt,
4089 "(%s)%i",
4090 m_type->get_debug_string (),
4091 m_value);
4094 /* The write_reproducer specialization for <int>. */
4096 template <>
4097 void
4098 memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
4100 const char *id = r.make_identifier (this, "rvalue");
4101 r.write (" gcc_jit_rvalue *%s =\n"
4102 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4103 " %s, /* gcc_jit_type *numeric_type */\n"
4104 " %i); /* int value */\n",
4106 r.get_identifier (get_context ()),
4107 r.get_identifier_as_type (m_type),
4108 m_value);
4111 /* The make_debug_string specialization for <long>, rendering it as
4112 (TARGET_TYPE)LITERAL
4113 e.g.
4114 "(long)42". */
4116 template <>
4117 string *
4118 memento_of_new_rvalue_from_const <long>::make_debug_string ()
4120 return string::from_printf (m_ctxt,
4121 "(%s)%li",
4122 m_type->get_debug_string (),
4123 m_value);
4126 /* The write_reproducer specialization for <long>. */
4128 template <>
4129 void
4130 recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
4132 const char *id = r.make_identifier (this, "rvalue");
4134 /* We have to special-case LONG_MIN, since e.g.
4135 -9223372036854775808L
4136 is parsed as
4137 -(9223372036854775808L)
4138 and hence we'd get:
4139 error: integer constant is so large that it is unsigned [-Werror]
4140 Workaround this by writing (LONG_MIN + 1) - 1. */
4141 if (m_value == LONG_MIN)
4143 r.write (" gcc_jit_rvalue *%s =\n"
4144 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4145 " %s, /* gcc_jit_type *numeric_type */\n"
4146 " %ldL - 1); /* long value */\n",
4148 r.get_identifier (get_context ()),
4149 r.get_identifier_as_type (m_type),
4150 m_value + 1);;
4151 return;
4154 r.write (" gcc_jit_rvalue *%s =\n"
4155 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4156 " %s, /* gcc_jit_type *numeric_type */\n"
4157 " %ldL); /* long value */\n",
4159 r.get_identifier (get_context ()),
4160 r.get_identifier_as_type (m_type),
4161 m_value);
4164 /* The make_debug_string specialization for <double>, rendering it as
4165 (TARGET_TYPE)LITERAL
4166 e.g.
4167 "(float)42.0". */
4169 template <>
4170 string *
4171 memento_of_new_rvalue_from_const <double>::make_debug_string ()
4173 return string::from_printf (m_ctxt,
4174 "(%s)%f",
4175 m_type->get_debug_string (),
4176 m_value);
4179 /* The write_reproducer specialization for <double>. */
4181 template <>
4182 void
4183 recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
4185 const char *id = r.make_identifier (this, "rvalue");
4186 r.write (" gcc_jit_rvalue *%s =\n"
4187 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4188 " %s, /* gcc_jit_type *numeric_type */\n"
4189 " %f); /* double value */\n",
4191 r.get_identifier (get_context ()),
4192 r.get_identifier_as_type (m_type),
4193 m_value);
4196 /* The make_debug_string specialization for <void *>, rendering it as
4197 (TARGET_TYPE)HEX
4198 e.g.
4199 "(int *)0xdeadbeef"
4201 Zero is rendered as NULL e.g.
4202 "(int *)NULL". */
4204 template <>
4205 string *
4206 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
4208 if (m_value != NULL)
4209 return string::from_printf (m_ctxt,
4210 "(%s)%p",
4211 m_type->get_debug_string (), m_value);
4212 else
4213 return string::from_printf (m_ctxt,
4214 "(%s)NULL",
4215 m_type->get_debug_string ());
4218 /* Implementation of recording::memento::write_reproducer for <void *>
4219 values. */
4221 template <>
4222 void
4223 memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
4225 const char *id = r.make_identifier (this, "rvalue");
4226 if (m_value)
4227 r.write (" gcc_jit_rvalue *%s =\n"
4228 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4229 " %s, /* gcc_jit_type *pointer_type */\n"
4230 " (void *)%p); /* void *value */\n",
4232 r.get_identifier (get_context ()),
4233 r.get_identifier_as_type (m_type),
4234 m_value);
4235 else
4236 r.write (" gcc_jit_rvalue *%s =\n"
4237 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4238 " %s); /* gcc_jit_type *pointer_type */\n",
4240 r.get_identifier (get_context ()),
4241 r.get_identifier_as_type (m_type));
4244 /* We're done specializing make_debug_string and write_reproducer, so we
4245 can exit the gcc::jit::recording namespace. */
4247 } // namespace recording
4249 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4251 /* Implementation of pure virtual hook recording::memento::replay_into
4252 for recording::memento_of_new_string_literal. */
4254 void
4255 recording::memento_of_new_string_literal::replay_into (replayer *r)
4257 set_playback_obj (r->new_string_literal (m_value->c_str ()));
4260 /* Implementation of recording::memento::make_debug_string for
4261 string literals. */
4263 recording::string *
4264 recording::memento_of_new_string_literal::make_debug_string ()
4266 return string::from_printf (m_ctxt,
4267 "%s",
4268 m_value->get_debug_string ());
4271 /* Implementation of recording::memento::write_reproducer for string literal
4272 values. */
4274 void
4275 recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
4277 const char *id = r.make_identifier (this, "rvalue");
4278 r.write (" gcc_jit_rvalue *%s =\n"
4279 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4280 " %s); /* const char *value */\n",
4282 r.get_identifier (get_context ()),
4283 m_value->get_debug_string ());
4286 /* The implementation of class gcc::jit::recording::unary_op. */
4288 /* Implementation of pure virtual hook recording::memento::replay_into
4289 for recording::unary_op. */
4291 void
4292 recording::unary_op::replay_into (replayer *r)
4294 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
4295 m_op,
4296 get_type ()->playback_type (),
4297 m_a->playback_rvalue ()));
4300 /* Implementation of pure virtual hook recording::rvalue::visit_children
4301 for recording::unary_op. */
4302 void
4303 recording::unary_op::visit_children (rvalue_visitor *v)
4305 v->visit (m_a);
4308 /* Implementation of recording::memento::make_debug_string for
4309 unary ops. */
4311 static const char * const unary_op_strings[] = {
4312 "-", /* GCC_JIT_UNARY_OP_MINUS */
4313 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4314 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4315 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4318 recording::string *
4319 recording::unary_op::make_debug_string ()
4321 return string::from_printf (m_ctxt,
4322 "%s(%s)",
4323 unary_op_strings[m_op],
4324 m_a->get_debug_string ());
4327 static const char * const unary_op_reproducer_strings[] = {
4328 "GCC_JIT_UNARY_OP_MINUS",
4329 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4330 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4331 "GCC_JIT_UNARY_OP_ABS"
4334 /* Implementation of recording::memento::write_reproducer for unary ops. */
4336 void
4337 recording::unary_op::write_reproducer (reproducer &r)
4339 const char *id = r.make_identifier (this, "rvalue");
4340 r.write (" gcc_jit_rvalue *%s =\n"
4341 " gcc_jit_context_new_unary_op (%s,\n"
4342 " %s, /* gcc_jit_location *loc */\n"
4343 " %s, /* enum gcc_jit_unary_op op */\n"
4344 " %s, /* gcc_jit_type *result_type */\n"
4345 " %s); /* gcc_jit_rvalue *a */\n",
4347 r.get_identifier (get_context ()),
4348 r.get_identifier (m_loc),
4349 unary_op_reproducer_strings[m_op],
4350 r.get_identifier_as_type (get_type ()),
4351 r.get_identifier_as_rvalue (m_a));
4354 /* The implementation of class gcc::jit::recording::binary_op. */
4356 /* Implementation of pure virtual hook recording::memento::replay_into
4357 for recording::binary_op. */
4359 void
4360 recording::binary_op::replay_into (replayer *r)
4362 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
4363 m_op,
4364 get_type ()->playback_type (),
4365 m_a->playback_rvalue (),
4366 m_b->playback_rvalue ()));
4369 /* Implementation of pure virtual hook recording::rvalue::visit_children
4370 for recording::binary_op. */
4371 void
4372 recording::binary_op::visit_children (rvalue_visitor *v)
4374 v->visit (m_a);
4375 v->visit (m_b);
4378 /* Implementation of recording::memento::make_debug_string for
4379 binary ops. */
4381 static const char * const binary_op_strings[] = {
4382 "+", /* GCC_JIT_BINARY_OP_PLUS */
4383 "-", /* GCC_JIT_BINARY_OP_MINUS */
4384 "*", /* GCC_JIT_BINARY_OP_MULT */
4385 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4386 "%", /* GCC_JIT_BINARY_OP_MODULO */
4387 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4388 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4389 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4390 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4391 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4392 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4393 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4396 recording::string *
4397 recording::binary_op::make_debug_string ()
4399 enum precedence prec = get_precedence ();
4400 return string::from_printf (m_ctxt,
4401 "%s %s %s",
4402 m_a->get_debug_string_parens (prec),
4403 binary_op_strings[m_op],
4404 m_b->get_debug_string_parens (prec));
4407 static const char * const binary_op_reproducer_strings[] = {
4408 "GCC_JIT_BINARY_OP_PLUS",
4409 "GCC_JIT_BINARY_OP_MINUS",
4410 "GCC_JIT_BINARY_OP_MULT",
4411 "GCC_JIT_BINARY_OP_DIVIDE",
4412 "GCC_JIT_BINARY_OP_MODULO",
4413 "GCC_JIT_BINARY_OP_BITWISE_AND",
4414 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4415 "GCC_JIT_BINARY_OP_BITWISE_OR",
4416 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4417 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4418 "GCC_JIT_BINARY_OP_LSHIFT",
4419 "GCC_JIT_BINARY_OP_RSHIFT"
4422 /* Implementation of recording::memento::write_reproducer for binary ops. */
4424 void
4425 recording::binary_op::write_reproducer (reproducer &r)
4427 const char *id = r.make_identifier (this, "rvalue");
4428 r.write (" gcc_jit_rvalue *%s =\n"
4429 " gcc_jit_context_new_binary_op (%s,\n"
4430 " %s, /* gcc_jit_location *loc */\n"
4431 " %s, /* enum gcc_jit_binary_op op */\n"
4432 " %s, /* gcc_jit_type *result_type */\n"
4433 " %s, /* gcc_jit_rvalue *a */\n"
4434 " %s); /* gcc_jit_rvalue *b */\n",
4436 r.get_identifier (get_context ()),
4437 r.get_identifier (m_loc),
4438 binary_op_reproducer_strings[m_op],
4439 r.get_identifier_as_type (get_type ()),
4440 r.get_identifier_as_rvalue (m_a),
4441 r.get_identifier_as_rvalue (m_b));
4444 namespace recording {
4445 static const enum precedence binary_op_precedence[] = {
4446 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
4447 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
4449 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
4450 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
4451 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
4453 PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4454 PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4455 PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4456 PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4457 PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4458 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
4459 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
4461 } /* namespace recording */
4463 enum recording::precedence
4464 recording::binary_op::get_precedence () const
4466 return binary_op_precedence[m_op];
4469 /* The implementation of class gcc::jit::recording::comparison. */
4471 /* Implementation of recording::memento::make_debug_string for
4472 comparisons. */
4474 static const char * const comparison_strings[] =
4476 "==", /* GCC_JIT_COMPARISON_EQ */
4477 "!=", /* GCC_JIT_COMPARISON_NE */
4478 "<", /* GCC_JIT_COMPARISON_LT */
4479 "<=", /* GCC_JIT_COMPARISON_LE */
4480 ">", /* GCC_JIT_COMPARISON_GT */
4481 ">=", /* GCC_JIT_COMPARISON_GE */
4484 recording::string *
4485 recording::comparison::make_debug_string ()
4487 enum precedence prec = get_precedence ();
4488 return string::from_printf (m_ctxt,
4489 "%s %s %s",
4490 m_a->get_debug_string_parens (prec),
4491 comparison_strings[m_op],
4492 m_b->get_debug_string_parens (prec));
4495 /* A table of enum gcc_jit_comparison values expressed in string
4496 form. */
4498 static const char * const comparison_reproducer_strings[] =
4500 "GCC_JIT_COMPARISON_EQ",
4501 "GCC_JIT_COMPARISON_NE",
4502 "GCC_JIT_COMPARISON_LT",
4503 "GCC_JIT_COMPARISON_LE",
4504 "GCC_JIT_COMPARISON_GT",
4505 "GCC_JIT_COMPARISON_GE"
4508 /* Implementation of recording::memento::write_reproducer for comparisons. */
4510 void
4511 recording::comparison::write_reproducer (reproducer &r)
4513 const char *id = r.make_identifier (this, "rvalue");
4514 r.write (" gcc_jit_rvalue *%s =\n"
4515 " gcc_jit_context_new_comparison (%s,\n"
4516 " %s, /* gcc_jit_location *loc */\n"
4517 " %s, /* enum gcc_jit_comparison op */\n"
4518 " %s, /* gcc_jit_rvalue *a */\n"
4519 " %s); /* gcc_jit_rvalue *b */\n",
4521 r.get_identifier (get_context ()),
4522 r.get_identifier (m_loc),
4523 comparison_reproducer_strings[m_op],
4524 r.get_identifier_as_rvalue (m_a),
4525 r.get_identifier_as_rvalue (m_b));
4528 /* Implementation of pure virtual hook recording::memento::replay_into
4529 for recording::comparison. */
4531 void
4532 recording::comparison::replay_into (replayer *r)
4534 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
4535 m_op,
4536 m_a->playback_rvalue (),
4537 m_b->playback_rvalue ()));
4540 /* Implementation of pure virtual hook recording::rvalue::visit_children
4541 for recording::comparison. */
4543 void
4544 recording::comparison::visit_children (rvalue_visitor *v)
4546 v->visit (m_a);
4547 v->visit (m_b);
4550 namespace recording {
4551 static const enum precedence comparison_precedence[] =
4553 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
4554 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
4556 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LT */
4557 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
4558 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GT */
4559 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
4561 } /* namespace recording */
4563 enum recording::precedence
4564 recording::comparison::get_precedence () const
4566 return comparison_precedence[m_op];
4569 /* Implementation of pure virtual hook recording::memento::replay_into
4570 for recording::cast. */
4572 void
4573 recording::cast::replay_into (replayer *r)
4575 set_playback_obj (r->new_cast (playback_location (r, m_loc),
4576 m_rvalue->playback_rvalue (),
4577 get_type ()->playback_type ()));
4580 /* Implementation of pure virtual hook recording::rvalue::visit_children
4581 for recording::cast. */
4582 void
4583 recording::cast::visit_children (rvalue_visitor *v)
4585 v->visit (m_rvalue);
4588 /* Implementation of recording::memento::make_debug_string for
4589 casts. */
4591 recording::string *
4592 recording::cast::make_debug_string ()
4594 enum precedence prec = get_precedence ();
4595 return string::from_printf (m_ctxt,
4596 "(%s)%s",
4597 get_type ()->get_debug_string (),
4598 m_rvalue->get_debug_string_parens (prec));
4601 /* Implementation of recording::memento::write_reproducer for casts. */
4603 void
4604 recording::cast::write_reproducer (reproducer &r)
4606 const char *id = r.make_identifier (this, "rvalue");
4607 r.write (" gcc_jit_rvalue *%s =\n"
4608 " gcc_jit_context_new_cast (%s,\n"
4609 " %s, /* gcc_jit_location *loc */\n"
4610 " %s, /* gcc_jit_rvalue *rvalue */\n"
4611 " %s); /* gcc_jit_type *type */\n",
4613 r.get_identifier (get_context ()),
4614 r.get_identifier (m_loc),
4615 r.get_identifier_as_rvalue (m_rvalue),
4616 r.get_identifier_as_type (get_type ()));
4619 /* The implementation of class gcc::jit::recording::call. */
4621 /* The constructor for gcc::jit::recording::call. */
4623 recording::call::call (recording::context *ctxt,
4624 recording::location *loc,
4625 recording::function *func,
4626 int numargs,
4627 rvalue **args)
4628 : rvalue (ctxt, loc, func->get_return_type ()),
4629 m_func (func),
4630 m_args ()
4632 for (int i = 0; i< numargs; i++)
4633 m_args.safe_push (args[i]);
4636 /* Implementation of pure virtual hook recording::memento::replay_into
4637 for recording::call. */
4639 void
4640 recording::call::replay_into (replayer *r)
4642 auto_vec<playback::rvalue *> playback_args;
4643 playback_args.create (m_args.length ());
4644 for (unsigned i = 0; i< m_args.length (); i++)
4645 playback_args.safe_push (m_args[i]->playback_rvalue ());
4647 set_playback_obj (r->new_call (playback_location (r, m_loc),
4648 m_func->playback_function (),
4649 &playback_args));
4652 /* Implementation of pure virtual hook recording::rvalue::visit_children
4653 for recording::call. */
4655 void
4656 recording::call::visit_children (rvalue_visitor *v)
4658 for (unsigned i = 0; i< m_args.length (); i++)
4659 v->visit (m_args[i]);
4662 /* Implementation of recording::memento::make_debug_string for
4663 function calls. */
4665 recording::string *
4666 recording::call::make_debug_string ()
4668 enum precedence prec = get_precedence ();
4669 /* First, build a buffer for the arguments. */
4670 /* Calculate length of said buffer. */
4671 size_t sz = 1; /* nil terminator */
4672 for (unsigned i = 0; i< m_args.length (); i++)
4674 sz += strlen (m_args[i]->get_debug_string_parens (prec));
4675 sz += 2; /* ", " separator */
4678 /* Now allocate and populate the buffer. */
4679 char *argbuf = new char[sz];
4680 size_t len = 0;
4682 for (unsigned i = 0; i< m_args.length (); i++)
4684 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4685 len += strlen (m_args[i]->get_debug_string_parens (prec));
4686 if (i + 1 < m_args.length ())
4688 strcpy (argbuf + len, ", ");
4689 len += 2;
4692 argbuf[len] = '\0';
4694 /* ...and use it to get the string for the call as a whole. */
4695 string *result = string::from_printf (m_ctxt,
4696 "%s (%s)",
4697 m_func->get_debug_string (),
4698 argbuf);
4700 delete[] argbuf;
4702 return result;
4705 void
4706 recording::call::write_reproducer (reproducer &r)
4708 const char *id = r.make_identifier (this, "call");
4709 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4710 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4711 args_id,
4712 m_args.length ());
4713 for (unsigned i = 0; i< m_args.length (); i++)
4714 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4715 r.write (" };\n");
4716 r.write (" gcc_jit_rvalue *%s =\n"
4717 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4718 " %s, /* gcc_jit_location *loc */\n"
4719 " %s, /* gcc_jit_function *func */\n"
4720 " %i, /* int numargs */ \n"
4721 " %s); /* gcc_jit_rvalue **args*/\n",
4723 r.get_identifier (get_context ()),
4724 r.get_identifier (m_loc),
4725 r.get_identifier (m_func),
4726 m_args.length (),
4727 args_id);
4730 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4732 /* The constructor for recording::call_through_ptr. */
4734 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
4735 recording::location *loc,
4736 recording::rvalue *fn_ptr,
4737 int numargs,
4738 rvalue **args)
4739 : rvalue (ctxt, loc,
4740 fn_ptr->get_type ()->dereference ()
4741 ->as_a_function_type ()->get_return_type ()),
4742 m_fn_ptr (fn_ptr),
4743 m_args ()
4745 for (int i = 0; i< numargs; i++)
4746 m_args.safe_push (args[i]);
4749 /* Implementation of pure virtual hook recording::memento::replay_into
4750 for recording::call_through_ptr. */
4752 void
4753 recording::call_through_ptr::replay_into (replayer *r)
4755 auto_vec<playback::rvalue *> playback_args;
4756 playback_args.create (m_args.length ());
4757 for (unsigned i = 0; i< m_args.length (); i++)
4758 playback_args.safe_push (m_args[i]->playback_rvalue ());
4760 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
4761 m_fn_ptr->playback_rvalue (),
4762 &playback_args));
4765 /* Implementation of pure virtual hook recording::rvalue::visit_children
4766 for recording::call_through_ptr. */
4768 void
4769 recording::call_through_ptr::visit_children (rvalue_visitor *v)
4771 v->visit (m_fn_ptr);
4772 for (unsigned i = 0; i< m_args.length (); i++)
4773 v->visit (m_args[i]);
4776 /* Implementation of recording::memento::make_debug_string for
4777 calls through function ptrs. */
4779 recording::string *
4780 recording::call_through_ptr::make_debug_string ()
4782 enum precedence prec = get_precedence ();
4783 /* First, build a buffer for the arguments. */
4784 /* Calculate length of said buffer. */
4785 size_t sz = 1; /* nil terminator */
4786 for (unsigned i = 0; i< m_args.length (); i++)
4788 sz += strlen (m_args[i]->get_debug_string_parens (prec));
4789 sz += 2; /* ", " separator */
4792 /* Now allocate and populate the buffer. */
4793 char *argbuf = new char[sz];
4794 size_t len = 0;
4796 for (unsigned i = 0; i< m_args.length (); i++)
4798 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4799 len += strlen (m_args[i]->get_debug_string_parens (prec));
4800 if (i + 1 < m_args.length ())
4802 strcpy (argbuf + len, ", ");
4803 len += 2;
4806 argbuf[len] = '\0';
4808 /* ...and use it to get the string for the call as a whole. */
4809 string *result = string::from_printf (m_ctxt,
4810 "%s (%s)",
4811 m_fn_ptr->get_debug_string_parens (prec),
4812 argbuf);
4814 delete[] argbuf;
4816 return result;
4819 /* Implementation of recording::memento::write_reproducer for
4820 call_through_ptr. */
4822 void
4823 recording::call_through_ptr::write_reproducer (reproducer &r)
4825 const char *id = r.make_identifier (this, "call");
4826 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4827 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4828 args_id,
4829 m_args.length ());
4830 for (unsigned i = 0; i< m_args.length (); i++)
4831 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4832 r.write (" };\n");
4833 r.write (" gcc_jit_rvalue *%s =\n"
4834 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
4835 " %s, /* gcc_jit_location *loc */\n"
4836 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
4837 " %i, /* int numargs */ \n"
4838 " %s); /* gcc_jit_rvalue **args*/\n",
4840 r.get_identifier (get_context ()),
4841 r.get_identifier (m_loc),
4842 r.get_identifier_as_rvalue (m_fn_ptr),
4843 m_args.length (),
4844 args_id);
4847 /* The implementation of class gcc::jit::recording::array_access. */
4849 /* Implementation of pure virtual hook recording::memento::replay_into
4850 for recording::array_access. */
4852 void
4853 recording::array_access::replay_into (replayer *r)
4855 set_playback_obj (
4856 r->new_array_access (playback_location (r, m_loc),
4857 m_ptr->playback_rvalue (),
4858 m_index->playback_rvalue ()));
4861 /* Implementation of pure virtual hook recording::rvalue::visit_children
4862 for recording::array_access. */
4864 void
4865 recording::array_access::visit_children (rvalue_visitor *v)
4867 v->visit (m_ptr);
4868 v->visit (m_index);
4871 /* Implementation of recording::memento::make_debug_string for
4872 array accesses. */
4874 recording::string *
4875 recording::array_access::make_debug_string ()
4877 enum precedence prec = get_precedence ();
4878 return string::from_printf (m_ctxt,
4879 "%s[%s]",
4880 m_ptr->get_debug_string_parens (prec),
4881 m_index->get_debug_string_parens (prec));
4884 /* Implementation of recording::memento::write_reproducer for
4885 array_access. */
4887 void
4888 recording::array_access::write_reproducer (reproducer &r)
4890 const char *id = r.make_identifier (this, "lvalue");
4891 r.write (" gcc_jit_lvalue *%s = \n"
4892 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
4893 " %s, /*gcc_jit_location *loc */\n"
4894 " %s, /* gcc_jit_rvalue *ptr */\n"
4895 " %s); /* gcc_jit_rvalue *index */\n",
4897 r.get_identifier (get_context ()),
4898 r.get_identifier (m_loc),
4899 r.get_identifier_as_rvalue (m_ptr),
4900 r.get_identifier_as_rvalue (m_index));
4903 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
4905 /* Implementation of pure virtual hook recording::memento::replay_into
4906 for recording::access_field_of_lvalue. */
4908 void
4909 recording::access_field_of_lvalue::replay_into (replayer *r)
4911 set_playback_obj (
4912 m_lvalue->playback_lvalue ()
4913 ->access_field (playback_location (r, m_loc),
4914 m_field->playback_field ()));
4918 /* Implementation of pure virtual hook recording::rvalue::visit_children
4919 for recording::access_field_of_lvalue. */
4921 void
4922 recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
4924 v->visit (m_lvalue);
4927 /* Implementation of recording::memento::make_debug_string for
4928 accessing a field of an lvalue. */
4930 recording::string *
4931 recording::access_field_of_lvalue::make_debug_string ()
4933 enum precedence prec = get_precedence ();
4934 return string::from_printf (m_ctxt,
4935 "%s.%s",
4936 m_lvalue->get_debug_string_parens (prec),
4937 m_field->get_debug_string ());
4940 /* Implementation of recording::memento::write_reproducer for
4941 access_field_of_lvalue. */
4943 void
4944 recording::access_field_of_lvalue::write_reproducer (reproducer &r)
4946 const char *id = r.make_identifier (this, "lvalue");
4947 r.write (" gcc_jit_lvalue *%s = \n"
4948 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
4949 " %s, /*gcc_jit_location *loc */\n"
4950 " %s);\n",
4952 r.get_identifier_as_lvalue (m_lvalue),
4953 r.get_identifier (m_loc),
4954 r.get_identifier (m_field));
4957 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
4959 /* Implementation of pure virtual hook recording::memento::replay_into
4960 for recording::access_field_rvalue. */
4962 void
4963 recording::access_field_rvalue::replay_into (replayer *r)
4965 set_playback_obj (
4966 m_rvalue->playback_rvalue ()
4967 ->access_field (playback_location (r, m_loc),
4968 m_field->playback_field ()));
4971 /* Implementation of pure virtual hook recording::rvalue::visit_children
4972 for recording::access_field_rvalue. */
4974 void
4975 recording::access_field_rvalue::visit_children (rvalue_visitor *v)
4977 v->visit (m_rvalue);
4980 /* Implementation of recording::memento::make_debug_string for
4981 accessing a field of an rvalue. */
4983 recording::string *
4984 recording::access_field_rvalue::make_debug_string ()
4986 enum precedence prec = get_precedence ();
4987 return string::from_printf (m_ctxt,
4988 "%s.%s",
4989 m_rvalue->get_debug_string_parens (prec),
4990 m_field->get_debug_string ());
4993 /* Implementation of recording::memento::write_reproducer for
4994 access_field_rvalue. */
4996 void
4997 recording::access_field_rvalue::write_reproducer (reproducer &r)
4999 const char *id = r.make_identifier (this, "rvalue");
5000 r.write (" gcc_jit_rvalue *%s = \n"
5001 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5002 " %s, /*gcc_jit_location *loc */\n"
5003 " %s);\n",
5005 r.get_identifier_as_rvalue (m_rvalue),
5006 r.get_identifier (m_loc),
5007 r.get_identifier (m_field));
5010 /* The implementation of class
5011 gcc::jit::recording::dereference_field_rvalue. */
5013 /* Implementation of pure virtual hook recording::memento::replay_into
5014 for recording::dereference_field_rvalue. */
5016 void
5017 recording::dereference_field_rvalue::replay_into (replayer *r)
5019 set_playback_obj (
5020 m_rvalue->playback_rvalue ()->
5021 dereference_field (playback_location (r, m_loc),
5022 m_field->playback_field ()));
5025 /* Implementation of pure virtual hook recording::rvalue::visit_children
5026 for recording::dereference_field_rvalue. */
5028 void
5029 recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
5031 v->visit (m_rvalue);
5034 /* Implementation of recording::memento::make_debug_string for
5035 dereferencing a field of an rvalue. */
5037 recording::string *
5038 recording::dereference_field_rvalue::make_debug_string ()
5040 enum precedence prec = get_precedence ();
5041 return string::from_printf (m_ctxt,
5042 "%s->%s",
5043 m_rvalue->get_debug_string_parens (prec),
5044 m_field->get_debug_string ());
5047 /* Implementation of recording::memento::write_reproducer for
5048 dereference_field_rvalue. */
5050 void
5051 recording::dereference_field_rvalue::write_reproducer (reproducer &r)
5053 const char *id = r.make_identifier (this, "lvalue");
5054 r.write (" gcc_jit_lvalue *%s=\n"
5055 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5056 " %s, /* gcc_jit_location *loc */\n"
5057 " %s); /* gcc_jit_field *field */\n",
5059 r.get_identifier_as_rvalue (m_rvalue),
5060 r.get_identifier (m_loc),
5061 r.get_identifier (m_field));
5064 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5066 /* Implementation of pure virtual hook recording::memento::replay_into
5067 for recording::dereference_rvalue. */
5069 void
5070 recording::dereference_rvalue::replay_into (replayer *r)
5072 set_playback_obj (
5073 m_rvalue->playback_rvalue ()->
5074 dereference (playback_location (r, m_loc)));
5077 /* Implementation of pure virtual hook recording::rvalue::visit_children
5078 for recording::dereference_rvalue. */
5080 void
5081 recording::dereference_rvalue::visit_children (rvalue_visitor *v)
5083 v->visit (m_rvalue);
5086 /* Implementation of recording::memento::make_debug_string for
5087 dereferencing an rvalue. */
5089 recording::string *
5090 recording::dereference_rvalue::make_debug_string ()
5092 enum precedence prec = get_precedence ();
5093 return string::from_printf (m_ctxt,
5094 "*%s",
5095 m_rvalue->get_debug_string_parens (prec));
5098 /* Implementation of recording::memento::write_reproducer for
5099 dereference_rvalue. */
5101 void
5102 recording::dereference_rvalue::write_reproducer (reproducer &r)
5104 const char *id = r.make_identifier (this, "dereference");
5105 r.write (" gcc_jit_lvalue *%s =\n"
5106 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5107 " %s); /* gcc_jit_location *loc */\n",
5109 r.get_identifier_as_rvalue (m_rvalue),
5110 r.get_identifier (m_loc));
5113 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5115 /* Implementation of pure virtual hook recording::memento::replay_into
5116 for recording::get_address_of_lvalue. */
5118 void
5119 recording::get_address_of_lvalue::replay_into (replayer *r)
5121 set_playback_obj (
5122 m_lvalue->playback_lvalue ()->
5123 get_address (playback_location (r, m_loc)));
5126 /* Implementation of pure virtual hook recording::rvalue::visit_children
5127 for recording::get_address_of_lvalue. */
5129 void
5130 recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
5132 v->visit (m_lvalue);
5135 /* Implementation of recording::memento::make_debug_string for
5136 getting the address of an lvalue. */
5138 recording::string *
5139 recording::get_address_of_lvalue::make_debug_string ()
5141 enum precedence prec = get_precedence ();
5142 return string::from_printf (m_ctxt,
5143 "&%s",
5144 m_lvalue->get_debug_string_parens (prec));
5147 /* Implementation of recording::memento::write_reproducer for
5148 get_address_of_lvalue. */
5150 void
5151 recording::get_address_of_lvalue::write_reproducer (reproducer &r)
5153 const char *id = r.make_identifier (this, "address_of");
5154 r.write (" gcc_jit_rvalue *%s =\n"
5155 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5156 " %s); /* gcc_jit_location *loc */\n",
5158 r.get_identifier_as_lvalue (m_lvalue),
5159 r.get_identifier (m_loc));
5162 /* The implementation of class gcc::jit::recording::local. */
5164 /* Implementation of pure virtual hook recording::memento::replay_into
5165 for recording::local. */
5167 void
5168 recording::local::replay_into (replayer *r)
5170 set_playback_obj (
5171 m_func->playback_function ()
5172 ->new_local (playback_location (r, m_loc),
5173 m_type->playback_type (),
5174 playback_string (m_name)));
5177 /* Override the default implementation of
5178 recording::memento::write_to_dump for locals by writing
5179 TYPE NAME;
5180 for use at the top of the function body as if it were a
5181 declaration. */
5183 void
5184 recording::local::write_to_dump (dump &d)
5186 if (d.update_locations ())
5187 m_loc = d.make_location ();
5188 d.write(" %s %s;\n",
5189 m_type->get_debug_string (),
5190 get_debug_string ());
5193 void
5194 recording::local::write_reproducer (reproducer &r)
5196 const char *id = r.make_identifier (this, "local");
5197 r.write (" gcc_jit_lvalue *%s =\n"
5198 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5199 " %s, /* gcc_jit_location *loc */\n"
5200 " %s, /* gcc_jit_type *type */\n"
5201 " %s); /* const char *name */\n",
5203 r.get_identifier (m_func),
5204 r.get_identifier (m_loc),
5205 r.get_identifier_as_type (m_type),
5206 m_name->get_debug_string ());
5209 /* The implementation of class gcc::jit::recording::statement. */
5211 /* We poison the default implementation of
5212 gcc::jit::recording::statement::get_successor_blocks
5213 since this vfunc must only ever be called on terminator
5214 statements. */
5217 recording::statement::get_successor_blocks (block **/*out_next1*/,
5218 block **/*out_next2*/) const
5220 /* The base class implementation is for non-terminating statements,
5221 and thus should never be called. */
5222 gcc_unreachable ();
5223 return 0;
5226 /* Extend the default implementation of
5227 recording::memento::write_to_dump for statements by (if requested)
5228 updating the location of the statement to the current location in
5229 the dumpfile. */
5231 void
5232 recording::statement::write_to_dump (dump &d)
5234 memento::write_to_dump (d);
5235 if (d.update_locations ())
5236 m_loc = d.make_location ();
5239 /* The implementation of class gcc::jit::recording::eval. */
5241 /* Implementation of pure virtual hook recording::memento::replay_into
5242 for recording::eval. */
5244 void
5245 recording::eval::replay_into (replayer *r)
5247 playback_block (get_block ())
5248 ->add_eval (playback_location (r),
5249 m_rvalue->playback_rvalue ());
5252 /* Implementation of recording::memento::make_debug_string for
5253 an eval statement. */
5255 recording::string *
5256 recording::eval::make_debug_string ()
5258 return string::from_printf (m_ctxt,
5259 "(void)%s;",
5260 m_rvalue->get_debug_string ());
5263 /* Implementation of recording::memento::write_reproducer for
5264 eval statements. */
5266 void
5267 recording::eval::write_reproducer (reproducer &r)
5269 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5270 " %s, /* gcc_jit_location *loc */\n"
5271 " %s); /* gcc_jit_rvalue *rvalue */\n",
5272 r.get_identifier (get_block ()),
5273 r.get_identifier (get_loc ()),
5274 r.get_identifier_as_rvalue (m_rvalue));
5277 /* The implementation of class gcc::jit::recording::assignment. */
5279 /* Implementation of pure virtual hook recording::memento::replay_into
5280 for recording::assignment. */
5282 void
5283 recording::assignment::replay_into (replayer *r)
5285 playback_block (get_block ())
5286 ->add_assignment (playback_location (r),
5287 m_lvalue->playback_lvalue (),
5288 m_rvalue->playback_rvalue ());
5291 /* Implementation of recording::memento::make_debug_string for
5292 an assignment statement. */
5294 recording::string *
5295 recording::assignment::make_debug_string ()
5297 return string::from_printf (m_ctxt,
5298 "%s = %s;",
5299 m_lvalue->get_debug_string (),
5300 m_rvalue->get_debug_string ());
5303 /* Implementation of recording::memento::write_reproducer for
5304 assignment statements. */
5306 void
5307 recording::assignment::write_reproducer (reproducer &r)
5309 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5310 " %s, /* gcc_jit_location *loc */\n"
5311 " %s, /* gcc_jit_lvalue *lvalue */\n"
5312 " %s); /* gcc_jit_rvalue *rvalue */\n",
5313 r.get_identifier (get_block ()),
5314 r.get_identifier (get_loc ()),
5315 r.get_identifier_as_lvalue (m_lvalue),
5316 r.get_identifier_as_rvalue (m_rvalue));
5319 /* The implementation of class gcc::jit::recording::assignment_op. */
5321 /* Implementation of pure virtual hook recording::memento::replay_into
5322 for recording::assignment_op. */
5324 void
5325 recording::assignment_op::replay_into (replayer *r)
5327 playback::type *result_type =
5328 m_lvalue->playback_lvalue ()->get_type ();
5330 playback::rvalue *binary_op =
5331 r->new_binary_op (playback_location (r),
5332 m_op,
5333 result_type,
5334 m_lvalue->playback_rvalue (),
5335 m_rvalue->playback_rvalue ());
5337 playback_block (get_block ())
5338 ->add_assignment (playback_location (r),
5339 m_lvalue->playback_lvalue (),
5340 binary_op);
5343 /* Implementation of recording::memento::make_debug_string for
5344 an assignment_op statement. */
5346 recording::string *
5347 recording::assignment_op::make_debug_string ()
5349 return string::from_printf (m_ctxt,
5350 "%s %s= %s;",
5351 m_lvalue->get_debug_string (),
5352 binary_op_strings[m_op],
5353 m_rvalue->get_debug_string ());
5356 /* Implementation of recording::memento::write_reproducer for
5357 assignment_op statements. */
5359 void
5360 recording::assignment_op::write_reproducer (reproducer &r)
5362 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5363 " %s, /* gcc_jit_location *loc */\n"
5364 " %s, /* gcc_jit_lvalue *lvalue */\n"
5365 " %s, /* enum gcc_jit_binary_op op */\n"
5366 " %s); /* gcc_jit_rvalue *rvalue */\n",
5367 r.get_identifier (get_block ()),
5368 r.get_identifier (get_loc ()),
5369 r.get_identifier_as_lvalue (m_lvalue),
5370 binary_op_reproducer_strings[m_op],
5371 r.get_identifier_as_rvalue (m_rvalue));
5374 /* The implementation of class gcc::jit::recording::comment. */
5376 /* Implementation of pure virtual hook recording::memento::replay_into
5377 for recording::comment. */
5379 void
5380 recording::comment::replay_into (replayer *r)
5382 playback_block (get_block ())
5383 ->add_comment (playback_location (r),
5384 m_text->c_str ());
5387 /* Implementation of recording::memento::make_debug_string for
5388 a comment "statement". */
5390 recording::string *
5391 recording::comment::make_debug_string ()
5393 return string::from_printf (m_ctxt,
5394 "/* %s */",
5395 m_text->c_str ());
5398 /* Implementation of recording::memento::write_reproducer for
5399 comments. */
5401 void
5402 recording::comment::write_reproducer (reproducer &r)
5404 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5405 " %s, /* gcc_jit_location *loc */\n"
5406 " %s); /* const char *text */\n",
5407 r.get_identifier (get_block ()),
5408 r.get_identifier (get_loc ()),
5409 m_text->get_debug_string ());
5412 /* The implementation of class gcc::jit::recording::conditional. */
5414 /* Implementation of pure virtual hook recording::memento::replay_into
5415 for recording::conditional. */
5417 void
5418 recording::conditional::replay_into (replayer *r)
5420 playback_block (get_block ())
5421 ->add_conditional (playback_location (r),
5422 m_boolval->playback_rvalue (),
5423 playback_block (m_on_true),
5424 playback_block (m_on_false));
5427 /* Override the poisoned default implementation of
5428 gcc::jit::recording::statement::get_successor_blocks
5430 A conditional jump has 2 successor blocks. */
5433 recording::conditional::get_successor_blocks (block **out_next1,
5434 block **out_next2) const
5436 *out_next1 = m_on_true;
5437 *out_next2 = m_on_false;
5438 return 2;
5441 /* Implementation of recording::memento::make_debug_string for
5442 a conditional jump statement. */
5444 recording::string *
5445 recording::conditional::make_debug_string ()
5447 if (m_on_false)
5448 return string::from_printf (m_ctxt,
5449 "if (%s) goto %s; else goto %s;",
5450 m_boolval->get_debug_string (),
5451 m_on_true->get_debug_string (),
5452 m_on_false->get_debug_string ());
5453 else
5454 return string::from_printf (m_ctxt,
5455 "if (%s) goto %s;",
5456 m_boolval->get_debug_string (),
5457 m_on_true->get_debug_string ());
5460 /* Implementation of recording::memento::write_reproducer for
5461 conditional statements. */
5463 void
5464 recording::conditional::write_reproducer (reproducer &r)
5466 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5467 " %s, /* gcc_jit_location *loc */\n"
5468 " %s, /* gcc_jit_rvalue *boolval */\n"
5469 " %s, /* gcc_jit_block *on_true */\n"
5470 " %s); /* gcc_jit_block *on_false */\n",
5471 r.get_identifier (get_block ()),
5472 r.get_identifier (get_loc ()),
5473 r.get_identifier_as_rvalue (m_boolval),
5474 r.get_identifier (m_on_true),
5475 r.get_identifier (m_on_false));
5478 /* The implementation of class gcc::jit::recording::jump. */
5480 /* Implementation of pure virtual hook recording::memento::replay_into
5481 for recording::jump. */
5483 void
5484 recording::jump::replay_into (replayer *r)
5486 playback_block (get_block ())
5487 ->add_jump (playback_location (r),
5488 m_target->playback_block ());
5491 /* Override the poisoned default implementation of
5492 gcc::jit::recording::statement::get_successor_blocks
5494 An unconditional jump has 1 successor block. */
5497 recording::jump::get_successor_blocks (block **out_next1,
5498 block **/*out_next2*/) const
5500 *out_next1 = m_target;
5501 return 1;
5504 /* Implementation of recording::memento::make_debug_string for
5505 a unconditional jump statement. */
5507 recording::string *
5508 recording::jump::make_debug_string ()
5510 return string::from_printf (m_ctxt,
5511 "goto %s;",
5512 m_target->get_debug_string ());
5515 /* Implementation of recording::memento::write_reproducer for
5516 jump statements. */
5518 void
5519 recording::jump::write_reproducer (reproducer &r)
5521 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5522 " %s, /* gcc_jit_location *loc */\n"
5523 " %s); /* gcc_jit_block *target */\n",
5524 r.get_identifier (get_block ()),
5525 r.get_identifier (get_loc ()),
5526 r.get_identifier (m_target));
5529 /* The implementation of class gcc::jit::recording::return_. */
5531 /* Implementation of pure virtual hook recording::memento::replay_into
5532 for recording::return_. */
5534 void
5535 recording::return_::replay_into (replayer *r)
5537 playback_block (get_block ())
5538 ->add_return (playback_location (r),
5539 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
5542 /* Override the poisoned default implementation of
5543 gcc::jit::recording::statement::get_successor_blocks
5545 A return statement has no successor block. */
5548 recording::return_::get_successor_blocks (block **/*out_next1*/,
5549 block **/*out_next2*/) const
5551 return 0;
5554 /* Implementation of recording::memento::make_debug_string for
5555 a return statement (covers both those with and without rvalues). */
5557 recording::string *
5558 recording::return_::make_debug_string ()
5560 if (m_rvalue)
5561 return string::from_printf (m_ctxt,
5562 "return %s;",
5563 m_rvalue->get_debug_string ());
5564 else
5565 return string::from_printf (m_ctxt,
5566 "return;");
5569 /* Implementation of recording::memento::write_reproducer for
5570 return statements. */
5572 void
5573 recording::return_::write_reproducer (reproducer &r)
5575 if (m_rvalue)
5576 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5577 " %s, /* gcc_jit_location *loc */\n"
5578 " %s); /* gcc_jit_rvalue *rvalue */\n",
5579 r.get_identifier (get_block ()),
5580 r.get_identifier (get_loc ()),
5581 r.get_identifier_as_rvalue (m_rvalue));
5582 else
5583 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5584 " %s); /* gcc_jit_location *loc */\n",
5585 r.get_identifier (get_block ()),
5586 r.get_identifier (get_loc ()));
5589 } // namespace gcc::jit
5591 } // namespace gcc