Patch for RTL expand bug affecting aarch64 vector code.
[official-gcc.git] / gcc / jit / jit-recording.c
blob723ddb375075e8f5f462dd026c82443854e1f923
1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2017 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 "toplev.h"
28 #include <pthread.h>
30 #include "jit-builtins.h"
31 #include "jit-recording.h"
32 #include "jit-playback.h"
34 namespace gcc {
35 namespace jit {
37 // class dump
39 dump::dump (recording::context &ctxt,
40 const char *filename,
41 bool update_locations)
42 : m_ctxt (ctxt),
43 m_filename (filename),
44 m_update_locations (update_locations),
45 m_line (0),
46 m_column (0)
48 m_file = fopen (filename, "w");
49 if (!m_file)
50 ctxt.add_error (NULL,
51 "error opening dump file %s for writing: %s",
52 filename,
53 xstrerror (errno));
56 dump::~dump ()
58 if (m_file)
60 int err = fclose (m_file);
61 if (err)
62 m_ctxt.add_error (NULL,
63 "error closing dump file %s: %s",
64 m_filename,
65 xstrerror (errno));
69 /* Write the given message to the dump, using printf-formatting
70 conventions, updating the line/column within the dump.
72 Emit an error on the context if a failure occurs. */
74 void
75 dump::write (const char *fmt, ...)
77 int len;
78 va_list ap;
79 char *buf;
81 /* If there was an error opening the file, we've already reported it.
82 Don't attempt further work. */
83 if (!m_file)
84 return;
86 va_start (ap, fmt);
87 len = vasprintf (&buf, fmt, ap);
88 va_end (ap);
90 if (buf == NULL || len < 0)
92 m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
93 m_filename);
94 return;
97 if (fwrite (buf, strlen (buf), 1, m_file) != 1)
98 m_ctxt.add_error (NULL, "error writing to dump file %s",
99 m_filename);
101 /* Flush after each line, to ease debugging crashes. */
102 fflush (m_file);
104 /* Update line/column: */
105 for (const char *ptr = buf; *ptr; ptr++)
107 if ('\n' == *ptr)
109 m_line++;
110 m_column = 0;
112 else
113 m_column++;
116 free (buf);
119 /* Construct a gcc::jit::recording::location instance for the current
120 location within the dump. */
122 recording::location *
123 dump::make_location () const
125 return m_ctxt.new_location (m_filename, m_line, m_column,
126 /* We need to flag such locations as *not*
127 created by the user, so that
128 reproducer::get_identifier can cope with
129 them appearing *after* the memento that
130 refers to them. */
131 false);
134 /* A collection of allocations, all of which can be released together, to
135 avoid needing to track and release them individually. */
137 class allocator
139 public:
140 ~allocator ();
142 char *
143 xstrdup_printf (const char *, ...)
144 ATTRIBUTE_RETURNS_NONNULL
145 GNU_PRINTF(2, 3);
147 char *
148 xstrdup_printf_va (const char *, va_list ap)
149 ATTRIBUTE_RETURNS_NONNULL
150 GNU_PRINTF(2, 0);
152 private:
153 auto_vec <void *> m_buffers;
156 /* allocator's destructor. Call "free" on all of the allocations. */
158 allocator::~allocator ()
160 unsigned i;
161 void *buffer;
162 FOR_EACH_VEC_ELT (m_buffers, i, buffer)
163 free (buffer);
166 /* Formatted printing, allocating to a buffer (or exiting the process if
167 the allocation fails).
169 The buffer exists until the allocator is cleaned up, and is freed at
170 that point, so the caller doesn't need to track the result. */
172 char *
173 allocator::xstrdup_printf (const char *fmt, ...)
175 char *result;
176 va_list ap;
177 va_start (ap, fmt);
178 result = xstrdup_printf_va (fmt, ap);
179 va_end (ap);
180 return result;
183 /* Formatted printing, allocating to a buffer (or exiting the process if
184 the allocation fails).
186 The buffer exists until the allocator is cleaned up, and is freed at
187 that point, so the caller doesn't need to track the result. */
189 char *
190 allocator::xstrdup_printf_va (const char *fmt, va_list ap)
192 char *result = xvasprintf (fmt, ap);
193 m_buffers.safe_push (result);
194 return result;
197 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
198 implementing gcc_jit_context_dump_reproducer_to_file. */
200 class reproducer : public dump
202 public:
203 reproducer (recording::context &ctxt,
204 const char *filename);
206 void
207 write_params (const vec <recording::context *> &contexts);
209 void
210 write_args (const vec <recording::context *> &contexts);
212 const char *
213 make_identifier (recording::memento *m, const char *prefix);
215 const char *
216 make_tmp_identifier (const char *prefix, recording::memento *m);
218 const char *
219 get_identifier (recording::context *ctxt);
221 const char *
222 get_identifier (recording::memento *m);
224 const char *
225 get_identifier_as_rvalue (recording::rvalue *m);
227 const char *
228 get_identifier_as_lvalue (recording::lvalue *m);
230 const char *
231 get_identifier_as_type (recording::type *m);
233 char *
234 xstrdup_printf (const char *, ...)
235 ATTRIBUTE_RETURNS_NONNULL
236 GNU_PRINTF(2, 3);
238 private:
239 hash_map<recording::memento *, const char *> m_identifiers;
240 allocator m_allocator;
243 /* gcc::jit::reproducer's constructor. */
245 reproducer::reproducer (recording::context &ctxt,
246 const char *filename) :
247 dump (ctxt, filename, 0),
248 m_identifiers (),
249 m_allocator ()
253 /* Write out a list of contexts as a set of parameters within a
254 C function declaration. */
256 void
257 reproducer::write_params (const vec <recording::context *> &contexts)
259 unsigned i;
260 recording::context *ctxt;
261 FOR_EACH_VEC_ELT (contexts, i, ctxt)
263 write ("gcc_jit_context *%s",
264 get_identifier (ctxt));
265 if (i < contexts.length () - 1)
266 write (",\n"
267 " ");
271 /* Write out a list of contexts as a set of arguments within a call
272 to a C function. */
274 void
275 reproducer::write_args (const vec <recording::context *> &contexts)
277 unsigned i;
278 recording::context *ctxt;
279 FOR_EACH_VEC_ELT (contexts, i, ctxt)
281 write ("%s",
282 get_identifier (ctxt));
283 if (i < contexts.length () - 1)
284 write (",\n"
285 " ");
289 /* Generate a C identifier for the given memento, associating the generated
290 buffer with the memento (for future calls to get_identifier et al).
292 The reproducer will eventually clean up the buffer in its dtor. */
293 const char *
294 reproducer::make_identifier (recording::memento *m, const char *prefix)
296 char *result;
297 if (strlen (m->get_debug_string ()) < 100)
299 result = m_allocator.xstrdup_printf ("%s_%s_%p",
300 prefix,
301 m->get_debug_string (),
302 (void *) m);
303 for (char *p = result; *p; p++)
304 if (!ISALNUM (*p))
305 *p = '_';
307 else
308 result = m_allocator.xstrdup_printf ("%s_%p",
309 prefix, (void *) m);
310 m_identifiers.put (m, result);
311 return result;
314 /* Generate a C identifier for a temporary variable.
315 The reproducer will eventually clean up the buffer in its dtor. */
317 const char *
318 reproducer::make_tmp_identifier (const char *prefix, recording::memento *m)
320 return m_allocator.xstrdup_printf ("%s_%s",
321 prefix, get_identifier (m));
324 /* Generate a C identifier for the given context.
325 The reproducer will eventually clean up the buffer in its dtor. */
327 const char *
328 reproducer::get_identifier (recording::context *ctxt)
330 return m_allocator.xstrdup_printf ("ctxt_%p",
331 (void *)ctxt);
334 /* Locate the C identifier for the given memento, which is assumed to
335 have already been created via make_identifier. */
337 const char *
338 reproducer::get_identifier (recording::memento *m)
340 if (!m)
341 return "NULL";
343 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
344 and hence these locations appear in the context's memento list
345 out-of-order: they appear in the context's memento list *after*
346 the memento that refers to them. For this case, it's simplest to
347 pretend that they're NULL when writing out the code to recreate the
348 memento that uses them. */
349 if (recording::location *loc = m->dyn_cast_location ())
350 if (!loc->created_by_user ())
351 return "NULL";
353 const char **slot = m_identifiers.get (m);
354 if (!slot)
356 get_context ().add_error (NULL,
357 "unable to find identifier for %p: %s",
358 (void *)m,
359 m->get_debug_string ());
360 gcc_unreachable ();
362 return *slot;
365 /* Locate the C identifier for the given rvalue, wrapping it within
366 a gcc_*_as_rvalue upcast if necessary. */
368 const char *
369 reproducer::get_identifier_as_rvalue (recording::rvalue *m)
371 return m->access_as_rvalue (*this);
374 /* Locate the C identifier for the given lvalue, wrapping it within
375 a gcc_*_as_lvalue upcast if necessary. */
377 const char *
378 reproducer::get_identifier_as_lvalue (recording::lvalue *m)
380 return m->access_as_lvalue (*this);
383 /* Locate the C identifier for the given type, wrapping it within
384 a gcc_*_as_type upcast if necessary. */
386 const char *
387 reproducer::get_identifier_as_type (recording::type *m)
389 return m->access_as_type (*this);
392 /* Formatted printing, allocating to a buffer (or exiting the process if
393 the allocation fails).
395 The buffer exists until the allocator is cleaned up, and is freed at
396 that point, so the caller doesn't need to track the result.
398 Note that we can't use ggc_printf since we're not within the compiler
399 proper (when within gcc_jit_context_dump_reproducer_to_file). */
401 char *
402 reproducer::xstrdup_printf (const char *fmt, ...)
404 char *result;
405 va_list ap;
406 va_start (ap, fmt);
407 result = m_allocator.xstrdup_printf_va (fmt, ap);
408 va_end (ap);
409 return result;
412 /**********************************************************************
413 Recording.
414 **********************************************************************/
416 /* Get the playback::location for the given recording::location,
417 handling a NULL input with a NULL output. */
419 playback::location *
420 recording::playback_location (replayer *r, recording::location *loc)
422 if (loc)
423 return loc->playback_location (r);
424 else
425 return NULL;
428 /* Get a const char * for the given recording::string
429 handling a NULL input with a NULL output. */
431 const char *
432 recording::playback_string (recording::string *str)
434 if (str)
435 return str->c_str ();
436 else
437 return NULL;
440 /* Get the playback::block for the given recording::block,
441 handling a NULL input with a NULL output. */
443 playback::block *
444 recording::playback_block (recording::block *b)
446 if (b)
447 return b->playback_block ();
448 else
449 return NULL;
452 /* Methods of cc::jit::recording::context. */
454 /* The constructor for gcc::jit::recording::context, used by
455 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
457 recording::context::context (context *parent_ctxt)
458 : log_user (NULL),
459 m_parent_ctxt (parent_ctxt),
460 m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this),
461 m_timer (NULL),
462 m_error_count (0),
463 m_first_error_str (NULL),
464 m_owns_first_error_str (false),
465 m_last_error_str (NULL),
466 m_owns_last_error_str (false),
467 m_mementos (),
468 m_compound_types (),
469 m_globals (),
470 m_functions (),
471 m_FILE_type (NULL),
472 m_builtins_manager(NULL)
474 if (parent_ctxt)
476 /* Inherit options from parent. */
477 for (unsigned i = 0;
478 i < sizeof (m_str_options) / sizeof (m_str_options[0]);
479 i++)
481 const char *parent_opt = parent_ctxt->m_str_options[i];
482 m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
484 memcpy (m_int_options,
485 parent_ctxt->m_int_options,
486 sizeof (m_int_options));
487 memcpy (m_bool_options,
488 parent_ctxt->m_bool_options,
489 sizeof (m_bool_options));
490 memcpy (m_inner_bool_options,
491 parent_ctxt->m_inner_bool_options,
492 sizeof (m_inner_bool_options));
493 set_logger (parent_ctxt->get_logger ());
495 else
497 memset (m_str_options, 0, sizeof (m_str_options));
498 memset (m_int_options, 0, sizeof (m_int_options));
499 memset (m_bool_options, 0, sizeof (m_bool_options));
500 memset (m_inner_bool_options, 0, sizeof (m_inner_bool_options));
503 memset (m_basic_types, 0, sizeof (m_basic_types));
506 /* The destructor for gcc::jit::recording::context, implicitly used by
507 gcc_jit_context_release. */
509 recording::context::~context ()
511 JIT_LOG_SCOPE (get_logger ());
512 int i;
513 memento *m;
514 FOR_EACH_VEC_ELT (m_mementos, i, m)
516 delete m;
519 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
520 free (m_str_options[i]);
522 char *optname;
523 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
524 free (optname);
526 if (m_builtins_manager)
527 delete m_builtins_manager;
529 if (m_owns_first_error_str)
530 free (m_first_error_str);
532 if (m_owns_last_error_str)
533 if (m_last_error_str != m_first_error_str)
534 free (m_last_error_str);
537 /* Add the given mememto to the list of those tracked by this
538 gcc::jit::recording::context, so that e.g. it can be deleted
539 when this context is released. */
541 void
542 recording::context::record (memento *m)
544 gcc_assert (m);
546 m_mementos.safe_push (m);
549 /* Replay this context (and any parents) into the given replayer. */
551 void
552 recording::context::replay_into (replayer *r)
554 JIT_LOG_SCOPE (get_logger ());
555 int i;
556 memento *m;
558 /* If we have a parent context, we must replay it. This will
559 recursively walk backwards up the historical tree, then replay things
560 forwards "in historical order", starting with the ultimate parent
561 context, until we reach the "this" context.
563 Note that we fully replay the parent, then fully replay the child,
564 which means that inter-context references can only exist from child
565 to parent, not the other way around.
567 All of this replaying is suboptimal - it would be better to do the
568 work for the parent context *once*, rather than replaying the parent
569 every time we replay each child. However, fixing this requires deep
570 surgery to lifetime-management: we'd need every context family tree
571 to have its own GC heap, and to initialize the GCC code to use that
572 heap (with a mutex on such a heap). */
573 if (m_parent_ctxt)
574 m_parent_ctxt->replay_into (r);
576 if (r->errors_occurred ())
577 return;
579 /* Replay this context's saved operations into r. */
580 FOR_EACH_VEC_ELT (m_mementos, i, m)
582 /* Disabled low-level debugging, here if we need it: print what
583 we're replaying.
584 Note that the calls to get_debug_string might lead to more
585 mementos being created for the strings.
586 This can also be used to exercise the debug_string
587 machinery. */
588 if (0)
589 printf ("context %p replaying (%p): %s\n",
590 (void *)this, (void *)m, m->get_debug_string ());
592 m->replay_into (r);
594 if (r->errors_occurred ())
595 return;
599 /* During a playback, we associate objects from the recording with
600 their counterparts during this playback.
602 For simplicity, we store this within the recording objects.
604 The following method cleans away these associations, to ensure that
605 we never have out-of-date associations lingering on subsequent
606 playbacks (the objects pointed to are GC-managed, but the
607 recording objects don't own refs to them). */
609 void
610 recording::context::disassociate_from_playback ()
612 JIT_LOG_SCOPE (get_logger ());
613 int i;
614 memento *m;
616 if (m_parent_ctxt)
617 m_parent_ctxt->disassociate_from_playback ();
619 FOR_EACH_VEC_ELT (m_mementos, i, m)
621 m->set_playback_obj (NULL);
625 /* Create a recording::string instance and add it to this context's list
626 of mementos.
628 This creates a fresh copy of the given 0-terminated buffer. */
630 recording::string *
631 recording::context::new_string (const char *text)
633 if (!text)
634 return NULL;
636 recording::string *result = new string (this, text);
637 record (result);
638 return result;
641 /* Create a recording::location instance and add it to this context's
642 list of mementos.
644 Implements the post-error-checking part of
645 gcc_jit_context_new_location. */
647 recording::location *
648 recording::context::new_location (const char *filename,
649 int line,
650 int column,
651 bool created_by_user)
653 recording::location *result =
654 new recording::location (this,
655 new_string (filename),
656 line, column,
657 created_by_user);
658 record (result);
659 return result;
662 /* If we haven't seen this enum value yet, create a recording::type
663 instance and add it to this context's list of mementos.
665 If we have seen it before, reuse our cached value, so that repeated
666 calls on the context give the same object.
668 If we have a parent context, the cache is within the ultimate
669 ancestor context.
671 Implements the post-error-checking part of
672 gcc_jit_context_get_type. */
674 recording::type *
675 recording::context::get_type (enum gcc_jit_types kind)
677 if (!m_basic_types[kind])
679 if (m_parent_ctxt)
680 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
681 else
683 recording::type *result = new memento_of_get_type (this, kind);
684 record (result);
685 m_basic_types[kind] = result;
689 return m_basic_types[kind];
692 /* Get a recording::type instance for the given size and signedness.
693 This is implemented in terms of recording::context::get_type
694 above.
696 Implements the post-error-checking part of
697 gcc_jit_context_get_int_type. */
699 recording::type *
700 recording::context::get_int_type (int num_bytes, int is_signed)
702 /* We can't use a switch here since some of the values are macros affected
703 by options; e.g. i386.h has
704 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
705 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
706 are in bits, rather than bytes.
708 const int num_bits = num_bytes * 8;
709 if (num_bits == INT_TYPE_SIZE)
710 return get_type (is_signed
711 ? GCC_JIT_TYPE_INT
712 : GCC_JIT_TYPE_UNSIGNED_INT);
713 if (num_bits == CHAR_TYPE_SIZE)
714 return get_type (is_signed
715 ? GCC_JIT_TYPE_SIGNED_CHAR
716 : GCC_JIT_TYPE_UNSIGNED_CHAR);
717 if (num_bits == SHORT_TYPE_SIZE)
718 return get_type (is_signed
719 ? GCC_JIT_TYPE_SHORT
720 : GCC_JIT_TYPE_UNSIGNED_SHORT);
721 if (num_bits == LONG_TYPE_SIZE)
722 return get_type (is_signed
723 ? GCC_JIT_TYPE_LONG
724 : GCC_JIT_TYPE_UNSIGNED_LONG);
725 if (num_bits == LONG_LONG_TYPE_SIZE)
726 return get_type (is_signed
727 ? GCC_JIT_TYPE_LONG_LONG
728 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
730 /* Some other size, not corresponding to the C int types. */
731 /* To be written: support arbitrary other sizes, sharing by
732 memoizing at the recording::context level? */
733 gcc_unreachable ();
736 /* Create a recording::type instance and add it to this context's list
737 of mementos.
739 Implements the post-error-checking part of
740 gcc_jit_context_new_array_type. */
742 recording::type *
743 recording::context::new_array_type (recording::location *loc,
744 recording::type *element_type,
745 int num_elements)
747 if (struct_ *s = element_type->dyn_cast_struct ())
748 if (!s->get_fields ())
750 add_error (NULL,
751 "cannot create an array of type %s"
752 " until the fields have been set",
753 s->get_name ()->c_str ());
754 return NULL;
756 recording::type *result =
757 new recording::array_type (this, loc, element_type, num_elements);
758 record (result);
759 return result;
762 /* Create a recording::field instance and add it to this context's list
763 of mementos.
765 Implements the post-error-checking part of
766 gcc_jit_context_new_field. */
768 recording::field *
769 recording::context::new_field (recording::location *loc,
770 recording::type *type,
771 const char *name)
773 recording::field *result =
774 new recording::field (this, loc, type, new_string (name));
775 record (result);
776 return result;
779 /* Create a recording::struct_ instance and add it to this context's
780 list of mementos and list of compound types.
782 Implements the post-error-checking part of
783 gcc_jit_context_new_struct_type. */
785 recording::struct_ *
786 recording::context::new_struct_type (recording::location *loc,
787 const char *name)
789 recording::struct_ *result = new struct_ (this, loc, new_string (name));
790 record (result);
791 m_compound_types.safe_push (result);
792 return result;
795 /* Create a recording::union_ instance and add it to this context's
796 list of mementos and list of compound types.
798 Implements the first post-error-checking part of
799 gcc_jit_context_new_union_type. */
801 recording::union_ *
802 recording::context::new_union_type (recording::location *loc,
803 const char *name)
805 recording::union_ *result = new union_ (this, loc, new_string (name));
806 record (result);
807 m_compound_types.safe_push (result);
808 return result;
811 /* Create a recording::function_type instance and add it to this context's
812 list of mementos.
814 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
816 recording::function_type *
817 recording::context::new_function_type (recording::type *return_type,
818 int num_params,
819 recording::type **param_types,
820 int is_variadic)
822 recording::function_type *fn_type
823 = new function_type (this,
824 return_type,
825 num_params,
826 param_types,
827 is_variadic);
828 record (fn_type);
829 return fn_type;
832 /* Create a recording::type instance and add it to this context's list
833 of mementos.
835 Implements the post-error-checking part of
836 gcc_jit_context_new_function_ptr_type. */
838 recording::type *
839 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
840 recording::type *return_type,
841 int num_params,
842 recording::type **param_types,
843 int is_variadic)
845 recording::function_type *fn_type
846 = new_function_type (return_type,
847 num_params,
848 param_types,
849 is_variadic);
851 /* Return a pointer-type to the function type. */
852 return fn_type->get_pointer ();
855 /* Create a recording::param instance and add it to this context's list
856 of mementos.
858 Implements the post-error-checking part of
859 gcc_jit_context_new_param. */
861 recording::param *
862 recording::context::new_param (recording::location *loc,
863 recording::type *type,
864 const char *name)
866 recording::param *result = new recording::param (this, loc, type, new_string (name));
867 record (result);
868 return result;
871 /* Create a recording::function instance and add it to this context's list
872 of mementos and list of functions.
874 Implements the post-error-checking part of
875 gcc_jit_context_new_function. */
877 recording::function *
878 recording::context::new_function (recording::location *loc,
879 enum gcc_jit_function_kind kind,
880 recording::type *return_type,
881 const char *name,
882 int num_params,
883 recording::param **params,
884 int is_variadic,
885 enum built_in_function builtin_id)
887 recording::function *result =
888 new recording::function (this,
889 loc, kind, return_type,
890 new_string (name),
891 num_params, params, is_variadic,
892 builtin_id);
893 record (result);
894 m_functions.safe_push (result);
896 return result;
899 /* Locate the builtins_manager (if any) for this family of contexts,
900 creating it if it doesn't exist already.
902 All of the recording contexts in a family share one builtins_manager:
903 if we have a child context, follow the parent links to get the
904 ultimate ancestor context, and look for it/store it there. */
906 builtins_manager *
907 recording::context::get_builtins_manager ()
909 if (m_parent_ctxt)
910 return m_parent_ctxt->get_builtins_manager ();
912 if (!m_builtins_manager)
913 m_builtins_manager = new builtins_manager (this);
915 return m_builtins_manager;
918 /* Get a recording::function instance, which is lazily-created and added
919 to the context's lists of mementos.
921 Implements the post-error-checking part of
922 gcc_jit_context_get_builtin_function. */
924 recording::function *
925 recording::context::get_builtin_function (const char *name)
927 builtins_manager *bm = get_builtins_manager ();
928 return bm->get_builtin_function (name);
931 /* Create a recording::global instance and add it to this context's list
932 of mementos.
934 Implements the post-error-checking part of
935 gcc_jit_context_new_global. */
937 recording::lvalue *
938 recording::context::new_global (recording::location *loc,
939 enum gcc_jit_global_kind kind,
940 recording::type *type,
941 const char *name)
943 recording::global *result =
944 new recording::global (this, loc, kind, type, new_string (name));
945 record (result);
946 m_globals.safe_push (result);
948 return result;
951 /* Create a recording::memento_of_new_string_literal instance and add it
952 to this context's list of mementos.
954 Implements the post-error-checking part of
955 gcc_jit_context_new_string_literal. */
957 recording::rvalue *
958 recording::context::new_string_literal (const char *value)
960 recording::rvalue *result =
961 new memento_of_new_string_literal (this, NULL, new_string (value));
962 record (result);
963 return result;
966 /* Create a recording::unary_op instance and add it to this context's
967 list of mementos.
969 Implements the post-error-checking part of
970 gcc_jit_context_new_unary_op. */
972 recording::rvalue *
973 recording::context::new_unary_op (recording::location *loc,
974 enum gcc_jit_unary_op op,
975 recording::type *result_type,
976 recording::rvalue *a)
978 recording::rvalue *result =
979 new unary_op (this, loc, op, result_type, a);
980 record (result);
981 return result;
984 /* Create a recording::binary_op instance and add it to this context's
985 list of mementos.
987 Implements the post-error-checking part of
988 gcc_jit_context_new_binary_op. */
990 recording::rvalue *
991 recording::context::new_binary_op (recording::location *loc,
992 enum gcc_jit_binary_op op,
993 recording::type *result_type,
994 recording::rvalue *a,
995 recording::rvalue *b)
997 recording::rvalue *result =
998 new binary_op (this, loc, op, result_type, a, b);
999 record (result);
1000 return result;
1003 /* Create a recording::comparison instance and add it to this context's
1004 list of mementos.
1006 Implements the post-error-checking part of
1007 gcc_jit_context_new_comparison. */
1009 recording::rvalue *
1010 recording::context::new_comparison (recording::location *loc,
1011 enum gcc_jit_comparison op,
1012 recording::rvalue *a,
1013 recording::rvalue *b)
1015 recording::rvalue *result = new comparison (this, loc, op, a, b);
1016 record (result);
1017 return result;
1020 /* Create a recording::cast instance and add it to this context's list
1021 of mementos.
1023 Implements the post-error-checking part of
1024 gcc_jit_context_new_cast. */
1026 recording::rvalue *
1027 recording::context::new_cast (recording::location *loc,
1028 recording::rvalue *expr,
1029 recording::type *type_)
1031 recording::rvalue *result = new cast (this, loc, expr, type_);
1032 record (result);
1033 return result;
1036 /* Create a recording::call instance and add it to this context's list
1037 of mementos.
1039 Implements the post-error-checking part of
1040 gcc_jit_context_new_call. */
1042 recording::rvalue *
1043 recording::context::new_call (recording::location *loc,
1044 function *func,
1045 int numargs , recording::rvalue **args)
1047 recording::rvalue *result = new call (this, loc, func, numargs, args);
1048 record (result);
1049 return result;
1052 /* Create a recording::call_through_ptr instance and add it to this
1053 context's list of mementos.
1055 Implements the post-error-checking part of
1056 gcc_jit_context_new_call_through_ptr. */
1058 recording::rvalue *
1059 recording::context::new_call_through_ptr (recording::location *loc,
1060 recording::rvalue *fn_ptr,
1061 int numargs,
1062 recording::rvalue **args)
1064 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
1065 record (result);
1066 return result;
1069 /* Create a recording::array_access instance and add it to this context's list
1070 of mementos.
1072 Implements the post-error-checking part of
1073 gcc_jit_context_new_array_access. */
1075 recording::lvalue *
1076 recording::context::new_array_access (recording::location *loc,
1077 recording::rvalue *ptr,
1078 recording::rvalue *index)
1080 recording::lvalue *result = new array_access (this, loc, ptr, index);
1081 record (result);
1082 return result;
1085 /* Create a recording::case_ instance and add it to this context's list
1086 of mementos.
1088 Implements the post-error-checking part of
1089 gcc_jit_context_new_case. */
1091 recording::case_ *
1092 recording::context::new_case (recording::rvalue *min_value,
1093 recording::rvalue *max_value,
1094 recording::block *block)
1096 recording::case_ *result = new case_ (this, min_value, max_value, block);
1097 record (result);
1098 return result;
1101 /* Set the given string option for this context, or add an error if
1102 it's not recognized.
1104 Implements the post-error-checking part of
1105 gcc_jit_context_set_str_option. */
1107 void
1108 recording::context::set_str_option (enum gcc_jit_str_option opt,
1109 const char *value)
1111 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
1113 add_error (NULL,
1114 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
1115 return;
1117 free (m_str_options[opt]);
1118 m_str_options[opt] = value ? xstrdup (value) : NULL;
1119 log_str_option (opt);
1122 /* Set the given integer option for this context, or add an error if
1123 it's not recognized.
1125 Implements the post-error-checking part of
1126 gcc_jit_context_set_int_option. */
1128 void
1129 recording::context::set_int_option (enum gcc_jit_int_option opt,
1130 int value)
1132 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
1134 add_error (NULL,
1135 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
1136 return;
1138 m_int_options[opt] = value;
1139 log_int_option (opt);
1142 /* Set the given boolean option for this context, or add an error if
1143 it's not recognized.
1145 Implements the post-error-checking part of
1146 gcc_jit_context_set_bool_option. */
1148 void
1149 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
1150 int value)
1152 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
1154 add_error (NULL,
1155 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
1156 return;
1158 m_bool_options[opt] = value ? true : false;
1159 log_bool_option (opt);
1162 void
1163 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt,
1164 int value)
1166 gcc_assert (inner_opt >= 0 && inner_opt < NUM_INNER_BOOL_OPTIONS);
1167 m_inner_bool_options[inner_opt] = value ? true : false;
1168 log_inner_bool_option (inner_opt);
1172 /* Add the given optname to this context's list of extra options.
1174 Implements the post-error-checking part of
1175 gcc_jit_context_add_command_line_option. */
1177 void
1178 recording::context::add_command_line_option (const char *optname)
1180 m_command_line_options.safe_push (xstrdup (optname));
1183 /* Add any user-provided extra options, starting with any from
1184 parent contexts.
1185 Called by playback::context::make_fake_args. */
1187 void
1188 recording::context::append_command_line_options (vec <char *> *argvec)
1190 if (m_parent_ctxt)
1191 m_parent_ctxt->append_command_line_options (argvec);
1193 int i;
1194 char *optname;
1195 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1196 argvec->safe_push (xstrdup (optname));
1199 /* Add the given dumpname/out_ptr pair to this context's list of requested
1200 dumps.
1202 Implements the post-error-checking part of
1203 gcc_jit_context_enable_dump. */
1205 void
1206 recording::context::enable_dump (const char *dumpname,
1207 char **out_ptr)
1209 requested_dump d;
1210 gcc_assert (dumpname);
1211 gcc_assert (out_ptr);
1213 d.m_dumpname = dumpname;
1214 d.m_out_ptr = out_ptr;
1215 *out_ptr = NULL;
1216 m_requested_dumps.safe_push (d);
1219 /* Validate this context, and if it passes, compile it to memory
1220 (within a mutex).
1222 Implements the post-error-checking part of
1223 gcc_jit_context_compile. */
1225 result *
1226 recording::context::compile ()
1228 JIT_LOG_SCOPE (get_logger ());
1230 log_all_options ();
1232 validate ();
1234 if (errors_occurred ())
1235 return NULL;
1237 /* Set up a compile_to_memory playback context. */
1238 ::gcc::jit::playback::compile_to_memory replayer (this);
1240 /* Use it. */
1241 replayer.compile ();
1243 /* Get the jit::result (or NULL) from the
1244 compile_to_memory playback context. */
1245 return replayer.get_result_obj ();
1248 /* Validate this context, and if it passes, compile it to a file
1249 (within a mutex).
1251 Implements the post-error-checking part of
1252 gcc_jit_context_compile_to_file. */
1254 void
1255 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
1256 const char *output_path)
1258 JIT_LOG_SCOPE (get_logger ());
1260 log_all_options ();
1262 validate ();
1264 if (errors_occurred ())
1265 return;
1267 /* Set up a compile_to_file playback context. */
1268 ::gcc::jit::playback::compile_to_file replayer (this,
1269 output_kind,
1270 output_path);
1272 /* Use it. */
1273 replayer.compile ();
1276 /* Format the given error using printf's conventions, print
1277 it to stderr, and add it to the context. */
1279 void
1280 recording::context::add_error (location *loc, const char *fmt, ...)
1282 va_list ap;
1283 va_start (ap, fmt);
1284 add_error_va (loc, fmt, ap);
1285 va_end (ap);
1288 /* Format the given error using printf's conventions, print
1289 it to stderr, and add it to the context. */
1291 void
1292 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
1294 int len;
1295 char *malloced_msg;
1296 const char *errmsg;
1297 bool has_ownership;
1299 JIT_LOG_SCOPE (get_logger ());
1301 len = vasprintf (&malloced_msg, fmt, ap);
1302 if (malloced_msg == NULL || len < 0)
1304 errmsg = "out of memory generating error message";
1305 has_ownership = false;
1307 else
1309 errmsg = malloced_msg;
1310 has_ownership = true;
1312 if (get_logger ())
1313 get_logger ()->log ("error %i: %s", m_error_count, errmsg);
1315 const char *ctxt_progname =
1316 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
1317 if (!ctxt_progname)
1318 ctxt_progname = "libgccjit.so";
1320 if (loc)
1321 fprintf (stderr, "%s: %s: error: %s\n",
1322 ctxt_progname,
1323 loc->get_debug_string (),
1324 errmsg);
1325 else
1326 fprintf (stderr, "%s: error: %s\n",
1327 ctxt_progname,
1328 errmsg);
1330 if (!m_error_count)
1332 m_first_error_str = const_cast <char *> (errmsg);
1333 m_owns_first_error_str = has_ownership;
1336 if (m_owns_last_error_str)
1337 if (m_last_error_str != m_first_error_str)
1338 free (m_last_error_str);
1339 m_last_error_str = const_cast <char *> (errmsg);
1340 m_owns_last_error_str = has_ownership;
1342 m_error_count++;
1345 /* Get the message for the first error that occurred on this context, or
1346 NULL if no errors have occurred on it.
1348 Implements the post-error-checking part of
1349 gcc_jit_context_get_first_error. */
1351 const char *
1352 recording::context::get_first_error () const
1354 return m_first_error_str;
1357 /* Get the message for the last error that occurred on this context, or
1358 NULL if no errors have occurred on it.
1360 Implements the post-error-checking part of
1361 gcc_jit_context_get_last_error. */
1363 const char *
1364 recording::context::get_last_error () const
1366 return m_last_error_str;
1369 /* Lazily generate and record a recording::type representing an opaque
1370 struct named "FILE".
1372 For use if client code tries to dereference the result of
1373 get_type (GCC_JIT_TYPE_FILE_PTR). */
1375 recording::type *
1376 recording::context::get_opaque_FILE_type ()
1378 if (!m_FILE_type)
1379 m_FILE_type = new_struct_type (NULL, "FILE");
1380 return m_FILE_type;
1383 /* Dump a C-like representation of the given context to the given path.
1384 If UPDATE_LOCATIONS is true, update the locations within the
1385 context's mementos to point to the dumpfile.
1387 Implements the post-error-checking part of
1388 gcc_jit_context_dump_to_file. */
1390 void
1391 recording::context::dump_to_file (const char *path, bool update_locations)
1393 int i;
1394 dump d (*this, path, update_locations);
1396 /* Forward declaration of structs and unions. */
1397 compound_type *st;
1398 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1400 d.write ("%s;\n\n", st->get_debug_string ());
1403 /* Content of structs, where set. */
1404 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1405 if (st->get_fields ())
1407 st->get_fields ()->write_to_dump (d);
1408 d.write ("\n");
1411 /* Globals. */
1412 global *g;
1413 FOR_EACH_VEC_ELT (m_globals, i, g)
1415 g->write_to_dump (d);
1417 if (!m_globals.is_empty ())
1418 d.write ("\n");
1420 function *fn;
1421 FOR_EACH_VEC_ELT (m_functions, i, fn)
1423 fn->write_to_dump (d);
1427 static const char * const
1428 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
1429 "GCC_JIT_STR_OPTION_PROGNAME"
1432 static const char * const
1433 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
1434 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1437 static const char * const
1438 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
1439 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1440 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1441 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1442 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1443 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1444 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1445 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1446 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1449 static const char * const
1450 inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = {
1451 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1452 "gcc_jit_context_set_bool_use_external_driver"
1455 /* Write the current value of all options to the log file (if any). */
1457 void
1458 recording::context::log_all_options () const
1460 int opt_idx;
1462 if (!get_logger ())
1463 return;
1465 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1466 log_str_option ((enum gcc_jit_str_option)opt_idx);
1468 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1469 log_int_option ((enum gcc_jit_int_option)opt_idx);
1471 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1472 log_bool_option ((enum gcc_jit_bool_option)opt_idx);
1473 for (opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1474 log_inner_bool_option ((enum inner_bool_option)opt_idx);
1477 /* Write the current value of the given string option to the
1478 log file (if any). */
1480 void
1481 recording::context::log_str_option (enum gcc_jit_str_option opt) const
1483 gcc_assert (opt < GCC_JIT_NUM_STR_OPTIONS);
1484 if (get_logger ())
1486 if (m_str_options[opt])
1487 log ("%s: \"%s\"",
1488 str_option_reproducer_strings[opt],
1489 m_str_options[opt]);
1490 else
1491 log ("%s: NULL",
1492 str_option_reproducer_strings[opt]);
1496 /* Write the current value of the given int option to the
1497 log file (if any). */
1499 void
1500 recording::context::log_int_option (enum gcc_jit_int_option opt) const
1502 gcc_assert (opt < GCC_JIT_NUM_INT_OPTIONS);
1503 if (get_logger ())
1504 log ("%s: %i",
1505 int_option_reproducer_strings[opt],
1506 m_int_options[opt]);
1509 /* Write the current value of the given bool option to the
1510 log file (if any). */
1512 void
1513 recording::context::log_bool_option (enum gcc_jit_bool_option opt) const
1515 gcc_assert (opt < GCC_JIT_NUM_BOOL_OPTIONS);
1516 if (get_logger ())
1517 log ("%s: %s",
1518 bool_option_reproducer_strings[opt],
1519 m_bool_options[opt] ? "true" : "false");
1522 /* Write the current value of the given "inner" bool option to the
1523 log file (if any). */
1525 void
1526 recording::context::log_inner_bool_option (enum inner_bool_option opt) const
1528 gcc_assert (opt < NUM_INNER_BOOL_OPTIONS);
1529 if (get_logger ())
1530 log ("%s: %s",
1531 inner_bool_option_reproducer_strings[opt],
1532 m_inner_bool_options[opt] ? "true" : "false");
1535 /* Write C source code to PATH that attempts to replay the API
1536 calls made to this context (and its parents), for use in
1537 minimizing test cases for libgccjit.
1539 Implements the post-error-checking part of
1540 gcc_jit_context_dump_reproducer_to_file. */
1542 void
1543 recording::context::dump_reproducer_to_file (const char *path)
1545 JIT_LOG_SCOPE (get_logger ());
1546 reproducer r (*this, path);
1548 /* Generate the "ancestry" of this context, as a list. */
1549 auto_vec <context *> ascending_contexts;
1550 for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
1551 ascending_contexts.safe_push (ctxt);
1553 /* Reverse the list, giving a list of contexts from
1554 top-most parent context down through to youngest child context.
1555 We will use this list as the parameters of the functions in
1556 our generated file. */
1557 unsigned num_ctxts = ascending_contexts.length ();
1558 auto_vec <context *> contexts (num_ctxts);
1559 for (unsigned i = 0; i < num_ctxts; i++)
1560 contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
1562 /* contexts[0] should be the top-level context. */
1563 gcc_assert (contexts[0]);
1564 gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
1566 /* The final element in contexts should be "this". */
1567 gcc_assert (contexts[contexts.length () - 1] == this);
1568 gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
1569 == contexts[0]);
1571 r.write ("/* This code was autogenerated by"
1572 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1573 print_version (r.get_file (), " ", false);
1574 r.write ("*/\n");
1575 r.write ("#include <libgccjit.h>\n\n");
1576 r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1577 r.write ("static void\nset_options (");
1578 r.write_params (contexts);
1579 r.write (");\n\n");
1580 r.write ("static void\ncreate_code (");
1581 r.write_params (contexts);
1582 r.write (");\n\n");
1583 r.write ("int\nmain (int argc, const char **argv)\n");
1584 r.write ("{\n");
1585 for (unsigned i = 0; i < num_ctxts; i++)
1586 r.write (" gcc_jit_context *%s;\n",
1587 r.get_identifier (contexts[i]));
1588 r.write (" gcc_jit_result *result;\n"
1589 "\n");
1591 /* Create the contexts.
1592 The top-level context is acquired from a clean slate, the others as
1593 children of the prior context. */
1594 r.write (" %s = gcc_jit_context_acquire ();\n",
1595 r.get_identifier (contexts[0]));
1596 for (unsigned i = 1; i < num_ctxts; i++)
1597 r.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1598 r.get_identifier (contexts[i]),
1599 r.get_identifier (contexts[i - 1]));
1600 r.write (" set_options (");
1601 r.write_args (contexts);
1602 r.write (");\n");
1603 r.write (" create_code (");
1604 r.write_args (contexts);
1605 r.write (");\n");
1607 r.write (" result = gcc_jit_context_compile (%s);\n",
1608 r.get_identifier (this));
1610 for (unsigned i = num_ctxts; i > 0; i--)
1611 r.write (" gcc_jit_context_release (%s);\n",
1612 r.get_identifier (contexts[i - 1]));
1614 r.write (" gcc_jit_result_release (result);\n"
1615 " return 0;\n"
1616 "}\n\n");
1618 /* Define (char *) variables for use in calls to
1619 gcc_jit_context_enable_dump. */
1620 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1622 if (m_requested_dumps.length ())
1624 r.write ("/* Requested dumps for %s. */\n",
1625 r.get_identifier (contexts[ctxt_idx]));
1626 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1627 r.write ("static char *dump_%p;\n",
1628 (void *)&m_requested_dumps[i]);
1629 r.write ("\n");
1633 /* Write out values of options. */
1634 r.write ("static void\nset_options (");
1635 r.write_params (contexts);
1636 r.write (")\n{\n");
1637 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1639 if (ctxt_idx > 0)
1640 r.write ("\n");
1642 r.write (" /* Set options for %s. */\n",
1643 r.get_identifier (contexts[ctxt_idx]));
1645 r.write (" /* String options. */\n");
1646 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1648 r.write (" gcc_jit_context_set_str_option (%s,\n"
1649 " %s,\n",
1650 r.get_identifier (contexts[ctxt_idx]),
1651 str_option_reproducer_strings[opt_idx]);
1652 if (m_str_options[opt_idx])
1653 r.write (" \"%s\");\n",
1654 m_str_options[opt_idx]);
1655 else
1656 r.write (" NULL);\n");
1658 r.write (" /* Int options. */\n");
1659 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1660 r.write (" gcc_jit_context_set_int_option (%s,\n"
1661 " %s,\n"
1662 " %i);\n",
1663 r.get_identifier (contexts[ctxt_idx]),
1664 int_option_reproducer_strings[opt_idx],
1665 m_int_options[opt_idx]);
1666 r.write (" /* Boolean options. */\n");
1667 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1668 r.write (" gcc_jit_context_set_bool_option (%s,\n"
1669 " %s,\n"
1670 " %i);\n",
1671 r.get_identifier (contexts[ctxt_idx]),
1672 bool_option_reproducer_strings[opt_idx],
1673 m_bool_options[opt_idx]);
1674 for (int opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1675 r.write (" %s (%s, %i);\n",
1676 inner_bool_option_reproducer_strings[opt_idx],
1677 r.get_identifier (contexts[ctxt_idx]),
1678 m_inner_bool_options[opt_idx]);
1680 if (!m_command_line_options.is_empty ())
1682 int i;
1683 char *optname;
1684 r.write (" /* User-provided command-line options. */\n");
1685 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1686 r.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1687 r.get_identifier (contexts[ctxt_idx]),
1688 optname);
1691 if (m_requested_dumps.length ())
1693 r.write (" /* Requested dumps. */\n");
1694 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1695 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1697 r.write (" gcc_jit_context_enable_dump (%s,\n"
1698 " \"%s\",\n"
1699 " &dump_%p);\n",
1700 r.get_identifier (contexts[ctxt_idx]),
1701 m_requested_dumps[i].m_dumpname,
1702 (void *)&m_requested_dumps[i]);
1706 r.write ("}\n\n");
1708 r.write ("static void\ncreate_code (");
1709 r.write_params (contexts);
1710 r.write (")\n"
1711 "{\n");
1712 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1714 memento *m;
1715 int i;
1716 if (ctxt_idx > 0)
1717 r.write ("\n\n");
1719 r.write (" /* Replay of API calls for %s. */\n",
1720 r.get_identifier (contexts[ctxt_idx]));
1721 FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
1722 m->write_reproducer (r);
1724 r.write ("}\n");
1727 /* Copy the requested dumps within this context and all ancestors into
1728 OUT. */
1730 void
1731 recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
1733 if (m_parent_ctxt)
1734 m_parent_ctxt->get_all_requested_dumps (out);
1736 out->reserve (m_requested_dumps.length ());
1737 out->splice (m_requested_dumps);
1740 /* This is a pre-compilation check for the context (and any parents).
1742 Detect errors within the context, adding errors if any are found. */
1744 void
1745 recording::context::validate ()
1747 JIT_LOG_SCOPE (get_logger ());
1749 if (m_parent_ctxt)
1750 m_parent_ctxt->validate ();
1752 int i;
1753 function *fn;
1754 FOR_EACH_VEC_ELT (m_functions, i, fn)
1755 fn->validate ();
1758 /* The implementation of class gcc::jit::recording::memento. */
1760 /* Get a (const char *) debug description of the given memento, by
1761 calling the pure-virtual make_debug_string hook, caching the
1762 result.
1764 It is intended that this should only be called in debugging and
1765 error-handling paths, so this doesn't need to be particularly
1766 optimized. */
1768 const char *
1769 recording::memento::get_debug_string ()
1771 if (!m_debug_string)
1772 m_debug_string = make_debug_string ();
1773 return m_debug_string->c_str ();
1776 /* Default implementation of recording::memento::write_to_dump, writing
1777 an indented form of the memento's debug string to the dump. */
1779 void
1780 recording::memento::write_to_dump (dump &d)
1782 d.write(" %s\n", get_debug_string ());
1785 /* The implementation of class gcc::jit::recording::string. */
1787 /* Constructor for gcc::jit::recording::string::string, allocating a
1788 copy of the given text using new char[]. */
1790 recording::string::string (context *ctxt, const char *text)
1791 : memento (ctxt)
1793 m_len = strlen (text);
1794 m_buffer = new char[m_len + 1];
1795 strcpy (m_buffer, text);
1798 /* Destructor for gcc::jit::recording::string::string. */
1800 recording::string::~string ()
1802 delete[] m_buffer;
1805 /* Function for making gcc::jit::recording::string instances on a
1806 context via printf-style formatting.
1808 It is intended that this should only be called in debugging and
1809 error-handling paths, so this doesn't need to be particularly
1810 optimized, hence the double-copy of the string is acceptable. */
1812 recording::string *
1813 recording::string::from_printf (context *ctxt, const char *fmt, ...)
1815 int len;
1816 va_list ap;
1817 char *buf;
1818 recording::string *result;
1820 va_start (ap, fmt);
1821 len = vasprintf (&buf, fmt, ap);
1822 va_end (ap);
1824 if (buf == NULL || len < 0)
1826 ctxt->add_error (NULL, "malloc failure");
1827 return NULL;
1830 result = ctxt->new_string (buf);
1831 free (buf);
1832 return result;
1835 /* Implementation of recording::memento::make_debug_string for strings,
1836 wrapping the given string in quotes and escaping as necessary. */
1838 recording::string *
1839 recording::string::make_debug_string ()
1841 /* Hack to avoid infinite recursion into strings when logging all
1842 mementos: don't re-escape strings: */
1843 if (m_buffer[0] == '"')
1844 return this;
1846 /* Wrap in quotes and do escaping etc */
1848 size_t sz = (1 /* opening quote */
1849 + (m_len * 2) /* each char might get escaped */
1850 + 1 /* closing quote */
1851 + 1); /* nil termintator */
1852 char *tmp = new char[sz];
1853 size_t len = 0;
1855 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1856 APPEND('"'); /* opening quote */
1857 for (size_t i = 0; i < m_len ; i++)
1859 char ch = m_buffer[i];
1860 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
1861 APPEND('\\');
1862 APPEND(ch);
1864 APPEND('"'); /* closing quote */
1865 #undef APPEND
1866 tmp[len] = '\0'; /* nil termintator */
1868 string *result = m_ctxt->new_string (tmp);
1870 delete[] tmp;
1871 return result;
1874 /* Implementation of recording::memento::write_reproducer for strings. */
1876 void
1877 recording::string::write_reproducer (reproducer &)
1879 /* Empty. */
1882 /* The implementation of class gcc::jit::recording::location. */
1884 /* Implementation of recording::memento::replay_into for locations.
1886 Create a new playback::location and store it into the
1887 recording::location's m_playback_obj field. */
1889 void
1890 recording::location::replay_into (replayer *r)
1892 m_playback_obj = r->new_location (this,
1893 m_filename->c_str (),
1894 m_line,
1895 m_column);
1898 /* Implementation of recording::memento::make_debug_string for locations,
1899 turning them into the usual form:
1900 FILENAME:LINE:COLUMN
1901 like we do when emitting diagnostics. */
1903 recording::string *
1904 recording::location::make_debug_string ()
1906 return string::from_printf (m_ctxt,
1907 "%s:%i:%i",
1908 m_filename->c_str (), m_line, m_column);
1911 /* Implementation of recording::memento::write_reproducer for locations. */
1913 void
1914 recording::location::write_reproducer (reproducer &r)
1916 const char *id = r.make_identifier (this, "loc");
1917 r.write (" gcc_jit_location *%s =\n"
1918 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1919 " %s, /* const char *filename */\n"
1920 " %i, /* int line */\n"
1921 " %i);/* int column */\n",
1923 r.get_identifier (get_context ()),
1924 m_filename->get_debug_string (),
1925 m_line, m_column);
1928 /* The implementation of class gcc::jit::recording::type. */
1930 /* Given a type T, get the type T*.
1932 If this doesn't already exist, generate a new memento_of_get_pointer
1933 instance and add it to this type's context's list of mementos.
1935 Otherwise, use the cached type.
1937 Implements the post-error-checking part of
1938 gcc_jit_type_get_pointer. */
1940 recording::type *
1941 recording::type::get_pointer ()
1943 if (!m_pointer_to_this_type)
1945 m_pointer_to_this_type = new memento_of_get_pointer (this);
1946 m_ctxt->record (m_pointer_to_this_type);
1948 return m_pointer_to_this_type;
1951 /* Given a type T, get the type const T.
1953 Implements the post-error-checking part of
1954 gcc_jit_type_get_const. */
1956 recording::type *
1957 recording::type::get_const ()
1959 recording::type *result = new memento_of_get_const (this);
1960 m_ctxt->record (result);
1961 return result;
1964 /* Given a type T, get the type volatile T.
1966 Implements the post-error-checking part of
1967 gcc_jit_type_get_volatile. */
1969 recording::type *
1970 recording::type::get_volatile ()
1972 recording::type *result = new memento_of_get_volatile (this);
1973 m_ctxt->record (result);
1974 return result;
1977 /* Given a type, get an aligned version of the type.
1979 Implements the post-error-checking part of
1980 gcc_jit_type_get_aligned. */
1982 recording::type *
1983 recording::type::get_aligned (size_t alignment_in_bytes)
1985 recording::type *result
1986 = new memento_of_get_aligned (this, alignment_in_bytes);
1987 m_ctxt->record (result);
1988 return result;
1991 const char *
1992 recording::type::access_as_type (reproducer &r)
1994 return r.get_identifier (this);
1997 /* Implementation of pure virtual hook recording::type::dereference for
1998 recording::memento_of_get_type. */
2000 recording::type *
2001 recording::memento_of_get_type::dereference ()
2003 switch (m_kind)
2005 default: gcc_unreachable ();
2007 case GCC_JIT_TYPE_VOID:
2008 return NULL;
2010 case GCC_JIT_TYPE_VOID_PTR:
2011 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
2013 case GCC_JIT_TYPE_BOOL:
2014 case GCC_JIT_TYPE_CHAR:
2015 case GCC_JIT_TYPE_SIGNED_CHAR:
2016 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2017 case GCC_JIT_TYPE_SHORT:
2018 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2019 case GCC_JIT_TYPE_INT:
2020 case GCC_JIT_TYPE_UNSIGNED_INT:
2021 case GCC_JIT_TYPE_LONG:
2022 case GCC_JIT_TYPE_UNSIGNED_LONG:
2023 case GCC_JIT_TYPE_LONG_LONG:
2024 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2025 case GCC_JIT_TYPE_FLOAT:
2026 case GCC_JIT_TYPE_DOUBLE:
2027 case GCC_JIT_TYPE_LONG_DOUBLE:
2028 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2029 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2030 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2031 /* Not a pointer: */
2032 return NULL;
2034 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2035 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
2037 case GCC_JIT_TYPE_SIZE_T:
2038 /* Not a pointer: */
2039 return NULL;
2041 case GCC_JIT_TYPE_FILE_PTR:
2042 /* Give the client code back an opaque "struct FILE". */
2043 return m_ctxt->get_opaque_FILE_type ();
2047 /* Implementation of pure virtual hook recording::type::is_int for
2048 recording::memento_of_get_type. */
2050 bool
2051 recording::memento_of_get_type::is_int () const
2053 switch (m_kind)
2055 default: gcc_unreachable ();
2057 case GCC_JIT_TYPE_VOID:
2058 return false;
2060 case GCC_JIT_TYPE_VOID_PTR:
2061 return false;
2063 case GCC_JIT_TYPE_BOOL:
2064 return false;
2066 case GCC_JIT_TYPE_CHAR:
2067 case GCC_JIT_TYPE_SIGNED_CHAR:
2068 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2069 case GCC_JIT_TYPE_SHORT:
2070 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2071 case GCC_JIT_TYPE_INT:
2072 case GCC_JIT_TYPE_UNSIGNED_INT:
2073 case GCC_JIT_TYPE_LONG:
2074 case GCC_JIT_TYPE_UNSIGNED_LONG:
2075 case GCC_JIT_TYPE_LONG_LONG:
2076 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2077 return true;
2079 case GCC_JIT_TYPE_FLOAT:
2080 case GCC_JIT_TYPE_DOUBLE:
2081 case GCC_JIT_TYPE_LONG_DOUBLE:
2082 return false;
2084 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2085 return false;
2087 case GCC_JIT_TYPE_SIZE_T:
2088 return true;
2090 case GCC_JIT_TYPE_FILE_PTR:
2091 return false;
2093 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2094 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2095 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2096 return false;
2100 /* Implementation of pure virtual hook recording::type::is_float for
2101 recording::memento_of_get_type. */
2103 bool
2104 recording::memento_of_get_type::is_float () const
2106 switch (m_kind)
2108 default: gcc_unreachable ();
2110 case GCC_JIT_TYPE_VOID:
2111 return false;
2113 case GCC_JIT_TYPE_VOID_PTR:
2114 return false;
2116 case GCC_JIT_TYPE_BOOL:
2117 return false;
2119 case GCC_JIT_TYPE_CHAR:
2120 case GCC_JIT_TYPE_SIGNED_CHAR:
2121 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2122 case GCC_JIT_TYPE_SHORT:
2123 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2124 case GCC_JIT_TYPE_INT:
2125 case GCC_JIT_TYPE_UNSIGNED_INT:
2126 case GCC_JIT_TYPE_LONG:
2127 case GCC_JIT_TYPE_UNSIGNED_LONG:
2128 case GCC_JIT_TYPE_LONG_LONG:
2129 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2130 return false;
2132 case GCC_JIT_TYPE_FLOAT:
2133 case GCC_JIT_TYPE_DOUBLE:
2134 case GCC_JIT_TYPE_LONG_DOUBLE:
2135 return true;
2137 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2138 return false;
2140 case GCC_JIT_TYPE_SIZE_T:
2141 return false;
2143 case GCC_JIT_TYPE_FILE_PTR:
2144 return false;
2146 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2147 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2148 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2149 return true;
2153 /* Implementation of pure virtual hook recording::type::is_bool for
2154 recording::memento_of_get_type. */
2156 bool
2157 recording::memento_of_get_type::is_bool () const
2159 switch (m_kind)
2161 default: gcc_unreachable ();
2163 case GCC_JIT_TYPE_VOID:
2164 return false;
2166 case GCC_JIT_TYPE_VOID_PTR:
2167 return false;
2169 case GCC_JIT_TYPE_BOOL:
2170 return true;
2172 case GCC_JIT_TYPE_CHAR:
2173 case GCC_JIT_TYPE_SIGNED_CHAR:
2174 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2175 case GCC_JIT_TYPE_SHORT:
2176 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2177 case GCC_JIT_TYPE_INT:
2178 case GCC_JIT_TYPE_UNSIGNED_INT:
2179 case GCC_JIT_TYPE_LONG:
2180 case GCC_JIT_TYPE_UNSIGNED_LONG:
2181 case GCC_JIT_TYPE_LONG_LONG:
2182 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2183 return false;
2185 case GCC_JIT_TYPE_FLOAT:
2186 case GCC_JIT_TYPE_DOUBLE:
2187 case GCC_JIT_TYPE_LONG_DOUBLE:
2188 return false;
2190 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2191 return false;
2193 case GCC_JIT_TYPE_SIZE_T:
2194 return false;
2196 case GCC_JIT_TYPE_FILE_PTR:
2197 return false;
2199 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2200 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2201 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2202 return false;
2206 /* Implementation of pure virtual hook recording::memento::replay_into
2207 for recording::memento_of_get_type. */
2209 void
2210 recording::memento_of_get_type::replay_into (replayer *r)
2212 set_playback_obj (r->get_type (m_kind));
2215 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2217 /* Descriptive strings for each of enum gcc_jit_types. */
2219 static const char * const get_type_strings[] = {
2220 "void", /* GCC_JIT_TYPE_VOID */
2221 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2223 "bool", /* GCC_JIT_TYPE_BOOL */
2225 "char", /* GCC_JIT_TYPE_CHAR */
2226 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2227 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2229 "short", /* GCC_JIT_TYPE_SHORT */
2230 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2232 "int", /* GCC_JIT_TYPE_INT */
2233 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2235 "long", /* GCC_JIT_TYPE_LONG */
2236 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2238 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2239 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2241 "float", /* GCC_JIT_TYPE_FLOAT */
2242 "double", /* GCC_JIT_TYPE_DOUBLE */
2243 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2245 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2247 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2249 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2251 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2252 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2253 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2257 /* Implementation of recording::memento::make_debug_string for
2258 results of get_type, using a simple table of type names. */
2260 recording::string *
2261 recording::memento_of_get_type::make_debug_string ()
2263 return m_ctxt->new_string (get_type_strings[m_kind]);
2266 static const char * const get_type_enum_strings[] = {
2267 "GCC_JIT_TYPE_VOID",
2268 "GCC_JIT_TYPE_VOID_PTR",
2269 "GCC_JIT_TYPE_BOOL",
2270 "GCC_JIT_TYPE_CHAR",
2271 "GCC_JIT_TYPE_SIGNED_CHAR",
2272 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2273 "GCC_JIT_TYPE_SHORT",
2274 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2275 "GCC_JIT_TYPE_INT",
2276 "GCC_JIT_TYPE_UNSIGNED_INT",
2277 "GCC_JIT_TYPE_LONG",
2278 "GCC_JIT_TYPE_UNSIGNED_LONG",
2279 "GCC_JIT_TYPE_LONG_LONG",
2280 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2281 "GCC_JIT_TYPE_FLOAT",
2282 "GCC_JIT_TYPE_DOUBLE",
2283 "GCC_JIT_TYPE_LONG_DOUBLE",
2284 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2285 "GCC_JIT_TYPE_SIZE_T",
2286 "GCC_JIT_TYPE_FILE_PTR",
2287 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2288 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2289 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2292 void
2293 recording::memento_of_get_type::write_reproducer (reproducer &r)
2295 const char *id = r.make_identifier (this, "type");
2296 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2298 r.get_identifier (get_context ()),
2299 get_type_enum_strings[m_kind]);
2302 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2304 /* Override of default implementation of
2305 recording::type::accepts_writes_from for get_pointer.
2307 Require a pointer type, and allowing writes to
2308 (const T *) from a (T*), but not the other way around. */
2310 bool
2311 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2313 /* Must be a pointer type: */
2314 type *rtype_points_to = rtype->is_pointer ();
2315 if (!rtype_points_to)
2316 return false;
2318 /* It's OK to assign to a (const T *) from a (T *). */
2319 return m_other_type->unqualified ()
2320 ->accepts_writes_from (rtype_points_to);
2323 /* Implementation of pure virtual hook recording::memento::replay_into
2324 for recording::memento_of_get_pointer. */
2326 void
2327 recording::memento_of_get_pointer::replay_into (replayer *)
2329 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2332 /* Implementation of recording::memento::make_debug_string for
2333 results of get_pointer, adding " *" to the underlying type,
2334 with special-casing to handle function pointer types. */
2336 recording::string *
2337 recording::memento_of_get_pointer::make_debug_string ()
2339 /* Special-case function pointer types, to put the "*" in parens between
2340 the return type and the params (for one level of dereferencing, at
2341 least). */
2342 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2343 return fn_type->make_debug_string_with_ptr ();
2345 return string::from_printf (m_ctxt,
2346 "%s *", m_other_type->get_debug_string ());
2349 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2351 void
2352 recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2354 /* We need to special-case function pointer types; see the notes in
2355 recording::function_type::write_deferred_reproducer. */
2356 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2358 fn_type->write_deferred_reproducer (r, this);
2359 return;
2362 const char *id = r.make_identifier (this, "type");
2363 r.write (" gcc_jit_type *%s =\n"
2364 " gcc_jit_type_get_pointer (%s);\n",
2366 r.get_identifier_as_type (m_other_type));
2369 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2371 /* Implementation of pure virtual hook recording::memento::replay_into
2372 for recording::memento_of_get_const. */
2374 void
2375 recording::memento_of_get_const::replay_into (replayer *)
2377 set_playback_obj (m_other_type->playback_type ()->get_const ());
2380 /* Implementation of recording::memento::make_debug_string for
2381 results of get_const, prepending "const ". */
2383 recording::string *
2384 recording::memento_of_get_const::make_debug_string ()
2386 return string::from_printf (m_ctxt,
2387 "const %s", m_other_type->get_debug_string ());
2390 /* Implementation of recording::memento::write_reproducer for const types. */
2392 void
2393 recording::memento_of_get_const::write_reproducer (reproducer &r)
2395 const char *id = r.make_identifier (this, "type");
2396 r.write (" gcc_jit_type *%s =\n"
2397 " gcc_jit_type_get_const (%s);\n",
2399 r.get_identifier_as_type (m_other_type));
2402 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2404 /* Implementation of pure virtual hook recording::memento::replay_into
2405 for recording::memento_of_get_volatile. */
2407 void
2408 recording::memento_of_get_volatile::replay_into (replayer *)
2410 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2413 /* Implementation of recording::memento::make_debug_string for
2414 results of get_volatile, prepending "volatile ". */
2416 recording::string *
2417 recording::memento_of_get_volatile::make_debug_string ()
2419 return string::from_printf (m_ctxt,
2420 "volatile %s", m_other_type->get_debug_string ());
2423 /* Implementation of recording::memento::write_reproducer for volatile
2424 types. */
2426 void
2427 recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2429 const char *id = r.make_identifier (this, "type");
2430 r.write (" gcc_jit_type *%s =\n"
2431 " gcc_jit_type_get_volatile (%s);\n",
2433 r.get_identifier_as_type (m_other_type));
2436 /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
2438 /* Implementation of pure virtual hook recording::memento::replay_into
2439 for recording::memento_of_get_aligned. */
2441 void
2442 recording::memento_of_get_aligned::replay_into (replayer *)
2444 set_playback_obj
2445 (m_other_type->playback_type ()->get_aligned (m_alignment_in_bytes));
2448 /* Implementation of recording::memento::make_debug_string for
2449 results of get_aligned. */
2451 recording::string *
2452 recording::memento_of_get_aligned::make_debug_string ()
2454 return string::from_printf (m_ctxt,
2455 "%s __attribute__((aligned(%zi)))",
2456 m_other_type->get_debug_string (),
2457 m_alignment_in_bytes);
2460 /* Implementation of recording::memento::write_reproducer for volatile
2461 types. */
2463 void
2464 recording::memento_of_get_aligned::write_reproducer (reproducer &r)
2466 const char *id = r.make_identifier (this, "type");
2467 r.write (" gcc_jit_type *%s =\n"
2468 " gcc_jit_type_get_aligned (%s, %zi);\n",
2470 r.get_identifier_as_type (m_other_type),
2471 m_alignment_in_bytes);
2474 /* The implementation of class gcc::jit::recording::array_type */
2476 /* Implementation of pure virtual hook recording::type::dereference for
2477 recording::array_type. */
2479 recording::type *
2480 recording::array_type::dereference ()
2482 return m_element_type;
2485 /* Implementation of pure virtual hook recording::memento::replay_into
2486 for recording::array_type. */
2488 void
2489 recording::array_type::replay_into (replayer *r)
2491 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
2492 m_element_type->playback_type (),
2493 m_num_elements));
2496 /* Implementation of recording::memento::make_debug_string for
2497 results of new_array_type. */
2499 recording::string *
2500 recording::array_type::make_debug_string ()
2502 return string::from_printf (m_ctxt,
2503 "%s[%d]",
2504 m_element_type->get_debug_string (),
2505 m_num_elements);
2508 /* Implementation of recording::memento::write_reproducer for array
2509 types. */
2511 void
2512 recording::array_type::write_reproducer (reproducer &r)
2514 const char *id = r.make_identifier (this, "array_type");
2515 r.write (" gcc_jit_type *%s =\n"
2516 " gcc_jit_context_new_array_type (%s,\n"
2517 " %s, /* gcc_jit_location *loc */\n"
2518 " %s, /* gcc_jit_type *element_type */\n"
2519 " %i); /* int num_elements */\n",
2521 r.get_identifier (get_context ()),
2522 r.get_identifier (m_loc),
2523 r.get_identifier_as_type (m_element_type),
2524 m_num_elements);
2527 /* The implementation of class gcc::jit::recording::function_type */
2529 /* Constructor for gcc::jit::recording::function_type. */
2531 recording::function_type::function_type (context *ctxt,
2532 type *return_type,
2533 int num_params,
2534 type **param_types,
2535 int is_variadic)
2536 : type (ctxt),
2537 m_return_type (return_type),
2538 m_param_types (),
2539 m_is_variadic (is_variadic)
2541 for (int i = 0; i< num_params; i++)
2542 m_param_types.safe_push (param_types[i]);
2545 /* Implementation of pure virtual hook recording::type::dereference for
2546 recording::function_type. */
2548 recording::type *
2549 recording::function_type::dereference ()
2551 return NULL;
2554 /* Implementation of pure virtual hook recording::memento::replay_into
2555 for recording::function_type. */
2557 void
2558 recording::function_type::replay_into (replayer *r)
2560 /* Convert m_param_types to a vec of playback type. */
2561 auto_vec <playback::type *> param_types;
2562 int i;
2563 recording::type *type;
2564 param_types.create (m_param_types.length ());
2565 FOR_EACH_VEC_ELT (m_param_types, i, type)
2566 param_types.safe_push (type->playback_type ());
2568 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
2569 &param_types,
2570 m_is_variadic));
2573 /* Special-casing for make_debug_string for get_pointer results for
2574 handling (one level) of pointers to functions. */
2576 recording::string *
2577 recording::function_type::make_debug_string_with_ptr ()
2579 return make_debug_string_with ("(*) ");
2582 /* Implementation of recording::memento::make_debug_string for
2583 results of new_function_type. */
2585 recording::string *
2586 recording::function_type::make_debug_string ()
2588 return make_debug_string_with ("");
2591 /* Build a debug string representation of the form:
2593 RESULT_TYPE INSERT (PARAM_TYPES)
2595 for use when handling 0 and 1 level of indirection to this
2596 function type. */
2598 recording::string *
2599 recording::function_type::make_debug_string_with (const char *insert)
2601 /* First, build a buffer for the arguments. */
2602 /* Calculate length of said buffer. */
2603 size_t sz = 1; /* nil terminator */
2604 for (unsigned i = 0; i< m_param_types.length (); i++)
2606 sz += strlen (m_param_types[i]->get_debug_string ());
2607 sz += 2; /* ", " separator */
2609 if (m_is_variadic)
2610 sz += 5; /* ", ..." separator and ellipsis */
2612 /* Now allocate and populate the buffer. */
2613 char *argbuf = new char[sz];
2614 size_t len = 0;
2616 for (unsigned i = 0; i< m_param_types.length (); i++)
2618 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
2619 len += strlen (m_param_types[i]->get_debug_string ());
2620 if (i + 1 < m_param_types.length ())
2622 strcpy (argbuf + len, ", ");
2623 len += 2;
2626 if (m_is_variadic)
2628 if (m_param_types.length ())
2630 strcpy (argbuf + len, ", ");
2631 len += 2;
2633 strcpy (argbuf + len, "...");
2634 len += 3;
2636 argbuf[len] = '\0';
2638 /* ...and use it to get the string for the call as a whole. */
2639 string *result = string::from_printf (m_ctxt,
2640 "%s %s(%s)",
2641 m_return_type->get_debug_string (),
2642 insert,
2643 argbuf);
2645 delete[] argbuf;
2647 return result;
2650 /* Implementation of recording::memento::write_reproducer for function
2651 types. */
2653 void
2654 recording::function_type::write_reproducer (reproducer &)
2656 /* see notes below. */
2659 /* There's a get_pointer within context::new_function_ptr_type:
2660 the type received by client code isn't the memento for the
2661 function_type, but instead the result of get_pointer on it.
2663 Hence we can't directly write a reproducer that gives function_type.
2664 Instead we special-case things within get_pointer, detecting this
2665 case, calling the following function. */
2667 void
2668 recording::function_type::write_deferred_reproducer (reproducer &r,
2669 memento *ptr_type)
2671 gcc_assert (ptr_type);
2672 r.make_identifier (this, "function_type");
2673 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
2674 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
2675 r.write (" gcc_jit_type *%s[%i] = {\n",
2676 param_types_id,
2677 m_param_types.length ());
2678 int i;
2679 type *param_type;
2680 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2681 r.write (" %s,\n", r.get_identifier_as_type (param_type));
2682 r.write (" };\n");
2683 r.write (" gcc_jit_type *%s =\n"
2684 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2685 " %s, /* gcc_jit_location *loc */\n"
2686 " %s, /* gcc_jit_type *return_type */\n"
2687 " %i, /* int num_params */\n"
2688 " %s, /* gcc_jit_type **param_types */\n"
2689 " %i); /* int is_variadic */\n",
2690 ptr_id,
2691 r.get_identifier (get_context ()),
2692 "NULL", /* location is not stored */
2693 r.get_identifier_as_type (m_return_type),
2694 m_param_types.length (),
2695 param_types_id,
2696 m_is_variadic);
2699 /* The implementation of class gcc::jit::recording::field. */
2701 /* Implementation of pure virtual hook recording::memento::replay_into
2702 for recording::field. */
2704 void
2705 recording::field::replay_into (replayer *r)
2707 set_playback_obj (r->new_field (playback_location (r, m_loc),
2708 m_type->playback_type (),
2709 playback_string (m_name)));
2712 /* Override the default implementation of
2713 recording::memento::write_to_dump. Dump each field
2714 by dumping a line of the form:
2715 TYPE NAME;
2716 so that we can build up a struct/union field-byfield. */
2718 void
2719 recording::field::write_to_dump (dump &d)
2721 d.write (" %s %s;\n",
2722 m_type->get_debug_string (),
2723 m_name->c_str ());
2726 /* Implementation of recording::memento::make_debug_string for
2727 results of new_field. */
2729 recording::string *
2730 recording::field::make_debug_string ()
2732 return m_name;
2735 /* Implementation of recording::memento::write_reproducer for fields. */
2737 void
2738 recording::field::write_reproducer (reproducer &r)
2740 const char *id = r.make_identifier (this, "field");
2741 r.write(" gcc_jit_field *%s =\n"
2742 " gcc_jit_context_new_field (%s,\n"
2743 " %s, /* gcc_jit_location *loc */\n"
2744 " %s, /* gcc_jit_type *type, */\n"
2745 " %s); /* const char *name */\n",
2747 r.get_identifier (get_context ()),
2748 r.get_identifier (m_loc),
2749 r.get_identifier_as_type (m_type),
2750 m_name->get_debug_string ());
2753 /* The implementation of class gcc::jit::recording::compound_type */
2755 /* The constructor for gcc::jit::recording::compound_type. */
2757 recording::compound_type::compound_type (context *ctxt,
2758 location *loc,
2759 string *name)
2760 : type (ctxt),
2761 m_loc (loc),
2762 m_name (name),
2763 m_fields (NULL)
2767 /* Set the fields of a compound type.
2769 Implements the post-error-checking part of
2770 gcc_jit_struct_set_fields, and is also used by
2771 gcc_jit_context_new_union_type. */
2773 void
2774 recording::compound_type::set_fields (location *loc,
2775 int num_fields,
2776 field **field_array)
2778 m_loc = loc;
2779 gcc_assert (NULL == m_fields);
2781 m_fields = new fields (this, num_fields, field_array);
2782 m_ctxt->record (m_fields);
2785 /* Implementation of pure virtual hook recording::type::dereference for
2786 recording::compound_type. */
2788 recording::type *
2789 recording::compound_type::dereference ()
2791 return NULL; /* not a pointer */
2794 /* The implementation of class gcc::jit::recording::struct_. */
2796 /* The constructor for gcc::jit::recording::struct_. */
2798 recording::struct_::struct_ (context *ctxt,
2799 location *loc,
2800 string *name)
2801 : compound_type (ctxt, loc, name)
2805 /* Implementation of pure virtual hook recording::memento::replay_into
2806 for recording::struct_. */
2808 void
2809 recording::struct_::replay_into (replayer *r)
2811 set_playback_obj (
2812 r->new_compound_type (playback_location (r, get_loc ()),
2813 get_name ()->c_str (),
2814 true /* is_struct */));
2817 const char *
2818 recording::struct_::access_as_type (reproducer &r)
2820 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2821 r.get_identifier (this));
2824 /* Implementation of recording::memento::make_debug_string for
2825 structs. */
2827 recording::string *
2828 recording::struct_::make_debug_string ()
2830 return string::from_printf (m_ctxt,
2831 "struct %s", get_name ()->c_str ());
2834 void
2835 recording::struct_::write_reproducer (reproducer &r)
2837 const char *id = r.make_identifier (this, "struct");
2838 r.write (" gcc_jit_struct *%s =\n"
2839 " gcc_jit_context_new_opaque_struct (%s,\n"
2840 " %s, /* gcc_jit_location *loc */\n"
2841 " %s); /* const char *name */\n",
2843 r.get_identifier (get_context ()),
2844 r.get_identifier (get_loc ()),
2845 get_name ()->get_debug_string ());
2848 /* The implementation of class gcc::jit::recording::union_. */
2850 /* The constructor for gcc::jit::recording::union_. */
2852 recording::union_::union_ (context *ctxt,
2853 location *loc,
2854 string *name)
2855 : compound_type (ctxt, loc, name)
2859 /* Implementation of pure virtual hook recording::memento::replay_into
2860 for recording::union_. */
2862 void
2863 recording::union_::replay_into (replayer *r)
2865 set_playback_obj (
2866 r->new_compound_type (playback_location (r, get_loc ()),
2867 get_name ()->c_str (),
2868 false /* is_struct */));
2871 /* Implementation of recording::memento::make_debug_string for
2872 unions. */
2874 recording::string *
2875 recording::union_::make_debug_string ()
2877 return string::from_printf (m_ctxt,
2878 "union %s", get_name ()->c_str ());
2881 /* Implementation of recording::memento::write_reproducer for unions. */
2883 void
2884 recording::union_::write_reproducer (reproducer &r)
2886 const char *id = r.make_identifier (this, "union");
2888 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
2889 r.write (" gcc_jit_field *%s[%i] = {\n",
2890 fields_id,
2891 get_fields ()->length ());
2892 for (int i = 0; i < get_fields ()->length (); i++)
2893 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
2894 r.write (" };\n");
2896 r.write (" gcc_jit_type *%s =\n"
2897 " gcc_jit_context_new_union_type (%s,\n"
2898 " %s, /* gcc_jit_location *loc */\n"
2899 " %s, /* const char *name */\n"
2900 " %i, /* int num_fields */\n"
2901 " %s); /* gcc_jit_field **fields */\n",
2903 r.get_identifier (get_context ()),
2904 r.get_identifier (get_loc ()),
2905 get_name ()->get_debug_string (),
2906 get_fields ()->length (),
2907 fields_id);
2910 /* The implementation of class gcc::jit::recording::fields. */
2912 /* The constructor for gcc::jit::recording::fields. */
2914 recording::fields::fields (compound_type *struct_or_union,
2915 int num_fields,
2916 field **fields)
2917 : memento (struct_or_union->m_ctxt),
2918 m_struct_or_union (struct_or_union),
2919 m_fields ()
2921 for (int i = 0; i < num_fields; i++)
2923 gcc_assert (fields[i]->get_container () == NULL);
2924 fields[i]->set_container (m_struct_or_union);
2925 m_fields.safe_push (fields[i]);
2929 /* Implementation of pure virtual hook recording::memento::replay_into
2930 for recording::fields. */
2932 void
2933 recording::fields::replay_into (replayer *)
2935 auto_vec<playback::field *> playback_fields;
2936 playback_fields.create (m_fields.length ());
2937 for (unsigned i = 0; i < m_fields.length (); i++)
2938 playback_fields.safe_push (m_fields[i]->playback_field ());
2939 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
2942 /* Override the default implementation of
2943 recording::memento::write_to_dump by writing a union/struct
2944 declaration of this form:
2946 struct/union NAME {
2947 TYPE_1 NAME_1;
2948 TYPE_2 NAME_2;
2949 ....
2950 TYPE_N NAME_N;
2953 to the dump. */
2955 void
2956 recording::fields::write_to_dump (dump &d)
2958 int i;
2959 field *f;
2961 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
2962 FOR_EACH_VEC_ELT (m_fields, i, f)
2963 f->write_to_dump (d);
2964 d.write ("};\n");
2967 /* Implementation of recording::memento::write_reproducer for the fields
2968 subclass. */
2970 void
2971 recording::fields::write_reproducer (reproducer &r)
2973 if (m_struct_or_union)
2974 if (NULL == m_struct_or_union->dyn_cast_struct ())
2975 /* We have a union; the fields have already been written by
2976 union::write_reproducer. */
2977 return;
2979 const char *fields_id = r.make_identifier (this, "fields");
2980 r.write (" gcc_jit_field *%s[%i] = {\n",
2981 fields_id,
2982 m_fields.length ());
2983 int i;
2984 field *field;
2985 FOR_EACH_VEC_ELT (m_fields, i, field)
2986 r.write (" %s,\n", r.get_identifier (field));
2987 r.write (" };\n");
2989 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
2990 " %s, /* gcc_jit_location *loc */\n"
2991 " %i, /* int num_fields */\n"
2992 " %s); /* gcc_jit_field **fields */\n",
2993 r.get_identifier (m_struct_or_union),
2994 r.get_identifier ((memento *)NULL),
2995 m_fields.length (),
2996 fields_id);
2999 /* Implementation of recording::memento::make_debug_string for
3000 field tables. */
3002 recording::string *
3003 recording::fields::make_debug_string ()
3005 return string::from_printf (m_ctxt,
3006 "fields");
3009 /* The implementation of class gcc::jit::recording::rvalue. */
3011 /* Create a recording::access_field_rvalue instance and add it to
3012 the rvalue's context's list of mementos.
3014 Implements the post-error-checking part of
3015 gcc_jit_rvalue_access_field. */
3017 recording::rvalue *
3018 recording::rvalue::access_field (recording::location *loc,
3019 field *field)
3021 recording::rvalue *result =
3022 new access_field_rvalue (m_ctxt, loc, this, field);
3023 m_ctxt->record (result);
3024 return result;
3027 /* Create a recording::dereference_field_rvalue instance and add it to
3028 the rvalue's context's list of mementos.
3030 Implements the post-error-checking part of
3031 gcc_jit_rvalue_dereference_field. */
3033 recording::lvalue *
3034 recording::rvalue::dereference_field (recording::location *loc,
3035 field *field)
3037 recording::lvalue *result =
3038 new dereference_field_rvalue (m_ctxt, loc, this, field);
3039 m_ctxt->record (result);
3040 return result;
3043 /* Create a recording::dereference_rvalue instance and add it to the
3044 rvalue's context's list of mementos.
3046 Implements the post-error-checking part of
3047 gcc_jit_rvalue_dereference. */
3049 recording::lvalue *
3050 recording::rvalue::dereference (recording::location *loc)
3052 recording::lvalue *result =
3053 new dereference_rvalue (m_ctxt, loc, this);
3054 m_ctxt->record (result);
3055 return result;
3058 /* An rvalue visitor, for validating that every rvalue within an expression
3059 trees within "STMT" has the correct scope (e.g. no access to locals
3060 of a different function). */
3062 class rvalue_usage_validator : public recording::rvalue_visitor
3064 public:
3065 rvalue_usage_validator (const char *api_funcname,
3066 recording::context *ctxt,
3067 recording::statement *stmt);
3069 void
3070 visit (recording::rvalue *rvalue) FINAL OVERRIDE;
3072 private:
3073 const char *m_api_funcname;
3074 recording::context *m_ctxt;
3075 recording::statement *m_stmt;
3078 /* The trivial constructor for rvalue_usage_validator. */
3080 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
3081 recording::context *ctxt,
3082 recording::statement *stmt)
3083 : m_api_funcname (api_funcname),
3084 m_ctxt (ctxt),
3085 m_stmt (stmt)
3089 /* Verify that the given rvalue is in the correct scope. */
3091 void
3092 rvalue_usage_validator::visit (recording::rvalue *rvalue)
3094 gcc_assert (m_stmt->get_block ());
3095 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
3097 /* Most rvalues don't have a scope (only locals and params). */
3098 if (rvalue->get_scope ())
3100 if (rvalue->get_scope () != stmt_scope)
3101 m_ctxt->add_error
3102 (rvalue->get_loc (),
3103 "%s:"
3104 " rvalue %s (type: %s)"
3105 " has scope limited to function %s"
3106 " but was used within function %s"
3107 " (in statement: %s)",
3108 m_api_funcname,
3109 rvalue->get_debug_string (),
3110 rvalue->get_type ()->get_debug_string (),
3111 rvalue->get_scope ()->get_debug_string (),
3112 stmt_scope->get_debug_string (),
3113 m_stmt->get_debug_string ());
3115 else
3117 if (rvalue->dyn_cast_param ())
3118 m_ctxt->add_error
3119 (rvalue->get_loc (),
3120 "%s:"
3121 " param %s (type: %s)"
3122 " was used within function %s"
3123 " (in statement: %s)"
3124 " but is not associated with any function",
3125 m_api_funcname,
3126 rvalue->get_debug_string (),
3127 rvalue->get_type ()->get_debug_string (),
3128 stmt_scope->get_debug_string (),
3129 m_stmt->get_debug_string ());
3133 /* Verify that it's valid to use this rvalue (and all expressions
3134 in the tree below it) within the given statement.
3136 For example, we must reject attempts to use a local from one
3137 function within a different function here, or we'll get
3138 an ICE deep inside toplev::main. */
3140 void
3141 recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
3143 rvalue_usage_validator v (api_funcname,
3144 s->get_context (),
3147 /* Verify that it's OK to use this rvalue within s. */
3148 v.visit (this);
3150 /* Traverse the expression tree below "this", verifying all rvalues
3151 within it. */
3152 visit_children (&v);
3155 /* Set the scope of this rvalue to be the given function. This can only
3156 be done once on a given rvalue. */
3158 void
3159 recording::rvalue::set_scope (function *scope)
3161 gcc_assert (scope);
3162 gcc_assert (NULL == m_scope);
3163 m_scope = scope;
3167 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3168 themselves.
3169 Instances of rvalue don't need an upcast call. */
3171 const char *
3172 recording::rvalue::access_as_rvalue (reproducer &r)
3174 return r.get_identifier (this);
3177 /* Return a debug string for the given rvalue, wrapping it in parentheses
3178 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3179 stronger precedence that this rvalue's precedence.
3181 For example, given:
3183 MULT
3185 PLUS MINUS
3186 / \ / \
3187 A B C D
3189 we want to emit:
3191 (A + B) * (C - D)
3193 since MULT has strong precedence than PLUS and MINUS, whereas for:
3195 PLUS
3197 MULT DIVIDE
3198 / \ / \
3199 A B C D
3201 we can simply emit:
3203 A * B + C / D
3205 since PLUS has weaker precedence than MULT and DIVIDE. */
3207 const char *
3208 recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
3210 enum precedence this_prec = get_precedence ();
3212 /* If this_prec has stronger precedence than outer_prec, we don't
3213 need to wrap this in parens within the outer debug string.
3214 Stronger precedences occur earlier than weaker within the enum,
3215 so this is a less than test. Equal precedences don't need
3216 parentheses. */
3217 if (this_prec <= outer_prec)
3218 return get_debug_string();
3220 /* Otherwise, we need parentheses. */
3222 /* Lazily-build and cache m_parenthesized_string. */
3223 if (!m_parenthesized_string)
3225 const char *debug_string = get_debug_string ();
3226 m_parenthesized_string = string::from_printf (get_context (),
3227 "(%s)",
3228 debug_string);
3230 gcc_assert (m_parenthesized_string);
3231 return m_parenthesized_string->c_str ();
3235 /* The implementation of class gcc::jit::recording::lvalue. */
3237 /* Create a recording::new_access_field_of_lvalue instance and add it to
3238 the lvalue's context's list of mementos.
3240 Implements the post-error-checking part of
3241 gcc_jit_lvalue_access_field. */
3243 recording::lvalue *
3244 recording::lvalue::access_field (recording::location *loc,
3245 field *field)
3247 recording::lvalue *result =
3248 new access_field_of_lvalue (m_ctxt, loc, this, field);
3249 m_ctxt->record (result);
3250 return result;
3253 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3254 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3255 upcast call. */
3257 const char *
3258 recording::lvalue::access_as_rvalue (reproducer &r)
3260 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3261 r.get_identifier (this));
3264 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3265 Instances of lvalue don't need to be upcast. */
3267 const char *
3268 recording::lvalue::access_as_lvalue (reproducer &r)
3270 return r.get_identifier (this);
3273 /* Create a recording::get_address_of_lvalue instance and add it to
3274 the lvalue's context's list of mementos.
3276 Implements the post-error-checking part of
3277 gcc_jit_lvalue_get_address. */
3279 recording::rvalue *
3280 recording::lvalue::get_address (recording::location *loc)
3282 recording::rvalue *result =
3283 new get_address_of_lvalue (m_ctxt, loc, this);
3284 m_ctxt->record (result);
3285 return result;
3288 /* The implementation of class gcc::jit::recording::param. */
3290 /* Implementation of pure virtual hook recording::memento::replay_into
3291 for recording::param. */
3293 void
3294 recording::param::replay_into (replayer *r)
3296 set_playback_obj (r->new_param (playback_location (r, m_loc),
3297 m_type->playback_type (),
3298 m_name->c_str ()));
3301 /* Implementation of recording::rvalue::access_as_rvalue for params.
3302 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3303 upcast call. */
3305 const char *
3306 recording::param::access_as_rvalue (reproducer &r)
3308 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3309 r.get_identifier (this));
3312 /* Implementation of recording::lvalue::access_as_lvalue for params.
3313 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3314 upcast call. */
3316 const char *
3317 recording::param::access_as_lvalue (reproducer &r)
3319 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3320 r.get_identifier (this));
3323 /* Implementation of recording::memento::write_reproducer for params. */
3325 void
3326 recording::param::write_reproducer (reproducer &r)
3328 const char *id = r.make_identifier (this, "param");
3329 r.write (" gcc_jit_param *%s =\n"
3330 " gcc_jit_context_new_param (%s,\n"
3331 " %s, /* gcc_jit_location *loc */\n"
3332 " %s, /*gcc_jit_type *type */\n"
3333 " %s); /* const char *name */\n",
3335 r.get_identifier (get_context ()),
3336 r.get_identifier (m_loc),
3337 r.get_identifier_as_type (m_type),
3338 m_name->get_debug_string ());
3341 /* The implementation of class gcc::jit::recording::function. */
3343 /* gcc::jit::recording::function's constructor. */
3345 recording::function::function (context *ctxt,
3346 recording::location *loc,
3347 enum gcc_jit_function_kind kind,
3348 type *return_type,
3349 recording::string *name,
3350 int num_params,
3351 recording::param **params,
3352 int is_variadic,
3353 enum built_in_function builtin_id)
3354 : memento (ctxt),
3355 m_loc (loc),
3356 m_kind (kind),
3357 m_return_type (return_type),
3358 m_name (name),
3359 m_params (),
3360 m_is_variadic (is_variadic),
3361 m_builtin_id (builtin_id),
3362 m_locals (),
3363 m_blocks ()
3365 for (int i = 0; i< num_params; i++)
3367 param *param = params[i];
3368 gcc_assert (param);
3370 /* Associate each param with this function.
3372 Verify that the param doesn't already have a function. */
3373 if (param->get_scope ())
3375 /* We've already rejected attempts to reuse a param between
3376 different functions (within gcc_jit_context_new_function), so
3377 if the param *does* already have a function, it must be being
3378 reused within the params array for this function. We must
3379 produce an error for this reuse (blocking the compile), since
3380 otherwise we'd have an ICE later on. */
3381 gcc_assert (this == param->get_scope ());
3382 ctxt->add_error
3383 (loc,
3384 "gcc_jit_context_new_function:"
3385 " parameter %s (type: %s)"
3386 " is used more than once when creating function %s",
3387 param->get_debug_string (),
3388 param->get_type ()->get_debug_string (),
3389 name->c_str ());
3391 else
3393 /* The normal, non-error case: associate this function with the
3394 param. */
3395 param->set_scope (this);
3398 m_params.safe_push (param);
3402 /* Implementation of pure virtual hook recording::memento::replay_into
3403 for recording::function. */
3405 void
3406 recording::function::replay_into (replayer *r)
3408 /* Convert m_params to a vec of playback param. */
3409 auto_vec <playback::param *> params;
3410 int i;
3411 recording::param *param;
3412 params.create (m_params.length ());
3413 FOR_EACH_VEC_ELT (m_params, i, param)
3414 params.safe_push (param->playback_param ());
3416 set_playback_obj (r->new_function (playback_location (r, m_loc),
3417 m_kind,
3418 m_return_type->playback_type (),
3419 m_name->c_str (),
3420 &params,
3421 m_is_variadic,
3422 m_builtin_id));
3425 /* Create a recording::local instance and add it to
3426 the functions's context's list of mementos, and to the function's
3427 list of locals.
3429 Implements the post-error-checking part of
3430 gcc_jit_function_new_local. */
3432 recording::lvalue *
3433 recording::function::new_local (recording::location *loc,
3434 type *type,
3435 const char *name)
3437 local *result = new local (this, loc, type, new_string (name));
3438 m_ctxt->record (result);
3439 m_locals.safe_push (result);
3440 return result;
3443 /* Create a recording::block instance and add it to
3444 the functions's context's list of mementos, and to the function's
3445 list of blocks.
3447 Implements the post-error-checking part of
3448 gcc_jit_function_new_block. */
3450 recording::block*
3451 recording::function::new_block (const char *name)
3453 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
3455 recording::block *result =
3456 new recording::block (this, m_blocks.length (), new_string (name));
3457 m_ctxt->record (result);
3458 m_blocks.safe_push (result);
3459 return result;
3462 /* Override the default implementation of
3463 recording::memento::write_to_dump by dumping a C-like
3464 representation of the function; either like a prototype
3465 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3466 all other kinds of function. */
3468 void
3469 recording::function::write_to_dump (dump &d)
3471 switch (m_kind)
3473 default: gcc_unreachable ();
3474 case GCC_JIT_FUNCTION_EXPORTED:
3475 case GCC_JIT_FUNCTION_IMPORTED:
3476 d.write ("extern ");
3477 break;
3478 case GCC_JIT_FUNCTION_INTERNAL:
3479 d.write ("static ");
3480 break;
3481 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
3482 d.write ("static inline ");
3483 break;
3485 d.write ("%s\n", m_return_type->get_debug_string ());
3487 if (d.update_locations ())
3488 m_loc = d.make_location ();
3490 d.write ("%s (", get_debug_string ());
3492 int i;
3493 recording::param *param;
3494 FOR_EACH_VEC_ELT (m_params, i, param)
3496 if (i > 0)
3497 d.write (", ");
3498 d.write ("%s %s",
3499 param->get_type ()->get_debug_string (),
3500 param->get_debug_string ());
3502 d.write (")");
3503 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
3505 d.write ("; /* (imported) */\n\n");
3507 else
3509 int i;
3510 local *var = NULL;
3511 block *b;
3512 d.write ("\n{\n");
3514 /* Write locals: */
3515 FOR_EACH_VEC_ELT (m_locals, i, var)
3516 var->write_to_dump (d);
3517 if (m_locals.length ())
3518 d.write ("\n");
3520 /* Write each block: */
3521 FOR_EACH_VEC_ELT (m_blocks, i, b)
3523 if (i > 0)
3524 d.write ("\n");
3525 b->write_to_dump (d);
3528 d.write ("}\n\n");
3532 /* Pre-compilation validation of a function, for those things we can't
3533 check until the context is (supposedly) fully-populated. */
3535 void
3536 recording::function::validate ()
3538 /* Complain about empty functions with non-void return type. */
3539 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
3540 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
3541 if (0 == m_blocks.length ())
3542 m_ctxt->add_error (m_loc,
3543 "function %s returns non-void (type: %s)"
3544 " but has no blocks",
3545 get_debug_string (),
3546 m_return_type->get_debug_string ());
3548 /* Check that all blocks are terminated. */
3549 int num_invalid_blocks = 0;
3551 int i;
3552 block *b;
3554 FOR_EACH_VEC_ELT (m_blocks, i, b)
3555 if (!b->validate ())
3556 num_invalid_blocks++;
3559 /* Check that all blocks are reachable. */
3560 if (!m_ctxt->get_inner_bool_option
3561 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
3562 && m_blocks.length () > 0 && 0 == num_invalid_blocks)
3564 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3565 flag, starting at the initial block. */
3566 auto_vec<block *> worklist (m_blocks.length ());
3567 worklist.safe_push (m_blocks[0]);
3568 while (worklist.length () > 0)
3570 block *b = worklist.pop ();
3571 b->m_is_reachable = true;
3573 /* Add successor blocks that aren't yet marked to the worklist. */
3574 /* We checked that each block has a terminating statement above . */
3575 vec <block *> successors = b->get_successor_blocks ();
3576 int i;
3577 block *succ;
3578 FOR_EACH_VEC_ELT (successors, i, succ)
3579 if (!succ->m_is_reachable)
3580 worklist.safe_push (succ);
3581 successors.release ();
3584 /* Now complain about any blocks that haven't been marked. */
3586 int i;
3587 block *b;
3588 FOR_EACH_VEC_ELT (m_blocks, i, b)
3589 if (!b->m_is_reachable)
3590 m_ctxt->add_error (b->get_loc (),
3591 "unreachable block: %s",
3592 b->get_debug_string ());
3597 /* Implements the post-error-checking part of
3598 gcc_jit_function_dump_to_dot. */
3600 void
3601 recording::function::dump_to_dot (const char *path)
3603 FILE *fp = fopen (path, "w");
3604 if (!fp)
3605 return;
3607 pretty_printer the_pp;
3608 the_pp.buffer->stream = fp;
3610 pretty_printer *pp = &the_pp;
3612 pp_printf (pp,
3613 "digraph %s {\n", get_debug_string ());
3615 /* Blocks: */
3617 int i;
3618 block *b;
3619 FOR_EACH_VEC_ELT (m_blocks, i, b)
3620 b->dump_to_dot (pp);
3623 /* Edges: */
3625 int i;
3626 block *b;
3627 FOR_EACH_VEC_ELT (m_blocks, i, b)
3628 b->dump_edges_to_dot (pp);
3631 pp_printf (pp, "}\n");
3632 pp_flush (pp);
3633 fclose (fp);
3636 /* Implementation of recording::memento::make_debug_string for
3637 functions. */
3639 recording::string *
3640 recording::function::make_debug_string ()
3642 return m_name;
3645 /* A table of enum gcc_jit_function_kind values expressed in string
3646 form. */
3648 static const char * const names_of_function_kinds[] = {
3649 "GCC_JIT_FUNCTION_EXPORTED",
3650 "GCC_JIT_FUNCTION_INTERNAL",
3651 "GCC_JIT_FUNCTION_IMPORTED",
3652 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3655 /* Implementation of recording::memento::write_reproducer for functions. */
3657 void
3658 recording::function::write_reproducer (reproducer &r)
3660 const char *id = r.make_identifier (this, "func");
3662 if (m_builtin_id)
3664 r.write (" gcc_jit_function *%s =\n"
3665 " gcc_jit_context_get_builtin_function (%s,\n"
3666 " %s);\n",
3668 r.get_identifier (get_context ()),
3669 m_name->get_debug_string ());
3670 return;
3672 const char *params_id = r.make_tmp_identifier ("params_for", this);
3673 r.write (" gcc_jit_param *%s[%i] = {\n",
3674 params_id,
3675 m_params.length ());
3676 int i;
3677 param *param;
3678 FOR_EACH_VEC_ELT (m_params, i, param)
3679 r.write (" %s,\n", r.get_identifier (param));
3680 r.write (" };\n");
3681 r.write (" gcc_jit_function *%s =\n"
3682 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3683 " %s, /* gcc_jit_location *loc */\n"
3684 " %s, /* enum gcc_jit_function_kind kind */\n"
3685 " %s, /* gcc_jit_type *return_type */\n"
3686 " %s, /* const char *name */\n"
3687 " %i, /* int num_params */\n"
3688 " %s, /* gcc_jit_param **params */\n"
3689 " %i); /* int is_variadic */\n",
3691 r.get_identifier (get_context ()),
3692 r.get_identifier (m_loc),
3693 names_of_function_kinds[m_kind],
3694 r.get_identifier_as_type (m_return_type),
3695 m_name->get_debug_string (),
3696 m_params.length (),
3697 params_id,
3698 m_is_variadic);
3702 /* The implementation of class gcc::jit::recording::block. */
3704 /* Create a recording::eval instance and add it to
3705 the block's context's list of mementos, and to the block's
3706 list of statements.
3708 Implements the heart of gcc_jit_block_add_eval. */
3710 recording::statement *
3711 recording::block::add_eval (recording::location *loc,
3712 recording::rvalue *rvalue)
3714 statement *result = new eval (this, loc, rvalue);
3715 m_ctxt->record (result);
3716 m_statements.safe_push (result);
3717 return result;
3720 /* Create a recording::assignment instance and add it to
3721 the block's context's list of mementos, and to the block's
3722 list of statements.
3724 Implements the heart of gcc_jit_block_add_assignment. */
3726 recording::statement *
3727 recording::block::add_assignment (recording::location *loc,
3728 recording::lvalue *lvalue,
3729 recording::rvalue *rvalue)
3731 statement *result = new assignment (this, loc, lvalue, rvalue);
3732 m_ctxt->record (result);
3733 m_statements.safe_push (result);
3734 return result;
3737 /* Create a recording::assignment_op instance and add it to
3738 the block's context's list of mementos, and to the block's
3739 list of statements.
3741 Implements the heart of gcc_jit_block_add_assignment_op. */
3743 recording::statement *
3744 recording::block::add_assignment_op (recording::location *loc,
3745 recording::lvalue *lvalue,
3746 enum gcc_jit_binary_op op,
3747 recording::rvalue *rvalue)
3749 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
3750 m_ctxt->record (result);
3751 m_statements.safe_push (result);
3752 return result;
3755 /* Create a recording::comment instance and add it to
3756 the block's context's list of mementos, and to the block's
3757 list of statements.
3759 Implements the heart of gcc_jit_block_add_comment. */
3761 recording::statement *
3762 recording::block::add_comment (recording::location *loc,
3763 const char *text)
3765 statement *result = new comment (this, loc, new_string (text));
3766 m_ctxt->record (result);
3767 m_statements.safe_push (result);
3768 return result;
3771 /* Create a recording::end_with_conditional instance and add it to
3772 the block's context's list of mementos, and to the block's
3773 list of statements.
3775 Implements the heart of gcc_jit_block_end_with_conditional. */
3777 recording::statement *
3778 recording::block::end_with_conditional (recording::location *loc,
3779 recording::rvalue *boolval,
3780 recording::block *on_true,
3781 recording::block *on_false)
3783 statement *result = new conditional (this, loc, boolval, on_true, on_false);
3784 m_ctxt->record (result);
3785 m_statements.safe_push (result);
3786 m_has_been_terminated = true;
3787 return result;
3790 /* Create a recording::end_with_jump instance and add it to
3791 the block's context's list of mementos, and to the block's
3792 list of statements.
3794 Implements the heart of gcc_jit_block_end_with_jump. */
3796 recording::statement *
3797 recording::block::end_with_jump (recording::location *loc,
3798 recording::block *target)
3800 statement *result = new jump (this, loc, target);
3801 m_ctxt->record (result);
3802 m_statements.safe_push (result);
3803 m_has_been_terminated = true;
3804 return result;
3807 /* Create a recording::end_with_return instance and add it to
3808 the block's context's list of mementos, and to the block's
3809 list of statements.
3811 Implements the post-error-checking parts of
3812 gcc_jit_block_end_with_return and
3813 gcc_jit_block_end_with_void_return. */
3815 recording::statement *
3816 recording::block::end_with_return (recording::location *loc,
3817 recording::rvalue *rvalue)
3819 /* This is used by both gcc_jit_function_add_return and
3820 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3821 the former and NULL for the latter. */
3822 statement *result = new return_ (this, loc, rvalue);
3823 m_ctxt->record (result);
3824 m_statements.safe_push (result);
3825 m_has_been_terminated = true;
3826 return result;
3829 /* Create a recording::switch_ instance and add it to
3830 the block's context's list of mementos, and to the block's
3831 list of statements.
3833 Implements the heart of gcc_jit_block_end_with_switch. */
3835 recording::statement *
3836 recording::block::end_with_switch (recording::location *loc,
3837 recording::rvalue *expr,
3838 recording::block *default_block,
3839 int num_cases,
3840 recording::case_ **cases)
3842 statement *result = new switch_ (this, loc,
3843 expr,
3844 default_block,
3845 num_cases,
3846 cases);
3847 m_ctxt->record (result);
3848 m_statements.safe_push (result);
3849 m_has_been_terminated = true;
3850 return result;
3853 /* Override the default implementation of
3854 recording::memento::write_to_dump for blocks by writing
3855 an unindented block name as a label, followed by the indented
3856 statements:
3858 BLOCK_NAME:
3859 STATEMENT_1;
3860 STATEMENT_2;
3862 STATEMENT_N; */
3864 void
3865 recording::block::write_to_dump (dump &d)
3867 d.write ("%s:\n", get_debug_string ());
3869 int i;
3870 statement *s;
3871 FOR_EACH_VEC_ELT (m_statements, i, s)
3872 s->write_to_dump (d);
3875 /* Validate a block by ensuring that it has been terminated. */
3877 bool
3878 recording::block::validate ()
3880 /* Check for termination. */
3881 if (!has_been_terminated ())
3883 statement *stmt = get_last_statement ();
3884 location *loc = stmt ? stmt->get_loc () : NULL;
3885 m_func->get_context ()->add_error (loc,
3886 "unterminated block in %s: %s",
3887 m_func->get_debug_string (),
3888 get_debug_string ());
3889 return false;
3892 return true;
3895 /* Get the source-location of a block by using that of the first
3896 statement within it, if any. */
3898 recording::location *
3899 recording::block::get_loc () const
3901 recording::statement *stmt = get_first_statement ();
3902 if (stmt)
3903 return stmt->get_loc ();
3904 else
3905 return NULL;
3908 /* Get the first statement within a block, if any. */
3910 recording::statement *
3911 recording::block::get_first_statement () const
3913 if (m_statements.length ())
3914 return m_statements[0];
3915 else
3916 return NULL;
3919 /* Get the last statement within a block, if any. */
3921 recording::statement *
3922 recording::block::get_last_statement () const
3924 if (m_statements.length ())
3925 return m_statements[m_statements.length () - 1];
3926 else
3927 return NULL;
3930 /* Assuming that this block has been terminated, get the successor blocks
3931 as a vector. Ownership of the vector transfers to the caller, which
3932 must call its release () method.
3934 Used when validating functions, and when dumping dot representations
3935 of them. */
3937 vec <recording::block *>
3938 recording::block::get_successor_blocks () const
3940 gcc_assert (m_has_been_terminated);
3941 statement *last_statement = get_last_statement ();
3942 gcc_assert (last_statement);
3943 return last_statement->get_successor_blocks ();
3946 /* Implementation of pure virtual hook recording::memento::replay_into
3947 for recording::block. */
3949 void
3950 recording::block::replay_into (replayer *)
3952 set_playback_obj (m_func->playback_function ()
3953 ->new_block (playback_string (m_name)));
3956 /* Implementation of recording::memento::make_debug_string for
3957 blocks. */
3959 recording::string *
3960 recording::block::make_debug_string ()
3962 if (m_name)
3963 return m_name;
3964 else
3965 return string::from_printf (m_ctxt,
3966 "<UNNAMED BLOCK %p>",
3967 (void *)this);
3970 /* Implementation of recording::memento::write_reproducer for blocks. */
3972 void
3973 recording::block::write_reproducer (reproducer &r)
3975 const char *id = r.make_identifier (this, "block");
3976 r.write (" gcc_jit_block *%s =\n"
3977 " gcc_jit_function_new_block (%s, %s);\n",
3979 r.get_identifier (m_func),
3980 m_name ? m_name->get_debug_string () : "NULL");
3983 /* Dump a block in graphviz form into PP, capturing the block name (if
3984 any) and the statements. */
3986 void
3987 recording::block::dump_to_dot (pretty_printer *pp)
3989 pp_printf (pp,
3990 ("\tblock_%d "
3991 "[shape=record,style=filled,fillcolor=white,label=\"{"),
3992 m_index);
3993 pp_write_text_to_stream (pp);
3994 if (m_name)
3996 pp_string (pp, m_name->c_str ());
3997 pp_string (pp, ":");
3998 pp_newline (pp);
3999 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4002 int i;
4003 statement *s;
4004 FOR_EACH_VEC_ELT (m_statements, i, s)
4006 pp_string (pp, s->get_debug_string ());
4007 pp_newline (pp);
4008 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4011 pp_printf (pp,
4012 "}\"];\n\n");
4013 pp_flush (pp);
4016 /* Dump the out-edges of the block in graphviz form into PP. */
4018 void
4019 recording::block::dump_edges_to_dot (pretty_printer *pp)
4021 vec <block *> successors = get_successor_blocks ();
4022 int i;
4023 block *succ;
4024 FOR_EACH_VEC_ELT (successors, i, succ)
4025 pp_printf (pp,
4026 "\tblock_%d:s -> block_%d:n;\n",
4027 m_index, succ->m_index);
4028 successors.release ();
4031 /* The implementation of class gcc::jit::recording::global. */
4033 /* Implementation of pure virtual hook recording::memento::replay_into
4034 for recording::global. */
4036 void
4037 recording::global::replay_into (replayer *r)
4039 set_playback_obj (r->new_global (playback_location (r, m_loc),
4040 m_kind,
4041 m_type->playback_type (),
4042 playback_string (m_name)));
4045 /* Override the default implementation of
4046 recording::memento::write_to_dump for globals.
4047 This will be of the form:
4049 GCC_JIT_GLOBAL_EXPORTED:
4050 "TYPE NAME;"
4051 e.g. "int foo;"
4053 GCC_JIT_GLOBAL_INTERNAL:
4054 "static TYPE NAME;"
4055 e.g. "static int foo;"
4057 GCC_JIT_GLOBAL_IMPORTED:
4058 "extern TYPE NAME;"
4059 e.g. "extern int foo;"
4061 These are written to the top of the dump by
4062 recording::context::dump_to_file. */
4064 void
4065 recording::global::write_to_dump (dump &d)
4067 if (d.update_locations ())
4068 m_loc = d.make_location ();
4070 switch (m_kind)
4072 default:
4073 gcc_unreachable ();
4075 case GCC_JIT_GLOBAL_EXPORTED:
4076 break;
4078 case GCC_JIT_GLOBAL_INTERNAL:
4079 d.write ("static ");
4080 break;
4082 case GCC_JIT_GLOBAL_IMPORTED:
4083 d.write ("extern ");
4084 break;
4086 d.write ("%s %s;\n",
4087 m_type->get_debug_string (),
4088 get_debug_string ());
4091 /* A table of enum gcc_jit_global_kind values expressed in string
4092 form. */
4094 static const char * const global_kind_reproducer_strings[] = {
4095 "GCC_JIT_GLOBAL_EXPORTED",
4096 "GCC_JIT_GLOBAL_INTERNAL",
4097 "GCC_JIT_GLOBAL_IMPORTED"
4100 /* Implementation of recording::memento::write_reproducer for globals. */
4102 void
4103 recording::global::write_reproducer (reproducer &r)
4105 const char *id = r.make_identifier (this, "block");
4106 r.write (" gcc_jit_lvalue *%s =\n"
4107 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4108 " %s, /* gcc_jit_location *loc */\n"
4109 " %s, /* enum gcc_jit_global_kind kind */\n"
4110 " %s, /* gcc_jit_type *type */\n"
4111 " %s); /* const char *name */\n",
4113 r.get_identifier (get_context ()),
4114 r.get_identifier (m_loc),
4115 global_kind_reproducer_strings[m_kind],
4116 r.get_identifier_as_type (get_type ()),
4117 m_name->get_debug_string ());
4120 /* The implementation of the various const-handling classes:
4121 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4123 /* Explicit specialization of the various mementos we're interested in. */
4124 template class recording::memento_of_new_rvalue_from_const <int>;
4125 template class recording::memento_of_new_rvalue_from_const <long>;
4126 template class recording::memento_of_new_rvalue_from_const <double>;
4127 template class recording::memento_of_new_rvalue_from_const <void *>;
4129 /* Implementation of the pure virtual hook recording::memento::replay_into
4130 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4132 template <typename HOST_TYPE>
4133 void
4134 recording::
4135 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
4137 set_playback_obj
4138 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
4139 m_value));
4142 /* The make_debug_string and write_reproducer methods vary between the
4143 various
4144 memento_of_new_rvalue_from_const <HOST_TYPE>
4145 classes, so we explicitly write specializations of them.
4147 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4148 namespaces are written out explicitly, which is why most of this file
4149 doesn't abbreviate things by entering the "recording" namespace.
4151 However, these specializations are required to be in the same namespace
4152 as the template, hence we now have to enter the gcc::jit::recording
4153 namespace. */
4155 namespace recording
4158 /* The make_debug_string specialization for <int>, which renders it as
4159 (TARGET_TYPE)LITERAL
4160 e.g.
4161 "(int)42". */
4163 template <>
4164 string *
4165 memento_of_new_rvalue_from_const <int>::make_debug_string ()
4167 return string::from_printf (m_ctxt,
4168 "(%s)%i",
4169 m_type->get_debug_string (),
4170 m_value);
4173 /* The get_wide_int specialization for <int>. */
4175 template <>
4176 bool
4177 memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const
4179 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4180 return true;
4183 /* The write_reproducer specialization for <int>. */
4185 template <>
4186 void
4187 memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
4189 const char *id = r.make_identifier (this, "rvalue");
4190 r.write (" gcc_jit_rvalue *%s =\n"
4191 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4192 " %s, /* gcc_jit_type *numeric_type */\n"
4193 " %i); /* int value */\n",
4195 r.get_identifier (get_context ()),
4196 r.get_identifier_as_type (m_type),
4197 m_value);
4200 /* The make_debug_string specialization for <long>, rendering it as
4201 (TARGET_TYPE)LITERAL
4202 e.g.
4203 "(long)42". */
4205 template <>
4206 string *
4207 memento_of_new_rvalue_from_const <long>::make_debug_string ()
4209 return string::from_printf (m_ctxt,
4210 "(%s)%li",
4211 m_type->get_debug_string (),
4212 m_value);
4215 /* The get_wide_int specialization for <long>. */
4217 template <>
4218 bool
4219 memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const
4221 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4222 return true;
4225 /* The write_reproducer specialization for <long>. */
4227 template <>
4228 void
4229 recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
4231 const char *id = r.make_identifier (this, "rvalue");
4233 /* We have to special-case LONG_MIN, since e.g.
4234 -9223372036854775808L
4235 is parsed as
4236 -(9223372036854775808L)
4237 and hence we'd get:
4238 error: integer constant is so large that it is unsigned [-Werror]
4239 Workaround this by writing (LONG_MIN + 1) - 1. */
4240 if (m_value == LONG_MIN)
4242 r.write (" gcc_jit_rvalue *%s =\n"
4243 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4244 " %s, /* gcc_jit_type *numeric_type */\n"
4245 " %ldL - 1); /* long value */\n",
4247 r.get_identifier (get_context ()),
4248 r.get_identifier_as_type (m_type),
4249 m_value + 1);;
4250 return;
4253 r.write (" gcc_jit_rvalue *%s =\n"
4254 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4255 " %s, /* gcc_jit_type *numeric_type */\n"
4256 " %ldL); /* long value */\n",
4258 r.get_identifier (get_context ()),
4259 r.get_identifier_as_type (m_type),
4260 m_value);
4263 /* The make_debug_string specialization for <double>, rendering it as
4264 (TARGET_TYPE)LITERAL
4265 e.g.
4266 "(float)42.0". */
4268 template <>
4269 string *
4270 memento_of_new_rvalue_from_const <double>::make_debug_string ()
4272 return string::from_printf (m_ctxt,
4273 "(%s)%f",
4274 m_type->get_debug_string (),
4275 m_value);
4278 /* The get_wide_int specialization for <double>. */
4280 template <>
4281 bool
4282 memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
4284 return false;
4287 /* The write_reproducer specialization for <double>. */
4289 template <>
4290 void
4291 recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
4293 const char *id = r.make_identifier (this, "rvalue");
4294 r.write (" gcc_jit_rvalue *%s =\n"
4295 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4296 " %s, /* gcc_jit_type *numeric_type */\n"
4297 " %f); /* double value */\n",
4299 r.get_identifier (get_context ()),
4300 r.get_identifier_as_type (m_type),
4301 m_value);
4304 /* The make_debug_string specialization for <void *>, rendering it as
4305 (TARGET_TYPE)HEX
4306 e.g.
4307 "(int *)0xdeadbeef"
4309 Zero is rendered as NULL e.g.
4310 "(int *)NULL". */
4312 template <>
4313 string *
4314 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
4316 if (m_value != NULL)
4317 return string::from_printf (m_ctxt,
4318 "(%s)%p",
4319 m_type->get_debug_string (), m_value);
4320 else
4321 return string::from_printf (m_ctxt,
4322 "(%s)NULL",
4323 m_type->get_debug_string ());
4326 /* The get_wide_int specialization for <void *>. */
4328 template <>
4329 bool
4330 memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const
4332 return false;
4335 /* Implementation of recording::memento::write_reproducer for <void *>
4336 values. */
4338 template <>
4339 void
4340 memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
4342 const char *id = r.make_identifier (this, "rvalue");
4343 if (m_value)
4344 r.write (" gcc_jit_rvalue *%s =\n"
4345 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4346 " %s, /* gcc_jit_type *pointer_type */\n"
4347 " (void *)%p); /* void *value */\n",
4349 r.get_identifier (get_context ()),
4350 r.get_identifier_as_type (m_type),
4351 m_value);
4352 else
4353 r.write (" gcc_jit_rvalue *%s =\n"
4354 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4355 " %s); /* gcc_jit_type *pointer_type */\n",
4357 r.get_identifier (get_context ()),
4358 r.get_identifier_as_type (m_type));
4361 /* We're done specializing make_debug_string and write_reproducer, so we
4362 can exit the gcc::jit::recording namespace. */
4364 } // namespace recording
4366 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4368 /* Implementation of pure virtual hook recording::memento::replay_into
4369 for recording::memento_of_new_string_literal. */
4371 void
4372 recording::memento_of_new_string_literal::replay_into (replayer *r)
4374 set_playback_obj (r->new_string_literal (m_value->c_str ()));
4377 /* Implementation of recording::memento::make_debug_string for
4378 string literals. */
4380 recording::string *
4381 recording::memento_of_new_string_literal::make_debug_string ()
4383 return string::from_printf (m_ctxt,
4384 "%s",
4385 m_value->get_debug_string ());
4388 /* Implementation of recording::memento::write_reproducer for string literal
4389 values. */
4391 void
4392 recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
4394 const char *id = r.make_identifier (this, "rvalue");
4395 r.write (" gcc_jit_rvalue *%s =\n"
4396 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4397 " %s); /* const char *value */\n",
4399 r.get_identifier (get_context ()),
4400 m_value->get_debug_string ());
4403 /* The implementation of class gcc::jit::recording::unary_op. */
4405 /* Implementation of pure virtual hook recording::memento::replay_into
4406 for recording::unary_op. */
4408 void
4409 recording::unary_op::replay_into (replayer *r)
4411 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
4412 m_op,
4413 get_type ()->playback_type (),
4414 m_a->playback_rvalue ()));
4417 /* Implementation of pure virtual hook recording::rvalue::visit_children
4418 for recording::unary_op. */
4419 void
4420 recording::unary_op::visit_children (rvalue_visitor *v)
4422 v->visit (m_a);
4425 /* Implementation of recording::memento::make_debug_string for
4426 unary ops. */
4428 static const char * const unary_op_strings[] = {
4429 "-", /* GCC_JIT_UNARY_OP_MINUS */
4430 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4431 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4432 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4435 recording::string *
4436 recording::unary_op::make_debug_string ()
4438 return string::from_printf (m_ctxt,
4439 "%s(%s)",
4440 unary_op_strings[m_op],
4441 m_a->get_debug_string ());
4444 static const char * const unary_op_reproducer_strings[] = {
4445 "GCC_JIT_UNARY_OP_MINUS",
4446 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4447 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4448 "GCC_JIT_UNARY_OP_ABS"
4451 /* Implementation of recording::memento::write_reproducer for unary ops. */
4453 void
4454 recording::unary_op::write_reproducer (reproducer &r)
4456 const char *id = r.make_identifier (this, "rvalue");
4457 r.write (" gcc_jit_rvalue *%s =\n"
4458 " gcc_jit_context_new_unary_op (%s,\n"
4459 " %s, /* gcc_jit_location *loc */\n"
4460 " %s, /* enum gcc_jit_unary_op op */\n"
4461 " %s, /* gcc_jit_type *result_type */\n"
4462 " %s); /* gcc_jit_rvalue *a */\n",
4464 r.get_identifier (get_context ()),
4465 r.get_identifier (m_loc),
4466 unary_op_reproducer_strings[m_op],
4467 r.get_identifier_as_type (get_type ()),
4468 r.get_identifier_as_rvalue (m_a));
4471 /* The implementation of class gcc::jit::recording::binary_op. */
4473 /* Implementation of pure virtual hook recording::memento::replay_into
4474 for recording::binary_op. */
4476 void
4477 recording::binary_op::replay_into (replayer *r)
4479 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
4480 m_op,
4481 get_type ()->playback_type (),
4482 m_a->playback_rvalue (),
4483 m_b->playback_rvalue ()));
4486 /* Implementation of pure virtual hook recording::rvalue::visit_children
4487 for recording::binary_op. */
4488 void
4489 recording::binary_op::visit_children (rvalue_visitor *v)
4491 v->visit (m_a);
4492 v->visit (m_b);
4495 /* Implementation of recording::memento::make_debug_string for
4496 binary ops. */
4498 static const char * const binary_op_strings[] = {
4499 "+", /* GCC_JIT_BINARY_OP_PLUS */
4500 "-", /* GCC_JIT_BINARY_OP_MINUS */
4501 "*", /* GCC_JIT_BINARY_OP_MULT */
4502 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4503 "%", /* GCC_JIT_BINARY_OP_MODULO */
4504 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4505 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4506 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4507 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4508 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4509 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4510 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4513 recording::string *
4514 recording::binary_op::make_debug_string ()
4516 enum precedence prec = get_precedence ();
4517 return string::from_printf (m_ctxt,
4518 "%s %s %s",
4519 m_a->get_debug_string_parens (prec),
4520 binary_op_strings[m_op],
4521 m_b->get_debug_string_parens (prec));
4524 static const char * const binary_op_reproducer_strings[] = {
4525 "GCC_JIT_BINARY_OP_PLUS",
4526 "GCC_JIT_BINARY_OP_MINUS",
4527 "GCC_JIT_BINARY_OP_MULT",
4528 "GCC_JIT_BINARY_OP_DIVIDE",
4529 "GCC_JIT_BINARY_OP_MODULO",
4530 "GCC_JIT_BINARY_OP_BITWISE_AND",
4531 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4532 "GCC_JIT_BINARY_OP_BITWISE_OR",
4533 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4534 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4535 "GCC_JIT_BINARY_OP_LSHIFT",
4536 "GCC_JIT_BINARY_OP_RSHIFT"
4539 /* Implementation of recording::memento::write_reproducer for binary ops. */
4541 void
4542 recording::binary_op::write_reproducer (reproducer &r)
4544 const char *id = r.make_identifier (this, "rvalue");
4545 r.write (" gcc_jit_rvalue *%s =\n"
4546 " gcc_jit_context_new_binary_op (%s,\n"
4547 " %s, /* gcc_jit_location *loc */\n"
4548 " %s, /* enum gcc_jit_binary_op op */\n"
4549 " %s, /* gcc_jit_type *result_type */\n"
4550 " %s, /* gcc_jit_rvalue *a */\n"
4551 " %s); /* gcc_jit_rvalue *b */\n",
4553 r.get_identifier (get_context ()),
4554 r.get_identifier (m_loc),
4555 binary_op_reproducer_strings[m_op],
4556 r.get_identifier_as_type (get_type ()),
4557 r.get_identifier_as_rvalue (m_a),
4558 r.get_identifier_as_rvalue (m_b));
4561 namespace recording {
4562 static const enum precedence binary_op_precedence[] = {
4563 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
4564 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
4566 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
4567 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
4568 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
4570 PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4571 PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4572 PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4573 PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4574 PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4575 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
4576 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
4578 } /* namespace recording */
4580 enum recording::precedence
4581 recording::binary_op::get_precedence () const
4583 return binary_op_precedence[m_op];
4586 /* The implementation of class gcc::jit::recording::comparison. */
4588 /* Implementation of recording::memento::make_debug_string for
4589 comparisons. */
4591 static const char * const comparison_strings[] =
4593 "==", /* GCC_JIT_COMPARISON_EQ */
4594 "!=", /* GCC_JIT_COMPARISON_NE */
4595 "<", /* GCC_JIT_COMPARISON_LT */
4596 "<=", /* GCC_JIT_COMPARISON_LE */
4597 ">", /* GCC_JIT_COMPARISON_GT */
4598 ">=", /* GCC_JIT_COMPARISON_GE */
4601 recording::string *
4602 recording::comparison::make_debug_string ()
4604 enum precedence prec = get_precedence ();
4605 return string::from_printf (m_ctxt,
4606 "%s %s %s",
4607 m_a->get_debug_string_parens (prec),
4608 comparison_strings[m_op],
4609 m_b->get_debug_string_parens (prec));
4612 /* A table of enum gcc_jit_comparison values expressed in string
4613 form. */
4615 static const char * const comparison_reproducer_strings[] =
4617 "GCC_JIT_COMPARISON_EQ",
4618 "GCC_JIT_COMPARISON_NE",
4619 "GCC_JIT_COMPARISON_LT",
4620 "GCC_JIT_COMPARISON_LE",
4621 "GCC_JIT_COMPARISON_GT",
4622 "GCC_JIT_COMPARISON_GE"
4625 /* Implementation of recording::memento::write_reproducer for comparisons. */
4627 void
4628 recording::comparison::write_reproducer (reproducer &r)
4630 const char *id = r.make_identifier (this, "rvalue");
4631 r.write (" gcc_jit_rvalue *%s =\n"
4632 " gcc_jit_context_new_comparison (%s,\n"
4633 " %s, /* gcc_jit_location *loc */\n"
4634 " %s, /* enum gcc_jit_comparison op */\n"
4635 " %s, /* gcc_jit_rvalue *a */\n"
4636 " %s); /* gcc_jit_rvalue *b */\n",
4638 r.get_identifier (get_context ()),
4639 r.get_identifier (m_loc),
4640 comparison_reproducer_strings[m_op],
4641 r.get_identifier_as_rvalue (m_a),
4642 r.get_identifier_as_rvalue (m_b));
4645 /* Implementation of pure virtual hook recording::memento::replay_into
4646 for recording::comparison. */
4648 void
4649 recording::comparison::replay_into (replayer *r)
4651 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
4652 m_op,
4653 m_a->playback_rvalue (),
4654 m_b->playback_rvalue ()));
4657 /* Implementation of pure virtual hook recording::rvalue::visit_children
4658 for recording::comparison. */
4660 void
4661 recording::comparison::visit_children (rvalue_visitor *v)
4663 v->visit (m_a);
4664 v->visit (m_b);
4667 namespace recording {
4668 static const enum precedence comparison_precedence[] =
4670 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
4671 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
4673 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LT */
4674 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
4675 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GT */
4676 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
4678 } /* namespace recording */
4680 enum recording::precedence
4681 recording::comparison::get_precedence () const
4683 return comparison_precedence[m_op];
4686 /* Implementation of pure virtual hook recording::memento::replay_into
4687 for recording::cast. */
4689 void
4690 recording::cast::replay_into (replayer *r)
4692 set_playback_obj (r->new_cast (playback_location (r, m_loc),
4693 m_rvalue->playback_rvalue (),
4694 get_type ()->playback_type ()));
4697 /* Implementation of pure virtual hook recording::rvalue::visit_children
4698 for recording::cast. */
4699 void
4700 recording::cast::visit_children (rvalue_visitor *v)
4702 v->visit (m_rvalue);
4705 /* Implementation of recording::memento::make_debug_string for
4706 casts. */
4708 recording::string *
4709 recording::cast::make_debug_string ()
4711 enum precedence prec = get_precedence ();
4712 return string::from_printf (m_ctxt,
4713 "(%s)%s",
4714 get_type ()->get_debug_string (),
4715 m_rvalue->get_debug_string_parens (prec));
4718 /* Implementation of recording::memento::write_reproducer for casts. */
4720 void
4721 recording::cast::write_reproducer (reproducer &r)
4723 const char *id = r.make_identifier (this, "rvalue");
4724 r.write (" gcc_jit_rvalue *%s =\n"
4725 " gcc_jit_context_new_cast (%s,\n"
4726 " %s, /* gcc_jit_location *loc */\n"
4727 " %s, /* gcc_jit_rvalue *rvalue */\n"
4728 " %s); /* gcc_jit_type *type */\n",
4730 r.get_identifier (get_context ()),
4731 r.get_identifier (m_loc),
4732 r.get_identifier_as_rvalue (m_rvalue),
4733 r.get_identifier_as_type (get_type ()));
4736 /* The implementation of class gcc::jit::recording::base_call. */
4738 /* The constructor for gcc::jit::recording::base_call. */
4740 recording::base_call::base_call (context *ctxt,
4741 location *loc,
4742 type *type_,
4743 int numargs,
4744 rvalue **args)
4745 : rvalue (ctxt, loc, type_),
4746 m_args (),
4747 m_require_tail_call (0)
4749 for (int i = 0; i< numargs; i++)
4750 m_args.safe_push (args[i]);
4753 /* Subroutine for use by call and call_though_ptr's write_reproducer
4754 methods. */
4756 void
4757 recording::base_call::write_reproducer_tail_call (reproducer &r,
4758 const char *id)
4760 if (m_require_tail_call)
4762 r.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
4763 " %i); /* int require_tail_call*/\n",
4769 /* The implementation of class gcc::jit::recording::call. */
4771 /* The constructor for gcc::jit::recording::call. */
4773 recording::call::call (recording::context *ctxt,
4774 recording::location *loc,
4775 recording::function *func,
4776 int numargs,
4777 rvalue **args)
4778 : base_call (ctxt, loc, func->get_return_type (), numargs, args),
4779 m_func (func)
4783 /* Implementation of pure virtual hook recording::memento::replay_into
4784 for recording::call. */
4786 void
4787 recording::call::replay_into (replayer *r)
4789 auto_vec<playback::rvalue *> playback_args;
4790 playback_args.create (m_args.length ());
4791 for (unsigned i = 0; i< m_args.length (); i++)
4792 playback_args.safe_push (m_args[i]->playback_rvalue ());
4794 set_playback_obj (r->new_call (playback_location (r, m_loc),
4795 m_func->playback_function (),
4796 &playback_args,
4797 m_require_tail_call));
4800 /* Implementation of pure virtual hook recording::rvalue::visit_children
4801 for recording::call. */
4803 void
4804 recording::call::visit_children (rvalue_visitor *v)
4806 for (unsigned i = 0; i< m_args.length (); i++)
4807 v->visit (m_args[i]);
4810 /* Implementation of recording::memento::make_debug_string for
4811 function calls. */
4813 recording::string *
4814 recording::call::make_debug_string ()
4816 enum precedence prec = get_precedence ();
4817 /* First, build a buffer for the arguments. */
4818 /* Calculate length of said buffer. */
4819 size_t sz = 1; /* nil terminator */
4820 for (unsigned i = 0; i< m_args.length (); i++)
4822 sz += strlen (m_args[i]->get_debug_string_parens (prec));
4823 sz += 2; /* ", " separator */
4826 /* Now allocate and populate the buffer. */
4827 char *argbuf = new char[sz];
4828 size_t len = 0;
4830 for (unsigned i = 0; i< m_args.length (); i++)
4832 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4833 len += strlen (m_args[i]->get_debug_string_parens (prec));
4834 if (i + 1 < m_args.length ())
4836 strcpy (argbuf + len, ", ");
4837 len += 2;
4840 argbuf[len] = '\0';
4842 /* ...and use it to get the string for the call as a whole. */
4843 string *result = string::from_printf (m_ctxt,
4844 "%s (%s)",
4845 m_func->get_debug_string (),
4846 argbuf);
4848 delete[] argbuf;
4850 return result;
4853 void
4854 recording::call::write_reproducer (reproducer &r)
4856 const char *id = r.make_identifier (this, "call");
4857 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4858 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4859 args_id,
4860 m_args.length ());
4861 for (unsigned i = 0; i< m_args.length (); i++)
4862 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4863 r.write (" };\n");
4864 r.write (" gcc_jit_rvalue *%s =\n"
4865 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4866 " %s, /* gcc_jit_location *loc */\n"
4867 " %s, /* gcc_jit_function *func */\n"
4868 " %i, /* int numargs */ \n"
4869 " %s); /* gcc_jit_rvalue **args*/\n",
4871 r.get_identifier (get_context ()),
4872 r.get_identifier (m_loc),
4873 r.get_identifier (m_func),
4874 m_args.length (),
4875 args_id);
4876 write_reproducer_tail_call (r, id);
4879 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4881 /* The constructor for recording::call_through_ptr. */
4883 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
4884 recording::location *loc,
4885 recording::rvalue *fn_ptr,
4886 int numargs,
4887 rvalue **args)
4888 : base_call (ctxt, loc,
4889 fn_ptr->get_type ()->dereference ()
4890 ->as_a_function_type ()->get_return_type (),
4891 numargs, args),
4892 m_fn_ptr (fn_ptr)
4896 /* Implementation of pure virtual hook recording::memento::replay_into
4897 for recording::call_through_ptr. */
4899 void
4900 recording::call_through_ptr::replay_into (replayer *r)
4902 auto_vec<playback::rvalue *> playback_args;
4903 playback_args.create (m_args.length ());
4904 for (unsigned i = 0; i< m_args.length (); i++)
4905 playback_args.safe_push (m_args[i]->playback_rvalue ());
4907 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
4908 m_fn_ptr->playback_rvalue (),
4909 &playback_args,
4910 m_require_tail_call));
4913 /* Implementation of pure virtual hook recording::rvalue::visit_children
4914 for recording::call_through_ptr. */
4916 void
4917 recording::call_through_ptr::visit_children (rvalue_visitor *v)
4919 v->visit (m_fn_ptr);
4920 for (unsigned i = 0; i< m_args.length (); i++)
4921 v->visit (m_args[i]);
4924 /* Implementation of recording::memento::make_debug_string for
4925 calls through function ptrs. */
4927 recording::string *
4928 recording::call_through_ptr::make_debug_string ()
4930 enum precedence prec = get_precedence ();
4931 /* First, build a buffer for the arguments. */
4932 /* Calculate length of said buffer. */
4933 size_t sz = 1; /* nil terminator */
4934 for (unsigned i = 0; i< m_args.length (); i++)
4936 sz += strlen (m_args[i]->get_debug_string_parens (prec));
4937 sz += 2; /* ", " separator */
4940 /* Now allocate and populate the buffer. */
4941 char *argbuf = new char[sz];
4942 size_t len = 0;
4944 for (unsigned i = 0; i< m_args.length (); i++)
4946 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4947 len += strlen (m_args[i]->get_debug_string_parens (prec));
4948 if (i + 1 < m_args.length ())
4950 strcpy (argbuf + len, ", ");
4951 len += 2;
4954 argbuf[len] = '\0';
4956 /* ...and use it to get the string for the call as a whole. */
4957 string *result = string::from_printf (m_ctxt,
4958 "%s (%s)",
4959 m_fn_ptr->get_debug_string_parens (prec),
4960 argbuf);
4962 delete[] argbuf;
4964 return result;
4967 /* Implementation of recording::memento::write_reproducer for
4968 call_through_ptr. */
4970 void
4971 recording::call_through_ptr::write_reproducer (reproducer &r)
4973 const char *id = r.make_identifier (this, "call");
4974 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4975 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4976 args_id,
4977 m_args.length ());
4978 for (unsigned i = 0; i< m_args.length (); i++)
4979 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4980 r.write (" };\n");
4981 r.write (" gcc_jit_rvalue *%s =\n"
4982 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
4983 " %s, /* gcc_jit_location *loc */\n"
4984 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
4985 " %i, /* int numargs */ \n"
4986 " %s); /* gcc_jit_rvalue **args*/\n",
4988 r.get_identifier (get_context ()),
4989 r.get_identifier (m_loc),
4990 r.get_identifier_as_rvalue (m_fn_ptr),
4991 m_args.length (),
4992 args_id);
4993 write_reproducer_tail_call (r, id);
4996 /* The implementation of class gcc::jit::recording::array_access. */
4998 /* Implementation of pure virtual hook recording::memento::replay_into
4999 for recording::array_access. */
5001 void
5002 recording::array_access::replay_into (replayer *r)
5004 set_playback_obj (
5005 r->new_array_access (playback_location (r, m_loc),
5006 m_ptr->playback_rvalue (),
5007 m_index->playback_rvalue ()));
5010 /* Implementation of pure virtual hook recording::rvalue::visit_children
5011 for recording::array_access. */
5013 void
5014 recording::array_access::visit_children (rvalue_visitor *v)
5016 v->visit (m_ptr);
5017 v->visit (m_index);
5020 /* Implementation of recording::memento::make_debug_string for
5021 array accesses. */
5023 recording::string *
5024 recording::array_access::make_debug_string ()
5026 enum precedence prec = get_precedence ();
5027 return string::from_printf (m_ctxt,
5028 "%s[%s]",
5029 m_ptr->get_debug_string_parens (prec),
5030 m_index->get_debug_string_parens (prec));
5033 /* Implementation of recording::memento::write_reproducer for
5034 array_access. */
5036 void
5037 recording::array_access::write_reproducer (reproducer &r)
5039 const char *id = r.make_identifier (this, "lvalue");
5040 r.write (" gcc_jit_lvalue *%s = \n"
5041 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
5042 " %s, /*gcc_jit_location *loc */\n"
5043 " %s, /* gcc_jit_rvalue *ptr */\n"
5044 " %s); /* gcc_jit_rvalue *index */\n",
5046 r.get_identifier (get_context ()),
5047 r.get_identifier (m_loc),
5048 r.get_identifier_as_rvalue (m_ptr),
5049 r.get_identifier_as_rvalue (m_index));
5052 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
5054 /* Implementation of pure virtual hook recording::memento::replay_into
5055 for recording::access_field_of_lvalue. */
5057 void
5058 recording::access_field_of_lvalue::replay_into (replayer *r)
5060 set_playback_obj (
5061 m_lvalue->playback_lvalue ()
5062 ->access_field (playback_location (r, m_loc),
5063 m_field->playback_field ()));
5067 /* Implementation of pure virtual hook recording::rvalue::visit_children
5068 for recording::access_field_of_lvalue. */
5070 void
5071 recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
5073 v->visit (m_lvalue);
5076 /* Implementation of recording::memento::make_debug_string for
5077 accessing a field of an lvalue. */
5079 recording::string *
5080 recording::access_field_of_lvalue::make_debug_string ()
5082 enum precedence prec = get_precedence ();
5083 return string::from_printf (m_ctxt,
5084 "%s.%s",
5085 m_lvalue->get_debug_string_parens (prec),
5086 m_field->get_debug_string ());
5089 /* Implementation of recording::memento::write_reproducer for
5090 access_field_of_lvalue. */
5092 void
5093 recording::access_field_of_lvalue::write_reproducer (reproducer &r)
5095 const char *id = r.make_identifier (this, "lvalue");
5096 r.write (" gcc_jit_lvalue *%s = \n"
5097 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5098 " %s, /*gcc_jit_location *loc */\n"
5099 " %s);\n",
5101 r.get_identifier_as_lvalue (m_lvalue),
5102 r.get_identifier (m_loc),
5103 r.get_identifier (m_field));
5106 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
5108 /* Implementation of pure virtual hook recording::memento::replay_into
5109 for recording::access_field_rvalue. */
5111 void
5112 recording::access_field_rvalue::replay_into (replayer *r)
5114 set_playback_obj (
5115 m_rvalue->playback_rvalue ()
5116 ->access_field (playback_location (r, m_loc),
5117 m_field->playback_field ()));
5120 /* Implementation of pure virtual hook recording::rvalue::visit_children
5121 for recording::access_field_rvalue. */
5123 void
5124 recording::access_field_rvalue::visit_children (rvalue_visitor *v)
5126 v->visit (m_rvalue);
5129 /* Implementation of recording::memento::make_debug_string for
5130 accessing a field of an rvalue. */
5132 recording::string *
5133 recording::access_field_rvalue::make_debug_string ()
5135 enum precedence prec = get_precedence ();
5136 return string::from_printf (m_ctxt,
5137 "%s.%s",
5138 m_rvalue->get_debug_string_parens (prec),
5139 m_field->get_debug_string ());
5142 /* Implementation of recording::memento::write_reproducer for
5143 access_field_rvalue. */
5145 void
5146 recording::access_field_rvalue::write_reproducer (reproducer &r)
5148 const char *id = r.make_identifier (this, "rvalue");
5149 r.write (" gcc_jit_rvalue *%s = \n"
5150 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5151 " %s, /*gcc_jit_location *loc */\n"
5152 " %s);\n",
5154 r.get_identifier_as_rvalue (m_rvalue),
5155 r.get_identifier (m_loc),
5156 r.get_identifier (m_field));
5159 /* The implementation of class
5160 gcc::jit::recording::dereference_field_rvalue. */
5162 /* Implementation of pure virtual hook recording::memento::replay_into
5163 for recording::dereference_field_rvalue. */
5165 void
5166 recording::dereference_field_rvalue::replay_into (replayer *r)
5168 set_playback_obj (
5169 m_rvalue->playback_rvalue ()->
5170 dereference_field (playback_location (r, m_loc),
5171 m_field->playback_field ()));
5174 /* Implementation of pure virtual hook recording::rvalue::visit_children
5175 for recording::dereference_field_rvalue. */
5177 void
5178 recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
5180 v->visit (m_rvalue);
5183 /* Implementation of recording::memento::make_debug_string for
5184 dereferencing a field of an rvalue. */
5186 recording::string *
5187 recording::dereference_field_rvalue::make_debug_string ()
5189 enum precedence prec = get_precedence ();
5190 return string::from_printf (m_ctxt,
5191 "%s->%s",
5192 m_rvalue->get_debug_string_parens (prec),
5193 m_field->get_debug_string ());
5196 /* Implementation of recording::memento::write_reproducer for
5197 dereference_field_rvalue. */
5199 void
5200 recording::dereference_field_rvalue::write_reproducer (reproducer &r)
5202 const char *id = r.make_identifier (this, "lvalue");
5203 r.write (" gcc_jit_lvalue *%s=\n"
5204 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5205 " %s, /* gcc_jit_location *loc */\n"
5206 " %s); /* gcc_jit_field *field */\n",
5208 r.get_identifier_as_rvalue (m_rvalue),
5209 r.get_identifier (m_loc),
5210 r.get_identifier (m_field));
5213 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5215 /* Implementation of pure virtual hook recording::memento::replay_into
5216 for recording::dereference_rvalue. */
5218 void
5219 recording::dereference_rvalue::replay_into (replayer *r)
5221 set_playback_obj (
5222 m_rvalue->playback_rvalue ()->
5223 dereference (playback_location (r, m_loc)));
5226 /* Implementation of pure virtual hook recording::rvalue::visit_children
5227 for recording::dereference_rvalue. */
5229 void
5230 recording::dereference_rvalue::visit_children (rvalue_visitor *v)
5232 v->visit (m_rvalue);
5235 /* Implementation of recording::memento::make_debug_string for
5236 dereferencing an rvalue. */
5238 recording::string *
5239 recording::dereference_rvalue::make_debug_string ()
5241 enum precedence prec = get_precedence ();
5242 return string::from_printf (m_ctxt,
5243 "*%s",
5244 m_rvalue->get_debug_string_parens (prec));
5247 /* Implementation of recording::memento::write_reproducer for
5248 dereference_rvalue. */
5250 void
5251 recording::dereference_rvalue::write_reproducer (reproducer &r)
5253 const char *id = r.make_identifier (this, "dereference");
5254 r.write (" gcc_jit_lvalue *%s =\n"
5255 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5256 " %s); /* gcc_jit_location *loc */\n",
5258 r.get_identifier_as_rvalue (m_rvalue),
5259 r.get_identifier (m_loc));
5262 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5264 /* Implementation of pure virtual hook recording::memento::replay_into
5265 for recording::get_address_of_lvalue. */
5267 void
5268 recording::get_address_of_lvalue::replay_into (replayer *r)
5270 set_playback_obj (
5271 m_lvalue->playback_lvalue ()->
5272 get_address (playback_location (r, m_loc)));
5275 /* Implementation of pure virtual hook recording::rvalue::visit_children
5276 for recording::get_address_of_lvalue. */
5278 void
5279 recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
5281 v->visit (m_lvalue);
5284 /* Implementation of recording::memento::make_debug_string for
5285 getting the address of an lvalue. */
5287 recording::string *
5288 recording::get_address_of_lvalue::make_debug_string ()
5290 enum precedence prec = get_precedence ();
5291 return string::from_printf (m_ctxt,
5292 "&%s",
5293 m_lvalue->get_debug_string_parens (prec));
5296 /* Implementation of recording::memento::write_reproducer for
5297 get_address_of_lvalue. */
5299 void
5300 recording::get_address_of_lvalue::write_reproducer (reproducer &r)
5302 const char *id = r.make_identifier (this, "address_of");
5303 r.write (" gcc_jit_rvalue *%s =\n"
5304 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5305 " %s); /* gcc_jit_location *loc */\n",
5307 r.get_identifier_as_lvalue (m_lvalue),
5308 r.get_identifier (m_loc));
5311 /* The implementation of class gcc::jit::recording::local. */
5313 /* Implementation of pure virtual hook recording::memento::replay_into
5314 for recording::local. */
5316 void
5317 recording::local::replay_into (replayer *r)
5319 set_playback_obj (
5320 m_func->playback_function ()
5321 ->new_local (playback_location (r, m_loc),
5322 m_type->playback_type (),
5323 playback_string (m_name)));
5326 /* Override the default implementation of
5327 recording::memento::write_to_dump for locals by writing
5328 TYPE NAME;
5329 for use at the top of the function body as if it were a
5330 declaration. */
5332 void
5333 recording::local::write_to_dump (dump &d)
5335 if (d.update_locations ())
5336 m_loc = d.make_location ();
5337 d.write(" %s %s;\n",
5338 m_type->get_debug_string (),
5339 get_debug_string ());
5342 void
5343 recording::local::write_reproducer (reproducer &r)
5345 const char *id = r.make_identifier (this, "local");
5346 r.write (" gcc_jit_lvalue *%s =\n"
5347 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5348 " %s, /* gcc_jit_location *loc */\n"
5349 " %s, /* gcc_jit_type *type */\n"
5350 " %s); /* const char *name */\n",
5352 r.get_identifier (m_func),
5353 r.get_identifier (m_loc),
5354 r.get_identifier_as_type (m_type),
5355 m_name->get_debug_string ());
5358 /* The implementation of class gcc::jit::recording::statement. */
5360 /* We poison the default implementation of
5361 gcc::jit::recording::statement::get_successor_blocks
5362 since this vfunc must only ever be called on terminator
5363 statements. */
5365 vec <recording::block *>
5366 recording::statement::get_successor_blocks () const
5368 /* The base class implementation is for non-terminating statements,
5369 and thus should never be called. */
5370 gcc_unreachable ();
5371 vec <block *> result;
5372 result.create (0);
5373 return result;
5376 /* Extend the default implementation of
5377 recording::memento::write_to_dump for statements by (if requested)
5378 updating the location of the statement to the current location in
5379 the dumpfile. */
5381 void
5382 recording::statement::write_to_dump (dump &d)
5384 memento::write_to_dump (d);
5385 if (d.update_locations ())
5386 m_loc = d.make_location ();
5389 /* The implementation of class gcc::jit::recording::eval. */
5391 /* Implementation of pure virtual hook recording::memento::replay_into
5392 for recording::eval. */
5394 void
5395 recording::eval::replay_into (replayer *r)
5397 playback_block (get_block ())
5398 ->add_eval (playback_location (r),
5399 m_rvalue->playback_rvalue ());
5402 /* Implementation of recording::memento::make_debug_string for
5403 an eval statement. */
5405 recording::string *
5406 recording::eval::make_debug_string ()
5408 return string::from_printf (m_ctxt,
5409 "(void)%s;",
5410 m_rvalue->get_debug_string ());
5413 /* Implementation of recording::memento::write_reproducer for
5414 eval statements. */
5416 void
5417 recording::eval::write_reproducer (reproducer &r)
5419 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5420 " %s, /* gcc_jit_location *loc */\n"
5421 " %s); /* gcc_jit_rvalue *rvalue */\n",
5422 r.get_identifier (get_block ()),
5423 r.get_identifier (get_loc ()),
5424 r.get_identifier_as_rvalue (m_rvalue));
5427 /* The implementation of class gcc::jit::recording::assignment. */
5429 /* Implementation of pure virtual hook recording::memento::replay_into
5430 for recording::assignment. */
5432 void
5433 recording::assignment::replay_into (replayer *r)
5435 playback_block (get_block ())
5436 ->add_assignment (playback_location (r),
5437 m_lvalue->playback_lvalue (),
5438 m_rvalue->playback_rvalue ());
5441 /* Implementation of recording::memento::make_debug_string for
5442 an assignment statement. */
5444 recording::string *
5445 recording::assignment::make_debug_string ()
5447 return string::from_printf (m_ctxt,
5448 "%s = %s;",
5449 m_lvalue->get_debug_string (),
5450 m_rvalue->get_debug_string ());
5453 /* Implementation of recording::memento::write_reproducer for
5454 assignment statements. */
5456 void
5457 recording::assignment::write_reproducer (reproducer &r)
5459 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5460 " %s, /* gcc_jit_location *loc */\n"
5461 " %s, /* gcc_jit_lvalue *lvalue */\n"
5462 " %s); /* gcc_jit_rvalue *rvalue */\n",
5463 r.get_identifier (get_block ()),
5464 r.get_identifier (get_loc ()),
5465 r.get_identifier_as_lvalue (m_lvalue),
5466 r.get_identifier_as_rvalue (m_rvalue));
5469 /* The implementation of class gcc::jit::recording::assignment_op. */
5471 /* Implementation of pure virtual hook recording::memento::replay_into
5472 for recording::assignment_op. */
5474 void
5475 recording::assignment_op::replay_into (replayer *r)
5477 playback::type *result_type =
5478 m_lvalue->playback_lvalue ()->get_type ();
5480 playback::rvalue *binary_op =
5481 r->new_binary_op (playback_location (r),
5482 m_op,
5483 result_type,
5484 m_lvalue->playback_rvalue (),
5485 m_rvalue->playback_rvalue ());
5487 playback_block (get_block ())
5488 ->add_assignment (playback_location (r),
5489 m_lvalue->playback_lvalue (),
5490 binary_op);
5493 /* Implementation of recording::memento::make_debug_string for
5494 an assignment_op statement. */
5496 recording::string *
5497 recording::assignment_op::make_debug_string ()
5499 return string::from_printf (m_ctxt,
5500 "%s %s= %s;",
5501 m_lvalue->get_debug_string (),
5502 binary_op_strings[m_op],
5503 m_rvalue->get_debug_string ());
5506 /* Implementation of recording::memento::write_reproducer for
5507 assignment_op statements. */
5509 void
5510 recording::assignment_op::write_reproducer (reproducer &r)
5512 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5513 " %s, /* gcc_jit_location *loc */\n"
5514 " %s, /* gcc_jit_lvalue *lvalue */\n"
5515 " %s, /* enum gcc_jit_binary_op op */\n"
5516 " %s); /* gcc_jit_rvalue *rvalue */\n",
5517 r.get_identifier (get_block ()),
5518 r.get_identifier (get_loc ()),
5519 r.get_identifier_as_lvalue (m_lvalue),
5520 binary_op_reproducer_strings[m_op],
5521 r.get_identifier_as_rvalue (m_rvalue));
5524 /* The implementation of class gcc::jit::recording::comment. */
5526 /* Implementation of pure virtual hook recording::memento::replay_into
5527 for recording::comment. */
5529 void
5530 recording::comment::replay_into (replayer *r)
5532 playback_block (get_block ())
5533 ->add_comment (playback_location (r),
5534 m_text->c_str ());
5537 /* Implementation of recording::memento::make_debug_string for
5538 a comment "statement". */
5540 recording::string *
5541 recording::comment::make_debug_string ()
5543 return string::from_printf (m_ctxt,
5544 "/* %s */",
5545 m_text->c_str ());
5548 /* Implementation of recording::memento::write_reproducer for
5549 comments. */
5551 void
5552 recording::comment::write_reproducer (reproducer &r)
5554 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5555 " %s, /* gcc_jit_location *loc */\n"
5556 " %s); /* const char *text */\n",
5557 r.get_identifier (get_block ()),
5558 r.get_identifier (get_loc ()),
5559 m_text->get_debug_string ());
5562 /* The implementation of class gcc::jit::recording::conditional. */
5564 /* Implementation of pure virtual hook recording::memento::replay_into
5565 for recording::conditional. */
5567 void
5568 recording::conditional::replay_into (replayer *r)
5570 playback_block (get_block ())
5571 ->add_conditional (playback_location (r),
5572 m_boolval->playback_rvalue (),
5573 playback_block (m_on_true),
5574 playback_block (m_on_false));
5577 /* Override the poisoned default implementation of
5578 gcc::jit::recording::statement::get_successor_blocks
5580 A conditional jump has 2 successor blocks. */
5582 vec <recording::block *>
5583 recording::conditional::get_successor_blocks () const
5585 vec <block *> result;
5586 result.create (2);
5587 result.quick_push (m_on_true);
5588 result.quick_push (m_on_false);
5589 return result;
5592 /* Implementation of recording::memento::make_debug_string for
5593 a conditional jump statement. */
5595 recording::string *
5596 recording::conditional::make_debug_string ()
5598 if (m_on_false)
5599 return string::from_printf (m_ctxt,
5600 "if (%s) goto %s; else goto %s;",
5601 m_boolval->get_debug_string (),
5602 m_on_true->get_debug_string (),
5603 m_on_false->get_debug_string ());
5604 else
5605 return string::from_printf (m_ctxt,
5606 "if (%s) goto %s;",
5607 m_boolval->get_debug_string (),
5608 m_on_true->get_debug_string ());
5611 /* Implementation of recording::memento::write_reproducer for
5612 conditional statements. */
5614 void
5615 recording::conditional::write_reproducer (reproducer &r)
5617 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5618 " %s, /* gcc_jit_location *loc */\n"
5619 " %s, /* gcc_jit_rvalue *boolval */\n"
5620 " %s, /* gcc_jit_block *on_true */\n"
5621 " %s); /* gcc_jit_block *on_false */\n",
5622 r.get_identifier (get_block ()),
5623 r.get_identifier (get_loc ()),
5624 r.get_identifier_as_rvalue (m_boolval),
5625 r.get_identifier (m_on_true),
5626 r.get_identifier (m_on_false));
5629 /* The implementation of class gcc::jit::recording::jump. */
5631 /* Implementation of pure virtual hook recording::memento::replay_into
5632 for recording::jump. */
5634 void
5635 recording::jump::replay_into (replayer *r)
5637 playback_block (get_block ())
5638 ->add_jump (playback_location (r),
5639 m_target->playback_block ());
5642 /* Override the poisoned default implementation of
5643 gcc::jit::recording::statement::get_successor_blocks
5645 An unconditional jump has 1 successor block. */
5647 vec <recording::block *>
5648 recording::jump::get_successor_blocks () const
5650 vec <block *> result;
5651 result.create (1);
5652 result.quick_push (m_target);
5653 return result;
5656 /* Implementation of recording::memento::make_debug_string for
5657 a unconditional jump statement. */
5659 recording::string *
5660 recording::jump::make_debug_string ()
5662 return string::from_printf (m_ctxt,
5663 "goto %s;",
5664 m_target->get_debug_string ());
5667 /* Implementation of recording::memento::write_reproducer for
5668 jump statements. */
5670 void
5671 recording::jump::write_reproducer (reproducer &r)
5673 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5674 " %s, /* gcc_jit_location *loc */\n"
5675 " %s); /* gcc_jit_block *target */\n",
5676 r.get_identifier (get_block ()),
5677 r.get_identifier (get_loc ()),
5678 r.get_identifier (m_target));
5681 /* The implementation of class gcc::jit::recording::return_. */
5683 /* Implementation of pure virtual hook recording::memento::replay_into
5684 for recording::return_. */
5686 void
5687 recording::return_::replay_into (replayer *r)
5689 playback_block (get_block ())
5690 ->add_return (playback_location (r),
5691 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
5694 /* Override the poisoned default implementation of
5695 gcc::jit::recording::statement::get_successor_blocks
5697 A return statement has no successor block. */
5699 vec <recording::block *>
5700 recording::return_::get_successor_blocks () const
5702 vec <block *> result;
5703 result.create (0);
5704 return result;
5707 /* Implementation of recording::memento::make_debug_string for
5708 a return statement (covers both those with and without rvalues). */
5710 recording::string *
5711 recording::return_::make_debug_string ()
5713 if (m_rvalue)
5714 return string::from_printf (m_ctxt,
5715 "return %s;",
5716 m_rvalue->get_debug_string ());
5717 else
5718 return string::from_printf (m_ctxt,
5719 "return;");
5722 /* Implementation of recording::memento::write_reproducer for
5723 return statements. */
5725 void
5726 recording::return_::write_reproducer (reproducer &r)
5728 if (m_rvalue)
5729 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5730 " %s, /* gcc_jit_location *loc */\n"
5731 " %s); /* gcc_jit_rvalue *rvalue */\n",
5732 r.get_identifier (get_block ()),
5733 r.get_identifier (get_loc ()),
5734 r.get_identifier_as_rvalue (m_rvalue));
5735 else
5736 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5737 " %s); /* gcc_jit_location *loc */\n",
5738 r.get_identifier (get_block ()),
5739 r.get_identifier (get_loc ()));
5742 /* The implementation of class gcc::jit::recording::case_. */
5744 void
5745 recording::case_::write_reproducer (reproducer &r)
5747 const char *id = r.make_identifier (this, "case");
5748 const char *fmt =
5749 " gcc_jit_case *%s = \n"
5750 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
5751 " %s, /* gcc_jit_rvalue *min_value */\n"
5752 " %s, /* gcc_jit_rvalue *max_value */\n"
5753 " %s); /* gcc_jit_block *dest_block */\n";
5754 r.write (fmt,
5756 r.get_identifier (get_context ()),
5757 r.get_identifier_as_rvalue (m_min_value),
5758 r.get_identifier_as_rvalue (m_max_value),
5759 r.get_identifier (m_dest_block));
5762 recording::string *
5763 recording::case_::make_debug_string ()
5765 return string::from_printf (get_context (),
5766 "case %s ... %s: goto %s;",
5767 m_min_value->get_debug_string (),
5768 m_max_value->get_debug_string (),
5769 m_dest_block->get_debug_string ());
5772 /* The implementation of class gcc::jit::recording::switch_. */
5774 /* gcc::jit::recording::switch_'s constructor. */
5776 recording::switch_::switch_ (block *b,
5777 location *loc,
5778 rvalue *expr,
5779 block *default_block,
5780 int num_cases,
5781 case_ **cases)
5782 : statement (b, loc),
5783 m_expr (expr),
5784 m_default_block (default_block)
5786 m_cases.reserve_exact (num_cases);
5787 for (int i = 0; i< num_cases; i++)
5788 m_cases.quick_push (cases[i]);
5791 /* Implementation of pure virtual hook recording::memento::replay_into
5792 for recording::switch_. */
5794 void
5795 recording::switch_::replay_into (replayer *r)
5797 auto_vec <playback::case_> pcases;
5798 int i;
5799 recording::case_ *rcase;
5800 pcases.reserve_exact (m_cases.length ());
5801 FOR_EACH_VEC_ELT (m_cases, i, rcase)
5803 playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (),
5804 rcase->get_max_value ()->playback_rvalue (),
5805 rcase->get_dest_block ()->playback_block ());
5806 pcases.safe_push (pcase);
5808 playback_block (get_block ())
5809 ->add_switch (playback_location (r),
5810 m_expr->playback_rvalue (),
5811 m_default_block->playback_block (),
5812 &pcases);
5815 /* Override the poisoned default implementation of
5816 gcc::jit::recording::statement::get_successor_blocks
5818 A switch statement has (NUM_CASES + 1) successor blocks. */
5820 vec <recording::block *>
5821 recording::switch_::get_successor_blocks () const
5823 vec <block *> result;
5824 result.create (m_cases.length () + 1);
5825 result.quick_push (m_default_block);
5826 int i;
5827 case_ *c;
5828 FOR_EACH_VEC_ELT (m_cases, i, c)
5829 result.quick_push (c->get_dest_block ());
5830 return result;
5833 /* Implementation of recording::memento::make_debug_string for
5834 a switch statement. */
5836 recording::string *
5837 recording::switch_::make_debug_string ()
5839 auto_vec <char> cases_str;
5840 int i;
5841 case_ *c;
5842 FOR_EACH_VEC_ELT (m_cases, i, c)
5844 size_t len = strlen (c->get_debug_string ());
5845 unsigned idx = cases_str.length ();
5846 cases_str.safe_grow (idx + 1 + len);
5847 cases_str[idx] = ' ';
5848 memcpy (&(cases_str[idx + 1]),
5849 c->get_debug_string (),
5850 len);
5852 cases_str.safe_push ('\0');
5854 return string::from_printf (m_ctxt,
5855 "switch (%s) {default: goto %s;%s}",
5856 m_expr->get_debug_string (),
5857 m_default_block->get_debug_string (),
5858 &cases_str[0]);
5861 /* Implementation of recording::memento::write_reproducer for
5862 switch statements. */
5864 void
5865 recording::switch_::write_reproducer (reproducer &r)
5867 r.make_identifier (this, "switch");
5868 int i;
5869 case_ *c;
5870 const char *cases_id =
5871 r.make_tmp_identifier ("cases_for", this);
5872 r.write (" gcc_jit_case *%s[%i] = {\n",
5873 cases_id,
5874 m_cases.length ());
5875 FOR_EACH_VEC_ELT (m_cases, i, c)
5876 r.write (" %s,\n", r.get_identifier (c));
5877 r.write (" };\n");
5878 const char *fmt =
5879 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
5880 " %s, /* gcc_jit_location *loc */\n"
5881 " %s, /* gcc_jit_rvalue *expr */\n"
5882 " %s, /* gcc_jit_block *default_block */\n"
5883 " %i, /* int num_cases */\n"
5884 " %s); /* gcc_jit_case **cases */\n";
5885 r.write (fmt,
5886 r.get_identifier (get_block ()),
5887 r.get_identifier (get_loc ()),
5888 r.get_identifier_as_rvalue (m_expr),
5889 r.get_identifier (m_default_block),
5890 m_cases.length (),
5891 cases_id);
5894 } // namespace gcc::jit
5896 } // namespace gcc