2016-07-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
[official-gcc.git] / gcc / jit / jit-recording.c
blob937634207d652e187f0ff9fc0555d23ddec01174
1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2016 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 const char *
1978 recording::type::access_as_type (reproducer &r)
1980 return r.get_identifier (this);
1983 /* Implementation of pure virtual hook recording::type::dereference for
1984 recording::memento_of_get_type. */
1986 recording::type *
1987 recording::memento_of_get_type::dereference ()
1989 switch (m_kind)
1991 default: gcc_unreachable ();
1993 case GCC_JIT_TYPE_VOID:
1994 return NULL;
1996 case GCC_JIT_TYPE_VOID_PTR:
1997 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
1999 case GCC_JIT_TYPE_BOOL:
2000 case GCC_JIT_TYPE_CHAR:
2001 case GCC_JIT_TYPE_SIGNED_CHAR:
2002 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2003 case GCC_JIT_TYPE_SHORT:
2004 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2005 case GCC_JIT_TYPE_INT:
2006 case GCC_JIT_TYPE_UNSIGNED_INT:
2007 case GCC_JIT_TYPE_LONG:
2008 case GCC_JIT_TYPE_UNSIGNED_LONG:
2009 case GCC_JIT_TYPE_LONG_LONG:
2010 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2011 case GCC_JIT_TYPE_FLOAT:
2012 case GCC_JIT_TYPE_DOUBLE:
2013 case GCC_JIT_TYPE_LONG_DOUBLE:
2014 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2015 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2016 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2017 /* Not a pointer: */
2018 return NULL;
2020 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2021 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
2023 case GCC_JIT_TYPE_SIZE_T:
2024 /* Not a pointer: */
2025 return NULL;
2027 case GCC_JIT_TYPE_FILE_PTR:
2028 /* Give the client code back an opaque "struct FILE". */
2029 return m_ctxt->get_opaque_FILE_type ();
2033 /* Implementation of pure virtual hook recording::type::is_int for
2034 recording::memento_of_get_type. */
2036 bool
2037 recording::memento_of_get_type::is_int () const
2039 switch (m_kind)
2041 default: gcc_unreachable ();
2043 case GCC_JIT_TYPE_VOID:
2044 return false;
2046 case GCC_JIT_TYPE_VOID_PTR:
2047 return false;
2049 case GCC_JIT_TYPE_BOOL:
2050 return false;
2052 case GCC_JIT_TYPE_CHAR:
2053 case GCC_JIT_TYPE_SIGNED_CHAR:
2054 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2055 case GCC_JIT_TYPE_SHORT:
2056 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2057 case GCC_JIT_TYPE_INT:
2058 case GCC_JIT_TYPE_UNSIGNED_INT:
2059 case GCC_JIT_TYPE_LONG:
2060 case GCC_JIT_TYPE_UNSIGNED_LONG:
2061 case GCC_JIT_TYPE_LONG_LONG:
2062 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2063 return true;
2065 case GCC_JIT_TYPE_FLOAT:
2066 case GCC_JIT_TYPE_DOUBLE:
2067 case GCC_JIT_TYPE_LONG_DOUBLE:
2068 return false;
2070 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2071 return false;
2073 case GCC_JIT_TYPE_SIZE_T:
2074 return true;
2076 case GCC_JIT_TYPE_FILE_PTR:
2077 return false;
2079 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2080 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2081 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2082 return false;
2086 /* Implementation of pure virtual hook recording::type::is_float for
2087 recording::memento_of_get_type. */
2089 bool
2090 recording::memento_of_get_type::is_float () const
2092 switch (m_kind)
2094 default: gcc_unreachable ();
2096 case GCC_JIT_TYPE_VOID:
2097 return false;
2099 case GCC_JIT_TYPE_VOID_PTR:
2100 return false;
2102 case GCC_JIT_TYPE_BOOL:
2103 return false;
2105 case GCC_JIT_TYPE_CHAR:
2106 case GCC_JIT_TYPE_SIGNED_CHAR:
2107 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2108 case GCC_JIT_TYPE_SHORT:
2109 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2110 case GCC_JIT_TYPE_INT:
2111 case GCC_JIT_TYPE_UNSIGNED_INT:
2112 case GCC_JIT_TYPE_LONG:
2113 case GCC_JIT_TYPE_UNSIGNED_LONG:
2114 case GCC_JIT_TYPE_LONG_LONG:
2115 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2116 return false;
2118 case GCC_JIT_TYPE_FLOAT:
2119 case GCC_JIT_TYPE_DOUBLE:
2120 case GCC_JIT_TYPE_LONG_DOUBLE:
2121 return true;
2123 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2124 return false;
2126 case GCC_JIT_TYPE_SIZE_T:
2127 return false;
2129 case GCC_JIT_TYPE_FILE_PTR:
2130 return false;
2132 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2133 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2134 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2135 return true;
2139 /* Implementation of pure virtual hook recording::type::is_bool for
2140 recording::memento_of_get_type. */
2142 bool
2143 recording::memento_of_get_type::is_bool () const
2145 switch (m_kind)
2147 default: gcc_unreachable ();
2149 case GCC_JIT_TYPE_VOID:
2150 return false;
2152 case GCC_JIT_TYPE_VOID_PTR:
2153 return false;
2155 case GCC_JIT_TYPE_BOOL:
2156 return true;
2158 case GCC_JIT_TYPE_CHAR:
2159 case GCC_JIT_TYPE_SIGNED_CHAR:
2160 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2161 case GCC_JIT_TYPE_SHORT:
2162 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2163 case GCC_JIT_TYPE_INT:
2164 case GCC_JIT_TYPE_UNSIGNED_INT:
2165 case GCC_JIT_TYPE_LONG:
2166 case GCC_JIT_TYPE_UNSIGNED_LONG:
2167 case GCC_JIT_TYPE_LONG_LONG:
2168 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2169 return false;
2171 case GCC_JIT_TYPE_FLOAT:
2172 case GCC_JIT_TYPE_DOUBLE:
2173 case GCC_JIT_TYPE_LONG_DOUBLE:
2174 return false;
2176 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2177 return false;
2179 case GCC_JIT_TYPE_SIZE_T:
2180 return false;
2182 case GCC_JIT_TYPE_FILE_PTR:
2183 return false;
2185 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2186 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2187 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2188 return false;
2192 /* Implementation of pure virtual hook recording::memento::replay_into
2193 for recording::memento_of_get_type. */
2195 void
2196 recording::memento_of_get_type::replay_into (replayer *r)
2198 set_playback_obj (r->get_type (m_kind));
2201 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2203 /* Descriptive strings for each of enum gcc_jit_types. */
2205 static const char * const get_type_strings[] = {
2206 "void", /* GCC_JIT_TYPE_VOID */
2207 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2209 "bool", /* GCC_JIT_TYPE_BOOL */
2211 "char", /* GCC_JIT_TYPE_CHAR */
2212 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2213 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2215 "short", /* GCC_JIT_TYPE_SHORT */
2216 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2218 "int", /* GCC_JIT_TYPE_INT */
2219 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2221 "long", /* GCC_JIT_TYPE_LONG */
2222 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2224 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2225 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2227 "float", /* GCC_JIT_TYPE_FLOAT */
2228 "double", /* GCC_JIT_TYPE_DOUBLE */
2229 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2231 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2233 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2235 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2237 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2238 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2239 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2243 /* Implementation of recording::memento::make_debug_string for
2244 results of get_type, using a simple table of type names. */
2246 recording::string *
2247 recording::memento_of_get_type::make_debug_string ()
2249 return m_ctxt->new_string (get_type_strings[m_kind]);
2252 static const char * const get_type_enum_strings[] = {
2253 "GCC_JIT_TYPE_VOID",
2254 "GCC_JIT_TYPE_VOID_PTR",
2255 "GCC_JIT_TYPE_BOOL",
2256 "GCC_JIT_TYPE_CHAR",
2257 "GCC_JIT_TYPE_SIGNED_CHAR",
2258 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2259 "GCC_JIT_TYPE_SHORT",
2260 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2261 "GCC_JIT_TYPE_INT",
2262 "GCC_JIT_TYPE_UNSIGNED_INT",
2263 "GCC_JIT_TYPE_LONG",
2264 "GCC_JIT_TYPE_UNSIGNED_LONG",
2265 "GCC_JIT_TYPE_LONG_LONG",
2266 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2267 "GCC_JIT_TYPE_FLOAT",
2268 "GCC_JIT_TYPE_DOUBLE",
2269 "GCC_JIT_TYPE_LONG_DOUBLE",
2270 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2271 "GCC_JIT_TYPE_SIZE_T",
2272 "GCC_JIT_TYPE_FILE_PTR",
2273 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2274 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2275 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2278 void
2279 recording::memento_of_get_type::write_reproducer (reproducer &r)
2281 const char *id = r.make_identifier (this, "type");
2282 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2284 r.get_identifier (get_context ()),
2285 get_type_enum_strings[m_kind]);
2288 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2290 /* Override of default implementation of
2291 recording::type::accepts_writes_from for get_pointer.
2293 Require a pointer type, and allowing writes to
2294 (const T *) from a (T*), but not the other way around. */
2296 bool
2297 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2299 /* Must be a pointer type: */
2300 type *rtype_points_to = rtype->is_pointer ();
2301 if (!rtype_points_to)
2302 return false;
2304 /* It's OK to assign to a (const T *) from a (T *). */
2305 return m_other_type->unqualified ()
2306 ->accepts_writes_from (rtype_points_to);
2309 /* Implementation of pure virtual hook recording::memento::replay_into
2310 for recording::memento_of_get_pointer. */
2312 void
2313 recording::memento_of_get_pointer::replay_into (replayer *)
2315 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2318 /* Implementation of recording::memento::make_debug_string for
2319 results of get_pointer, adding " *" to the underlying type,
2320 with special-casing to handle function pointer types. */
2322 recording::string *
2323 recording::memento_of_get_pointer::make_debug_string ()
2325 /* Special-case function pointer types, to put the "*" in parens between
2326 the return type and the params (for one level of dereferencing, at
2327 least). */
2328 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2329 return fn_type->make_debug_string_with_ptr ();
2331 return string::from_printf (m_ctxt,
2332 "%s *", m_other_type->get_debug_string ());
2335 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2337 void
2338 recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2340 /* We need to special-case function pointer types; see the notes in
2341 recording::function_type::write_deferred_reproducer. */
2342 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2344 fn_type->write_deferred_reproducer (r, this);
2345 return;
2348 const char *id = r.make_identifier (this, "type");
2349 r.write (" gcc_jit_type *%s =\n"
2350 " gcc_jit_type_get_pointer (%s);\n",
2352 r.get_identifier_as_type (m_other_type));
2355 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2357 /* Implementation of pure virtual hook recording::memento::replay_into
2358 for recording::memento_of_get_const. */
2360 void
2361 recording::memento_of_get_const::replay_into (replayer *)
2363 set_playback_obj (m_other_type->playback_type ()->get_const ());
2366 /* Implementation of recording::memento::make_debug_string for
2367 results of get_const, prepending "const ". */
2369 recording::string *
2370 recording::memento_of_get_const::make_debug_string ()
2372 return string::from_printf (m_ctxt,
2373 "const %s", m_other_type->get_debug_string ());
2376 /* Implementation of recording::memento::write_reproducer for const types. */
2378 void
2379 recording::memento_of_get_const::write_reproducer (reproducer &r)
2381 const char *id = r.make_identifier (this, "type");
2382 r.write (" gcc_jit_type *%s =\n"
2383 " gcc_jit_type_get_const (%s);\n",
2385 r.get_identifier_as_type (m_other_type));
2388 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2390 /* Implementation of pure virtual hook recording::memento::replay_into
2391 for recording::memento_of_get_volatile. */
2393 void
2394 recording::memento_of_get_volatile::replay_into (replayer *)
2396 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2399 /* Implementation of recording::memento::make_debug_string for
2400 results of get_volatile, prepending "volatile ". */
2402 recording::string *
2403 recording::memento_of_get_volatile::make_debug_string ()
2405 return string::from_printf (m_ctxt,
2406 "volatile %s", m_other_type->get_debug_string ());
2409 /* Implementation of recording::memento::write_reproducer for volatile
2410 types. */
2412 void
2413 recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2415 const char *id = r.make_identifier (this, "type");
2416 r.write (" gcc_jit_type *%s =\n"
2417 " gcc_jit_type_get_volatile (%s);\n",
2419 r.get_identifier_as_type (m_other_type));
2422 /* The implementation of class gcc::jit::recording::array_type */
2424 /* Implementation of pure virtual hook recording::type::dereference for
2425 recording::array_type. */
2427 recording::type *
2428 recording::array_type::dereference ()
2430 return m_element_type;
2433 /* Implementation of pure virtual hook recording::memento::replay_into
2434 for recording::array_type. */
2436 void
2437 recording::array_type::replay_into (replayer *r)
2439 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
2440 m_element_type->playback_type (),
2441 m_num_elements));
2444 /* Implementation of recording::memento::make_debug_string for
2445 results of new_array_type. */
2447 recording::string *
2448 recording::array_type::make_debug_string ()
2450 return string::from_printf (m_ctxt,
2451 "%s[%d]",
2452 m_element_type->get_debug_string (),
2453 m_num_elements);
2456 /* Implementation of recording::memento::write_reproducer for array
2457 types. */
2459 void
2460 recording::array_type::write_reproducer (reproducer &r)
2462 const char *id = r.make_identifier (this, "array_type");
2463 r.write (" gcc_jit_type *%s =\n"
2464 " gcc_jit_context_new_array_type (%s,\n"
2465 " %s, /* gcc_jit_location *loc */\n"
2466 " %s, /* gcc_jit_type *element_type */\n"
2467 " %i); /* int num_elements */\n",
2469 r.get_identifier (get_context ()),
2470 r.get_identifier (m_loc),
2471 r.get_identifier_as_type (m_element_type),
2472 m_num_elements);
2475 /* The implementation of class gcc::jit::recording::function_type */
2477 /* Constructor for gcc::jit::recording::function_type. */
2479 recording::function_type::function_type (context *ctxt,
2480 type *return_type,
2481 int num_params,
2482 type **param_types,
2483 int is_variadic)
2484 : type (ctxt),
2485 m_return_type (return_type),
2486 m_param_types (),
2487 m_is_variadic (is_variadic)
2489 for (int i = 0; i< num_params; i++)
2490 m_param_types.safe_push (param_types[i]);
2493 /* Implementation of pure virtual hook recording::type::dereference for
2494 recording::function_type. */
2496 recording::type *
2497 recording::function_type::dereference ()
2499 return NULL;
2502 /* Implementation of pure virtual hook recording::memento::replay_into
2503 for recording::function_type. */
2505 void
2506 recording::function_type::replay_into (replayer *r)
2508 /* Convert m_param_types to a vec of playback type. */
2509 auto_vec <playback::type *> param_types;
2510 int i;
2511 recording::type *type;
2512 param_types.create (m_param_types.length ());
2513 FOR_EACH_VEC_ELT (m_param_types, i, type)
2514 param_types.safe_push (type->playback_type ());
2516 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
2517 &param_types,
2518 m_is_variadic));
2521 /* Special-casing for make_debug_string for get_pointer results for
2522 handling (one level) of pointers to functions. */
2524 recording::string *
2525 recording::function_type::make_debug_string_with_ptr ()
2527 return make_debug_string_with ("(*) ");
2530 /* Implementation of recording::memento::make_debug_string for
2531 results of new_function_type. */
2533 recording::string *
2534 recording::function_type::make_debug_string ()
2536 return make_debug_string_with ("");
2539 /* Build a debug string representation of the form:
2541 RESULT_TYPE INSERT (PARAM_TYPES)
2543 for use when handling 0 and 1 level of indirection to this
2544 function type. */
2546 recording::string *
2547 recording::function_type::make_debug_string_with (const char *insert)
2549 /* First, build a buffer for the arguments. */
2550 /* Calculate length of said buffer. */
2551 size_t sz = 1; /* nil terminator */
2552 for (unsigned i = 0; i< m_param_types.length (); i++)
2554 sz += strlen (m_param_types[i]->get_debug_string ());
2555 sz += 2; /* ", " separator */
2557 if (m_is_variadic)
2558 sz += 5; /* ", ..." separator and ellipsis */
2560 /* Now allocate and populate the buffer. */
2561 char *argbuf = new char[sz];
2562 size_t len = 0;
2564 for (unsigned i = 0; i< m_param_types.length (); i++)
2566 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
2567 len += strlen (m_param_types[i]->get_debug_string ());
2568 if (i + 1 < m_param_types.length ())
2570 strcpy (argbuf + len, ", ");
2571 len += 2;
2574 if (m_is_variadic)
2576 if (m_param_types.length ())
2578 strcpy (argbuf + len, ", ");
2579 len += 2;
2581 strcpy (argbuf + len, "...");
2582 len += 3;
2584 argbuf[len] = '\0';
2586 /* ...and use it to get the string for the call as a whole. */
2587 string *result = string::from_printf (m_ctxt,
2588 "%s %s(%s)",
2589 m_return_type->get_debug_string (),
2590 insert,
2591 argbuf);
2593 delete[] argbuf;
2595 return result;
2598 /* Implementation of recording::memento::write_reproducer for function
2599 types. */
2601 void
2602 recording::function_type::write_reproducer (reproducer &)
2604 /* see notes below. */
2607 /* There's a get_pointer within context::new_function_ptr_type:
2608 the type received by client code isn't the memento for the
2609 function_type, but instead the result of get_pointer on it.
2611 Hence we can't directly write a reproducer that gives function_type.
2612 Instead we special-case things within get_pointer, detecting this
2613 case, calling the following function. */
2615 void
2616 recording::function_type::write_deferred_reproducer (reproducer &r,
2617 memento *ptr_type)
2619 gcc_assert (ptr_type);
2620 r.make_identifier (this, "function_type");
2621 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
2622 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
2623 r.write (" gcc_jit_type *%s[%i] = {\n",
2624 param_types_id,
2625 m_param_types.length ());
2626 int i;
2627 type *param_type;
2628 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2629 r.write (" %s,\n", r.get_identifier_as_type (param_type));
2630 r.write (" };\n");
2631 r.write (" gcc_jit_type *%s =\n"
2632 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2633 " %s, /* gcc_jit_location *loc */\n"
2634 " %s, /* gcc_jit_type *return_type */\n"
2635 " %i, /* int num_params */\n"
2636 " %s, /* gcc_jit_type **param_types */\n"
2637 " %i); /* int is_variadic */\n",
2638 ptr_id,
2639 r.get_identifier (get_context ()),
2640 "NULL", /* location is not stored */
2641 r.get_identifier_as_type (m_return_type),
2642 m_param_types.length (),
2643 param_types_id,
2644 m_is_variadic);
2647 /* The implementation of class gcc::jit::recording::field. */
2649 /* Implementation of pure virtual hook recording::memento::replay_into
2650 for recording::field. */
2652 void
2653 recording::field::replay_into (replayer *r)
2655 set_playback_obj (r->new_field (playback_location (r, m_loc),
2656 m_type->playback_type (),
2657 playback_string (m_name)));
2660 /* Override the default implementation of
2661 recording::memento::write_to_dump. Dump each field
2662 by dumping a line of the form:
2663 TYPE NAME;
2664 so that we can build up a struct/union field-byfield. */
2666 void
2667 recording::field::write_to_dump (dump &d)
2669 d.write (" %s %s;\n",
2670 m_type->get_debug_string (),
2671 m_name->c_str ());
2674 /* Implementation of recording::memento::make_debug_string for
2675 results of new_field. */
2677 recording::string *
2678 recording::field::make_debug_string ()
2680 return m_name;
2683 /* Implementation of recording::memento::write_reproducer for fields. */
2685 void
2686 recording::field::write_reproducer (reproducer &r)
2688 const char *id = r.make_identifier (this, "field");
2689 r.write(" gcc_jit_field *%s =\n"
2690 " gcc_jit_context_new_field (%s,\n"
2691 " %s, /* gcc_jit_location *loc */\n"
2692 " %s, /* gcc_jit_type *type, */\n"
2693 " %s); /* const char *name */\n",
2695 r.get_identifier (get_context ()),
2696 r.get_identifier (m_loc),
2697 r.get_identifier_as_type (m_type),
2698 m_name->get_debug_string ());
2701 /* The implementation of class gcc::jit::recording::compound_type */
2703 /* The constructor for gcc::jit::recording::compound_type. */
2705 recording::compound_type::compound_type (context *ctxt,
2706 location *loc,
2707 string *name)
2708 : type (ctxt),
2709 m_loc (loc),
2710 m_name (name),
2711 m_fields (NULL)
2715 /* Set the fields of a compound type.
2717 Implements the post-error-checking part of
2718 gcc_jit_struct_set_fields, and is also used by
2719 gcc_jit_context_new_union_type. */
2721 void
2722 recording::compound_type::set_fields (location *loc,
2723 int num_fields,
2724 field **field_array)
2726 m_loc = loc;
2727 gcc_assert (NULL == m_fields);
2729 m_fields = new fields (this, num_fields, field_array);
2730 m_ctxt->record (m_fields);
2733 /* Implementation of pure virtual hook recording::type::dereference for
2734 recording::compound_type. */
2736 recording::type *
2737 recording::compound_type::dereference ()
2739 return NULL; /* not a pointer */
2742 /* The implementation of class gcc::jit::recording::struct_. */
2744 /* The constructor for gcc::jit::recording::struct_. */
2746 recording::struct_::struct_ (context *ctxt,
2747 location *loc,
2748 string *name)
2749 : compound_type (ctxt, loc, name)
2753 /* Implementation of pure virtual hook recording::memento::replay_into
2754 for recording::struct_. */
2756 void
2757 recording::struct_::replay_into (replayer *r)
2759 set_playback_obj (
2760 r->new_compound_type (playback_location (r, get_loc ()),
2761 get_name ()->c_str (),
2762 true /* is_struct */));
2765 const char *
2766 recording::struct_::access_as_type (reproducer &r)
2768 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2769 r.get_identifier (this));
2772 /* Implementation of recording::memento::make_debug_string for
2773 structs. */
2775 recording::string *
2776 recording::struct_::make_debug_string ()
2778 return string::from_printf (m_ctxt,
2779 "struct %s", get_name ()->c_str ());
2782 void
2783 recording::struct_::write_reproducer (reproducer &r)
2785 const char *id = r.make_identifier (this, "struct");
2786 r.write (" gcc_jit_struct *%s =\n"
2787 " gcc_jit_context_new_opaque_struct (%s,\n"
2788 " %s, /* gcc_jit_location *loc */\n"
2789 " %s); /* const char *name */\n",
2791 r.get_identifier (get_context ()),
2792 r.get_identifier (get_loc ()),
2793 get_name ()->get_debug_string ());
2796 /* The implementation of class gcc::jit::recording::union_. */
2798 /* The constructor for gcc::jit::recording::union_. */
2800 recording::union_::union_ (context *ctxt,
2801 location *loc,
2802 string *name)
2803 : compound_type (ctxt, loc, name)
2807 /* Implementation of pure virtual hook recording::memento::replay_into
2808 for recording::union_. */
2810 void
2811 recording::union_::replay_into (replayer *r)
2813 set_playback_obj (
2814 r->new_compound_type (playback_location (r, get_loc ()),
2815 get_name ()->c_str (),
2816 false /* is_struct */));
2819 /* Implementation of recording::memento::make_debug_string for
2820 unions. */
2822 recording::string *
2823 recording::union_::make_debug_string ()
2825 return string::from_printf (m_ctxt,
2826 "union %s", get_name ()->c_str ());
2829 /* Implementation of recording::memento::write_reproducer for unions. */
2831 void
2832 recording::union_::write_reproducer (reproducer &r)
2834 const char *id = r.make_identifier (this, "union");
2836 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
2837 r.write (" gcc_jit_field *%s[%i] = {\n",
2838 fields_id,
2839 get_fields ()->length ());
2840 for (int i = 0; i < get_fields ()->length (); i++)
2841 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
2842 r.write (" };\n");
2844 r.write (" gcc_jit_type *%s =\n"
2845 " gcc_jit_context_new_union_type (%s,\n"
2846 " %s, /* gcc_jit_location *loc */\n"
2847 " %s, /* const char *name */\n"
2848 " %i, /* int num_fields */\n"
2849 " %s); /* gcc_jit_field **fields */\n",
2851 r.get_identifier (get_context ()),
2852 r.get_identifier (get_loc ()),
2853 get_name ()->get_debug_string (),
2854 get_fields ()->length (),
2855 fields_id);
2858 /* The implementation of class gcc::jit::recording::fields. */
2860 /* The constructor for gcc::jit::recording::fields. */
2862 recording::fields::fields (compound_type *struct_or_union,
2863 int num_fields,
2864 field **fields)
2865 : memento (struct_or_union->m_ctxt),
2866 m_struct_or_union (struct_or_union),
2867 m_fields ()
2869 for (int i = 0; i < num_fields; i++)
2871 gcc_assert (fields[i]->get_container () == NULL);
2872 fields[i]->set_container (m_struct_or_union);
2873 m_fields.safe_push (fields[i]);
2877 /* Implementation of pure virtual hook recording::memento::replay_into
2878 for recording::fields. */
2880 void
2881 recording::fields::replay_into (replayer *)
2883 auto_vec<playback::field *> playback_fields;
2884 playback_fields.create (m_fields.length ());
2885 for (unsigned i = 0; i < m_fields.length (); i++)
2886 playback_fields.safe_push (m_fields[i]->playback_field ());
2887 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
2890 /* Override the default implementation of
2891 recording::memento::write_to_dump by writing a union/struct
2892 declaration of this form:
2894 struct/union NAME {
2895 TYPE_1 NAME_1;
2896 TYPE_2 NAME_2;
2897 ....
2898 TYPE_N NAME_N;
2901 to the dump. */
2903 void
2904 recording::fields::write_to_dump (dump &d)
2906 int i;
2907 field *f;
2909 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
2910 FOR_EACH_VEC_ELT (m_fields, i, f)
2911 f->write_to_dump (d);
2912 d.write ("};\n");
2915 /* Implementation of recording::memento::write_reproducer for the fields
2916 subclass. */
2918 void
2919 recording::fields::write_reproducer (reproducer &r)
2921 if (m_struct_or_union)
2922 if (NULL == m_struct_or_union->dyn_cast_struct ())
2923 /* We have a union; the fields have already been written by
2924 union::write_reproducer. */
2925 return;
2927 const char *fields_id = r.make_identifier (this, "fields");
2928 r.write (" gcc_jit_field *%s[%i] = {\n",
2929 fields_id,
2930 m_fields.length ());
2931 int i;
2932 field *field;
2933 FOR_EACH_VEC_ELT (m_fields, i, field)
2934 r.write (" %s,\n", r.get_identifier (field));
2935 r.write (" };\n");
2937 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
2938 " %s, /* gcc_jit_location *loc */\n"
2939 " %i, /* int num_fields */\n"
2940 " %s); /* gcc_jit_field **fields */\n",
2941 r.get_identifier (m_struct_or_union),
2942 r.get_identifier ((memento *)NULL),
2943 m_fields.length (),
2944 fields_id);
2947 /* Implementation of recording::memento::make_debug_string for
2948 field tables. */
2950 recording::string *
2951 recording::fields::make_debug_string ()
2953 return string::from_printf (m_ctxt,
2954 "fields");
2957 /* The implementation of class gcc::jit::recording::rvalue. */
2959 /* Create a recording::access_field_rvalue instance and add it to
2960 the rvalue's context's list of mementos.
2962 Implements the post-error-checking part of
2963 gcc_jit_rvalue_access_field. */
2965 recording::rvalue *
2966 recording::rvalue::access_field (recording::location *loc,
2967 field *field)
2969 recording::rvalue *result =
2970 new access_field_rvalue (m_ctxt, loc, this, field);
2971 m_ctxt->record (result);
2972 return result;
2975 /* Create a recording::dereference_field_rvalue instance and add it to
2976 the rvalue's context's list of mementos.
2978 Implements the post-error-checking part of
2979 gcc_jit_rvalue_dereference_field. */
2981 recording::lvalue *
2982 recording::rvalue::dereference_field (recording::location *loc,
2983 field *field)
2985 recording::lvalue *result =
2986 new dereference_field_rvalue (m_ctxt, loc, this, field);
2987 m_ctxt->record (result);
2988 return result;
2991 /* Create a recording::dereference_rvalue instance and add it to the
2992 rvalue's context's list of mementos.
2994 Implements the post-error-checking part of
2995 gcc_jit_rvalue_dereference. */
2997 recording::lvalue *
2998 recording::rvalue::dereference (recording::location *loc)
3000 recording::lvalue *result =
3001 new dereference_rvalue (m_ctxt, loc, this);
3002 m_ctxt->record (result);
3003 return result;
3006 /* An rvalue visitor, for validating that every rvalue within an expression
3007 trees within "STMT" has the correct scope (e.g. no access to locals
3008 of a different function). */
3010 class rvalue_usage_validator : public recording::rvalue_visitor
3012 public:
3013 rvalue_usage_validator (const char *api_funcname,
3014 recording::context *ctxt,
3015 recording::statement *stmt);
3017 void
3018 visit (recording::rvalue *rvalue) FINAL OVERRIDE;
3020 private:
3021 const char *m_api_funcname;
3022 recording::context *m_ctxt;
3023 recording::statement *m_stmt;
3026 /* The trivial constructor for rvalue_usage_validator. */
3028 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
3029 recording::context *ctxt,
3030 recording::statement *stmt)
3031 : m_api_funcname (api_funcname),
3032 m_ctxt (ctxt),
3033 m_stmt (stmt)
3037 /* Verify that the given rvalue is in the correct scope. */
3039 void
3040 rvalue_usage_validator::visit (recording::rvalue *rvalue)
3042 gcc_assert (m_stmt->get_block ());
3043 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
3045 /* Most rvalues don't have a scope (only locals and params). */
3046 if (rvalue->get_scope ())
3048 if (rvalue->get_scope () != stmt_scope)
3049 m_ctxt->add_error
3050 (rvalue->get_loc (),
3051 "%s:"
3052 " rvalue %s (type: %s)"
3053 " has scope limited to function %s"
3054 " but was used within function %s"
3055 " (in statement: %s)",
3056 m_api_funcname,
3057 rvalue->get_debug_string (),
3058 rvalue->get_type ()->get_debug_string (),
3059 rvalue->get_scope ()->get_debug_string (),
3060 stmt_scope->get_debug_string (),
3061 m_stmt->get_debug_string ());
3063 else
3065 if (rvalue->dyn_cast_param ())
3066 m_ctxt->add_error
3067 (rvalue->get_loc (),
3068 "%s:"
3069 " param %s (type: %s)"
3070 " was used within function %s"
3071 " (in statement: %s)"
3072 " but is not associated with any function",
3073 m_api_funcname,
3074 rvalue->get_debug_string (),
3075 rvalue->get_type ()->get_debug_string (),
3076 stmt_scope->get_debug_string (),
3077 m_stmt->get_debug_string ());
3081 /* Verify that it's valid to use this rvalue (and all expressions
3082 in the tree below it) within the given statement.
3084 For example, we must reject attempts to use a local from one
3085 function within a different function here, or we'll get
3086 an ICE deep inside toplev::main. */
3088 void
3089 recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
3091 rvalue_usage_validator v (api_funcname,
3092 s->get_context (),
3095 /* Verify that it's OK to use this rvalue within s. */
3096 v.visit (this);
3098 /* Traverse the expression tree below "this", verifying all rvalues
3099 within it. */
3100 visit_children (&v);
3103 /* Set the scope of this rvalue to be the given function. This can only
3104 be done once on a given rvalue. */
3106 void
3107 recording::rvalue::set_scope (function *scope)
3109 gcc_assert (scope);
3110 gcc_assert (NULL == m_scope);
3111 m_scope = scope;
3115 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3116 themselves.
3117 Instances of rvalue don't need an upcast call. */
3119 const char *
3120 recording::rvalue::access_as_rvalue (reproducer &r)
3122 return r.get_identifier (this);
3125 /* Return a debug string for the given rvalue, wrapping it in parentheses
3126 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3127 stronger precedence that this rvalue's precedence.
3129 For example, given:
3131 MULT
3133 PLUS MINUS
3134 / \ / \
3135 A B C D
3137 we want to emit:
3139 (A + B) * (C - D)
3141 since MULT has strong precedence than PLUS and MINUS, whereas for:
3143 PLUS
3145 MULT DIVIDE
3146 / \ / \
3147 A B C D
3149 we can simply emit:
3151 A * B + C / D
3153 since PLUS has weaker precedence than MULT and DIVIDE. */
3155 const char *
3156 recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
3158 enum precedence this_prec = get_precedence ();
3160 /* If this_prec has stronger precedence than outer_prec, we don't
3161 need to wrap this in parens within the outer debug string.
3162 Stronger precedences occur earlier than weaker within the enum,
3163 so this is a less than test. Equal precedences don't need
3164 parentheses. */
3165 if (this_prec <= outer_prec)
3166 return get_debug_string();
3168 /* Otherwise, we need parentheses. */
3170 /* Lazily-build and cache m_parenthesized_string. */
3171 if (!m_parenthesized_string)
3173 const char *debug_string = get_debug_string ();
3174 m_parenthesized_string = string::from_printf (get_context (),
3175 "(%s)",
3176 debug_string);
3178 gcc_assert (m_parenthesized_string);
3179 return m_parenthesized_string->c_str ();
3183 /* The implementation of class gcc::jit::recording::lvalue. */
3185 /* Create a recording::new_access_field_of_lvalue instance and add it to
3186 the lvalue's context's list of mementos.
3188 Implements the post-error-checking part of
3189 gcc_jit_lvalue_access_field. */
3191 recording::lvalue *
3192 recording::lvalue::access_field (recording::location *loc,
3193 field *field)
3195 recording::lvalue *result =
3196 new access_field_of_lvalue (m_ctxt, loc, this, field);
3197 m_ctxt->record (result);
3198 return result;
3201 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3202 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3203 upcast call. */
3205 const char *
3206 recording::lvalue::access_as_rvalue (reproducer &r)
3208 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3209 r.get_identifier (this));
3212 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3213 Instances of lvalue don't need to be upcast. */
3215 const char *
3216 recording::lvalue::access_as_lvalue (reproducer &r)
3218 return r.get_identifier (this);
3221 /* Create a recording::get_address_of_lvalue instance and add it to
3222 the lvalue's context's list of mementos.
3224 Implements the post-error-checking part of
3225 gcc_jit_lvalue_get_address. */
3227 recording::rvalue *
3228 recording::lvalue::get_address (recording::location *loc)
3230 recording::rvalue *result =
3231 new get_address_of_lvalue (m_ctxt, loc, this);
3232 m_ctxt->record (result);
3233 return result;
3236 /* The implementation of class gcc::jit::recording::param. */
3238 /* Implementation of pure virtual hook recording::memento::replay_into
3239 for recording::param. */
3241 void
3242 recording::param::replay_into (replayer *r)
3244 set_playback_obj (r->new_param (playback_location (r, m_loc),
3245 m_type->playback_type (),
3246 m_name->c_str ()));
3249 /* Implementation of recording::rvalue::access_as_rvalue for params.
3250 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3251 upcast call. */
3253 const char *
3254 recording::param::access_as_rvalue (reproducer &r)
3256 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3257 r.get_identifier (this));
3260 /* Implementation of recording::lvalue::access_as_lvalue for params.
3261 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3262 upcast call. */
3264 const char *
3265 recording::param::access_as_lvalue (reproducer &r)
3267 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3268 r.get_identifier (this));
3271 /* Implementation of recording::memento::write_reproducer for params. */
3273 void
3274 recording::param::write_reproducer (reproducer &r)
3276 const char *id = r.make_identifier (this, "param");
3277 r.write (" gcc_jit_param *%s =\n"
3278 " gcc_jit_context_new_param (%s,\n"
3279 " %s, /* gcc_jit_location *loc */\n"
3280 " %s, /*gcc_jit_type *type */\n"
3281 " %s); /* const char *name */\n",
3283 r.get_identifier (get_context ()),
3284 r.get_identifier (m_loc),
3285 r.get_identifier_as_type (m_type),
3286 m_name->get_debug_string ());
3289 /* The implementation of class gcc::jit::recording::function. */
3291 /* gcc::jit::recording::function's constructor. */
3293 recording::function::function (context *ctxt,
3294 recording::location *loc,
3295 enum gcc_jit_function_kind kind,
3296 type *return_type,
3297 recording::string *name,
3298 int num_params,
3299 recording::param **params,
3300 int is_variadic,
3301 enum built_in_function builtin_id)
3302 : memento (ctxt),
3303 m_loc (loc),
3304 m_kind (kind),
3305 m_return_type (return_type),
3306 m_name (name),
3307 m_params (),
3308 m_is_variadic (is_variadic),
3309 m_builtin_id (builtin_id),
3310 m_locals (),
3311 m_blocks ()
3313 for (int i = 0; i< num_params; i++)
3315 param *param = params[i];
3316 gcc_assert (param);
3318 /* Associate each param with this function.
3320 Verify that the param doesn't already have a function. */
3321 if (param->get_scope ())
3323 /* We've already rejected attempts to reuse a param between
3324 different functions (within gcc_jit_context_new_function), so
3325 if the param *does* already have a function, it must be being
3326 reused within the params array for this function. We must
3327 produce an error for this reuse (blocking the compile), since
3328 otherwise we'd have an ICE later on. */
3329 gcc_assert (this == param->get_scope ());
3330 ctxt->add_error
3331 (loc,
3332 "gcc_jit_context_new_function:"
3333 " parameter %s (type: %s)"
3334 " is used more than once when creating function %s",
3335 param->get_debug_string (),
3336 param->get_type ()->get_debug_string (),
3337 name->c_str ());
3339 else
3341 /* The normal, non-error case: associate this function with the
3342 param. */
3343 param->set_scope (this);
3346 m_params.safe_push (param);
3350 /* Implementation of pure virtual hook recording::memento::replay_into
3351 for recording::function. */
3353 void
3354 recording::function::replay_into (replayer *r)
3356 /* Convert m_params to a vec of playback param. */
3357 auto_vec <playback::param *> params;
3358 int i;
3359 recording::param *param;
3360 params.create (m_params.length ());
3361 FOR_EACH_VEC_ELT (m_params, i, param)
3362 params.safe_push (param->playback_param ());
3364 set_playback_obj (r->new_function (playback_location (r, m_loc),
3365 m_kind,
3366 m_return_type->playback_type (),
3367 m_name->c_str (),
3368 &params,
3369 m_is_variadic,
3370 m_builtin_id));
3373 /* Create a recording::local instance and add it to
3374 the functions's context's list of mementos, and to the function's
3375 list of locals.
3377 Implements the post-error-checking part of
3378 gcc_jit_function_new_local. */
3380 recording::lvalue *
3381 recording::function::new_local (recording::location *loc,
3382 type *type,
3383 const char *name)
3385 local *result = new local (this, loc, type, new_string (name));
3386 m_ctxt->record (result);
3387 m_locals.safe_push (result);
3388 return result;
3391 /* Create a recording::block instance and add it to
3392 the functions's context's list of mementos, and to the function's
3393 list of blocks.
3395 Implements the post-error-checking part of
3396 gcc_jit_function_new_block. */
3398 recording::block*
3399 recording::function::new_block (const char *name)
3401 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
3403 recording::block *result =
3404 new recording::block (this, m_blocks.length (), new_string (name));
3405 m_ctxt->record (result);
3406 m_blocks.safe_push (result);
3407 return result;
3410 /* Override the default implementation of
3411 recording::memento::write_to_dump by dumping a C-like
3412 representation of the function; either like a prototype
3413 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3414 all other kinds of function. */
3416 void
3417 recording::function::write_to_dump (dump &d)
3419 switch (m_kind)
3421 default: gcc_unreachable ();
3422 case GCC_JIT_FUNCTION_EXPORTED:
3423 case GCC_JIT_FUNCTION_IMPORTED:
3424 d.write ("extern ");
3425 break;
3426 case GCC_JIT_FUNCTION_INTERNAL:
3427 d.write ("static ");
3428 break;
3429 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
3430 d.write ("static inline ");
3431 break;
3433 d.write ("%s\n", m_return_type->get_debug_string ());
3435 if (d.update_locations ())
3436 m_loc = d.make_location ();
3438 d.write ("%s (", get_debug_string ());
3440 int i;
3441 recording::param *param;
3442 FOR_EACH_VEC_ELT (m_params, i, param)
3444 if (i > 0)
3445 d.write (", ");
3446 d.write ("%s %s",
3447 param->get_type ()->get_debug_string (),
3448 param->get_debug_string ());
3450 d.write (")");
3451 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
3453 d.write ("; /* (imported) */\n\n");
3455 else
3457 int i;
3458 local *var = NULL;
3459 block *b;
3460 d.write ("\n{\n");
3462 /* Write locals: */
3463 FOR_EACH_VEC_ELT (m_locals, i, var)
3464 var->write_to_dump (d);
3465 if (m_locals.length ())
3466 d.write ("\n");
3468 /* Write each block: */
3469 FOR_EACH_VEC_ELT (m_blocks, i, b)
3471 if (i > 0)
3472 d.write ("\n");
3473 b->write_to_dump (d);
3476 d.write ("}\n\n");
3480 /* Pre-compilation validation of a function, for those things we can't
3481 check until the context is (supposedly) fully-populated. */
3483 void
3484 recording::function::validate ()
3486 /* Complain about empty functions with non-void return type. */
3487 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
3488 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
3489 if (0 == m_blocks.length ())
3490 m_ctxt->add_error (m_loc,
3491 "function %s returns non-void (type: %s)"
3492 " but has no blocks",
3493 get_debug_string (),
3494 m_return_type->get_debug_string ());
3496 /* Check that all blocks are terminated. */
3497 int num_invalid_blocks = 0;
3499 int i;
3500 block *b;
3502 FOR_EACH_VEC_ELT (m_blocks, i, b)
3503 if (!b->validate ())
3504 num_invalid_blocks++;
3507 /* Check that all blocks are reachable. */
3508 if (!m_ctxt->get_inner_bool_option
3509 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
3510 && m_blocks.length () > 0 && 0 == num_invalid_blocks)
3512 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3513 flag, starting at the initial block. */
3514 auto_vec<block *> worklist (m_blocks.length ());
3515 worklist.safe_push (m_blocks[0]);
3516 while (worklist.length () > 0)
3518 block *b = worklist.pop ();
3519 b->m_is_reachable = true;
3521 /* Add successor blocks that aren't yet marked to the worklist. */
3522 /* We checked that each block has a terminating statement above . */
3523 vec <block *> successors = b->get_successor_blocks ();
3524 int i;
3525 block *succ;
3526 FOR_EACH_VEC_ELT (successors, i, succ)
3527 if (!succ->m_is_reachable)
3528 worklist.safe_push (succ);
3529 successors.release ();
3532 /* Now complain about any blocks that haven't been marked. */
3534 int i;
3535 block *b;
3536 FOR_EACH_VEC_ELT (m_blocks, i, b)
3537 if (!b->m_is_reachable)
3538 m_ctxt->add_error (b->get_loc (),
3539 "unreachable block: %s",
3540 b->get_debug_string ());
3545 /* Implements the post-error-checking part of
3546 gcc_jit_function_dump_to_dot. */
3548 void
3549 recording::function::dump_to_dot (const char *path)
3551 FILE *fp = fopen (path, "w");
3552 if (!fp)
3553 return;
3555 pretty_printer the_pp;
3556 the_pp.buffer->stream = fp;
3558 pretty_printer *pp = &the_pp;
3560 pp_printf (pp,
3561 "digraph %s {\n", get_debug_string ());
3563 /* Blocks: */
3565 int i;
3566 block *b;
3567 FOR_EACH_VEC_ELT (m_blocks, i, b)
3568 b->dump_to_dot (pp);
3571 /* Edges: */
3573 int i;
3574 block *b;
3575 FOR_EACH_VEC_ELT (m_blocks, i, b)
3576 b->dump_edges_to_dot (pp);
3579 pp_printf (pp, "}\n");
3580 pp_flush (pp);
3581 fclose (fp);
3584 /* Implementation of recording::memento::make_debug_string for
3585 functions. */
3587 recording::string *
3588 recording::function::make_debug_string ()
3590 return m_name;
3593 /* A table of enum gcc_jit_function_kind values expressed in string
3594 form. */
3596 static const char * const names_of_function_kinds[] = {
3597 "GCC_JIT_FUNCTION_EXPORTED",
3598 "GCC_JIT_FUNCTION_INTERNAL",
3599 "GCC_JIT_FUNCTION_IMPORTED",
3600 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3603 /* Implementation of recording::memento::write_reproducer for functions. */
3605 void
3606 recording::function::write_reproducer (reproducer &r)
3608 const char *id = r.make_identifier (this, "func");
3610 if (m_builtin_id)
3612 r.write (" gcc_jit_function *%s =\n"
3613 " gcc_jit_context_get_builtin_function (%s,\n"
3614 " %s);\n",
3616 r.get_identifier (get_context ()),
3617 m_name->get_debug_string ());
3618 return;
3620 const char *params_id = r.make_tmp_identifier ("params_for", this);
3621 r.write (" gcc_jit_param *%s[%i] = {\n",
3622 params_id,
3623 m_params.length ());
3624 int i;
3625 param *param;
3626 FOR_EACH_VEC_ELT (m_params, i, param)
3627 r.write (" %s,\n", r.get_identifier (param));
3628 r.write (" };\n");
3629 r.write (" gcc_jit_function *%s =\n"
3630 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3631 " %s, /* gcc_jit_location *loc */\n"
3632 " %s, /* enum gcc_jit_function_kind kind */\n"
3633 " %s, /* gcc_jit_type *return_type */\n"
3634 " %s, /* const char *name */\n"
3635 " %i, /* int num_params */\n"
3636 " %s, /* gcc_jit_param **params */\n"
3637 " %i); /* int is_variadic */\n",
3639 r.get_identifier (get_context ()),
3640 r.get_identifier (m_loc),
3641 names_of_function_kinds[m_kind],
3642 r.get_identifier_as_type (m_return_type),
3643 m_name->get_debug_string (),
3644 m_params.length (),
3645 params_id,
3646 m_is_variadic);
3650 /* The implementation of class gcc::jit::recording::block. */
3652 /* Create a recording::eval instance and add it to
3653 the block's context's list of mementos, and to the block's
3654 list of statements.
3656 Implements the heart of gcc_jit_block_add_eval. */
3658 recording::statement *
3659 recording::block::add_eval (recording::location *loc,
3660 recording::rvalue *rvalue)
3662 statement *result = new eval (this, loc, rvalue);
3663 m_ctxt->record (result);
3664 m_statements.safe_push (result);
3665 return result;
3668 /* Create a recording::assignment instance and add it to
3669 the block's context's list of mementos, and to the block's
3670 list of statements.
3672 Implements the heart of gcc_jit_block_add_assignment. */
3674 recording::statement *
3675 recording::block::add_assignment (recording::location *loc,
3676 recording::lvalue *lvalue,
3677 recording::rvalue *rvalue)
3679 statement *result = new assignment (this, loc, lvalue, rvalue);
3680 m_ctxt->record (result);
3681 m_statements.safe_push (result);
3682 return result;
3685 /* Create a recording::assignment_op instance and add it to
3686 the block's context's list of mementos, and to the block's
3687 list of statements.
3689 Implements the heart of gcc_jit_block_add_assignment_op. */
3691 recording::statement *
3692 recording::block::add_assignment_op (recording::location *loc,
3693 recording::lvalue *lvalue,
3694 enum gcc_jit_binary_op op,
3695 recording::rvalue *rvalue)
3697 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
3698 m_ctxt->record (result);
3699 m_statements.safe_push (result);
3700 return result;
3703 /* Create a recording::comment instance and add it to
3704 the block's context's list of mementos, and to the block's
3705 list of statements.
3707 Implements the heart of gcc_jit_block_add_comment. */
3709 recording::statement *
3710 recording::block::add_comment (recording::location *loc,
3711 const char *text)
3713 statement *result = new comment (this, loc, new_string (text));
3714 m_ctxt->record (result);
3715 m_statements.safe_push (result);
3716 return result;
3719 /* Create a recording::end_with_conditional instance and add it to
3720 the block's context's list of mementos, and to the block's
3721 list of statements.
3723 Implements the heart of gcc_jit_block_end_with_conditional. */
3725 recording::statement *
3726 recording::block::end_with_conditional (recording::location *loc,
3727 recording::rvalue *boolval,
3728 recording::block *on_true,
3729 recording::block *on_false)
3731 statement *result = new conditional (this, loc, boolval, on_true, on_false);
3732 m_ctxt->record (result);
3733 m_statements.safe_push (result);
3734 m_has_been_terminated = true;
3735 return result;
3738 /* Create a recording::end_with_jump instance and add it to
3739 the block's context's list of mementos, and to the block's
3740 list of statements.
3742 Implements the heart of gcc_jit_block_end_with_jump. */
3744 recording::statement *
3745 recording::block::end_with_jump (recording::location *loc,
3746 recording::block *target)
3748 statement *result = new jump (this, loc, target);
3749 m_ctxt->record (result);
3750 m_statements.safe_push (result);
3751 m_has_been_terminated = true;
3752 return result;
3755 /* Create a recording::end_with_return 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 post-error-checking parts of
3760 gcc_jit_block_end_with_return and
3761 gcc_jit_block_end_with_void_return. */
3763 recording::statement *
3764 recording::block::end_with_return (recording::location *loc,
3765 recording::rvalue *rvalue)
3767 /* This is used by both gcc_jit_function_add_return and
3768 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3769 the former and NULL for the latter. */
3770 statement *result = new return_ (this, loc, rvalue);
3771 m_ctxt->record (result);
3772 m_statements.safe_push (result);
3773 m_has_been_terminated = true;
3774 return result;
3777 /* Create a recording::switch_ instance and add it to
3778 the block's context's list of mementos, and to the block's
3779 list of statements.
3781 Implements the heart of gcc_jit_block_end_with_switch. */
3783 recording::statement *
3784 recording::block::end_with_switch (recording::location *loc,
3785 recording::rvalue *expr,
3786 recording::block *default_block,
3787 int num_cases,
3788 recording::case_ **cases)
3790 statement *result = new switch_ (this, loc,
3791 expr,
3792 default_block,
3793 num_cases,
3794 cases);
3795 m_ctxt->record (result);
3796 m_statements.safe_push (result);
3797 m_has_been_terminated = true;
3798 return result;
3801 /* Override the default implementation of
3802 recording::memento::write_to_dump for blocks by writing
3803 an unindented block name as a label, followed by the indented
3804 statements:
3806 BLOCK_NAME:
3807 STATEMENT_1;
3808 STATEMENT_2;
3810 STATEMENT_N; */
3812 void
3813 recording::block::write_to_dump (dump &d)
3815 d.write ("%s:\n", get_debug_string ());
3817 int i;
3818 statement *s;
3819 FOR_EACH_VEC_ELT (m_statements, i, s)
3820 s->write_to_dump (d);
3823 /* Validate a block by ensuring that it has been terminated. */
3825 bool
3826 recording::block::validate ()
3828 /* Check for termination. */
3829 if (!has_been_terminated ())
3831 statement *stmt = get_last_statement ();
3832 location *loc = stmt ? stmt->get_loc () : NULL;
3833 m_func->get_context ()->add_error (loc,
3834 "unterminated block in %s: %s",
3835 m_func->get_debug_string (),
3836 get_debug_string ());
3837 return false;
3840 return true;
3843 /* Get the source-location of a block by using that of the first
3844 statement within it, if any. */
3846 recording::location *
3847 recording::block::get_loc () const
3849 recording::statement *stmt = get_first_statement ();
3850 if (stmt)
3851 return stmt->get_loc ();
3852 else
3853 return NULL;
3856 /* Get the first statement within a block, if any. */
3858 recording::statement *
3859 recording::block::get_first_statement () const
3861 if (m_statements.length ())
3862 return m_statements[0];
3863 else
3864 return NULL;
3867 /* Get the last statement within a block, if any. */
3869 recording::statement *
3870 recording::block::get_last_statement () const
3872 if (m_statements.length ())
3873 return m_statements[m_statements.length () - 1];
3874 else
3875 return NULL;
3878 /* Assuming that this block has been terminated, get the successor blocks
3879 as a vector. Ownership of the vector transfers to the caller, which
3880 must call its release () method.
3882 Used when validating functions, and when dumping dot representations
3883 of them. */
3885 vec <recording::block *>
3886 recording::block::get_successor_blocks () const
3888 gcc_assert (m_has_been_terminated);
3889 statement *last_statement = get_last_statement ();
3890 gcc_assert (last_statement);
3891 return last_statement->get_successor_blocks ();
3894 /* Implementation of pure virtual hook recording::memento::replay_into
3895 for recording::block. */
3897 void
3898 recording::block::replay_into (replayer *)
3900 set_playback_obj (m_func->playback_function ()
3901 ->new_block (playback_string (m_name)));
3904 /* Implementation of recording::memento::make_debug_string for
3905 blocks. */
3907 recording::string *
3908 recording::block::make_debug_string ()
3910 if (m_name)
3911 return m_name;
3912 else
3913 return string::from_printf (m_ctxt,
3914 "<UNNAMED BLOCK %p>",
3915 (void *)this);
3918 /* Implementation of recording::memento::write_reproducer for blocks. */
3920 void
3921 recording::block::write_reproducer (reproducer &r)
3923 const char *id = r.make_identifier (this, "block");
3924 r.write (" gcc_jit_block *%s =\n"
3925 " gcc_jit_function_new_block (%s, %s);\n",
3927 r.get_identifier (m_func),
3928 m_name ? m_name->get_debug_string () : "NULL");
3931 /* Dump a block in graphviz form into PP, capturing the block name (if
3932 any) and the statements. */
3934 void
3935 recording::block::dump_to_dot (pretty_printer *pp)
3937 pp_printf (pp,
3938 ("\tblock_%d "
3939 "[shape=record,style=filled,fillcolor=white,label=\"{"),
3940 m_index);
3941 pp_write_text_to_stream (pp);
3942 if (m_name)
3944 pp_string (pp, m_name->c_str ());
3945 pp_string (pp, ":");
3946 pp_newline (pp);
3947 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3950 int i;
3951 statement *s;
3952 FOR_EACH_VEC_ELT (m_statements, i, s)
3954 pp_string (pp, s->get_debug_string ());
3955 pp_newline (pp);
3956 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3959 pp_printf (pp,
3960 "}\"];\n\n");
3961 pp_flush (pp);
3964 /* Dump the out-edges of the block in graphviz form into PP. */
3966 void
3967 recording::block::dump_edges_to_dot (pretty_printer *pp)
3969 vec <block *> successors = get_successor_blocks ();
3970 int i;
3971 block *succ;
3972 FOR_EACH_VEC_ELT (successors, i, succ)
3973 pp_printf (pp,
3974 "\tblock_%d:s -> block_%d:n;\n",
3975 m_index, succ->m_index);
3976 successors.release ();
3979 /* The implementation of class gcc::jit::recording::global. */
3981 /* Implementation of pure virtual hook recording::memento::replay_into
3982 for recording::global. */
3984 void
3985 recording::global::replay_into (replayer *r)
3987 set_playback_obj (r->new_global (playback_location (r, m_loc),
3988 m_kind,
3989 m_type->playback_type (),
3990 playback_string (m_name)));
3993 /* Override the default implementation of
3994 recording::memento::write_to_dump for globals.
3995 This will be of the form:
3997 GCC_JIT_GLOBAL_EXPORTED:
3998 "TYPE NAME;"
3999 e.g. "int foo;"
4001 GCC_JIT_GLOBAL_INTERNAL:
4002 "static TYPE NAME;"
4003 e.g. "static int foo;"
4005 GCC_JIT_GLOBAL_IMPORTED:
4006 "extern TYPE NAME;"
4007 e.g. "extern int foo;"
4009 These are written to the top of the dump by
4010 recording::context::dump_to_file. */
4012 void
4013 recording::global::write_to_dump (dump &d)
4015 if (d.update_locations ())
4016 m_loc = d.make_location ();
4018 switch (m_kind)
4020 default:
4021 gcc_unreachable ();
4023 case GCC_JIT_GLOBAL_EXPORTED:
4024 break;
4026 case GCC_JIT_GLOBAL_INTERNAL:
4027 d.write ("static ");
4028 break;
4030 case GCC_JIT_GLOBAL_IMPORTED:
4031 d.write ("extern ");
4032 break;
4034 d.write ("%s %s;\n",
4035 m_type->get_debug_string (),
4036 get_debug_string ());
4039 /* A table of enum gcc_jit_global_kind values expressed in string
4040 form. */
4042 static const char * const global_kind_reproducer_strings[] = {
4043 "GCC_JIT_GLOBAL_EXPORTED",
4044 "GCC_JIT_GLOBAL_INTERNAL",
4045 "GCC_JIT_GLOBAL_IMPORTED"
4048 /* Implementation of recording::memento::write_reproducer for globals. */
4050 void
4051 recording::global::write_reproducer (reproducer &r)
4053 const char *id = r.make_identifier (this, "block");
4054 r.write (" gcc_jit_lvalue *%s =\n"
4055 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4056 " %s, /* gcc_jit_location *loc */\n"
4057 " %s, /* enum gcc_jit_global_kind kind */\n"
4058 " %s, /* gcc_jit_type *type */\n"
4059 " %s); /* const char *name */\n",
4061 r.get_identifier (get_context ()),
4062 r.get_identifier (m_loc),
4063 global_kind_reproducer_strings[m_kind],
4064 r.get_identifier_as_type (get_type ()),
4065 m_name->get_debug_string ());
4068 /* The implementation of the various const-handling classes:
4069 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4071 /* Explicit specialization of the various mementos we're interested in. */
4072 template class recording::memento_of_new_rvalue_from_const <int>;
4073 template class recording::memento_of_new_rvalue_from_const <long>;
4074 template class recording::memento_of_new_rvalue_from_const <double>;
4075 template class recording::memento_of_new_rvalue_from_const <void *>;
4077 /* Implementation of the pure virtual hook recording::memento::replay_into
4078 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4080 template <typename HOST_TYPE>
4081 void
4082 recording::
4083 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
4085 set_playback_obj
4086 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
4087 m_value));
4090 /* The make_debug_string and write_reproducer methods vary between the
4091 various
4092 memento_of_new_rvalue_from_const <HOST_TYPE>
4093 classes, so we explicitly write specializations of them.
4095 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4096 namespaces are written out explicitly, which is why most of this file
4097 doesn't abbreviate things by entering the "recording" namespace.
4099 However, these specializations are required to be in the same namespace
4100 as the template, hence we now have to enter the gcc::jit::recording
4101 namespace. */
4103 namespace recording
4106 /* The make_debug_string specialization for <int>, which renders it as
4107 (TARGET_TYPE)LITERAL
4108 e.g.
4109 "(int)42". */
4111 template <>
4112 string *
4113 memento_of_new_rvalue_from_const <int>::make_debug_string ()
4115 return string::from_printf (m_ctxt,
4116 "(%s)%i",
4117 m_type->get_debug_string (),
4118 m_value);
4121 /* The get_wide_int specialization for <int>. */
4123 template <>
4124 bool
4125 memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const
4127 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4128 return true;
4131 /* The write_reproducer specialization for <int>. */
4133 template <>
4134 void
4135 memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
4137 const char *id = r.make_identifier (this, "rvalue");
4138 r.write (" gcc_jit_rvalue *%s =\n"
4139 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4140 " %s, /* gcc_jit_type *numeric_type */\n"
4141 " %i); /* int value */\n",
4143 r.get_identifier (get_context ()),
4144 r.get_identifier_as_type (m_type),
4145 m_value);
4148 /* The make_debug_string specialization for <long>, rendering it as
4149 (TARGET_TYPE)LITERAL
4150 e.g.
4151 "(long)42". */
4153 template <>
4154 string *
4155 memento_of_new_rvalue_from_const <long>::make_debug_string ()
4157 return string::from_printf (m_ctxt,
4158 "(%s)%li",
4159 m_type->get_debug_string (),
4160 m_value);
4163 /* The get_wide_int specialization for <long>. */
4165 template <>
4166 bool
4167 memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const
4169 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4170 return true;
4173 /* The write_reproducer specialization for <long>. */
4175 template <>
4176 void
4177 recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
4179 const char *id = r.make_identifier (this, "rvalue");
4181 /* We have to special-case LONG_MIN, since e.g.
4182 -9223372036854775808L
4183 is parsed as
4184 -(9223372036854775808L)
4185 and hence we'd get:
4186 error: integer constant is so large that it is unsigned [-Werror]
4187 Workaround this by writing (LONG_MIN + 1) - 1. */
4188 if (m_value == LONG_MIN)
4190 r.write (" gcc_jit_rvalue *%s =\n"
4191 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4192 " %s, /* gcc_jit_type *numeric_type */\n"
4193 " %ldL - 1); /* long value */\n",
4195 r.get_identifier (get_context ()),
4196 r.get_identifier_as_type (m_type),
4197 m_value + 1);;
4198 return;
4201 r.write (" gcc_jit_rvalue *%s =\n"
4202 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4203 " %s, /* gcc_jit_type *numeric_type */\n"
4204 " %ldL); /* long value */\n",
4206 r.get_identifier (get_context ()),
4207 r.get_identifier_as_type (m_type),
4208 m_value);
4211 /* The make_debug_string specialization for <double>, rendering it as
4212 (TARGET_TYPE)LITERAL
4213 e.g.
4214 "(float)42.0". */
4216 template <>
4217 string *
4218 memento_of_new_rvalue_from_const <double>::make_debug_string ()
4220 return string::from_printf (m_ctxt,
4221 "(%s)%f",
4222 m_type->get_debug_string (),
4223 m_value);
4226 /* The get_wide_int specialization for <double>. */
4228 template <>
4229 bool
4230 memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
4232 return false;
4235 /* The write_reproducer specialization for <double>. */
4237 template <>
4238 void
4239 recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
4241 const char *id = r.make_identifier (this, "rvalue");
4242 r.write (" gcc_jit_rvalue *%s =\n"
4243 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4244 " %s, /* gcc_jit_type *numeric_type */\n"
4245 " %f); /* double value */\n",
4247 r.get_identifier (get_context ()),
4248 r.get_identifier_as_type (m_type),
4249 m_value);
4252 /* The make_debug_string specialization for <void *>, rendering it as
4253 (TARGET_TYPE)HEX
4254 e.g.
4255 "(int *)0xdeadbeef"
4257 Zero is rendered as NULL e.g.
4258 "(int *)NULL". */
4260 template <>
4261 string *
4262 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
4264 if (m_value != NULL)
4265 return string::from_printf (m_ctxt,
4266 "(%s)%p",
4267 m_type->get_debug_string (), m_value);
4268 else
4269 return string::from_printf (m_ctxt,
4270 "(%s)NULL",
4271 m_type->get_debug_string ());
4274 /* The get_wide_int specialization for <void *>. */
4276 template <>
4277 bool
4278 memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const
4280 return false;
4283 /* Implementation of recording::memento::write_reproducer for <void *>
4284 values. */
4286 template <>
4287 void
4288 memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
4290 const char *id = r.make_identifier (this, "rvalue");
4291 if (m_value)
4292 r.write (" gcc_jit_rvalue *%s =\n"
4293 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4294 " %s, /* gcc_jit_type *pointer_type */\n"
4295 " (void *)%p); /* void *value */\n",
4297 r.get_identifier (get_context ()),
4298 r.get_identifier_as_type (m_type),
4299 m_value);
4300 else
4301 r.write (" gcc_jit_rvalue *%s =\n"
4302 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4303 " %s); /* gcc_jit_type *pointer_type */\n",
4305 r.get_identifier (get_context ()),
4306 r.get_identifier_as_type (m_type));
4309 /* We're done specializing make_debug_string and write_reproducer, so we
4310 can exit the gcc::jit::recording namespace. */
4312 } // namespace recording
4314 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4316 /* Implementation of pure virtual hook recording::memento::replay_into
4317 for recording::memento_of_new_string_literal. */
4319 void
4320 recording::memento_of_new_string_literal::replay_into (replayer *r)
4322 set_playback_obj (r->new_string_literal (m_value->c_str ()));
4325 /* Implementation of recording::memento::make_debug_string for
4326 string literals. */
4328 recording::string *
4329 recording::memento_of_new_string_literal::make_debug_string ()
4331 return string::from_printf (m_ctxt,
4332 "%s",
4333 m_value->get_debug_string ());
4336 /* Implementation of recording::memento::write_reproducer for string literal
4337 values. */
4339 void
4340 recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
4342 const char *id = r.make_identifier (this, "rvalue");
4343 r.write (" gcc_jit_rvalue *%s =\n"
4344 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4345 " %s); /* const char *value */\n",
4347 r.get_identifier (get_context ()),
4348 m_value->get_debug_string ());
4351 /* The implementation of class gcc::jit::recording::unary_op. */
4353 /* Implementation of pure virtual hook recording::memento::replay_into
4354 for recording::unary_op. */
4356 void
4357 recording::unary_op::replay_into (replayer *r)
4359 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
4360 m_op,
4361 get_type ()->playback_type (),
4362 m_a->playback_rvalue ()));
4365 /* Implementation of pure virtual hook recording::rvalue::visit_children
4366 for recording::unary_op. */
4367 void
4368 recording::unary_op::visit_children (rvalue_visitor *v)
4370 v->visit (m_a);
4373 /* Implementation of recording::memento::make_debug_string for
4374 unary ops. */
4376 static const char * const unary_op_strings[] = {
4377 "-", /* GCC_JIT_UNARY_OP_MINUS */
4378 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4379 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4380 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4383 recording::string *
4384 recording::unary_op::make_debug_string ()
4386 return string::from_printf (m_ctxt,
4387 "%s(%s)",
4388 unary_op_strings[m_op],
4389 m_a->get_debug_string ());
4392 static const char * const unary_op_reproducer_strings[] = {
4393 "GCC_JIT_UNARY_OP_MINUS",
4394 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4395 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4396 "GCC_JIT_UNARY_OP_ABS"
4399 /* Implementation of recording::memento::write_reproducer for unary ops. */
4401 void
4402 recording::unary_op::write_reproducer (reproducer &r)
4404 const char *id = r.make_identifier (this, "rvalue");
4405 r.write (" gcc_jit_rvalue *%s =\n"
4406 " gcc_jit_context_new_unary_op (%s,\n"
4407 " %s, /* gcc_jit_location *loc */\n"
4408 " %s, /* enum gcc_jit_unary_op op */\n"
4409 " %s, /* gcc_jit_type *result_type */\n"
4410 " %s); /* gcc_jit_rvalue *a */\n",
4412 r.get_identifier (get_context ()),
4413 r.get_identifier (m_loc),
4414 unary_op_reproducer_strings[m_op],
4415 r.get_identifier_as_type (get_type ()),
4416 r.get_identifier_as_rvalue (m_a));
4419 /* The implementation of class gcc::jit::recording::binary_op. */
4421 /* Implementation of pure virtual hook recording::memento::replay_into
4422 for recording::binary_op. */
4424 void
4425 recording::binary_op::replay_into (replayer *r)
4427 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
4428 m_op,
4429 get_type ()->playback_type (),
4430 m_a->playback_rvalue (),
4431 m_b->playback_rvalue ()));
4434 /* Implementation of pure virtual hook recording::rvalue::visit_children
4435 for recording::binary_op. */
4436 void
4437 recording::binary_op::visit_children (rvalue_visitor *v)
4439 v->visit (m_a);
4440 v->visit (m_b);
4443 /* Implementation of recording::memento::make_debug_string for
4444 binary ops. */
4446 static const char * const binary_op_strings[] = {
4447 "+", /* GCC_JIT_BINARY_OP_PLUS */
4448 "-", /* GCC_JIT_BINARY_OP_MINUS */
4449 "*", /* GCC_JIT_BINARY_OP_MULT */
4450 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4451 "%", /* GCC_JIT_BINARY_OP_MODULO */
4452 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4453 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4454 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4455 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4456 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4457 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4458 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4461 recording::string *
4462 recording::binary_op::make_debug_string ()
4464 enum precedence prec = get_precedence ();
4465 return string::from_printf (m_ctxt,
4466 "%s %s %s",
4467 m_a->get_debug_string_parens (prec),
4468 binary_op_strings[m_op],
4469 m_b->get_debug_string_parens (prec));
4472 static const char * const binary_op_reproducer_strings[] = {
4473 "GCC_JIT_BINARY_OP_PLUS",
4474 "GCC_JIT_BINARY_OP_MINUS",
4475 "GCC_JIT_BINARY_OP_MULT",
4476 "GCC_JIT_BINARY_OP_DIVIDE",
4477 "GCC_JIT_BINARY_OP_MODULO",
4478 "GCC_JIT_BINARY_OP_BITWISE_AND",
4479 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4480 "GCC_JIT_BINARY_OP_BITWISE_OR",
4481 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4482 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4483 "GCC_JIT_BINARY_OP_LSHIFT",
4484 "GCC_JIT_BINARY_OP_RSHIFT"
4487 /* Implementation of recording::memento::write_reproducer for binary ops. */
4489 void
4490 recording::binary_op::write_reproducer (reproducer &r)
4492 const char *id = r.make_identifier (this, "rvalue");
4493 r.write (" gcc_jit_rvalue *%s =\n"
4494 " gcc_jit_context_new_binary_op (%s,\n"
4495 " %s, /* gcc_jit_location *loc */\n"
4496 " %s, /* enum gcc_jit_binary_op op */\n"
4497 " %s, /* gcc_jit_type *result_type */\n"
4498 " %s, /* gcc_jit_rvalue *a */\n"
4499 " %s); /* gcc_jit_rvalue *b */\n",
4501 r.get_identifier (get_context ()),
4502 r.get_identifier (m_loc),
4503 binary_op_reproducer_strings[m_op],
4504 r.get_identifier_as_type (get_type ()),
4505 r.get_identifier_as_rvalue (m_a),
4506 r.get_identifier_as_rvalue (m_b));
4509 namespace recording {
4510 static const enum precedence binary_op_precedence[] = {
4511 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
4512 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
4514 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
4515 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
4516 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
4518 PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4519 PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4520 PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4521 PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4522 PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4523 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
4524 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
4526 } /* namespace recording */
4528 enum recording::precedence
4529 recording::binary_op::get_precedence () const
4531 return binary_op_precedence[m_op];
4534 /* The implementation of class gcc::jit::recording::comparison. */
4536 /* Implementation of recording::memento::make_debug_string for
4537 comparisons. */
4539 static const char * const comparison_strings[] =
4541 "==", /* GCC_JIT_COMPARISON_EQ */
4542 "!=", /* GCC_JIT_COMPARISON_NE */
4543 "<", /* GCC_JIT_COMPARISON_LT */
4544 "<=", /* GCC_JIT_COMPARISON_LE */
4545 ">", /* GCC_JIT_COMPARISON_GT */
4546 ">=", /* GCC_JIT_COMPARISON_GE */
4549 recording::string *
4550 recording::comparison::make_debug_string ()
4552 enum precedence prec = get_precedence ();
4553 return string::from_printf (m_ctxt,
4554 "%s %s %s",
4555 m_a->get_debug_string_parens (prec),
4556 comparison_strings[m_op],
4557 m_b->get_debug_string_parens (prec));
4560 /* A table of enum gcc_jit_comparison values expressed in string
4561 form. */
4563 static const char * const comparison_reproducer_strings[] =
4565 "GCC_JIT_COMPARISON_EQ",
4566 "GCC_JIT_COMPARISON_NE",
4567 "GCC_JIT_COMPARISON_LT",
4568 "GCC_JIT_COMPARISON_LE",
4569 "GCC_JIT_COMPARISON_GT",
4570 "GCC_JIT_COMPARISON_GE"
4573 /* Implementation of recording::memento::write_reproducer for comparisons. */
4575 void
4576 recording::comparison::write_reproducer (reproducer &r)
4578 const char *id = r.make_identifier (this, "rvalue");
4579 r.write (" gcc_jit_rvalue *%s =\n"
4580 " gcc_jit_context_new_comparison (%s,\n"
4581 " %s, /* gcc_jit_location *loc */\n"
4582 " %s, /* enum gcc_jit_comparison op */\n"
4583 " %s, /* gcc_jit_rvalue *a */\n"
4584 " %s); /* gcc_jit_rvalue *b */\n",
4586 r.get_identifier (get_context ()),
4587 r.get_identifier (m_loc),
4588 comparison_reproducer_strings[m_op],
4589 r.get_identifier_as_rvalue (m_a),
4590 r.get_identifier_as_rvalue (m_b));
4593 /* Implementation of pure virtual hook recording::memento::replay_into
4594 for recording::comparison. */
4596 void
4597 recording::comparison::replay_into (replayer *r)
4599 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
4600 m_op,
4601 m_a->playback_rvalue (),
4602 m_b->playback_rvalue ()));
4605 /* Implementation of pure virtual hook recording::rvalue::visit_children
4606 for recording::comparison. */
4608 void
4609 recording::comparison::visit_children (rvalue_visitor *v)
4611 v->visit (m_a);
4612 v->visit (m_b);
4615 namespace recording {
4616 static const enum precedence comparison_precedence[] =
4618 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
4619 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
4621 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LT */
4622 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
4623 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GT */
4624 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
4626 } /* namespace recording */
4628 enum recording::precedence
4629 recording::comparison::get_precedence () const
4631 return comparison_precedence[m_op];
4634 /* Implementation of pure virtual hook recording::memento::replay_into
4635 for recording::cast. */
4637 void
4638 recording::cast::replay_into (replayer *r)
4640 set_playback_obj (r->new_cast (playback_location (r, m_loc),
4641 m_rvalue->playback_rvalue (),
4642 get_type ()->playback_type ()));
4645 /* Implementation of pure virtual hook recording::rvalue::visit_children
4646 for recording::cast. */
4647 void
4648 recording::cast::visit_children (rvalue_visitor *v)
4650 v->visit (m_rvalue);
4653 /* Implementation of recording::memento::make_debug_string for
4654 casts. */
4656 recording::string *
4657 recording::cast::make_debug_string ()
4659 enum precedence prec = get_precedence ();
4660 return string::from_printf (m_ctxt,
4661 "(%s)%s",
4662 get_type ()->get_debug_string (),
4663 m_rvalue->get_debug_string_parens (prec));
4666 /* Implementation of recording::memento::write_reproducer for casts. */
4668 void
4669 recording::cast::write_reproducer (reproducer &r)
4671 const char *id = r.make_identifier (this, "rvalue");
4672 r.write (" gcc_jit_rvalue *%s =\n"
4673 " gcc_jit_context_new_cast (%s,\n"
4674 " %s, /* gcc_jit_location *loc */\n"
4675 " %s, /* gcc_jit_rvalue *rvalue */\n"
4676 " %s); /* gcc_jit_type *type */\n",
4678 r.get_identifier (get_context ()),
4679 r.get_identifier (m_loc),
4680 r.get_identifier_as_rvalue (m_rvalue),
4681 r.get_identifier_as_type (get_type ()));
4684 /* The implementation of class gcc::jit::recording::base_call. */
4686 /* The constructor for gcc::jit::recording::base_call. */
4688 recording::base_call::base_call (context *ctxt,
4689 location *loc,
4690 type *type_,
4691 int numargs,
4692 rvalue **args)
4693 : rvalue (ctxt, loc, type_),
4694 m_args (),
4695 m_require_tail_call (0)
4697 for (int i = 0; i< numargs; i++)
4698 m_args.safe_push (args[i]);
4701 /* Subroutine for use by call and call_though_ptr's write_reproducer
4702 methods. */
4704 void
4705 recording::base_call::write_reproducer_tail_call (reproducer &r,
4706 const char *id)
4708 if (m_require_tail_call)
4710 r.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
4711 " %i); /* int require_tail_call*/\n",
4717 /* The implementation of class gcc::jit::recording::call. */
4719 /* The constructor for gcc::jit::recording::call. */
4721 recording::call::call (recording::context *ctxt,
4722 recording::location *loc,
4723 recording::function *func,
4724 int numargs,
4725 rvalue **args)
4726 : base_call (ctxt, loc, func->get_return_type (), numargs, args),
4727 m_func (func)
4731 /* Implementation of pure virtual hook recording::memento::replay_into
4732 for recording::call. */
4734 void
4735 recording::call::replay_into (replayer *r)
4737 auto_vec<playback::rvalue *> playback_args;
4738 playback_args.create (m_args.length ());
4739 for (unsigned i = 0; i< m_args.length (); i++)
4740 playback_args.safe_push (m_args[i]->playback_rvalue ());
4742 set_playback_obj (r->new_call (playback_location (r, m_loc),
4743 m_func->playback_function (),
4744 &playback_args,
4745 m_require_tail_call));
4748 /* Implementation of pure virtual hook recording::rvalue::visit_children
4749 for recording::call. */
4751 void
4752 recording::call::visit_children (rvalue_visitor *v)
4754 for (unsigned i = 0; i< m_args.length (); i++)
4755 v->visit (m_args[i]);
4758 /* Implementation of recording::memento::make_debug_string for
4759 function calls. */
4761 recording::string *
4762 recording::call::make_debug_string ()
4764 enum precedence prec = get_precedence ();
4765 /* First, build a buffer for the arguments. */
4766 /* Calculate length of said buffer. */
4767 size_t sz = 1; /* nil terminator */
4768 for (unsigned i = 0; i< m_args.length (); i++)
4770 sz += strlen (m_args[i]->get_debug_string_parens (prec));
4771 sz += 2; /* ", " separator */
4774 /* Now allocate and populate the buffer. */
4775 char *argbuf = new char[sz];
4776 size_t len = 0;
4778 for (unsigned i = 0; i< m_args.length (); i++)
4780 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4781 len += strlen (m_args[i]->get_debug_string_parens (prec));
4782 if (i + 1 < m_args.length ())
4784 strcpy (argbuf + len, ", ");
4785 len += 2;
4788 argbuf[len] = '\0';
4790 /* ...and use it to get the string for the call as a whole. */
4791 string *result = string::from_printf (m_ctxt,
4792 "%s (%s)",
4793 m_func->get_debug_string (),
4794 argbuf);
4796 delete[] argbuf;
4798 return result;
4801 void
4802 recording::call::write_reproducer (reproducer &r)
4804 const char *id = r.make_identifier (this, "call");
4805 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4806 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4807 args_id,
4808 m_args.length ());
4809 for (unsigned i = 0; i< m_args.length (); i++)
4810 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4811 r.write (" };\n");
4812 r.write (" gcc_jit_rvalue *%s =\n"
4813 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4814 " %s, /* gcc_jit_location *loc */\n"
4815 " %s, /* gcc_jit_function *func */\n"
4816 " %i, /* int numargs */ \n"
4817 " %s); /* gcc_jit_rvalue **args*/\n",
4819 r.get_identifier (get_context ()),
4820 r.get_identifier (m_loc),
4821 r.get_identifier (m_func),
4822 m_args.length (),
4823 args_id);
4824 write_reproducer_tail_call (r, id);
4827 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4829 /* The constructor for recording::call_through_ptr. */
4831 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
4832 recording::location *loc,
4833 recording::rvalue *fn_ptr,
4834 int numargs,
4835 rvalue **args)
4836 : base_call (ctxt, loc,
4837 fn_ptr->get_type ()->dereference ()
4838 ->as_a_function_type ()->get_return_type (),
4839 numargs, args),
4840 m_fn_ptr (fn_ptr)
4844 /* Implementation of pure virtual hook recording::memento::replay_into
4845 for recording::call_through_ptr. */
4847 void
4848 recording::call_through_ptr::replay_into (replayer *r)
4850 auto_vec<playback::rvalue *> playback_args;
4851 playback_args.create (m_args.length ());
4852 for (unsigned i = 0; i< m_args.length (); i++)
4853 playback_args.safe_push (m_args[i]->playback_rvalue ());
4855 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
4856 m_fn_ptr->playback_rvalue (),
4857 &playback_args,
4858 m_require_tail_call));
4861 /* Implementation of pure virtual hook recording::rvalue::visit_children
4862 for recording::call_through_ptr. */
4864 void
4865 recording::call_through_ptr::visit_children (rvalue_visitor *v)
4867 v->visit (m_fn_ptr);
4868 for (unsigned i = 0; i< m_args.length (); i++)
4869 v->visit (m_args[i]);
4872 /* Implementation of recording::memento::make_debug_string for
4873 calls through function ptrs. */
4875 recording::string *
4876 recording::call_through_ptr::make_debug_string ()
4878 enum precedence prec = get_precedence ();
4879 /* First, build a buffer for the arguments. */
4880 /* Calculate length of said buffer. */
4881 size_t sz = 1; /* nil terminator */
4882 for (unsigned i = 0; i< m_args.length (); i++)
4884 sz += strlen (m_args[i]->get_debug_string_parens (prec));
4885 sz += 2; /* ", " separator */
4888 /* Now allocate and populate the buffer. */
4889 char *argbuf = new char[sz];
4890 size_t len = 0;
4892 for (unsigned i = 0; i< m_args.length (); i++)
4894 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4895 len += strlen (m_args[i]->get_debug_string_parens (prec));
4896 if (i + 1 < m_args.length ())
4898 strcpy (argbuf + len, ", ");
4899 len += 2;
4902 argbuf[len] = '\0';
4904 /* ...and use it to get the string for the call as a whole. */
4905 string *result = string::from_printf (m_ctxt,
4906 "%s (%s)",
4907 m_fn_ptr->get_debug_string_parens (prec),
4908 argbuf);
4910 delete[] argbuf;
4912 return result;
4915 /* Implementation of recording::memento::write_reproducer for
4916 call_through_ptr. */
4918 void
4919 recording::call_through_ptr::write_reproducer (reproducer &r)
4921 const char *id = r.make_identifier (this, "call");
4922 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4923 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4924 args_id,
4925 m_args.length ());
4926 for (unsigned i = 0; i< m_args.length (); i++)
4927 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4928 r.write (" };\n");
4929 r.write (" gcc_jit_rvalue *%s =\n"
4930 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
4931 " %s, /* gcc_jit_location *loc */\n"
4932 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
4933 " %i, /* int numargs */ \n"
4934 " %s); /* gcc_jit_rvalue **args*/\n",
4936 r.get_identifier (get_context ()),
4937 r.get_identifier (m_loc),
4938 r.get_identifier_as_rvalue (m_fn_ptr),
4939 m_args.length (),
4940 args_id);
4941 write_reproducer_tail_call (r, id);
4944 /* The implementation of class gcc::jit::recording::array_access. */
4946 /* Implementation of pure virtual hook recording::memento::replay_into
4947 for recording::array_access. */
4949 void
4950 recording::array_access::replay_into (replayer *r)
4952 set_playback_obj (
4953 r->new_array_access (playback_location (r, m_loc),
4954 m_ptr->playback_rvalue (),
4955 m_index->playback_rvalue ()));
4958 /* Implementation of pure virtual hook recording::rvalue::visit_children
4959 for recording::array_access. */
4961 void
4962 recording::array_access::visit_children (rvalue_visitor *v)
4964 v->visit (m_ptr);
4965 v->visit (m_index);
4968 /* Implementation of recording::memento::make_debug_string for
4969 array accesses. */
4971 recording::string *
4972 recording::array_access::make_debug_string ()
4974 enum precedence prec = get_precedence ();
4975 return string::from_printf (m_ctxt,
4976 "%s[%s]",
4977 m_ptr->get_debug_string_parens (prec),
4978 m_index->get_debug_string_parens (prec));
4981 /* Implementation of recording::memento::write_reproducer for
4982 array_access. */
4984 void
4985 recording::array_access::write_reproducer (reproducer &r)
4987 const char *id = r.make_identifier (this, "lvalue");
4988 r.write (" gcc_jit_lvalue *%s = \n"
4989 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
4990 " %s, /*gcc_jit_location *loc */\n"
4991 " %s, /* gcc_jit_rvalue *ptr */\n"
4992 " %s); /* gcc_jit_rvalue *index */\n",
4994 r.get_identifier (get_context ()),
4995 r.get_identifier (m_loc),
4996 r.get_identifier_as_rvalue (m_ptr),
4997 r.get_identifier_as_rvalue (m_index));
5000 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
5002 /* Implementation of pure virtual hook recording::memento::replay_into
5003 for recording::access_field_of_lvalue. */
5005 void
5006 recording::access_field_of_lvalue::replay_into (replayer *r)
5008 set_playback_obj (
5009 m_lvalue->playback_lvalue ()
5010 ->access_field (playback_location (r, m_loc),
5011 m_field->playback_field ()));
5015 /* Implementation of pure virtual hook recording::rvalue::visit_children
5016 for recording::access_field_of_lvalue. */
5018 void
5019 recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
5021 v->visit (m_lvalue);
5024 /* Implementation of recording::memento::make_debug_string for
5025 accessing a field of an lvalue. */
5027 recording::string *
5028 recording::access_field_of_lvalue::make_debug_string ()
5030 enum precedence prec = get_precedence ();
5031 return string::from_printf (m_ctxt,
5032 "%s.%s",
5033 m_lvalue->get_debug_string_parens (prec),
5034 m_field->get_debug_string ());
5037 /* Implementation of recording::memento::write_reproducer for
5038 access_field_of_lvalue. */
5040 void
5041 recording::access_field_of_lvalue::write_reproducer (reproducer &r)
5043 const char *id = r.make_identifier (this, "lvalue");
5044 r.write (" gcc_jit_lvalue *%s = \n"
5045 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5046 " %s, /*gcc_jit_location *loc */\n"
5047 " %s);\n",
5049 r.get_identifier_as_lvalue (m_lvalue),
5050 r.get_identifier (m_loc),
5051 r.get_identifier (m_field));
5054 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
5056 /* Implementation of pure virtual hook recording::memento::replay_into
5057 for recording::access_field_rvalue. */
5059 void
5060 recording::access_field_rvalue::replay_into (replayer *r)
5062 set_playback_obj (
5063 m_rvalue->playback_rvalue ()
5064 ->access_field (playback_location (r, m_loc),
5065 m_field->playback_field ()));
5068 /* Implementation of pure virtual hook recording::rvalue::visit_children
5069 for recording::access_field_rvalue. */
5071 void
5072 recording::access_field_rvalue::visit_children (rvalue_visitor *v)
5074 v->visit (m_rvalue);
5077 /* Implementation of recording::memento::make_debug_string for
5078 accessing a field of an rvalue. */
5080 recording::string *
5081 recording::access_field_rvalue::make_debug_string ()
5083 enum precedence prec = get_precedence ();
5084 return string::from_printf (m_ctxt,
5085 "%s.%s",
5086 m_rvalue->get_debug_string_parens (prec),
5087 m_field->get_debug_string ());
5090 /* Implementation of recording::memento::write_reproducer for
5091 access_field_rvalue. */
5093 void
5094 recording::access_field_rvalue::write_reproducer (reproducer &r)
5096 const char *id = r.make_identifier (this, "rvalue");
5097 r.write (" gcc_jit_rvalue *%s = \n"
5098 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5099 " %s, /*gcc_jit_location *loc */\n"
5100 " %s);\n",
5102 r.get_identifier_as_rvalue (m_rvalue),
5103 r.get_identifier (m_loc),
5104 r.get_identifier (m_field));
5107 /* The implementation of class
5108 gcc::jit::recording::dereference_field_rvalue. */
5110 /* Implementation of pure virtual hook recording::memento::replay_into
5111 for recording::dereference_field_rvalue. */
5113 void
5114 recording::dereference_field_rvalue::replay_into (replayer *r)
5116 set_playback_obj (
5117 m_rvalue->playback_rvalue ()->
5118 dereference_field (playback_location (r, m_loc),
5119 m_field->playback_field ()));
5122 /* Implementation of pure virtual hook recording::rvalue::visit_children
5123 for recording::dereference_field_rvalue. */
5125 void
5126 recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
5128 v->visit (m_rvalue);
5131 /* Implementation of recording::memento::make_debug_string for
5132 dereferencing a field of an rvalue. */
5134 recording::string *
5135 recording::dereference_field_rvalue::make_debug_string ()
5137 enum precedence prec = get_precedence ();
5138 return string::from_printf (m_ctxt,
5139 "%s->%s",
5140 m_rvalue->get_debug_string_parens (prec),
5141 m_field->get_debug_string ());
5144 /* Implementation of recording::memento::write_reproducer for
5145 dereference_field_rvalue. */
5147 void
5148 recording::dereference_field_rvalue::write_reproducer (reproducer &r)
5150 const char *id = r.make_identifier (this, "lvalue");
5151 r.write (" gcc_jit_lvalue *%s=\n"
5152 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5153 " %s, /* gcc_jit_location *loc */\n"
5154 " %s); /* gcc_jit_field *field */\n",
5156 r.get_identifier_as_rvalue (m_rvalue),
5157 r.get_identifier (m_loc),
5158 r.get_identifier (m_field));
5161 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5163 /* Implementation of pure virtual hook recording::memento::replay_into
5164 for recording::dereference_rvalue. */
5166 void
5167 recording::dereference_rvalue::replay_into (replayer *r)
5169 set_playback_obj (
5170 m_rvalue->playback_rvalue ()->
5171 dereference (playback_location (r, m_loc)));
5174 /* Implementation of pure virtual hook recording::rvalue::visit_children
5175 for recording::dereference_rvalue. */
5177 void
5178 recording::dereference_rvalue::visit_children (rvalue_visitor *v)
5180 v->visit (m_rvalue);
5183 /* Implementation of recording::memento::make_debug_string for
5184 dereferencing an rvalue. */
5186 recording::string *
5187 recording::dereference_rvalue::make_debug_string ()
5189 enum precedence prec = get_precedence ();
5190 return string::from_printf (m_ctxt,
5191 "*%s",
5192 m_rvalue->get_debug_string_parens (prec));
5195 /* Implementation of recording::memento::write_reproducer for
5196 dereference_rvalue. */
5198 void
5199 recording::dereference_rvalue::write_reproducer (reproducer &r)
5201 const char *id = r.make_identifier (this, "dereference");
5202 r.write (" gcc_jit_lvalue *%s =\n"
5203 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5204 " %s); /* gcc_jit_location *loc */\n",
5206 r.get_identifier_as_rvalue (m_rvalue),
5207 r.get_identifier (m_loc));
5210 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5212 /* Implementation of pure virtual hook recording::memento::replay_into
5213 for recording::get_address_of_lvalue. */
5215 void
5216 recording::get_address_of_lvalue::replay_into (replayer *r)
5218 set_playback_obj (
5219 m_lvalue->playback_lvalue ()->
5220 get_address (playback_location (r, m_loc)));
5223 /* Implementation of pure virtual hook recording::rvalue::visit_children
5224 for recording::get_address_of_lvalue. */
5226 void
5227 recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
5229 v->visit (m_lvalue);
5232 /* Implementation of recording::memento::make_debug_string for
5233 getting the address of an lvalue. */
5235 recording::string *
5236 recording::get_address_of_lvalue::make_debug_string ()
5238 enum precedence prec = get_precedence ();
5239 return string::from_printf (m_ctxt,
5240 "&%s",
5241 m_lvalue->get_debug_string_parens (prec));
5244 /* Implementation of recording::memento::write_reproducer for
5245 get_address_of_lvalue. */
5247 void
5248 recording::get_address_of_lvalue::write_reproducer (reproducer &r)
5250 const char *id = r.make_identifier (this, "address_of");
5251 r.write (" gcc_jit_rvalue *%s =\n"
5252 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5253 " %s); /* gcc_jit_location *loc */\n",
5255 r.get_identifier_as_lvalue (m_lvalue),
5256 r.get_identifier (m_loc));
5259 /* The implementation of class gcc::jit::recording::local. */
5261 /* Implementation of pure virtual hook recording::memento::replay_into
5262 for recording::local. */
5264 void
5265 recording::local::replay_into (replayer *r)
5267 set_playback_obj (
5268 m_func->playback_function ()
5269 ->new_local (playback_location (r, m_loc),
5270 m_type->playback_type (),
5271 playback_string (m_name)));
5274 /* Override the default implementation of
5275 recording::memento::write_to_dump for locals by writing
5276 TYPE NAME;
5277 for use at the top of the function body as if it were a
5278 declaration. */
5280 void
5281 recording::local::write_to_dump (dump &d)
5283 if (d.update_locations ())
5284 m_loc = d.make_location ();
5285 d.write(" %s %s;\n",
5286 m_type->get_debug_string (),
5287 get_debug_string ());
5290 void
5291 recording::local::write_reproducer (reproducer &r)
5293 const char *id = r.make_identifier (this, "local");
5294 r.write (" gcc_jit_lvalue *%s =\n"
5295 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5296 " %s, /* gcc_jit_location *loc */\n"
5297 " %s, /* gcc_jit_type *type */\n"
5298 " %s); /* const char *name */\n",
5300 r.get_identifier (m_func),
5301 r.get_identifier (m_loc),
5302 r.get_identifier_as_type (m_type),
5303 m_name->get_debug_string ());
5306 /* The implementation of class gcc::jit::recording::statement. */
5308 /* We poison the default implementation of
5309 gcc::jit::recording::statement::get_successor_blocks
5310 since this vfunc must only ever be called on terminator
5311 statements. */
5313 vec <recording::block *>
5314 recording::statement::get_successor_blocks () const
5316 /* The base class implementation is for non-terminating statements,
5317 and thus should never be called. */
5318 gcc_unreachable ();
5319 vec <block *> result;
5320 result.create (0);
5321 return result;
5324 /* Extend the default implementation of
5325 recording::memento::write_to_dump for statements by (if requested)
5326 updating the location of the statement to the current location in
5327 the dumpfile. */
5329 void
5330 recording::statement::write_to_dump (dump &d)
5332 memento::write_to_dump (d);
5333 if (d.update_locations ())
5334 m_loc = d.make_location ();
5337 /* The implementation of class gcc::jit::recording::eval. */
5339 /* Implementation of pure virtual hook recording::memento::replay_into
5340 for recording::eval. */
5342 void
5343 recording::eval::replay_into (replayer *r)
5345 playback_block (get_block ())
5346 ->add_eval (playback_location (r),
5347 m_rvalue->playback_rvalue ());
5350 /* Implementation of recording::memento::make_debug_string for
5351 an eval statement. */
5353 recording::string *
5354 recording::eval::make_debug_string ()
5356 return string::from_printf (m_ctxt,
5357 "(void)%s;",
5358 m_rvalue->get_debug_string ());
5361 /* Implementation of recording::memento::write_reproducer for
5362 eval statements. */
5364 void
5365 recording::eval::write_reproducer (reproducer &r)
5367 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5368 " %s, /* gcc_jit_location *loc */\n"
5369 " %s); /* gcc_jit_rvalue *rvalue */\n",
5370 r.get_identifier (get_block ()),
5371 r.get_identifier (get_loc ()),
5372 r.get_identifier_as_rvalue (m_rvalue));
5375 /* The implementation of class gcc::jit::recording::assignment. */
5377 /* Implementation of pure virtual hook recording::memento::replay_into
5378 for recording::assignment. */
5380 void
5381 recording::assignment::replay_into (replayer *r)
5383 playback_block (get_block ())
5384 ->add_assignment (playback_location (r),
5385 m_lvalue->playback_lvalue (),
5386 m_rvalue->playback_rvalue ());
5389 /* Implementation of recording::memento::make_debug_string for
5390 an assignment statement. */
5392 recording::string *
5393 recording::assignment::make_debug_string ()
5395 return string::from_printf (m_ctxt,
5396 "%s = %s;",
5397 m_lvalue->get_debug_string (),
5398 m_rvalue->get_debug_string ());
5401 /* Implementation of recording::memento::write_reproducer for
5402 assignment statements. */
5404 void
5405 recording::assignment::write_reproducer (reproducer &r)
5407 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5408 " %s, /* gcc_jit_location *loc */\n"
5409 " %s, /* gcc_jit_lvalue *lvalue */\n"
5410 " %s); /* gcc_jit_rvalue *rvalue */\n",
5411 r.get_identifier (get_block ()),
5412 r.get_identifier (get_loc ()),
5413 r.get_identifier_as_lvalue (m_lvalue),
5414 r.get_identifier_as_rvalue (m_rvalue));
5417 /* The implementation of class gcc::jit::recording::assignment_op. */
5419 /* Implementation of pure virtual hook recording::memento::replay_into
5420 for recording::assignment_op. */
5422 void
5423 recording::assignment_op::replay_into (replayer *r)
5425 playback::type *result_type =
5426 m_lvalue->playback_lvalue ()->get_type ();
5428 playback::rvalue *binary_op =
5429 r->new_binary_op (playback_location (r),
5430 m_op,
5431 result_type,
5432 m_lvalue->playback_rvalue (),
5433 m_rvalue->playback_rvalue ());
5435 playback_block (get_block ())
5436 ->add_assignment (playback_location (r),
5437 m_lvalue->playback_lvalue (),
5438 binary_op);
5441 /* Implementation of recording::memento::make_debug_string for
5442 an assignment_op statement. */
5444 recording::string *
5445 recording::assignment_op::make_debug_string ()
5447 return string::from_printf (m_ctxt,
5448 "%s %s= %s;",
5449 m_lvalue->get_debug_string (),
5450 binary_op_strings[m_op],
5451 m_rvalue->get_debug_string ());
5454 /* Implementation of recording::memento::write_reproducer for
5455 assignment_op statements. */
5457 void
5458 recording::assignment_op::write_reproducer (reproducer &r)
5460 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5461 " %s, /* gcc_jit_location *loc */\n"
5462 " %s, /* gcc_jit_lvalue *lvalue */\n"
5463 " %s, /* enum gcc_jit_binary_op op */\n"
5464 " %s); /* gcc_jit_rvalue *rvalue */\n",
5465 r.get_identifier (get_block ()),
5466 r.get_identifier (get_loc ()),
5467 r.get_identifier_as_lvalue (m_lvalue),
5468 binary_op_reproducer_strings[m_op],
5469 r.get_identifier_as_rvalue (m_rvalue));
5472 /* The implementation of class gcc::jit::recording::comment. */
5474 /* Implementation of pure virtual hook recording::memento::replay_into
5475 for recording::comment. */
5477 void
5478 recording::comment::replay_into (replayer *r)
5480 playback_block (get_block ())
5481 ->add_comment (playback_location (r),
5482 m_text->c_str ());
5485 /* Implementation of recording::memento::make_debug_string for
5486 a comment "statement". */
5488 recording::string *
5489 recording::comment::make_debug_string ()
5491 return string::from_printf (m_ctxt,
5492 "/* %s */",
5493 m_text->c_str ());
5496 /* Implementation of recording::memento::write_reproducer for
5497 comments. */
5499 void
5500 recording::comment::write_reproducer (reproducer &r)
5502 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5503 " %s, /* gcc_jit_location *loc */\n"
5504 " %s); /* const char *text */\n",
5505 r.get_identifier (get_block ()),
5506 r.get_identifier (get_loc ()),
5507 m_text->get_debug_string ());
5510 /* The implementation of class gcc::jit::recording::conditional. */
5512 /* Implementation of pure virtual hook recording::memento::replay_into
5513 for recording::conditional. */
5515 void
5516 recording::conditional::replay_into (replayer *r)
5518 playback_block (get_block ())
5519 ->add_conditional (playback_location (r),
5520 m_boolval->playback_rvalue (),
5521 playback_block (m_on_true),
5522 playback_block (m_on_false));
5525 /* Override the poisoned default implementation of
5526 gcc::jit::recording::statement::get_successor_blocks
5528 A conditional jump has 2 successor blocks. */
5530 vec <recording::block *>
5531 recording::conditional::get_successor_blocks () const
5533 vec <block *> result;
5534 result.create (2);
5535 result.quick_push (m_on_true);
5536 result.quick_push (m_on_false);
5537 return result;
5540 /* Implementation of recording::memento::make_debug_string for
5541 a conditional jump statement. */
5543 recording::string *
5544 recording::conditional::make_debug_string ()
5546 if (m_on_false)
5547 return string::from_printf (m_ctxt,
5548 "if (%s) goto %s; else goto %s;",
5549 m_boolval->get_debug_string (),
5550 m_on_true->get_debug_string (),
5551 m_on_false->get_debug_string ());
5552 else
5553 return string::from_printf (m_ctxt,
5554 "if (%s) goto %s;",
5555 m_boolval->get_debug_string (),
5556 m_on_true->get_debug_string ());
5559 /* Implementation of recording::memento::write_reproducer for
5560 conditional statements. */
5562 void
5563 recording::conditional::write_reproducer (reproducer &r)
5565 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5566 " %s, /* gcc_jit_location *loc */\n"
5567 " %s, /* gcc_jit_rvalue *boolval */\n"
5568 " %s, /* gcc_jit_block *on_true */\n"
5569 " %s); /* gcc_jit_block *on_false */\n",
5570 r.get_identifier (get_block ()),
5571 r.get_identifier (get_loc ()),
5572 r.get_identifier_as_rvalue (m_boolval),
5573 r.get_identifier (m_on_true),
5574 r.get_identifier (m_on_false));
5577 /* The implementation of class gcc::jit::recording::jump. */
5579 /* Implementation of pure virtual hook recording::memento::replay_into
5580 for recording::jump. */
5582 void
5583 recording::jump::replay_into (replayer *r)
5585 playback_block (get_block ())
5586 ->add_jump (playback_location (r),
5587 m_target->playback_block ());
5590 /* Override the poisoned default implementation of
5591 gcc::jit::recording::statement::get_successor_blocks
5593 An unconditional jump has 1 successor block. */
5595 vec <recording::block *>
5596 recording::jump::get_successor_blocks () const
5598 vec <block *> result;
5599 result.create (1);
5600 result.quick_push (m_target);
5601 return result;
5604 /* Implementation of recording::memento::make_debug_string for
5605 a unconditional jump statement. */
5607 recording::string *
5608 recording::jump::make_debug_string ()
5610 return string::from_printf (m_ctxt,
5611 "goto %s;",
5612 m_target->get_debug_string ());
5615 /* Implementation of recording::memento::write_reproducer for
5616 jump statements. */
5618 void
5619 recording::jump::write_reproducer (reproducer &r)
5621 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5622 " %s, /* gcc_jit_location *loc */\n"
5623 " %s); /* gcc_jit_block *target */\n",
5624 r.get_identifier (get_block ()),
5625 r.get_identifier (get_loc ()),
5626 r.get_identifier (m_target));
5629 /* The implementation of class gcc::jit::recording::return_. */
5631 /* Implementation of pure virtual hook recording::memento::replay_into
5632 for recording::return_. */
5634 void
5635 recording::return_::replay_into (replayer *r)
5637 playback_block (get_block ())
5638 ->add_return (playback_location (r),
5639 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
5642 /* Override the poisoned default implementation of
5643 gcc::jit::recording::statement::get_successor_blocks
5645 A return statement has no successor block. */
5647 vec <recording::block *>
5648 recording::return_::get_successor_blocks () const
5650 vec <block *> result;
5651 result.create (0);
5652 return result;
5655 /* Implementation of recording::memento::make_debug_string for
5656 a return statement (covers both those with and without rvalues). */
5658 recording::string *
5659 recording::return_::make_debug_string ()
5661 if (m_rvalue)
5662 return string::from_printf (m_ctxt,
5663 "return %s;",
5664 m_rvalue->get_debug_string ());
5665 else
5666 return string::from_printf (m_ctxt,
5667 "return;");
5670 /* Implementation of recording::memento::write_reproducer for
5671 return statements. */
5673 void
5674 recording::return_::write_reproducer (reproducer &r)
5676 if (m_rvalue)
5677 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5678 " %s, /* gcc_jit_location *loc */\n"
5679 " %s); /* gcc_jit_rvalue *rvalue */\n",
5680 r.get_identifier (get_block ()),
5681 r.get_identifier (get_loc ()),
5682 r.get_identifier_as_rvalue (m_rvalue));
5683 else
5684 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5685 " %s); /* gcc_jit_location *loc */\n",
5686 r.get_identifier (get_block ()),
5687 r.get_identifier (get_loc ()));
5690 /* The implementation of class gcc::jit::recording::case_. */
5692 void
5693 recording::case_::write_reproducer (reproducer &r)
5695 const char *id = r.make_identifier (this, "case");
5696 const char *fmt =
5697 " gcc_jit_case *%s = \n"
5698 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
5699 " %s, /* gcc_jit_rvalue *min_value */\n"
5700 " %s, /* gcc_jit_rvalue *max_value */\n"
5701 " %s); /* gcc_jit_block *dest_block */\n";
5702 r.write (fmt,
5704 r.get_identifier (get_context ()),
5705 r.get_identifier_as_rvalue (m_min_value),
5706 r.get_identifier_as_rvalue (m_max_value),
5707 r.get_identifier (m_dest_block));
5710 recording::string *
5711 recording::case_::make_debug_string ()
5713 return string::from_printf (get_context (),
5714 "case %s ... %s: goto %s;",
5715 m_min_value->get_debug_string (),
5716 m_max_value->get_debug_string (),
5717 m_dest_block->get_debug_string ());
5720 /* The implementation of class gcc::jit::recording::switch_. */
5722 /* gcc::jit::recording::switch_'s constructor. */
5724 recording::switch_::switch_ (block *b,
5725 location *loc,
5726 rvalue *expr,
5727 block *default_block,
5728 int num_cases,
5729 case_ **cases)
5730 : statement (b, loc),
5731 m_expr (expr),
5732 m_default_block (default_block)
5734 m_cases.reserve_exact (num_cases);
5735 for (int i = 0; i< num_cases; i++)
5736 m_cases.quick_push (cases[i]);
5739 /* Implementation of pure virtual hook recording::memento::replay_into
5740 for recording::switch_. */
5742 void
5743 recording::switch_::replay_into (replayer *r)
5745 auto_vec <playback::case_> pcases;
5746 int i;
5747 recording::case_ *rcase;
5748 pcases.reserve_exact (m_cases.length ());
5749 FOR_EACH_VEC_ELT (m_cases, i, rcase)
5751 playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (),
5752 rcase->get_max_value ()->playback_rvalue (),
5753 rcase->get_dest_block ()->playback_block ());
5754 pcases.safe_push (pcase);
5756 playback_block (get_block ())
5757 ->add_switch (playback_location (r),
5758 m_expr->playback_rvalue (),
5759 m_default_block->playback_block (),
5760 &pcases);
5763 /* Override the poisoned default implementation of
5764 gcc::jit::recording::statement::get_successor_blocks
5766 A switch statement has (NUM_CASES + 1) successor blocks. */
5768 vec <recording::block *>
5769 recording::switch_::get_successor_blocks () const
5771 vec <block *> result;
5772 result.create (m_cases.length () + 1);
5773 result.quick_push (m_default_block);
5774 int i;
5775 case_ *c;
5776 FOR_EACH_VEC_ELT (m_cases, i, c)
5777 result.quick_push (c->get_dest_block ());
5778 return result;
5781 /* Implementation of recording::memento::make_debug_string for
5782 a switch statement. */
5784 recording::string *
5785 recording::switch_::make_debug_string ()
5787 auto_vec <char> cases_str;
5788 int i;
5789 case_ *c;
5790 FOR_EACH_VEC_ELT (m_cases, i, c)
5792 size_t len = strlen (c->get_debug_string ());
5793 unsigned idx = cases_str.length ();
5794 cases_str.safe_grow (idx + 1 + len);
5795 cases_str[idx] = ' ';
5796 memcpy (&(cases_str[idx + 1]),
5797 c->get_debug_string (),
5798 len);
5800 cases_str.safe_push ('\0');
5802 return string::from_printf (m_ctxt,
5803 "switch (%s) {default: goto %s;%s}",
5804 m_expr->get_debug_string (),
5805 m_default_block->get_debug_string (),
5806 &cases_str[0]);
5809 /* Implementation of recording::memento::write_reproducer for
5810 switch statements. */
5812 void
5813 recording::switch_::write_reproducer (reproducer &r)
5815 r.make_identifier (this, "switch");
5816 int i;
5817 case_ *c;
5818 const char *cases_id =
5819 r.make_tmp_identifier ("cases_for", this);
5820 r.write (" gcc_jit_case *%s[%i] = {\n",
5821 cases_id,
5822 m_cases.length ());
5823 FOR_EACH_VEC_ELT (m_cases, i, c)
5824 r.write (" %s,\n", r.get_identifier (c));
5825 r.write (" };\n");
5826 const char *fmt =
5827 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
5828 " %s, /* gcc_jit_location *loc */\n"
5829 " %s, /* gcc_jit_rvalue *expr */\n"
5830 " %s, /* gcc_jit_block *default_block */\n"
5831 " %i, /* int num_cases */\n"
5832 " %s); /* gcc_jit_case **cases */\n";
5833 r.write (fmt,
5834 r.get_identifier (get_block ()),
5835 r.get_identifier (get_loc ()),
5836 r.get_identifier_as_rvalue (m_expr),
5837 r.get_identifier (m_default_block),
5838 m_cases.length (),
5839 cases_id);
5842 } // namespace gcc::jit
5844 } // namespace gcc