2015-07-14 Vladimir Makarov <vmakarov@redhat.com>
[official-gcc.git] / gcc / jit / jit-recording.c
blobd888b0e52c89f41ba23961cb96fe3be084a30a0b
1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2015 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "pretty-print.h"
26 #include "hash-map.h"
27 #include "toplev.h"
29 #include <pthread.h>
31 #include "jit-common.h"
32 #include "jit-builtins.h"
33 #include "jit-logging.h"
34 #include "jit-recording.h"
35 #include "jit-playback.h"
37 namespace gcc {
38 namespace jit {
40 // class dump
42 dump::dump (recording::context &ctxt,
43 const char *filename,
44 bool update_locations)
45 : m_ctxt (ctxt),
46 m_filename (filename),
47 m_update_locations (update_locations),
48 m_line (0),
49 m_column (0)
51 m_file = fopen (filename, "w");
52 if (!m_file)
53 ctxt.add_error (NULL,
54 "error opening dump file %s for writing: %s",
55 filename,
56 xstrerror (errno));
59 dump::~dump ()
61 if (m_file)
63 int err = fclose (m_file);
64 if (err)
65 m_ctxt.add_error (NULL,
66 "error closing dump file %s: %s",
67 m_filename,
68 xstrerror (errno));
72 /* Write the given message to the dump, using printf-formatting
73 conventions, updating the line/column within the dump.
75 Emit an error on the context if a failure occurs. */
77 void
78 dump::write (const char *fmt, ...)
80 int len;
81 va_list ap;
82 char *buf;
84 /* If there was an error opening the file, we've already reported it.
85 Don't attempt further work. */
86 if (!m_file)
87 return;
89 va_start (ap, fmt);
90 len = vasprintf (&buf, fmt, ap);
91 va_end (ap);
93 if (buf == NULL || len < 0)
95 m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
96 m_filename);
97 return;
100 if (fwrite (buf, strlen (buf), 1, m_file) != 1)
101 m_ctxt.add_error (NULL, "error writing to dump file %s",
102 m_filename);
104 /* Flush after each line, to ease debugging crashes. */
105 fflush (m_file);
107 /* Update line/column: */
108 for (const char *ptr = buf; *ptr; ptr++)
110 if ('\n' == *ptr)
112 m_line++;
113 m_column = 0;
115 else
116 m_column++;
119 free (buf);
122 /* Construct a gcc::jit::recording::location instance for the current
123 location within the dump. */
125 recording::location *
126 dump::make_location () const
128 return m_ctxt.new_location (m_filename, m_line, m_column,
129 /* We need to flag such locations as *not*
130 created by the user, so that
131 reproducer::get_identifier can cope with
132 them appearing *after* the memento that
133 refers to them. */
134 false);
137 /* A collection of allocations, all of which can be released together, to
138 avoid needing to track and release them individually. */
140 class allocator
142 public:
143 ~allocator ();
145 char *
146 xstrdup_printf (const char *, ...)
147 ATTRIBUTE_RETURNS_NONNULL
148 GNU_PRINTF(2, 3);
150 char *
151 xstrdup_printf_va (const char *, va_list ap)
152 ATTRIBUTE_RETURNS_NONNULL
153 GNU_PRINTF(2, 0);
155 private:
156 auto_vec <void *> m_buffers;
159 /* allocator's destructor. Call "free" on all of the allocations. */
161 allocator::~allocator ()
163 unsigned i;
164 void *buffer;
165 FOR_EACH_VEC_ELT (m_buffers, i, buffer)
166 free (buffer);
169 /* Formatted printing, allocating to a buffer (or exiting the process if
170 the allocation fails).
172 The buffer exists until the allocator is cleaned up, and is freed at
173 that point, so the caller doesn't need to track the result. */
175 char *
176 allocator::xstrdup_printf (const char *fmt, ...)
178 char *result;
179 va_list ap;
180 va_start (ap, fmt);
181 result = xstrdup_printf_va (fmt, ap);
182 va_end (ap);
183 return result;
186 /* Formatted printing, allocating to a buffer (or exiting the process if
187 the allocation fails).
189 The buffer exists until the allocator is cleaned up, and is freed at
190 that point, so the caller doesn't need to track the result. */
192 char *
193 allocator::xstrdup_printf_va (const char *fmt, va_list ap)
195 char *result = xvasprintf (fmt, ap);
196 m_buffers.safe_push (result);
197 return result;
200 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
201 implementing gcc_jit_context_dump_reproducer_to_file. */
203 class reproducer : public dump
205 public:
206 reproducer (recording::context &ctxt,
207 const char *filename);
209 void
210 write_params (const vec <recording::context *> &contexts);
212 void
213 write_args (const vec <recording::context *> &contexts);
215 const char *
216 make_identifier (recording::memento *m, const char *prefix);
218 const char *
219 make_tmp_identifier (const char *prefix, recording::memento *m);
221 const char *
222 get_identifier (recording::context *ctxt);
224 const char *
225 get_identifier (recording::memento *m);
227 const char *
228 get_identifier_as_rvalue (recording::rvalue *m);
230 const char *
231 get_identifier_as_lvalue (recording::lvalue *m);
233 const char *
234 get_identifier_as_type (recording::type *m);
236 char *
237 xstrdup_printf (const char *, ...)
238 ATTRIBUTE_RETURNS_NONNULL
239 GNU_PRINTF(2, 3);
241 private:
242 hash_map<recording::memento *, const char *> m_identifiers;
243 allocator m_allocator;
246 /* gcc::jit::reproducer's constructor. */
248 reproducer::reproducer (recording::context &ctxt,
249 const char *filename) :
250 dump (ctxt, filename, 0),
251 m_identifiers (),
252 m_allocator ()
256 /* Write out a list of contexts as a set of parameters within a
257 C function declaration. */
259 void
260 reproducer::write_params (const vec <recording::context *> &contexts)
262 unsigned i;
263 recording::context *ctxt;
264 FOR_EACH_VEC_ELT (contexts, i, ctxt)
266 write ("gcc_jit_context *%s",
267 get_identifier (ctxt));
268 if (i < contexts.length () - 1)
269 write (",\n"
270 " ");
274 /* Write out a list of contexts as a set of arguments within a call
275 to a C function. */
277 void
278 reproducer::write_args (const vec <recording::context *> &contexts)
280 unsigned i;
281 recording::context *ctxt;
282 FOR_EACH_VEC_ELT (contexts, i, ctxt)
284 write ("%s",
285 get_identifier (ctxt));
286 if (i < contexts.length () - 1)
287 write (",\n"
288 " ");
292 /* Generate a C identifier for the given memento, associating the generated
293 buffer with the memento (for future calls to get_identifier et al).
295 The reproducer will eventually clean up the buffer in its dtor. */
296 const char *
297 reproducer::make_identifier (recording::memento *m, const char *prefix)
299 char *result;
300 if (strlen (m->get_debug_string ()) < 100)
302 result = m_allocator.xstrdup_printf ("%s_%s_%p",
303 prefix,
304 m->get_debug_string (),
305 (void *) m);
306 for (char *p = result; *p; p++)
307 if (!ISALNUM (*p))
308 *p = '_';
310 else
311 result = m_allocator.xstrdup_printf ("%s_%p",
312 prefix, (void *) m);
313 m_identifiers.put (m, result);
314 return result;
317 /* Generate a C identifier for a temporary variable.
318 The reproducer will eventually clean up the buffer in its dtor. */
320 const char *
321 reproducer::make_tmp_identifier (const char *prefix, recording::memento *m)
323 return m_allocator.xstrdup_printf ("%s_%s",
324 prefix, get_identifier (m));
327 /* Generate a C identifier for the given context.
328 The reproducer will eventually clean up the buffer in its dtor. */
330 const char *
331 reproducer::get_identifier (recording::context *ctxt)
333 return m_allocator.xstrdup_printf ("ctxt_%p",
334 (void *)ctxt);
337 /* Locate the C identifier for the given memento, which is assumed to
338 have already been created via make_identifier. */
340 const char *
341 reproducer::get_identifier (recording::memento *m)
343 if (!m)
344 return "NULL";
346 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
347 and hence these locations appear in the context's memento list
348 out-of-order: they appear in the context's memento list *after*
349 the memento that refers to them. For this case, it's simplest to
350 pretend that they're NULL when writing out the code to recreate the
351 memento that uses them. */
352 if (recording::location *loc = m->dyn_cast_location ())
353 if (!loc->created_by_user ())
354 return "NULL";
356 const char **slot = m_identifiers.get (m);
357 if (!slot)
359 get_context ().add_error (NULL,
360 "unable to find identifier for %p: %s",
361 (void *)m,
362 m->get_debug_string ());
363 gcc_unreachable ();
365 return *slot;
368 /* Locate the C identifier for the given rvalue, wrapping it within
369 a gcc_*_as_rvalue upcast if necessary. */
371 const char *
372 reproducer::get_identifier_as_rvalue (recording::rvalue *m)
374 return m->access_as_rvalue (*this);
377 /* Locate the C identifier for the given lvalue, wrapping it within
378 a gcc_*_as_lvalue upcast if necessary. */
380 const char *
381 reproducer::get_identifier_as_lvalue (recording::lvalue *m)
383 return m->access_as_lvalue (*this);
386 /* Locate the C identifier for the given type, wrapping it within
387 a gcc_*_as_type upcast if necessary. */
389 const char *
390 reproducer::get_identifier_as_type (recording::type *m)
392 return m->access_as_type (*this);
395 /* Formatted printing, allocating to a buffer (or exiting the process if
396 the allocation fails).
398 The buffer exists until the allocator is cleaned up, and is freed at
399 that point, so the caller doesn't need to track the result.
401 Note that we can't use ggc_printf since we're not within the compiler
402 proper (when within gcc_jit_context_dump_reproducer_to_file). */
404 char *
405 reproducer::xstrdup_printf (const char *fmt, ...)
407 char *result;
408 va_list ap;
409 va_start (ap, fmt);
410 result = m_allocator.xstrdup_printf_va (fmt, ap);
411 va_end (ap);
412 return result;
415 /**********************************************************************
416 Recording.
417 **********************************************************************/
419 /* Get the playback::location for the given recording::location,
420 handling a NULL input with a NULL output. */
422 playback::location *
423 recording::playback_location (replayer *r, recording::location *loc)
425 if (loc)
426 return loc->playback_location (r);
427 else
428 return NULL;
431 /* Get a const char * for the given recording::string
432 handling a NULL input with a NULL output. */
434 const char *
435 recording::playback_string (recording::string *str)
437 if (str)
438 return str->c_str ();
439 else
440 return NULL;
443 /* Get the playback::block for the given recording::block,
444 handling a NULL input with a NULL output. */
446 playback::block *
447 recording::playback_block (recording::block *b)
449 if (b)
450 return b->playback_block ();
451 else
452 return NULL;
455 /* Methods of cc::jit::recording::context. */
457 /* The constructor for gcc::jit::recording::context, used by
458 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
460 recording::context::context (context *parent_ctxt)
461 : log_user (NULL),
462 m_parent_ctxt (parent_ctxt),
463 m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this),
464 m_error_count (0),
465 m_first_error_str (NULL),
466 m_owns_first_error_str (false),
467 m_last_error_str (NULL),
468 m_owns_last_error_str (false),
469 m_mementos (),
470 m_compound_types (),
471 m_globals (),
472 m_functions (),
473 m_FILE_type (NULL),
474 m_builtins_manager(NULL)
476 if (parent_ctxt)
478 /* Inherit options from parent. */
479 for (unsigned i = 0;
480 i < sizeof (m_str_options) / sizeof (m_str_options[0]);
481 i++)
483 const char *parent_opt = parent_ctxt->m_str_options[i];
484 m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
486 memcpy (m_int_options,
487 parent_ctxt->m_int_options,
488 sizeof (m_int_options));
489 memcpy (m_bool_options,
490 parent_ctxt->m_bool_options,
491 sizeof (m_bool_options));
492 memcpy (m_inner_bool_options,
493 parent_ctxt->m_inner_bool_options,
494 sizeof (m_inner_bool_options));
495 set_logger (parent_ctxt->get_logger ());
497 else
499 memset (m_str_options, 0, sizeof (m_str_options));
500 memset (m_int_options, 0, sizeof (m_int_options));
501 memset (m_bool_options, 0, sizeof (m_bool_options));
502 memset (m_inner_bool_options, 0, sizeof (m_inner_bool_options));
505 memset (m_basic_types, 0, sizeof (m_basic_types));
508 /* The destructor for gcc::jit::recording::context, implicitly used by
509 gcc_jit_context_release. */
511 recording::context::~context ()
513 JIT_LOG_SCOPE (get_logger ());
514 int i;
515 memento *m;
516 FOR_EACH_VEC_ELT (m_mementos, i, m)
518 delete m;
521 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
522 free (m_str_options[i]);
524 char *optname;
525 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
526 free (optname);
528 if (m_builtins_manager)
529 delete m_builtins_manager;
531 if (m_owns_first_error_str)
532 free (m_first_error_str);
534 if (m_owns_last_error_str)
535 if (m_last_error_str != m_first_error_str)
536 free (m_last_error_str);
539 /* Add the given mememto to the list of those tracked by this
540 gcc::jit::recording::context, so that e.g. it can be deleted
541 when this context is released. */
543 void
544 recording::context::record (memento *m)
546 gcc_assert (m);
548 m_mementos.safe_push (m);
551 /* Replay this context (and any parents) into the given replayer. */
553 void
554 recording::context::replay_into (replayer *r)
556 JIT_LOG_SCOPE (get_logger ());
557 int i;
558 memento *m;
560 /* If we have a parent context, we must replay it. This will
561 recursively walk backwards up the historical tree, then replay things
562 forwards "in historical order", starting with the ultimate parent
563 context, until we reach the "this" context.
565 Note that we fully replay the parent, then fully replay the child,
566 which means that inter-context references can only exist from child
567 to parent, not the other way around.
569 All of this replaying is suboptimal - it would be better to do the
570 work for the parent context *once*, rather than replaying the parent
571 every time we replay each child. However, fixing this requires deep
572 surgery to lifetime-management: we'd need every context family tree
573 to have its own GC heap, and to initialize the GCC code to use that
574 heap (with a mutex on such a heap). */
575 if (m_parent_ctxt)
576 m_parent_ctxt->replay_into (r);
578 if (r->errors_occurred ())
579 return;
581 /* Replay this context's saved operations into r. */
582 FOR_EACH_VEC_ELT (m_mementos, i, m)
584 /* Disabled low-level debugging, here if we need it: print what
585 we're replaying.
586 Note that the calls to get_debug_string might lead to more
587 mementos being created for the strings.
588 This can also be used to exercise the debug_string
589 machinery. */
590 if (0)
591 printf ("context %p replaying (%p): %s\n",
592 (void *)this, (void *)m, m->get_debug_string ());
594 m->replay_into (r);
596 if (r->errors_occurred ())
597 return;
601 /* During a playback, we associate objects from the recording with
602 their counterparts during this playback.
604 For simplicity, we store this within the recording objects.
606 The following method cleans away these associations, to ensure that
607 we never have out-of-date associations lingering on subsequent
608 playbacks (the objects pointed to are GC-managed, but the
609 recording objects don't own refs to them). */
611 void
612 recording::context::disassociate_from_playback ()
614 JIT_LOG_SCOPE (get_logger ());
615 int i;
616 memento *m;
618 if (m_parent_ctxt)
619 m_parent_ctxt->disassociate_from_playback ();
621 FOR_EACH_VEC_ELT (m_mementos, i, m)
623 m->set_playback_obj (NULL);
627 /* Create a recording::string instance and add it to this context's list
628 of mementos.
630 This creates a fresh copy of the given 0-terminated buffer. */
632 recording::string *
633 recording::context::new_string (const char *text)
635 if (!text)
636 return NULL;
638 recording::string *result = new string (this, text);
639 record (result);
640 return result;
643 /* Create a recording::location instance and add it to this context's
644 list of mementos.
646 Implements the post-error-checking part of
647 gcc_jit_context_new_location. */
649 recording::location *
650 recording::context::new_location (const char *filename,
651 int line,
652 int column,
653 bool created_by_user)
655 recording::location *result =
656 new recording::location (this,
657 new_string (filename),
658 line, column,
659 created_by_user);
660 record (result);
661 return result;
664 /* If we haven't seen this enum value yet, create a recording::type
665 instance and add it to this context's list of mementos.
667 If we have seen it before, reuse our cached value, so that repeated
668 calls on the context give the same object.
670 If we have a parent context, the cache is within the ultimate
671 ancestor context.
673 Implements the post-error-checking part of
674 gcc_jit_context_get_type. */
676 recording::type *
677 recording::context::get_type (enum gcc_jit_types kind)
679 if (!m_basic_types[kind])
681 if (m_parent_ctxt)
682 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
683 else
685 recording::type *result = new memento_of_get_type (this, kind);
686 record (result);
687 m_basic_types[kind] = result;
691 return m_basic_types[kind];
694 /* Get a recording::type instance for the given size and signedness.
695 This is implemented in terms of recording::context::get_type
696 above.
698 Implements the post-error-checking part of
699 gcc_jit_context_get_int_type. */
701 recording::type *
702 recording::context::get_int_type (int num_bytes, int is_signed)
704 /* We can't use a switch here since some of the values are macros affected
705 by options; e.g. i386.h has
706 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
707 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
708 are in bits, rather than bytes.
710 const int num_bits = num_bytes * 8;
711 if (num_bits == INT_TYPE_SIZE)
712 return get_type (is_signed
713 ? GCC_JIT_TYPE_INT
714 : GCC_JIT_TYPE_UNSIGNED_INT);
715 if (num_bits == CHAR_TYPE_SIZE)
716 return get_type (is_signed
717 ? GCC_JIT_TYPE_SIGNED_CHAR
718 : GCC_JIT_TYPE_UNSIGNED_CHAR);
719 if (num_bits == SHORT_TYPE_SIZE)
720 return get_type (is_signed
721 ? GCC_JIT_TYPE_SHORT
722 : GCC_JIT_TYPE_UNSIGNED_SHORT);
723 if (num_bits == LONG_TYPE_SIZE)
724 return get_type (is_signed
725 ? GCC_JIT_TYPE_LONG
726 : GCC_JIT_TYPE_UNSIGNED_LONG);
727 if (num_bits == LONG_LONG_TYPE_SIZE)
728 return get_type (is_signed
729 ? GCC_JIT_TYPE_LONG_LONG
730 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
732 /* Some other size, not corresponding to the C int types. */
733 /* To be written: support arbitrary other sizes, sharing by
734 memoizing at the recording::context level? */
735 gcc_unreachable ();
738 /* Create a recording::type instance and add it to this context's list
739 of mementos.
741 Implements the post-error-checking part of
742 gcc_jit_context_new_array_type. */
744 recording::type *
745 recording::context::new_array_type (recording::location *loc,
746 recording::type *element_type,
747 int num_elements)
749 if (struct_ *s = element_type->dyn_cast_struct ())
750 if (!s->get_fields ())
752 add_error (NULL,
753 "cannot create an array of type %s"
754 " until the fields have been set",
755 s->get_name ()->c_str ());
756 return NULL;
758 recording::type *result =
759 new recording::array_type (this, loc, element_type, num_elements);
760 record (result);
761 return result;
764 /* Create a recording::field instance and add it to this context's list
765 of mementos.
767 Implements the post-error-checking part of
768 gcc_jit_context_new_field. */
770 recording::field *
771 recording::context::new_field (recording::location *loc,
772 recording::type *type,
773 const char *name)
775 recording::field *result =
776 new recording::field (this, loc, type, new_string (name));
777 record (result);
778 return result;
781 /* Create a recording::struct_ instance and add it to this context's
782 list of mementos and list of compound types.
784 Implements the post-error-checking part of
785 gcc_jit_context_new_struct_type. */
787 recording::struct_ *
788 recording::context::new_struct_type (recording::location *loc,
789 const char *name)
791 recording::struct_ *result = new struct_ (this, loc, new_string (name));
792 record (result);
793 m_compound_types.safe_push (result);
794 return result;
797 /* Create a recording::union_ instance and add it to this context's
798 list of mementos and list of compound types.
800 Implements the first post-error-checking part of
801 gcc_jit_context_new_union_type. */
803 recording::union_ *
804 recording::context::new_union_type (recording::location *loc,
805 const char *name)
807 recording::union_ *result = new union_ (this, loc, new_string (name));
808 record (result);
809 m_compound_types.safe_push (result);
810 return result;
813 /* Create a recording::function_type instance and add it to this context's
814 list of mementos.
816 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
818 recording::function_type *
819 recording::context::new_function_type (recording::type *return_type,
820 int num_params,
821 recording::type **param_types,
822 int is_variadic)
824 recording::function_type *fn_type
825 = new function_type (this,
826 return_type,
827 num_params,
828 param_types,
829 is_variadic);
830 record (fn_type);
831 return fn_type;
834 /* Create a recording::type instance and add it to this context's list
835 of mementos.
837 Implements the post-error-checking part of
838 gcc_jit_context_new_function_ptr_type. */
840 recording::type *
841 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
842 recording::type *return_type,
843 int num_params,
844 recording::type **param_types,
845 int is_variadic)
847 recording::function_type *fn_type
848 = new_function_type (return_type,
849 num_params,
850 param_types,
851 is_variadic);
853 /* Return a pointer-type to the function type. */
854 return fn_type->get_pointer ();
857 /* Create a recording::param instance and add it to this context's list
858 of mementos.
860 Implements the post-error-checking part of
861 gcc_jit_context_new_param. */
863 recording::param *
864 recording::context::new_param (recording::location *loc,
865 recording::type *type,
866 const char *name)
868 recording::param *result = new recording::param (this, loc, type, new_string (name));
869 record (result);
870 return result;
873 /* Create a recording::function instance and add it to this context's list
874 of mementos and list of functions.
876 Implements the post-error-checking part of
877 gcc_jit_context_new_function. */
879 recording::function *
880 recording::context::new_function (recording::location *loc,
881 enum gcc_jit_function_kind kind,
882 recording::type *return_type,
883 const char *name,
884 int num_params,
885 recording::param **params,
886 int is_variadic,
887 enum built_in_function builtin_id)
889 recording::function *result =
890 new recording::function (this,
891 loc, kind, return_type,
892 new_string (name),
893 num_params, params, is_variadic,
894 builtin_id);
895 record (result);
896 m_functions.safe_push (result);
898 return result;
901 /* Locate the builtins_manager (if any) for this family of contexts,
902 creating it if it doesn't exist already.
904 All of the recording contexts in a family share one builtins_manager:
905 if we have a child context, follow the parent links to get the
906 ultimate ancestor context, and look for it/store it there. */
908 builtins_manager *
909 recording::context::get_builtins_manager ()
911 if (m_parent_ctxt)
912 return m_parent_ctxt->get_builtins_manager ();
914 if (!m_builtins_manager)
915 m_builtins_manager = new builtins_manager (this);
917 return m_builtins_manager;
920 /* Get a recording::function instance, which is lazily-created and added
921 to the context's lists of mementos.
923 Implements the post-error-checking part of
924 gcc_jit_context_get_builtin_function. */
926 recording::function *
927 recording::context::get_builtin_function (const char *name)
929 builtins_manager *bm = get_builtins_manager ();
930 return bm->get_builtin_function (name);
933 /* Create a recording::global instance and add it to this context's list
934 of mementos.
936 Implements the post-error-checking part of
937 gcc_jit_context_new_global. */
939 recording::lvalue *
940 recording::context::new_global (recording::location *loc,
941 enum gcc_jit_global_kind kind,
942 recording::type *type,
943 const char *name)
945 recording::global *result =
946 new recording::global (this, loc, kind, type, new_string (name));
947 record (result);
948 m_globals.safe_push (result);
950 return result;
953 /* Create a recording::memento_of_new_string_literal instance and add it
954 to this context's list of mementos.
956 Implements the post-error-checking part of
957 gcc_jit_context_new_string_literal. */
959 recording::rvalue *
960 recording::context::new_string_literal (const char *value)
962 recording::rvalue *result =
963 new memento_of_new_string_literal (this, NULL, new_string (value));
964 record (result);
965 return result;
968 /* Create a recording::unary_op instance and add it to this context's
969 list of mementos.
971 Implements the post-error-checking part of
972 gcc_jit_context_new_unary_op. */
974 recording::rvalue *
975 recording::context::new_unary_op (recording::location *loc,
976 enum gcc_jit_unary_op op,
977 recording::type *result_type,
978 recording::rvalue *a)
980 recording::rvalue *result =
981 new unary_op (this, loc, op, result_type, a);
982 record (result);
983 return result;
986 /* Create a recording::binary_op instance and add it to this context's
987 list of mementos.
989 Implements the post-error-checking part of
990 gcc_jit_context_new_binary_op. */
992 recording::rvalue *
993 recording::context::new_binary_op (recording::location *loc,
994 enum gcc_jit_binary_op op,
995 recording::type *result_type,
996 recording::rvalue *a,
997 recording::rvalue *b)
999 recording::rvalue *result =
1000 new binary_op (this, loc, op, result_type, a, b);
1001 record (result);
1002 return result;
1005 /* Create a recording::comparison instance and add it to this context's
1006 list of mementos.
1008 Implements the post-error-checking part of
1009 gcc_jit_context_new_comparison. */
1011 recording::rvalue *
1012 recording::context::new_comparison (recording::location *loc,
1013 enum gcc_jit_comparison op,
1014 recording::rvalue *a,
1015 recording::rvalue *b)
1017 recording::rvalue *result = new comparison (this, loc, op, a, b);
1018 record (result);
1019 return result;
1022 /* Create a recording::cast instance and add it to this context's list
1023 of mementos.
1025 Implements the post-error-checking part of
1026 gcc_jit_context_new_cast. */
1028 recording::rvalue *
1029 recording::context::new_cast (recording::location *loc,
1030 recording::rvalue *expr,
1031 recording::type *type_)
1033 recording::rvalue *result = new cast (this, loc, expr, type_);
1034 record (result);
1035 return result;
1038 /* Create a recording::call instance and add it to this context's list
1039 of mementos.
1041 Implements the post-error-checking part of
1042 gcc_jit_context_new_call. */
1044 recording::rvalue *
1045 recording::context::new_call (recording::location *loc,
1046 function *func,
1047 int numargs , recording::rvalue **args)
1049 recording::rvalue *result = new call (this, loc, func, numargs, args);
1050 record (result);
1051 return result;
1054 /* Create a recording::call_through_ptr instance and add it to this
1055 context's list of mementos.
1057 Implements the post-error-checking part of
1058 gcc_jit_context_new_call_through_ptr. */
1060 recording::rvalue *
1061 recording::context::new_call_through_ptr (recording::location *loc,
1062 recording::rvalue *fn_ptr,
1063 int numargs,
1064 recording::rvalue **args)
1066 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
1067 record (result);
1068 return result;
1071 /* Create a recording::array_access instance and add it to this context's list
1072 of mementos.
1074 Implements the post-error-checking part of
1075 gcc_jit_context_new_array_access. */
1077 recording::lvalue *
1078 recording::context::new_array_access (recording::location *loc,
1079 recording::rvalue *ptr,
1080 recording::rvalue *index)
1082 recording::lvalue *result = new array_access (this, loc, ptr, index);
1083 record (result);
1084 return result;
1087 /* Create a recording::case_ instance and add it to this context's list
1088 of mementos.
1090 Implements the post-error-checking part of
1091 gcc_jit_context_new_case. */
1093 recording::case_ *
1094 recording::context::new_case (recording::rvalue *min_value,
1095 recording::rvalue *max_value,
1096 recording::block *block)
1098 recording::case_ *result = new case_ (this, min_value, max_value, block);
1099 record (result);
1100 return result;
1103 /* Set the given string option for this context, or add an error if
1104 it's not recognized.
1106 Implements the post-error-checking part of
1107 gcc_jit_context_set_str_option. */
1109 void
1110 recording::context::set_str_option (enum gcc_jit_str_option opt,
1111 const char *value)
1113 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
1115 add_error (NULL,
1116 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
1117 return;
1119 free (m_str_options[opt]);
1120 m_str_options[opt] = value ? xstrdup (value) : NULL;
1121 log_str_option (opt);
1124 /* Set the given integer option for this context, or add an error if
1125 it's not recognized.
1127 Implements the post-error-checking part of
1128 gcc_jit_context_set_int_option. */
1130 void
1131 recording::context::set_int_option (enum gcc_jit_int_option opt,
1132 int value)
1134 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
1136 add_error (NULL,
1137 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
1138 return;
1140 m_int_options[opt] = value;
1141 log_int_option (opt);
1144 /* Set the given boolean option for this context, or add an error if
1145 it's not recognized.
1147 Implements the post-error-checking part of
1148 gcc_jit_context_set_bool_option. */
1150 void
1151 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
1152 int value)
1154 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
1156 add_error (NULL,
1157 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
1158 return;
1160 m_bool_options[opt] = value ? true : false;
1161 log_bool_option (opt);
1164 void
1165 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt,
1166 int value)
1168 gcc_assert (inner_opt >= 0 && inner_opt < NUM_INNER_BOOL_OPTIONS);
1169 m_inner_bool_options[inner_opt] = value ? true : false;
1170 log_inner_bool_option (inner_opt);
1174 /* Add the given optname to this context's list of extra options.
1176 Implements the post-error-checking part of
1177 gcc_jit_context_add_command_line_option. */
1179 void
1180 recording::context::add_command_line_option (const char *optname)
1182 m_command_line_options.safe_push (xstrdup (optname));
1185 /* Add any user-provided extra options, starting with any from
1186 parent contexts.
1187 Called by playback::context::make_fake_args. */
1189 void
1190 recording::context::append_command_line_options (vec <char *> *argvec)
1192 if (m_parent_ctxt)
1193 m_parent_ctxt->append_command_line_options (argvec);
1195 int i;
1196 char *optname;
1197 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1198 argvec->safe_push (xstrdup (optname));
1201 /* Add the given dumpname/out_ptr pair to this context's list of requested
1202 dumps.
1204 Implements the post-error-checking part of
1205 gcc_jit_context_enable_dump. */
1207 void
1208 recording::context::enable_dump (const char *dumpname,
1209 char **out_ptr)
1211 requested_dump d;
1212 gcc_assert (dumpname);
1213 gcc_assert (out_ptr);
1215 d.m_dumpname = dumpname;
1216 d.m_out_ptr = out_ptr;
1217 *out_ptr = NULL;
1218 m_requested_dumps.safe_push (d);
1221 /* Validate this context, and if it passes, compile it to memory
1222 (within a mutex).
1224 Implements the post-error-checking part of
1225 gcc_jit_context_compile. */
1227 result *
1228 recording::context::compile ()
1230 JIT_LOG_SCOPE (get_logger ());
1232 log_all_options ();
1234 validate ();
1236 if (errors_occurred ())
1237 return NULL;
1239 /* Set up a compile_to_memory playback context. */
1240 ::gcc::jit::playback::compile_to_memory replayer (this);
1242 /* Use it. */
1243 replayer.compile ();
1245 /* Get the jit::result (or NULL) from the
1246 compile_to_memory playback context. */
1247 return replayer.get_result_obj ();
1250 /* Validate this context, and if it passes, compile it to a file
1251 (within a mutex).
1253 Implements the post-error-checking part of
1254 gcc_jit_context_compile_to_file. */
1256 void
1257 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
1258 const char *output_path)
1260 JIT_LOG_SCOPE (get_logger ());
1262 log_all_options ();
1264 validate ();
1266 if (errors_occurred ())
1267 return;
1269 /* Set up a compile_to_file playback context. */
1270 ::gcc::jit::playback::compile_to_file replayer (this,
1271 output_kind,
1272 output_path);
1274 /* Use it. */
1275 replayer.compile ();
1278 /* Format the given error using printf's conventions, print
1279 it to stderr, and add it to the context. */
1281 void
1282 recording::context::add_error (location *loc, const char *fmt, ...)
1284 va_list ap;
1285 va_start (ap, fmt);
1286 add_error_va (loc, fmt, ap);
1287 va_end (ap);
1290 /* Format the given error using printf's conventions, print
1291 it to stderr, and add it to the context. */
1293 void
1294 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
1296 int len;
1297 char *malloced_msg;
1298 const char *errmsg;
1299 bool has_ownership;
1301 JIT_LOG_SCOPE (get_logger ());
1303 len = vasprintf (&malloced_msg, fmt, ap);
1304 if (malloced_msg == NULL || len < 0)
1306 errmsg = "out of memory generating error message";
1307 has_ownership = false;
1309 else
1311 errmsg = malloced_msg;
1312 has_ownership = true;
1314 if (get_logger ())
1315 get_logger ()->log ("error %i: %s", m_error_count, errmsg);
1317 const char *ctxt_progname =
1318 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
1319 if (!ctxt_progname)
1320 ctxt_progname = "libgccjit.so";
1322 if (loc)
1323 fprintf (stderr, "%s: %s: error: %s\n",
1324 ctxt_progname,
1325 loc->get_debug_string (),
1326 errmsg);
1327 else
1328 fprintf (stderr, "%s: error: %s\n",
1329 ctxt_progname,
1330 errmsg);
1332 if (!m_error_count)
1334 m_first_error_str = const_cast <char *> (errmsg);
1335 m_owns_first_error_str = has_ownership;
1338 if (m_owns_last_error_str)
1339 if (m_last_error_str != m_first_error_str)
1340 free (m_last_error_str);
1341 m_last_error_str = const_cast <char *> (errmsg);
1342 m_owns_last_error_str = has_ownership;
1344 m_error_count++;
1347 /* Get the message for the first error that occurred on this context, or
1348 NULL if no errors have occurred on it.
1350 Implements the post-error-checking part of
1351 gcc_jit_context_get_first_error. */
1353 const char *
1354 recording::context::get_first_error () const
1356 return m_first_error_str;
1359 /* Get the message for the last error that occurred on this context, or
1360 NULL if no errors have occurred on it.
1362 Implements the post-error-checking part of
1363 gcc_jit_context_get_last_error. */
1365 const char *
1366 recording::context::get_last_error () const
1368 return m_last_error_str;
1371 /* Lazily generate and record a recording::type representing an opaque
1372 struct named "FILE".
1374 For use if client code tries to dereference the result of
1375 get_type (GCC_JIT_TYPE_FILE_PTR). */
1377 recording::type *
1378 recording::context::get_opaque_FILE_type ()
1380 if (!m_FILE_type)
1381 m_FILE_type = new_struct_type (NULL, "FILE");
1382 return m_FILE_type;
1385 /* Dump a C-like representation of the given context to the given path.
1386 If UPDATE_LOCATIONS is true, update the locations within the
1387 context's mementos to point to the dumpfile.
1389 Implements the post-error-checking part of
1390 gcc_jit_context_dump_to_file. */
1392 void
1393 recording::context::dump_to_file (const char *path, bool update_locations)
1395 int i;
1396 dump d (*this, path, update_locations);
1398 /* Forward declaration of structs and unions. */
1399 compound_type *st;
1400 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1402 d.write ("%s;\n\n", st->get_debug_string ());
1405 /* Content of structs, where set. */
1406 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1407 if (st->get_fields ())
1409 st->get_fields ()->write_to_dump (d);
1410 d.write ("\n");
1413 /* Globals. */
1414 global *g;
1415 FOR_EACH_VEC_ELT (m_globals, i, g)
1417 g->write_to_dump (d);
1419 if (!m_globals.is_empty ())
1420 d.write ("\n");
1422 function *fn;
1423 FOR_EACH_VEC_ELT (m_functions, i, fn)
1425 fn->write_to_dump (d);
1429 static const char * const
1430 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
1431 "GCC_JIT_STR_OPTION_PROGNAME"
1434 static const char * const
1435 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
1436 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1439 static const char * const
1440 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
1441 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1442 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1443 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1444 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1445 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1446 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1447 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1448 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1451 static const char * const
1452 inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = {
1453 "gcc_jit_context_set_bool_allow_unreachable_blocks"
1456 /* Write the current value of all options to the log file (if any). */
1458 void
1459 recording::context::log_all_options () const
1461 int opt_idx;
1463 if (!get_logger ())
1464 return;
1466 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1467 log_str_option ((enum gcc_jit_str_option)opt_idx);
1469 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1470 log_int_option ((enum gcc_jit_int_option)opt_idx);
1472 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1473 log_bool_option ((enum gcc_jit_bool_option)opt_idx);
1474 for (opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1475 log_inner_bool_option ((enum inner_bool_option)opt_idx);
1478 /* Write the current value of the given string option to the
1479 log file (if any). */
1481 void
1482 recording::context::log_str_option (enum gcc_jit_str_option opt) const
1484 gcc_assert (opt < GCC_JIT_NUM_STR_OPTIONS);
1485 if (get_logger ())
1487 if (m_str_options[opt])
1488 log ("%s: \"%s\"",
1489 str_option_reproducer_strings[opt],
1490 m_str_options[opt]);
1491 else
1492 log ("%s: NULL",
1493 str_option_reproducer_strings[opt]);
1497 /* Write the current value of the given int option to the
1498 log file (if any). */
1500 void
1501 recording::context::log_int_option (enum gcc_jit_int_option opt) const
1503 gcc_assert (opt < GCC_JIT_NUM_INT_OPTIONS);
1504 if (get_logger ())
1505 log ("%s: %i",
1506 int_option_reproducer_strings[opt],
1507 m_int_options[opt]);
1510 /* Write the current value of the given bool option to the
1511 log file (if any). */
1513 void
1514 recording::context::log_bool_option (enum gcc_jit_bool_option opt) const
1516 gcc_assert (opt < GCC_JIT_NUM_BOOL_OPTIONS);
1517 if (get_logger ())
1518 log ("%s: %s",
1519 bool_option_reproducer_strings[opt],
1520 m_bool_options[opt] ? "true" : "false");
1523 /* Write the current value of the given "inner" bool option to the
1524 log file (if any). */
1526 void
1527 recording::context::log_inner_bool_option (enum inner_bool_option opt) const
1529 gcc_assert (opt < NUM_INNER_BOOL_OPTIONS);
1530 if (get_logger ())
1531 log ("%s: %s",
1532 inner_bool_option_reproducer_strings[opt],
1533 m_inner_bool_options[opt] ? "true" : "false");
1536 /* Write C source code to PATH that attempts to replay the API
1537 calls made to this context (and its parents), for use in
1538 minimizing test cases for libgccjit.
1540 Implements the post-error-checking part of
1541 gcc_jit_context_dump_reproducer_to_file. */
1543 void
1544 recording::context::dump_reproducer_to_file (const char *path)
1546 JIT_LOG_SCOPE (get_logger ());
1547 reproducer r (*this, path);
1549 /* Generate the "ancestry" of this context, as a list. */
1550 auto_vec <context *> ascending_contexts;
1551 for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
1552 ascending_contexts.safe_push (ctxt);
1554 /* Reverse the list, giving a list of contexts from
1555 top-most parent context down through to youngest child context.
1556 We will use this list as the parameters of the functions in
1557 our generated file. */
1558 unsigned num_ctxts = ascending_contexts.length ();
1559 auto_vec <context *> contexts (num_ctxts);
1560 for (unsigned i = 0; i < num_ctxts; i++)
1561 contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
1563 /* contexts[0] should be the top-level context. */
1564 gcc_assert (contexts[0]);
1565 gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
1567 /* The final element in contexts should be "this". */
1568 gcc_assert (contexts[contexts.length () - 1] == this);
1569 gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
1570 == contexts[0]);
1572 r.write ("/* This code was autogenerated by"
1573 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1574 print_version (r.get_file (), " ", false);
1575 r.write ("*/\n");
1576 r.write ("#include <libgccjit.h>\n\n");
1577 r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1578 r.write ("static void\nset_options (");
1579 r.write_params (contexts);
1580 r.write (");\n\n");
1581 r.write ("static void\ncreate_code (");
1582 r.write_params (contexts);
1583 r.write (");\n\n");
1584 r.write ("int\nmain (int argc, const char **argv)\n");
1585 r.write ("{\n");
1586 for (unsigned i = 0; i < num_ctxts; i++)
1587 r.write (" gcc_jit_context *%s;\n",
1588 r.get_identifier (contexts[i]));
1589 r.write (" gcc_jit_result *result;\n"
1590 "\n");
1592 /* Create the contexts.
1593 The top-level context is acquired from a clean slate, the others as
1594 children of the prior context. */
1595 r.write (" %s = gcc_jit_context_acquire ();\n",
1596 r.get_identifier (contexts[0]));
1597 for (unsigned i = 1; i < num_ctxts; i++)
1598 r.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1599 r.get_identifier (contexts[i]),
1600 r.get_identifier (contexts[i - 1]));
1601 r.write (" set_options (");
1602 r.write_args (contexts);
1603 r.write (");\n");
1604 r.write (" create_code (");
1605 r.write_args (contexts);
1606 r.write (");\n");
1608 r.write (" result = gcc_jit_context_compile (%s);\n",
1609 r.get_identifier (this));
1611 for (unsigned i = num_ctxts; i > 0; i--)
1612 r.write (" gcc_jit_context_release (%s);\n",
1613 r.get_identifier (contexts[i - 1]));
1615 r.write (" gcc_jit_result_release (result);\n"
1616 " return 0;\n"
1617 "}\n\n");
1619 /* Define (char *) variables for use in calls to
1620 gcc_jit_context_enable_dump. */
1621 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1623 if (m_requested_dumps.length ())
1625 r.write ("/* Requested dumps for %s. */\n",
1626 r.get_identifier (contexts[ctxt_idx]));
1627 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1628 r.write ("static char *dump_%p;\n",
1629 (void *)&m_requested_dumps[i]);
1630 r.write ("\n");
1634 /* Write out values of options. */
1635 r.write ("static void\nset_options (");
1636 r.write_params (contexts);
1637 r.write (")\n{\n");
1638 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1640 if (ctxt_idx > 0)
1641 r.write ("\n");
1643 r.write (" /* Set options for %s. */\n",
1644 r.get_identifier (contexts[ctxt_idx]));
1646 r.write (" /* String options. */\n");
1647 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1649 r.write (" gcc_jit_context_set_str_option (%s,\n"
1650 " %s,\n",
1651 r.get_identifier (contexts[ctxt_idx]),
1652 str_option_reproducer_strings[opt_idx]);
1653 if (m_str_options[opt_idx])
1654 r.write (" \"%s\");\n",
1655 m_str_options[opt_idx]);
1656 else
1657 r.write (" NULL);\n");
1659 r.write (" /* Int options. */\n");
1660 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1661 r.write (" gcc_jit_context_set_int_option (%s,\n"
1662 " %s,\n"
1663 " %i);\n",
1664 r.get_identifier (contexts[ctxt_idx]),
1665 int_option_reproducer_strings[opt_idx],
1666 m_int_options[opt_idx]);
1667 r.write (" /* Boolean options. */\n");
1668 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1669 r.write (" gcc_jit_context_set_bool_option (%s,\n"
1670 " %s,\n"
1671 " %i);\n",
1672 r.get_identifier (contexts[ctxt_idx]),
1673 bool_option_reproducer_strings[opt_idx],
1674 m_bool_options[opt_idx]);
1675 for (int opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1676 r.write (" %s (%s, %i);\n",
1677 inner_bool_option_reproducer_strings[opt_idx],
1678 r.get_identifier (contexts[ctxt_idx]),
1679 m_inner_bool_options[opt_idx]);
1681 if (!m_command_line_options.is_empty ())
1683 int i;
1684 char *optname;
1685 r.write (" /* User-provided command-line options. */\n");
1686 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1687 r.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1688 r.get_identifier (contexts[ctxt_idx]),
1689 optname);
1692 if (m_requested_dumps.length ())
1694 r.write (" /* Requested dumps. */\n");
1695 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1696 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1698 r.write (" gcc_jit_context_enable_dump (%s,\n"
1699 " \"%s\",\n"
1700 " &dump_%p);\n",
1701 r.get_identifier (contexts[ctxt_idx]),
1702 m_requested_dumps[i].m_dumpname,
1703 (void *)&m_requested_dumps[i]);
1707 r.write ("}\n\n");
1709 r.write ("static void\ncreate_code (");
1710 r.write_params (contexts);
1711 r.write (")\n"
1712 "{\n");
1713 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1715 memento *m;
1716 int i;
1717 if (ctxt_idx > 0)
1718 r.write ("\n\n");
1720 r.write (" /* Replay of API calls for %s. */\n",
1721 r.get_identifier (contexts[ctxt_idx]));
1722 FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
1723 m->write_reproducer (r);
1725 r.write ("}\n");
1728 /* Copy the requested dumps within this context and all ancestors into
1729 OUT. */
1731 void
1732 recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
1734 if (m_parent_ctxt)
1735 m_parent_ctxt->get_all_requested_dumps (out);
1737 out->reserve (m_requested_dumps.length ());
1738 out->splice (m_requested_dumps);
1741 /* This is a pre-compilation check for the context (and any parents).
1743 Detect errors within the context, adding errors if any are found. */
1745 void
1746 recording::context::validate ()
1748 JIT_LOG_SCOPE (get_logger ());
1750 if (m_parent_ctxt)
1751 m_parent_ctxt->validate ();
1753 int i;
1754 function *fn;
1755 FOR_EACH_VEC_ELT (m_functions, i, fn)
1756 fn->validate ();
1759 /* The implementation of class gcc::jit::recording::memento. */
1761 /* Get a (const char *) debug description of the given memento, by
1762 calling the pure-virtual make_debug_string hook, caching the
1763 result.
1765 It is intended that this should only be called in debugging and
1766 error-handling paths, so this doesn't need to be particularly
1767 optimized. */
1769 const char *
1770 recording::memento::get_debug_string ()
1772 if (!m_debug_string)
1773 m_debug_string = make_debug_string ();
1774 return m_debug_string->c_str ();
1777 /* Default implementation of recording::memento::write_to_dump, writing
1778 an indented form of the memento's debug string to the dump. */
1780 void
1781 recording::memento::write_to_dump (dump &d)
1783 d.write(" %s\n", get_debug_string ());
1786 /* The implementation of class gcc::jit::recording::string. */
1788 /* Constructor for gcc::jit::recording::string::string, allocating a
1789 copy of the given text using new char[]. */
1791 recording::string::string (context *ctxt, const char *text)
1792 : memento (ctxt)
1794 m_len = strlen (text);
1795 m_buffer = new char[m_len + 1];
1796 strcpy (m_buffer, text);
1799 /* Destructor for gcc::jit::recording::string::string. */
1801 recording::string::~string ()
1803 delete[] m_buffer;
1806 /* Function for making gcc::jit::recording::string instances on a
1807 context via printf-style formatting.
1809 It is intended that this should only be called in debugging and
1810 error-handling paths, so this doesn't need to be particularly
1811 optimized, hence the double-copy of the string is acceptable. */
1813 recording::string *
1814 recording::string::from_printf (context *ctxt, const char *fmt, ...)
1816 int len;
1817 va_list ap;
1818 char *buf;
1819 recording::string *result;
1821 va_start (ap, fmt);
1822 len = vasprintf (&buf, fmt, ap);
1823 va_end (ap);
1825 if (buf == NULL || len < 0)
1827 ctxt->add_error (NULL, "malloc failure");
1828 return NULL;
1831 result = ctxt->new_string (buf);
1832 free (buf);
1833 return result;
1836 /* Implementation of recording::memento::make_debug_string for strings,
1837 wrapping the given string in quotes and escaping as necessary. */
1839 recording::string *
1840 recording::string::make_debug_string ()
1842 /* Hack to avoid infinite recursion into strings when logging all
1843 mementos: don't re-escape strings: */
1844 if (m_buffer[0] == '"')
1845 return this;
1847 /* Wrap in quotes and do escaping etc */
1849 size_t sz = (1 /* opening quote */
1850 + (m_len * 2) /* each char might get escaped */
1851 + 1 /* closing quote */
1852 + 1); /* nil termintator */
1853 char *tmp = new char[sz];
1854 size_t len = 0;
1856 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1857 APPEND('"'); /* opening quote */
1858 for (size_t i = 0; i < m_len ; i++)
1860 char ch = m_buffer[i];
1861 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
1862 APPEND('\\');
1863 APPEND(ch);
1865 APPEND('"'); /* closing quote */
1866 #undef APPEND
1867 tmp[len] = '\0'; /* nil termintator */
1869 string *result = m_ctxt->new_string (tmp);
1871 delete[] tmp;
1872 return result;
1875 /* Implementation of recording::memento::write_reproducer for strings. */
1877 void
1878 recording::string::write_reproducer (reproducer &)
1880 /* Empty. */
1883 /* The implementation of class gcc::jit::recording::location. */
1885 /* Implementation of recording::memento::replay_into for locations.
1887 Create a new playback::location and store it into the
1888 recording::location's m_playback_obj field. */
1890 void
1891 recording::location::replay_into (replayer *r)
1893 m_playback_obj = r->new_location (this,
1894 m_filename->c_str (),
1895 m_line,
1896 m_column);
1899 /* Implementation of recording::memento::make_debug_string for locations,
1900 turning them into the usual form:
1901 FILENAME:LINE:COLUMN
1902 like we do when emitting diagnostics. */
1904 recording::string *
1905 recording::location::make_debug_string ()
1907 return string::from_printf (m_ctxt,
1908 "%s:%i:%i",
1909 m_filename->c_str (), m_line, m_column);
1912 /* Implementation of recording::memento::write_reproducer for locations. */
1914 void
1915 recording::location::write_reproducer (reproducer &r)
1917 const char *id = r.make_identifier (this, "loc");
1918 r.write (" gcc_jit_location *%s =\n"
1919 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1920 " %s, /* const char *filename */\n"
1921 " %i, /* int line */\n"
1922 " %i);/* int column */\n",
1924 r.get_identifier (get_context ()),
1925 m_filename->get_debug_string (),
1926 m_line, m_column);
1929 /* The implementation of class gcc::jit::recording::type. */
1931 /* Given a type T, get the type T*.
1933 If this doesn't already exist, generate a new memento_of_get_pointer
1934 instance and add it to this type's context's list of mementos.
1936 Otherwise, use the cached type.
1938 Implements the post-error-checking part of
1939 gcc_jit_type_get_pointer. */
1941 recording::type *
1942 recording::type::get_pointer ()
1944 if (!m_pointer_to_this_type)
1946 m_pointer_to_this_type = new memento_of_get_pointer (this);
1947 m_ctxt->record (m_pointer_to_this_type);
1949 return m_pointer_to_this_type;
1952 /* Given a type T, get the type const T.
1954 Implements the post-error-checking part of
1955 gcc_jit_type_get_const. */
1957 recording::type *
1958 recording::type::get_const ()
1960 recording::type *result = new memento_of_get_const (this);
1961 m_ctxt->record (result);
1962 return result;
1965 /* Given a type T, get the type volatile T.
1967 Implements the post-error-checking part of
1968 gcc_jit_type_get_volatile. */
1970 recording::type *
1971 recording::type::get_volatile ()
1973 recording::type *result = new memento_of_get_volatile (this);
1974 m_ctxt->record (result);
1975 return result;
1978 const char *
1979 recording::type::access_as_type (reproducer &r)
1981 return r.get_identifier (this);
1984 /* Implementation of pure virtual hook recording::type::dereference for
1985 recording::memento_of_get_type. */
1987 recording::type *
1988 recording::memento_of_get_type::dereference ()
1990 switch (m_kind)
1992 default: gcc_unreachable ();
1994 case GCC_JIT_TYPE_VOID:
1995 return NULL;
1997 case GCC_JIT_TYPE_VOID_PTR:
1998 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
2000 case GCC_JIT_TYPE_BOOL:
2001 case GCC_JIT_TYPE_CHAR:
2002 case GCC_JIT_TYPE_SIGNED_CHAR:
2003 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2004 case GCC_JIT_TYPE_SHORT:
2005 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2006 case GCC_JIT_TYPE_INT:
2007 case GCC_JIT_TYPE_UNSIGNED_INT:
2008 case GCC_JIT_TYPE_LONG:
2009 case GCC_JIT_TYPE_UNSIGNED_LONG:
2010 case GCC_JIT_TYPE_LONG_LONG:
2011 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2012 case GCC_JIT_TYPE_FLOAT:
2013 case GCC_JIT_TYPE_DOUBLE:
2014 case GCC_JIT_TYPE_LONG_DOUBLE:
2015 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2016 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2017 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2018 /* Not a pointer: */
2019 return NULL;
2021 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2022 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
2024 case GCC_JIT_TYPE_SIZE_T:
2025 /* Not a pointer: */
2026 return NULL;
2028 case GCC_JIT_TYPE_FILE_PTR:
2029 /* Give the client code back an opaque "struct FILE". */
2030 return m_ctxt->get_opaque_FILE_type ();
2034 /* Implementation of pure virtual hook recording::type::is_int for
2035 recording::memento_of_get_type. */
2037 bool
2038 recording::memento_of_get_type::is_int () const
2040 switch (m_kind)
2042 default: gcc_unreachable ();
2044 case GCC_JIT_TYPE_VOID:
2045 return false;
2047 case GCC_JIT_TYPE_VOID_PTR:
2048 return false;
2050 case GCC_JIT_TYPE_BOOL:
2051 return false;
2053 case GCC_JIT_TYPE_CHAR:
2054 case GCC_JIT_TYPE_SIGNED_CHAR:
2055 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2056 case GCC_JIT_TYPE_SHORT:
2057 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2058 case GCC_JIT_TYPE_INT:
2059 case GCC_JIT_TYPE_UNSIGNED_INT:
2060 case GCC_JIT_TYPE_LONG:
2061 case GCC_JIT_TYPE_UNSIGNED_LONG:
2062 case GCC_JIT_TYPE_LONG_LONG:
2063 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2064 return true;
2066 case GCC_JIT_TYPE_FLOAT:
2067 case GCC_JIT_TYPE_DOUBLE:
2068 case GCC_JIT_TYPE_LONG_DOUBLE:
2069 return false;
2071 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2072 return false;
2074 case GCC_JIT_TYPE_SIZE_T:
2075 return true;
2077 case GCC_JIT_TYPE_FILE_PTR:
2078 return false;
2080 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2081 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2082 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2083 return false;
2087 /* Implementation of pure virtual hook recording::type::is_float for
2088 recording::memento_of_get_type. */
2090 bool
2091 recording::memento_of_get_type::is_float () const
2093 switch (m_kind)
2095 default: gcc_unreachable ();
2097 case GCC_JIT_TYPE_VOID:
2098 return false;
2100 case GCC_JIT_TYPE_VOID_PTR:
2101 return false;
2103 case GCC_JIT_TYPE_BOOL:
2104 return false;
2106 case GCC_JIT_TYPE_CHAR:
2107 case GCC_JIT_TYPE_SIGNED_CHAR:
2108 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2109 case GCC_JIT_TYPE_SHORT:
2110 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2111 case GCC_JIT_TYPE_INT:
2112 case GCC_JIT_TYPE_UNSIGNED_INT:
2113 case GCC_JIT_TYPE_LONG:
2114 case GCC_JIT_TYPE_UNSIGNED_LONG:
2115 case GCC_JIT_TYPE_LONG_LONG:
2116 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2117 return false;
2119 case GCC_JIT_TYPE_FLOAT:
2120 case GCC_JIT_TYPE_DOUBLE:
2121 case GCC_JIT_TYPE_LONG_DOUBLE:
2122 return true;
2124 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2125 return false;
2127 case GCC_JIT_TYPE_SIZE_T:
2128 return false;
2130 case GCC_JIT_TYPE_FILE_PTR:
2131 return false;
2133 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2134 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2135 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2136 return true;
2140 /* Implementation of pure virtual hook recording::type::is_bool for
2141 recording::memento_of_get_type. */
2143 bool
2144 recording::memento_of_get_type::is_bool () const
2146 switch (m_kind)
2148 default: gcc_unreachable ();
2150 case GCC_JIT_TYPE_VOID:
2151 return false;
2153 case GCC_JIT_TYPE_VOID_PTR:
2154 return false;
2156 case GCC_JIT_TYPE_BOOL:
2157 return true;
2159 case GCC_JIT_TYPE_CHAR:
2160 case GCC_JIT_TYPE_SIGNED_CHAR:
2161 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2162 case GCC_JIT_TYPE_SHORT:
2163 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2164 case GCC_JIT_TYPE_INT:
2165 case GCC_JIT_TYPE_UNSIGNED_INT:
2166 case GCC_JIT_TYPE_LONG:
2167 case GCC_JIT_TYPE_UNSIGNED_LONG:
2168 case GCC_JIT_TYPE_LONG_LONG:
2169 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2170 return false;
2172 case GCC_JIT_TYPE_FLOAT:
2173 case GCC_JIT_TYPE_DOUBLE:
2174 case GCC_JIT_TYPE_LONG_DOUBLE:
2175 return false;
2177 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2178 return false;
2180 case GCC_JIT_TYPE_SIZE_T:
2181 return false;
2183 case GCC_JIT_TYPE_FILE_PTR:
2184 return false;
2186 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2187 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2188 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2189 return false;
2193 /* Implementation of pure virtual hook recording::memento::replay_into
2194 for recording::memento_of_get_type. */
2196 void
2197 recording::memento_of_get_type::replay_into (replayer *r)
2199 set_playback_obj (r->get_type (m_kind));
2202 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2204 /* Descriptive strings for each of enum gcc_jit_types. */
2206 static const char * const get_type_strings[] = {
2207 "void", /* GCC_JIT_TYPE_VOID */
2208 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2210 "bool", /* GCC_JIT_TYPE_BOOL */
2212 "char", /* GCC_JIT_TYPE_CHAR */
2213 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2214 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2216 "short", /* GCC_JIT_TYPE_SHORT */
2217 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2219 "int", /* GCC_JIT_TYPE_INT */
2220 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2222 "long", /* GCC_JIT_TYPE_LONG */
2223 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2225 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2226 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2228 "float", /* GCC_JIT_TYPE_FLOAT */
2229 "double", /* GCC_JIT_TYPE_DOUBLE */
2230 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2232 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2234 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2236 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2238 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2239 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2240 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2244 /* Implementation of recording::memento::make_debug_string for
2245 results of get_type, using a simple table of type names. */
2247 recording::string *
2248 recording::memento_of_get_type::make_debug_string ()
2250 return m_ctxt->new_string (get_type_strings[m_kind]);
2253 static const char * const get_type_enum_strings[] = {
2254 "GCC_JIT_TYPE_VOID",
2255 "GCC_JIT_TYPE_VOID_PTR",
2256 "GCC_JIT_TYPE_BOOL",
2257 "GCC_JIT_TYPE_CHAR",
2258 "GCC_JIT_TYPE_SIGNED_CHAR",
2259 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2260 "GCC_JIT_TYPE_SHORT",
2261 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2262 "GCC_JIT_TYPE_INT",
2263 "GCC_JIT_TYPE_UNSIGNED_INT",
2264 "GCC_JIT_TYPE_LONG",
2265 "GCC_JIT_TYPE_UNSIGNED_LONG",
2266 "GCC_JIT_TYPE_LONG_LONG",
2267 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2268 "GCC_JIT_TYPE_FLOAT",
2269 "GCC_JIT_TYPE_DOUBLE",
2270 "GCC_JIT_TYPE_LONG_DOUBLE",
2271 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2272 "GCC_JIT_TYPE_SIZE_T",
2273 "GCC_JIT_TYPE_FILE_PTR",
2274 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2275 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2276 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2279 void
2280 recording::memento_of_get_type::write_reproducer (reproducer &r)
2282 const char *id = r.make_identifier (this, "type");
2283 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2285 r.get_identifier (get_context ()),
2286 get_type_enum_strings[m_kind]);
2289 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2291 /* Override of default implementation of
2292 recording::type::accepts_writes_from for get_pointer.
2294 Require a pointer type, and allowing writes to
2295 (const T *) from a (T*), but not the other way around. */
2297 bool
2298 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2300 /* Must be a pointer type: */
2301 type *rtype_points_to = rtype->is_pointer ();
2302 if (!rtype_points_to)
2303 return false;
2305 /* It's OK to assign to a (const T *) from a (T *). */
2306 return m_other_type->unqualified ()
2307 ->accepts_writes_from (rtype_points_to);
2310 /* Implementation of pure virtual hook recording::memento::replay_into
2311 for recording::memento_of_get_pointer. */
2313 void
2314 recording::memento_of_get_pointer::replay_into (replayer *)
2316 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2319 /* Implementation of recording::memento::make_debug_string for
2320 results of get_pointer, adding " *" to the underlying type,
2321 with special-casing to handle function pointer types. */
2323 recording::string *
2324 recording::memento_of_get_pointer::make_debug_string ()
2326 /* Special-case function pointer types, to put the "*" in parens between
2327 the return type and the params (for one level of dereferencing, at
2328 least). */
2329 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2330 return fn_type->make_debug_string_with_ptr ();
2332 return string::from_printf (m_ctxt,
2333 "%s *", m_other_type->get_debug_string ());
2336 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2338 void
2339 recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2341 /* We need to special-case function pointer types; see the notes in
2342 recording::function_type::write_deferred_reproducer. */
2343 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2345 fn_type->write_deferred_reproducer (r, this);
2346 return;
2349 const char *id = r.make_identifier (this, "type");
2350 r.write (" gcc_jit_type *%s =\n"
2351 " gcc_jit_type_get_pointer (%s);\n",
2353 r.get_identifier_as_type (m_other_type));
2356 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2358 /* Implementation of pure virtual hook recording::memento::replay_into
2359 for recording::memento_of_get_const. */
2361 void
2362 recording::memento_of_get_const::replay_into (replayer *)
2364 set_playback_obj (m_other_type->playback_type ()->get_const ());
2367 /* Implementation of recording::memento::make_debug_string for
2368 results of get_const, prepending "const ". */
2370 recording::string *
2371 recording::memento_of_get_const::make_debug_string ()
2373 return string::from_printf (m_ctxt,
2374 "const %s", m_other_type->get_debug_string ());
2377 /* Implementation of recording::memento::write_reproducer for const types. */
2379 void
2380 recording::memento_of_get_const::write_reproducer (reproducer &r)
2382 const char *id = r.make_identifier (this, "type");
2383 r.write (" gcc_jit_type *%s =\n"
2384 " gcc_jit_type_get_const (%s);\n",
2386 r.get_identifier_as_type (m_other_type));
2389 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2391 /* Implementation of pure virtual hook recording::memento::replay_into
2392 for recording::memento_of_get_volatile. */
2394 void
2395 recording::memento_of_get_volatile::replay_into (replayer *)
2397 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2400 /* Implementation of recording::memento::make_debug_string for
2401 results of get_volatile, prepending "volatile ". */
2403 recording::string *
2404 recording::memento_of_get_volatile::make_debug_string ()
2406 return string::from_printf (m_ctxt,
2407 "volatile %s", m_other_type->get_debug_string ());
2410 /* Implementation of recording::memento::write_reproducer for volatile
2411 types. */
2413 void
2414 recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2416 const char *id = r.make_identifier (this, "type");
2417 r.write (" gcc_jit_type *%s =\n"
2418 " gcc_jit_type_get_volatile (%s);\n",
2420 r.get_identifier_as_type (m_other_type));
2423 /* The implementation of class gcc::jit::recording::array_type */
2425 /* Implementation of pure virtual hook recording::type::dereference for
2426 recording::array_type. */
2428 recording::type *
2429 recording::array_type::dereference ()
2431 return m_element_type;
2434 /* Implementation of pure virtual hook recording::memento::replay_into
2435 for recording::array_type. */
2437 void
2438 recording::array_type::replay_into (replayer *r)
2440 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
2441 m_element_type->playback_type (),
2442 m_num_elements));
2445 /* Implementation of recording::memento::make_debug_string for
2446 results of new_array_type. */
2448 recording::string *
2449 recording::array_type::make_debug_string ()
2451 return string::from_printf (m_ctxt,
2452 "%s[%d]",
2453 m_element_type->get_debug_string (),
2454 m_num_elements);
2457 /* Implementation of recording::memento::write_reproducer for array
2458 types. */
2460 void
2461 recording::array_type::write_reproducer (reproducer &r)
2463 const char *id = r.make_identifier (this, "array_type");
2464 r.write (" gcc_jit_type *%s =\n"
2465 " gcc_jit_context_new_array_type (%s,\n"
2466 " %s, /* gcc_jit_location *loc */\n"
2467 " %s, /* gcc_jit_type *element_type */\n"
2468 " %i); /* int num_elements */\n",
2470 r.get_identifier (get_context ()),
2471 r.get_identifier (m_loc),
2472 r.get_identifier_as_type (m_element_type),
2473 m_num_elements);
2476 /* The implementation of class gcc::jit::recording::function_type */
2478 /* Constructor for gcc::jit::recording::function_type. */
2480 recording::function_type::function_type (context *ctxt,
2481 type *return_type,
2482 int num_params,
2483 type **param_types,
2484 int is_variadic)
2485 : type (ctxt),
2486 m_return_type (return_type),
2487 m_param_types (),
2488 m_is_variadic (is_variadic)
2490 for (int i = 0; i< num_params; i++)
2491 m_param_types.safe_push (param_types[i]);
2494 /* Implementation of pure virtual hook recording::type::dereference for
2495 recording::function_type. */
2497 recording::type *
2498 recording::function_type::dereference ()
2500 return NULL;
2503 /* Implementation of pure virtual hook recording::memento::replay_into
2504 for recording::function_type. */
2506 void
2507 recording::function_type::replay_into (replayer *r)
2509 /* Convert m_param_types to a vec of playback type. */
2510 auto_vec <playback::type *> param_types;
2511 int i;
2512 recording::type *type;
2513 param_types.create (m_param_types.length ());
2514 FOR_EACH_VEC_ELT (m_param_types, i, type)
2515 param_types.safe_push (type->playback_type ());
2517 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
2518 &param_types,
2519 m_is_variadic));
2522 /* Special-casing for make_debug_string for get_pointer results for
2523 handling (one level) of pointers to functions. */
2525 recording::string *
2526 recording::function_type::make_debug_string_with_ptr ()
2528 return make_debug_string_with ("(*) ");
2531 /* Implementation of recording::memento::make_debug_string for
2532 results of new_function_type. */
2534 recording::string *
2535 recording::function_type::make_debug_string ()
2537 return make_debug_string_with ("");
2540 /* Build a debug string representation of the form:
2542 RESULT_TYPE INSERT (PARAM_TYPES)
2544 for use when handling 0 and 1 level of indirection to this
2545 function type. */
2547 recording::string *
2548 recording::function_type::make_debug_string_with (const char *insert)
2550 /* First, build a buffer for the arguments. */
2551 /* Calculate length of said buffer. */
2552 size_t sz = 1; /* nil terminator */
2553 for (unsigned i = 0; i< m_param_types.length (); i++)
2555 sz += strlen (m_param_types[i]->get_debug_string ());
2556 sz += 2; /* ", " separator */
2558 if (m_is_variadic)
2559 sz += 5; /* ", ..." separator and ellipsis */
2561 /* Now allocate and populate the buffer. */
2562 char *argbuf = new char[sz];
2563 size_t len = 0;
2565 for (unsigned i = 0; i< m_param_types.length (); i++)
2567 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
2568 len += strlen (m_param_types[i]->get_debug_string ());
2569 if (i + 1 < m_param_types.length ())
2571 strcpy (argbuf + len, ", ");
2572 len += 2;
2575 if (m_is_variadic)
2577 if (m_param_types.length ())
2579 strcpy (argbuf + len, ", ");
2580 len += 2;
2582 strcpy (argbuf + len, "...");
2583 len += 3;
2585 argbuf[len] = '\0';
2587 /* ...and use it to get the string for the call as a whole. */
2588 string *result = string::from_printf (m_ctxt,
2589 "%s %s(%s)",
2590 m_return_type->get_debug_string (),
2591 insert,
2592 argbuf);
2594 delete[] argbuf;
2596 return result;
2599 /* Implementation of recording::memento::write_reproducer for function
2600 types. */
2602 void
2603 recording::function_type::write_reproducer (reproducer &)
2605 /* see notes below. */
2608 /* There's a get_pointer within context::new_function_ptr_type:
2609 the type received by client code isn't the memento for the
2610 function_type, but instead the result of get_pointer on it.
2612 Hence we can't directly write a reproducer that gives function_type.
2613 Instead we special-case things within get_pointer, detecting this
2614 case, calling the following function. */
2616 void
2617 recording::function_type::write_deferred_reproducer (reproducer &r,
2618 memento *ptr_type)
2620 gcc_assert (ptr_type);
2621 r.make_identifier (this, "function_type");
2622 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
2623 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
2624 r.write (" gcc_jit_type *%s[%i] = {\n",
2625 param_types_id,
2626 m_param_types.length ());
2627 int i;
2628 type *param_type;
2629 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2630 r.write (" %s,\n", r.get_identifier_as_type (param_type));
2631 r.write (" };\n");
2632 r.write (" gcc_jit_type *%s =\n"
2633 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2634 " %s, /* gcc_jit_location *loc */\n"
2635 " %s, /* gcc_jit_type *return_type */\n"
2636 " %i, /* int num_params */\n"
2637 " %s, /* gcc_jit_type **param_types */\n"
2638 " %i); /* int is_variadic */\n",
2639 ptr_id,
2640 r.get_identifier (get_context ()),
2641 "NULL", /* location is not stored */
2642 r.get_identifier_as_type (m_return_type),
2643 m_param_types.length (),
2644 param_types_id,
2645 m_is_variadic);
2648 /* The implementation of class gcc::jit::recording::field. */
2650 /* Implementation of pure virtual hook recording::memento::replay_into
2651 for recording::field. */
2653 void
2654 recording::field::replay_into (replayer *r)
2656 set_playback_obj (r->new_field (playback_location (r, m_loc),
2657 m_type->playback_type (),
2658 playback_string (m_name)));
2661 /* Override the default implementation of
2662 recording::memento::write_to_dump. Dump each field
2663 by dumping a line of the form:
2664 TYPE NAME;
2665 so that we can build up a struct/union field-byfield. */
2667 void
2668 recording::field::write_to_dump (dump &d)
2670 d.write (" %s %s;\n",
2671 m_type->get_debug_string (),
2672 m_name->c_str ());
2675 /* Implementation of recording::memento::make_debug_string for
2676 results of new_field. */
2678 recording::string *
2679 recording::field::make_debug_string ()
2681 return m_name;
2684 /* Implementation of recording::memento::write_reproducer for fields. */
2686 void
2687 recording::field::write_reproducer (reproducer &r)
2689 const char *id = r.make_identifier (this, "field");
2690 r.write(" gcc_jit_field *%s =\n"
2691 " gcc_jit_context_new_field (%s,\n"
2692 " %s, /* gcc_jit_location *loc */\n"
2693 " %s, /* gcc_jit_type *type, */\n"
2694 " %s); /* const char *name */\n",
2696 r.get_identifier (get_context ()),
2697 r.get_identifier (m_loc),
2698 r.get_identifier_as_type (m_type),
2699 m_name->get_debug_string ());
2702 /* The implementation of class gcc::jit::recording::compound_type */
2704 /* The constructor for gcc::jit::recording::compound_type. */
2706 recording::compound_type::compound_type (context *ctxt,
2707 location *loc,
2708 string *name)
2709 : type (ctxt),
2710 m_loc (loc),
2711 m_name (name),
2712 m_fields (NULL)
2716 /* Set the fields of a compound type.
2718 Implements the post-error-checking part of
2719 gcc_jit_struct_set_fields, and is also used by
2720 gcc_jit_context_new_union_type. */
2722 void
2723 recording::compound_type::set_fields (location *loc,
2724 int num_fields,
2725 field **field_array)
2727 m_loc = loc;
2728 gcc_assert (NULL == m_fields);
2730 m_fields = new fields (this, num_fields, field_array);
2731 m_ctxt->record (m_fields);
2734 /* Implementation of pure virtual hook recording::type::dereference for
2735 recording::compound_type. */
2737 recording::type *
2738 recording::compound_type::dereference ()
2740 return NULL; /* not a pointer */
2743 /* The implementation of class gcc::jit::recording::struct_. */
2745 /* The constructor for gcc::jit::recording::struct_. */
2747 recording::struct_::struct_ (context *ctxt,
2748 location *loc,
2749 string *name)
2750 : compound_type (ctxt, loc, name)
2754 /* Implementation of pure virtual hook recording::memento::replay_into
2755 for recording::struct_. */
2757 void
2758 recording::struct_::replay_into (replayer *r)
2760 set_playback_obj (
2761 r->new_compound_type (playback_location (r, get_loc ()),
2762 get_name ()->c_str (),
2763 true /* is_struct */));
2766 const char *
2767 recording::struct_::access_as_type (reproducer &r)
2769 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2770 r.get_identifier (this));
2773 /* Implementation of recording::memento::make_debug_string for
2774 structs. */
2776 recording::string *
2777 recording::struct_::make_debug_string ()
2779 return string::from_printf (m_ctxt,
2780 "struct %s", get_name ()->c_str ());
2783 void
2784 recording::struct_::write_reproducer (reproducer &r)
2786 const char *id = r.make_identifier (this, "struct");
2787 r.write (" gcc_jit_struct *%s =\n"
2788 " gcc_jit_context_new_opaque_struct (%s,\n"
2789 " %s, /* gcc_jit_location *loc */\n"
2790 " %s); /* const char *name */\n",
2792 r.get_identifier (get_context ()),
2793 r.get_identifier (get_loc ()),
2794 get_name ()->get_debug_string ());
2797 /* The implementation of class gcc::jit::recording::union_. */
2799 /* The constructor for gcc::jit::recording::union_. */
2801 recording::union_::union_ (context *ctxt,
2802 location *loc,
2803 string *name)
2804 : compound_type (ctxt, loc, name)
2808 /* Implementation of pure virtual hook recording::memento::replay_into
2809 for recording::union_. */
2811 void
2812 recording::union_::replay_into (replayer *r)
2814 set_playback_obj (
2815 r->new_compound_type (playback_location (r, get_loc ()),
2816 get_name ()->c_str (),
2817 false /* is_struct */));
2820 /* Implementation of recording::memento::make_debug_string for
2821 unions. */
2823 recording::string *
2824 recording::union_::make_debug_string ()
2826 return string::from_printf (m_ctxt,
2827 "union %s", get_name ()->c_str ());
2830 /* Implementation of recording::memento::write_reproducer for unions. */
2832 void
2833 recording::union_::write_reproducer (reproducer &r)
2835 const char *id = r.make_identifier (this, "union");
2837 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
2838 r.write (" gcc_jit_field *%s[%i] = {\n",
2839 fields_id,
2840 get_fields ()->length ());
2841 for (int i = 0; i < get_fields ()->length (); i++)
2842 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
2843 r.write (" };\n");
2845 r.write (" gcc_jit_type *%s =\n"
2846 " gcc_jit_context_new_union_type (%s,\n"
2847 " %s, /* gcc_jit_location *loc */\n"
2848 " %s, /* const char *name */\n"
2849 " %i, /* int num_fields */\n"
2850 " %s); /* gcc_jit_field **fields */\n",
2852 r.get_identifier (get_context ()),
2853 r.get_identifier (get_loc ()),
2854 get_name ()->get_debug_string (),
2855 get_fields ()->length (),
2856 fields_id);
2859 /* The implementation of class gcc::jit::recording::fields. */
2861 /* The constructor for gcc::jit::recording::fields. */
2863 recording::fields::fields (compound_type *struct_or_union,
2864 int num_fields,
2865 field **fields)
2866 : memento (struct_or_union->m_ctxt),
2867 m_struct_or_union (struct_or_union),
2868 m_fields ()
2870 for (int i = 0; i < num_fields; i++)
2872 gcc_assert (fields[i]->get_container () == NULL);
2873 fields[i]->set_container (m_struct_or_union);
2874 m_fields.safe_push (fields[i]);
2878 /* Implementation of pure virtual hook recording::memento::replay_into
2879 for recording::fields. */
2881 void
2882 recording::fields::replay_into (replayer *)
2884 auto_vec<playback::field *> playback_fields;
2885 playback_fields.create (m_fields.length ());
2886 for (unsigned i = 0; i < m_fields.length (); i++)
2887 playback_fields.safe_push (m_fields[i]->playback_field ());
2888 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
2891 /* Override the default implementation of
2892 recording::memento::write_to_dump by writing a union/struct
2893 declaration of this form:
2895 struct/union NAME {
2896 TYPE_1 NAME_1;
2897 TYPE_2 NAME_2;
2898 ....
2899 TYPE_N NAME_N;
2902 to the dump. */
2904 void
2905 recording::fields::write_to_dump (dump &d)
2907 int i;
2908 field *f;
2910 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
2911 FOR_EACH_VEC_ELT (m_fields, i, f)
2912 f->write_to_dump (d);
2913 d.write ("};\n");
2916 /* Implementation of recording::memento::write_reproducer for the fields
2917 subclass. */
2919 void
2920 recording::fields::write_reproducer (reproducer &r)
2922 if (m_struct_or_union)
2923 if (NULL == m_struct_or_union->dyn_cast_struct ())
2924 /* We have a union; the fields have already been written by
2925 union::write_reproducer. */
2926 return;
2928 const char *fields_id = r.make_identifier (this, "fields");
2929 r.write (" gcc_jit_field *%s[%i] = {\n",
2930 fields_id,
2931 m_fields.length ());
2932 int i;
2933 field *field;
2934 FOR_EACH_VEC_ELT (m_fields, i, field)
2935 r.write (" %s,\n", r.get_identifier (field));
2936 r.write (" };\n");
2938 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
2939 " %s, /* gcc_jit_location *loc */\n"
2940 " %i, /* int num_fields */\n"
2941 " %s); /* gcc_jit_field **fields */\n",
2942 r.get_identifier (m_struct_or_union),
2943 r.get_identifier ((memento *)NULL),
2944 m_fields.length (),
2945 fields_id);
2948 /* Implementation of recording::memento::make_debug_string for
2949 field tables. */
2951 recording::string *
2952 recording::fields::make_debug_string ()
2954 return string::from_printf (m_ctxt,
2955 "fields");
2958 /* The implementation of class gcc::jit::recording::rvalue. */
2960 /* Create a recording::access_field_rvalue instance and add it to
2961 the rvalue's context's list of mementos.
2963 Implements the post-error-checking part of
2964 gcc_jit_rvalue_access_field. */
2966 recording::rvalue *
2967 recording::rvalue::access_field (recording::location *loc,
2968 field *field)
2970 recording::rvalue *result =
2971 new access_field_rvalue (m_ctxt, loc, this, field);
2972 m_ctxt->record (result);
2973 return result;
2976 /* Create a recording::dereference_field_rvalue instance and add it to
2977 the rvalue's context's list of mementos.
2979 Implements the post-error-checking part of
2980 gcc_jit_rvalue_dereference_field. */
2982 recording::lvalue *
2983 recording::rvalue::dereference_field (recording::location *loc,
2984 field *field)
2986 recording::lvalue *result =
2987 new dereference_field_rvalue (m_ctxt, loc, this, field);
2988 m_ctxt->record (result);
2989 return result;
2992 /* Create a recording::dereference_rvalue instance and add it to the
2993 rvalue's context's list of mementos.
2995 Implements the post-error-checking part of
2996 gcc_jit_rvalue_dereference. */
2998 recording::lvalue *
2999 recording::rvalue::dereference (recording::location *loc)
3001 recording::lvalue *result =
3002 new dereference_rvalue (m_ctxt, loc, this);
3003 m_ctxt->record (result);
3004 return result;
3007 /* An rvalue visitor, for validating that every rvalue within an expression
3008 trees within "STMT" has the correct scope (e.g. no access to locals
3009 of a different function). */
3011 class rvalue_usage_validator : public recording::rvalue_visitor
3013 public:
3014 rvalue_usage_validator (const char *api_funcname,
3015 recording::context *ctxt,
3016 recording::statement *stmt);
3018 void
3019 visit (recording::rvalue *rvalue);
3021 private:
3022 const char *m_api_funcname;
3023 recording::context *m_ctxt;
3024 recording::statement *m_stmt;
3027 /* The trivial constructor for rvalue_usage_validator. */
3029 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
3030 recording::context *ctxt,
3031 recording::statement *stmt)
3032 : m_api_funcname (api_funcname),
3033 m_ctxt (ctxt),
3034 m_stmt (stmt)
3038 /* Verify that the given rvalue is in the correct scope. */
3040 void
3041 rvalue_usage_validator::visit (recording::rvalue *rvalue)
3043 gcc_assert (m_stmt->get_block ());
3044 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
3046 /* Most rvalues don't have a scope (only locals and params). */
3047 if (rvalue->get_scope ())
3049 if (rvalue->get_scope () != stmt_scope)
3050 m_ctxt->add_error
3051 (rvalue->get_loc (),
3052 "%s:"
3053 " rvalue %s (type: %s)"
3054 " has scope limited to function %s"
3055 " but was used within function %s"
3056 " (in statement: %s)",
3057 m_api_funcname,
3058 rvalue->get_debug_string (),
3059 rvalue->get_type ()->get_debug_string (),
3060 rvalue->get_scope ()->get_debug_string (),
3061 stmt_scope->get_debug_string (),
3062 m_stmt->get_debug_string ());
3064 else
3066 if (rvalue->dyn_cast_param ())
3067 m_ctxt->add_error
3068 (rvalue->get_loc (),
3069 "%s:"
3070 " param %s (type: %s)"
3071 " was used within function %s"
3072 " (in statement: %s)"
3073 " but is not associated with any function",
3074 m_api_funcname,
3075 rvalue->get_debug_string (),
3076 rvalue->get_type ()->get_debug_string (),
3077 stmt_scope->get_debug_string (),
3078 m_stmt->get_debug_string ());
3082 /* Verify that it's valid to use this rvalue (and all expressions
3083 in the tree below it) within the given statement.
3085 For example, we must reject attempts to use a local from one
3086 function within a different function here, or we'll get
3087 an ICE deep inside toplev::main. */
3089 void
3090 recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
3092 rvalue_usage_validator v (api_funcname,
3093 s->get_context (),
3096 /* Verify that it's OK to use this rvalue within s. */
3097 v.visit (this);
3099 /* Traverse the expression tree below "this", verifying all rvalues
3100 within it. */
3101 visit_children (&v);
3104 /* Set the scope of this rvalue to be the given function. This can only
3105 be done once on a given rvalue. */
3107 void
3108 recording::rvalue::set_scope (function *scope)
3110 gcc_assert (scope);
3111 gcc_assert (NULL == m_scope);
3112 m_scope = scope;
3116 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3117 themselves.
3118 Instances of rvalue don't need an upcast call. */
3120 const char *
3121 recording::rvalue::access_as_rvalue (reproducer &r)
3123 return r.get_identifier (this);
3126 /* Return a debug string for the given rvalue, wrapping it in parentheses
3127 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3128 stronger precedence that this rvalue's precedence.
3130 For example, given:
3132 MULT
3134 PLUS MINUS
3135 / \ / \
3136 A B C D
3138 we want to emit:
3140 (A + B) * (C - D)
3142 since MULT has strong precedence than PLUS and MINUS, whereas for:
3144 PLUS
3146 MULT DIVIDE
3147 / \ / \
3148 A B C D
3150 we can simply emit:
3152 A * B + C / D
3154 since PLUS has weaker precedence than MULT and DIVIDE. */
3156 const char *
3157 recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
3159 enum precedence this_prec = get_precedence ();
3161 /* If this_prec has stronger precedence than outer_prec, we don't
3162 need to wrap this in parens within the outer debug string.
3163 Stronger precedences occur earlier than weaker within the enum,
3164 so this is a less than test. Equal precedences don't need
3165 parentheses. */
3166 if (this_prec <= outer_prec)
3167 return get_debug_string();
3169 /* Otherwise, we need parentheses. */
3171 /* Lazily-build and cache m_parenthesized_string. */
3172 if (!m_parenthesized_string)
3174 const char *debug_string = get_debug_string ();
3175 m_parenthesized_string = string::from_printf (get_context (),
3176 "(%s)",
3177 debug_string);
3179 gcc_assert (m_parenthesized_string);
3180 return m_parenthesized_string->c_str ();
3184 /* The implementation of class gcc::jit::recording::lvalue. */
3186 /* Create a recording::new_access_field_of_lvalue instance and add it to
3187 the lvalue's context's list of mementos.
3189 Implements the post-error-checking part of
3190 gcc_jit_lvalue_access_field. */
3192 recording::lvalue *
3193 recording::lvalue::access_field (recording::location *loc,
3194 field *field)
3196 recording::lvalue *result =
3197 new access_field_of_lvalue (m_ctxt, loc, this, field);
3198 m_ctxt->record (result);
3199 return result;
3202 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3203 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3204 upcast call. */
3206 const char *
3207 recording::lvalue::access_as_rvalue (reproducer &r)
3209 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3210 r.get_identifier (this));
3213 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3214 Instances of lvalue don't need to be upcast. */
3216 const char *
3217 recording::lvalue::access_as_lvalue (reproducer &r)
3219 return r.get_identifier (this);
3222 /* Create a recording::get_address_of_lvalue instance and add it to
3223 the lvalue's context's list of mementos.
3225 Implements the post-error-checking part of
3226 gcc_jit_lvalue_get_address. */
3228 recording::rvalue *
3229 recording::lvalue::get_address (recording::location *loc)
3231 recording::rvalue *result =
3232 new get_address_of_lvalue (m_ctxt, loc, this);
3233 m_ctxt->record (result);
3234 return result;
3237 /* The implementation of class gcc::jit::recording::param. */
3239 /* Implementation of pure virtual hook recording::memento::replay_into
3240 for recording::param. */
3242 void
3243 recording::param::replay_into (replayer *r)
3245 set_playback_obj (r->new_param (playback_location (r, m_loc),
3246 m_type->playback_type (),
3247 m_name->c_str ()));
3250 /* Implementation of recording::rvalue::access_as_rvalue for params.
3251 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3252 upcast call. */
3254 const char *
3255 recording::param::access_as_rvalue (reproducer &r)
3257 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3258 r.get_identifier (this));
3261 /* Implementation of recording::lvalue::access_as_lvalue for params.
3262 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3263 upcast call. */
3265 const char *
3266 recording::param::access_as_lvalue (reproducer &r)
3268 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3269 r.get_identifier (this));
3272 /* Implementation of recording::memento::write_reproducer for params. */
3274 void
3275 recording::param::write_reproducer (reproducer &r)
3277 const char *id = r.make_identifier (this, "param");
3278 r.write (" gcc_jit_param *%s =\n"
3279 " gcc_jit_context_new_param (%s,\n"
3280 " %s, /* gcc_jit_location *loc */\n"
3281 " %s, /*gcc_jit_type *type */\n"
3282 " %s); /* const char *name */\n",
3284 r.get_identifier (get_context ()),
3285 r.get_identifier (m_loc),
3286 r.get_identifier_as_type (m_type),
3287 m_name->get_debug_string ());
3290 /* The implementation of class gcc::jit::recording::function. */
3292 /* gcc::jit::recording::function's constructor. */
3294 recording::function::function (context *ctxt,
3295 recording::location *loc,
3296 enum gcc_jit_function_kind kind,
3297 type *return_type,
3298 recording::string *name,
3299 int num_params,
3300 recording::param **params,
3301 int is_variadic,
3302 enum built_in_function builtin_id)
3303 : memento (ctxt),
3304 m_loc (loc),
3305 m_kind (kind),
3306 m_return_type (return_type),
3307 m_name (name),
3308 m_params (),
3309 m_is_variadic (is_variadic),
3310 m_builtin_id (builtin_id),
3311 m_locals (),
3312 m_blocks ()
3314 for (int i = 0; i< num_params; i++)
3316 param *param = params[i];
3317 gcc_assert (param);
3319 /* Associate each param with this function.
3321 Verify that the param doesn't already have a function. */
3322 if (param->get_scope ())
3324 /* We've already rejected attempts to reuse a param between
3325 different functions (within gcc_jit_context_new_function), so
3326 if the param *does* already have a function, it must be being
3327 reused within the params array for this function. We must
3328 produce an error for this reuse (blocking the compile), since
3329 otherwise we'd have an ICE later on. */
3330 gcc_assert (this == param->get_scope ());
3331 ctxt->add_error
3332 (loc,
3333 "gcc_jit_context_new_function:"
3334 " parameter %s (type: %s)"
3335 " is used more than once when creating function %s",
3336 param->get_debug_string (),
3337 param->get_type ()->get_debug_string (),
3338 name->c_str ());
3340 else
3342 /* The normal, non-error case: associate this function with the
3343 param. */
3344 param->set_scope (this);
3347 m_params.safe_push (param);
3351 /* Implementation of pure virtual hook recording::memento::replay_into
3352 for recording::function. */
3354 void
3355 recording::function::replay_into (replayer *r)
3357 /* Convert m_params to a vec of playback param. */
3358 auto_vec <playback::param *> params;
3359 int i;
3360 recording::param *param;
3361 params.create (m_params.length ());
3362 FOR_EACH_VEC_ELT (m_params, i, param)
3363 params.safe_push (param->playback_param ());
3365 set_playback_obj (r->new_function (playback_location (r, m_loc),
3366 m_kind,
3367 m_return_type->playback_type (),
3368 m_name->c_str (),
3369 &params,
3370 m_is_variadic,
3371 m_builtin_id));
3374 /* Create a recording::local instance and add it to
3375 the functions's context's list of mementos, and to the function's
3376 list of locals.
3378 Implements the post-error-checking part of
3379 gcc_jit_function_new_local. */
3381 recording::lvalue *
3382 recording::function::new_local (recording::location *loc,
3383 type *type,
3384 const char *name)
3386 local *result = new local (this, loc, type, new_string (name));
3387 m_ctxt->record (result);
3388 m_locals.safe_push (result);
3389 return result;
3392 /* Create a recording::block instance and add it to
3393 the functions's context's list of mementos, and to the function's
3394 list of blocks.
3396 Implements the post-error-checking part of
3397 gcc_jit_function_new_block. */
3399 recording::block*
3400 recording::function::new_block (const char *name)
3402 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
3404 recording::block *result =
3405 new recording::block (this, m_blocks.length (), new_string (name));
3406 m_ctxt->record (result);
3407 m_blocks.safe_push (result);
3408 return result;
3411 /* Override the default implementation of
3412 recording::memento::write_to_dump by dumping a C-like
3413 representation of the function; either like a prototype
3414 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3415 all other kinds of function. */
3417 void
3418 recording::function::write_to_dump (dump &d)
3420 switch (m_kind)
3422 default: gcc_unreachable ();
3423 case GCC_JIT_FUNCTION_EXPORTED:
3424 case GCC_JIT_FUNCTION_IMPORTED:
3425 d.write ("extern ");
3426 break;
3427 case GCC_JIT_FUNCTION_INTERNAL:
3428 d.write ("static ");
3429 break;
3430 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
3431 d.write ("static inline ");
3432 break;
3434 d.write ("%s\n", m_return_type->get_debug_string ());
3436 if (d.update_locations ())
3437 m_loc = d.make_location ();
3439 d.write ("%s (", get_debug_string ());
3441 int i;
3442 recording::param *param;
3443 FOR_EACH_VEC_ELT (m_params, i, param)
3445 if (i > 0)
3446 d.write (", ");
3447 d.write ("%s %s",
3448 param->get_type ()->get_debug_string (),
3449 param->get_debug_string ());
3451 d.write (")");
3452 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
3454 d.write ("; /* (imported) */\n\n");
3456 else
3458 int i;
3459 local *var = NULL;
3460 block *b;
3461 d.write ("\n{\n");
3463 /* Write locals: */
3464 FOR_EACH_VEC_ELT (m_locals, i, var)
3465 var->write_to_dump (d);
3466 if (m_locals.length ())
3467 d.write ("\n");
3469 /* Write each block: */
3470 FOR_EACH_VEC_ELT (m_blocks, i, b)
3472 if (i > 0)
3473 d.write ("\n");
3474 b->write_to_dump (d);
3477 d.write ("}\n\n");
3481 /* Pre-compilation validation of a function, for those things we can't
3482 check until the context is (supposedly) fully-populated. */
3484 void
3485 recording::function::validate ()
3487 /* Complain about empty functions with non-void return type. */
3488 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
3489 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
3490 if (0 == m_blocks.length ())
3491 m_ctxt->add_error (m_loc,
3492 "function %s returns non-void (type: %s)"
3493 " but has no blocks",
3494 get_debug_string (),
3495 m_return_type->get_debug_string ());
3497 /* Check that all blocks are terminated. */
3498 int num_invalid_blocks = 0;
3500 int i;
3501 block *b;
3503 FOR_EACH_VEC_ELT (m_blocks, i, b)
3504 if (!b->validate ())
3505 num_invalid_blocks++;
3508 /* Check that all blocks are reachable. */
3509 if (!m_ctxt->get_inner_bool_option
3510 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
3511 && m_blocks.length () > 0 && 0 == num_invalid_blocks)
3513 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3514 flag, starting at the initial block. */
3515 auto_vec<block *> worklist (m_blocks.length ());
3516 worklist.safe_push (m_blocks[0]);
3517 while (worklist.length () > 0)
3519 block *b = worklist.pop ();
3520 b->m_is_reachable = true;
3522 /* Add successor blocks that aren't yet marked to the worklist. */
3523 /* We checked that each block has a terminating statement above . */
3524 vec <block *> successors = b->get_successor_blocks ();
3525 int i;
3526 block *succ;
3527 FOR_EACH_VEC_ELT (successors, i, succ)
3528 if (!succ->m_is_reachable)
3529 worklist.safe_push (succ);
3530 successors.release ();
3533 /* Now complain about any blocks that haven't been marked. */
3535 int i;
3536 block *b;
3537 FOR_EACH_VEC_ELT (m_blocks, i, b)
3538 if (!b->m_is_reachable)
3539 m_ctxt->add_error (b->get_loc (),
3540 "unreachable block: %s",
3541 b->get_debug_string ());
3546 /* Implements the post-error-checking part of
3547 gcc_jit_function_dump_to_dot. */
3549 void
3550 recording::function::dump_to_dot (const char *path)
3552 FILE *fp = fopen (path, "w");
3553 if (!fp)
3554 return;
3556 pretty_printer the_pp;
3557 the_pp.buffer->stream = fp;
3559 pretty_printer *pp = &the_pp;
3561 pp_printf (pp,
3562 "digraph %s {\n", get_debug_string ());
3564 /* Blocks: */
3566 int i;
3567 block *b;
3568 FOR_EACH_VEC_ELT (m_blocks, i, b)
3569 b->dump_to_dot (pp);
3572 /* Edges: */
3574 int i;
3575 block *b;
3576 FOR_EACH_VEC_ELT (m_blocks, i, b)
3577 b->dump_edges_to_dot (pp);
3580 pp_printf (pp, "}\n");
3581 pp_flush (pp);
3582 fclose (fp);
3585 /* Implementation of recording::memento::make_debug_string for
3586 functions. */
3588 recording::string *
3589 recording::function::make_debug_string ()
3591 return m_name;
3594 /* A table of enum gcc_jit_function_kind values expressed in string
3595 form. */
3597 static const char * const names_of_function_kinds[] = {
3598 "GCC_JIT_FUNCTION_EXPORTED",
3599 "GCC_JIT_FUNCTION_INTERNAL",
3600 "GCC_JIT_FUNCTION_IMPORTED",
3601 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3604 /* Implementation of recording::memento::write_reproducer for functions. */
3606 void
3607 recording::function::write_reproducer (reproducer &r)
3609 const char *id = r.make_identifier (this, "func");
3611 if (m_builtin_id)
3613 r.write (" gcc_jit_function *%s =\n"
3614 " gcc_jit_context_get_builtin_function (%s,\n"
3615 " %s);\n",
3617 r.get_identifier (get_context ()),
3618 m_name->get_debug_string ());
3619 return;
3621 const char *params_id = r.make_tmp_identifier ("params_for", this);
3622 r.write (" gcc_jit_param *%s[%i] = {\n",
3623 params_id,
3624 m_params.length ());
3625 int i;
3626 param *param;
3627 FOR_EACH_VEC_ELT (m_params, i, param)
3628 r.write (" %s,\n", r.get_identifier (param));
3629 r.write (" };\n");
3630 r.write (" gcc_jit_function *%s =\n"
3631 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3632 " %s, /* gcc_jit_location *loc */\n"
3633 " %s, /* enum gcc_jit_function_kind kind */\n"
3634 " %s, /* gcc_jit_type *return_type */\n"
3635 " %s, /* const char *name */\n"
3636 " %i, /* int num_params */\n"
3637 " %s, /* gcc_jit_param **params */\n"
3638 " %i); /* int is_variadic */\n",
3640 r.get_identifier (get_context ()),
3641 r.get_identifier (m_loc),
3642 names_of_function_kinds[m_kind],
3643 r.get_identifier_as_type (m_return_type),
3644 m_name->get_debug_string (),
3645 m_params.length (),
3646 params_id,
3647 m_is_variadic);
3651 /* The implementation of class gcc::jit::recording::block. */
3653 /* Create a recording::eval instance and add it to
3654 the block's context's list of mementos, and to the block's
3655 list of statements.
3657 Implements the heart of gcc_jit_block_add_eval. */
3659 recording::statement *
3660 recording::block::add_eval (recording::location *loc,
3661 recording::rvalue *rvalue)
3663 statement *result = new eval (this, loc, rvalue);
3664 m_ctxt->record (result);
3665 m_statements.safe_push (result);
3666 return result;
3669 /* Create a recording::assignment instance and add it to
3670 the block's context's list of mementos, and to the block's
3671 list of statements.
3673 Implements the heart of gcc_jit_block_add_assignment. */
3675 recording::statement *
3676 recording::block::add_assignment (recording::location *loc,
3677 recording::lvalue *lvalue,
3678 recording::rvalue *rvalue)
3680 statement *result = new assignment (this, loc, lvalue, rvalue);
3681 m_ctxt->record (result);
3682 m_statements.safe_push (result);
3683 return result;
3686 /* Create a recording::assignment_op instance and add it to
3687 the block's context's list of mementos, and to the block's
3688 list of statements.
3690 Implements the heart of gcc_jit_block_add_assignment_op. */
3692 recording::statement *
3693 recording::block::add_assignment_op (recording::location *loc,
3694 recording::lvalue *lvalue,
3695 enum gcc_jit_binary_op op,
3696 recording::rvalue *rvalue)
3698 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
3699 m_ctxt->record (result);
3700 m_statements.safe_push (result);
3701 return result;
3704 /* Create a recording::comment instance and add it to
3705 the block's context's list of mementos, and to the block's
3706 list of statements.
3708 Implements the heart of gcc_jit_block_add_comment. */
3710 recording::statement *
3711 recording::block::add_comment (recording::location *loc,
3712 const char *text)
3714 statement *result = new comment (this, loc, new_string (text));
3715 m_ctxt->record (result);
3716 m_statements.safe_push (result);
3717 return result;
3720 /* Create a recording::end_with_conditional instance and add it to
3721 the block's context's list of mementos, and to the block's
3722 list of statements.
3724 Implements the heart of gcc_jit_block_end_with_conditional. */
3726 recording::statement *
3727 recording::block::end_with_conditional (recording::location *loc,
3728 recording::rvalue *boolval,
3729 recording::block *on_true,
3730 recording::block *on_false)
3732 statement *result = new conditional (this, loc, boolval, on_true, on_false);
3733 m_ctxt->record (result);
3734 m_statements.safe_push (result);
3735 m_has_been_terminated = true;
3736 return result;
3739 /* Create a recording::end_with_jump instance and add it to
3740 the block's context's list of mementos, and to the block's
3741 list of statements.
3743 Implements the heart of gcc_jit_block_end_with_jump. */
3745 recording::statement *
3746 recording::block::end_with_jump (recording::location *loc,
3747 recording::block *target)
3749 statement *result = new jump (this, loc, target);
3750 m_ctxt->record (result);
3751 m_statements.safe_push (result);
3752 m_has_been_terminated = true;
3753 return result;
3756 /* Create a recording::end_with_return instance and add it to
3757 the block's context's list of mementos, and to the block's
3758 list of statements.
3760 Implements the post-error-checking parts of
3761 gcc_jit_block_end_with_return and
3762 gcc_jit_block_end_with_void_return. */
3764 recording::statement *
3765 recording::block::end_with_return (recording::location *loc,
3766 recording::rvalue *rvalue)
3768 /* This is used by both gcc_jit_function_add_return and
3769 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3770 the former and NULL for the latter. */
3771 statement *result = new return_ (this, loc, rvalue);
3772 m_ctxt->record (result);
3773 m_statements.safe_push (result);
3774 m_has_been_terminated = true;
3775 return result;
3778 /* Create a recording::switch_ instance and add it to
3779 the block's context's list of mementos, and to the block's
3780 list of statements.
3782 Implements the heart of gcc_jit_block_end_with_switch. */
3784 recording::statement *
3785 recording::block::end_with_switch (recording::location *loc,
3786 recording::rvalue *expr,
3787 recording::block *default_block,
3788 int num_cases,
3789 recording::case_ **cases)
3791 statement *result = new switch_ (this, loc,
3792 expr,
3793 default_block,
3794 num_cases,
3795 cases);
3796 m_ctxt->record (result);
3797 m_statements.safe_push (result);
3798 m_has_been_terminated = true;
3799 return result;
3802 /* Override the default implementation of
3803 recording::memento::write_to_dump for blocks by writing
3804 an unindented block name as a label, followed by the indented
3805 statements:
3807 BLOCK_NAME:
3808 STATEMENT_1;
3809 STATEMENT_2;
3811 STATEMENT_N; */
3813 void
3814 recording::block::write_to_dump (dump &d)
3816 d.write ("%s:\n", get_debug_string ());
3818 int i;
3819 statement *s;
3820 FOR_EACH_VEC_ELT (m_statements, i, s)
3821 s->write_to_dump (d);
3824 /* Validate a block by ensuring that it has been terminated. */
3826 bool
3827 recording::block::validate ()
3829 /* Check for termination. */
3830 if (!has_been_terminated ())
3832 statement *stmt = get_last_statement ();
3833 location *loc = stmt ? stmt->get_loc () : NULL;
3834 m_func->get_context ()->add_error (loc,
3835 "unterminated block in %s: %s",
3836 m_func->get_debug_string (),
3837 get_debug_string ());
3838 return false;
3841 return true;
3844 /* Get the source-location of a block by using that of the first
3845 statement within it, if any. */
3847 recording::location *
3848 recording::block::get_loc () const
3850 recording::statement *stmt = get_first_statement ();
3851 if (stmt)
3852 return stmt->get_loc ();
3853 else
3854 return NULL;
3857 /* Get the first statement within a block, if any. */
3859 recording::statement *
3860 recording::block::get_first_statement () const
3862 if (m_statements.length ())
3863 return m_statements[0];
3864 else
3865 return NULL;
3868 /* Get the last statement within a block, if any. */
3870 recording::statement *
3871 recording::block::get_last_statement () const
3873 if (m_statements.length ())
3874 return m_statements[m_statements.length () - 1];
3875 else
3876 return NULL;
3879 /* Assuming that this block has been terminated, get the successor blocks
3880 as a vector. Ownership of the vector transfers to the caller, which
3881 must call its release () method.
3883 Used when validating functions, and when dumping dot representations
3884 of them. */
3886 vec <recording::block *>
3887 recording::block::get_successor_blocks () const
3889 gcc_assert (m_has_been_terminated);
3890 statement *last_statement = get_last_statement ();
3891 gcc_assert (last_statement);
3892 return last_statement->get_successor_blocks ();
3895 /* Implementation of pure virtual hook recording::memento::replay_into
3896 for recording::block. */
3898 void
3899 recording::block::replay_into (replayer *)
3901 set_playback_obj (m_func->playback_function ()
3902 ->new_block (playback_string (m_name)));
3905 /* Implementation of recording::memento::make_debug_string for
3906 blocks. */
3908 recording::string *
3909 recording::block::make_debug_string ()
3911 if (m_name)
3912 return m_name;
3913 else
3914 return string::from_printf (m_ctxt,
3915 "<UNNAMED BLOCK %p>",
3916 (void *)this);
3919 /* Implementation of recording::memento::write_reproducer for blocks. */
3921 void
3922 recording::block::write_reproducer (reproducer &r)
3924 const char *id = r.make_identifier (this, "block");
3925 r.write (" gcc_jit_block *%s =\n"
3926 " gcc_jit_function_new_block (%s, %s);\n",
3928 r.get_identifier (m_func),
3929 m_name ? m_name->get_debug_string () : "NULL");
3932 /* Dump a block in graphviz form into PP, capturing the block name (if
3933 any) and the statements. */
3935 void
3936 recording::block::dump_to_dot (pretty_printer *pp)
3938 pp_printf (pp,
3939 ("\tblock_%d "
3940 "[shape=record,style=filled,fillcolor=white,label=\"{"),
3941 m_index);
3942 pp_write_text_to_stream (pp);
3943 if (m_name)
3945 pp_string (pp, m_name->c_str ());
3946 pp_string (pp, ":");
3947 pp_newline (pp);
3948 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3951 int i;
3952 statement *s;
3953 FOR_EACH_VEC_ELT (m_statements, i, s)
3955 pp_string (pp, s->get_debug_string ());
3956 pp_newline (pp);
3957 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3960 pp_printf (pp,
3961 "}\"];\n\n");
3962 pp_flush (pp);
3965 /* Dump the out-edges of the block in graphviz form into PP. */
3967 void
3968 recording::block::dump_edges_to_dot (pretty_printer *pp)
3970 vec <block *> successors = get_successor_blocks ();
3971 int i;
3972 block *succ;
3973 FOR_EACH_VEC_ELT (successors, i, succ)
3974 pp_printf (pp,
3975 "\tblock_%d:s -> block_%d:n;\n",
3976 m_index, succ->m_index);
3977 successors.release ();
3980 /* The implementation of class gcc::jit::recording::global. */
3982 /* Implementation of pure virtual hook recording::memento::replay_into
3983 for recording::global. */
3985 void
3986 recording::global::replay_into (replayer *r)
3988 set_playback_obj (r->new_global (playback_location (r, m_loc),
3989 m_kind,
3990 m_type->playback_type (),
3991 playback_string (m_name)));
3994 /* Override the default implementation of
3995 recording::memento::write_to_dump for globals.
3996 This will be of the form:
3998 GCC_JIT_GLOBAL_EXPORTED:
3999 "TYPE NAME;"
4000 e.g. "int foo;"
4002 GCC_JIT_GLOBAL_INTERNAL:
4003 "static TYPE NAME;"
4004 e.g. "static int foo;"
4006 GCC_JIT_GLOBAL_IMPORTED:
4007 "extern TYPE NAME;"
4008 e.g. "extern int foo;"
4010 These are written to the top of the dump by
4011 recording::context::dump_to_file. */
4013 void
4014 recording::global::write_to_dump (dump &d)
4016 if (d.update_locations ())
4017 m_loc = d.make_location ();
4019 switch (m_kind)
4021 default:
4022 gcc_unreachable ();
4024 case GCC_JIT_GLOBAL_EXPORTED:
4025 break;
4027 case GCC_JIT_GLOBAL_INTERNAL:
4028 d.write ("static ");
4029 break;
4031 case GCC_JIT_GLOBAL_IMPORTED:
4032 d.write ("extern ");
4033 break;
4035 d.write ("%s %s;\n",
4036 m_type->get_debug_string (),
4037 get_debug_string ());
4040 /* A table of enum gcc_jit_global_kind values expressed in string
4041 form. */
4043 static const char * const global_kind_reproducer_strings[] = {
4044 "GCC_JIT_GLOBAL_EXPORTED",
4045 "GCC_JIT_GLOBAL_INTERNAL",
4046 "GCC_JIT_GLOBAL_IMPORTED"
4049 /* Implementation of recording::memento::write_reproducer for globals. */
4051 void
4052 recording::global::write_reproducer (reproducer &r)
4054 const char *id = r.make_identifier (this, "block");
4055 r.write (" gcc_jit_lvalue *%s =\n"
4056 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4057 " %s, /* gcc_jit_location *loc */\n"
4058 " %s, /* enum gcc_jit_global_kind kind */\n"
4059 " %s, /* gcc_jit_type *type */\n"
4060 " %s); /* const char *name */\n",
4062 r.get_identifier (get_context ()),
4063 r.get_identifier (m_loc),
4064 global_kind_reproducer_strings[m_kind],
4065 r.get_identifier_as_type (get_type ()),
4066 m_name->get_debug_string ());
4069 /* The implementation of the various const-handling classes:
4070 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4072 /* Explicit specialization of the various mementos we're interested in. */
4073 template class recording::memento_of_new_rvalue_from_const <int>;
4074 template class recording::memento_of_new_rvalue_from_const <long>;
4075 template class recording::memento_of_new_rvalue_from_const <double>;
4076 template class recording::memento_of_new_rvalue_from_const <void *>;
4078 /* Implementation of the pure virtual hook recording::memento::replay_into
4079 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4081 template <typename HOST_TYPE>
4082 void
4083 recording::
4084 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
4086 set_playback_obj
4087 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
4088 m_value));
4091 /* The make_debug_string and write_reproducer methods vary between the
4092 various
4093 memento_of_new_rvalue_from_const <HOST_TYPE>
4094 classes, so we explicitly write specializations of them.
4096 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4097 namespaces are written out explicitly, which is why most of this file
4098 doesn't abbreviate things by entering the "recording" namespace.
4100 However, these specializations are required to be in the same namespace
4101 as the template, hence we now have to enter the gcc::jit::recording
4102 namespace. */
4104 namespace recording
4107 /* The make_debug_string specialization for <int>, which renders it as
4108 (TARGET_TYPE)LITERAL
4109 e.g.
4110 "(int)42". */
4112 template <>
4113 string *
4114 memento_of_new_rvalue_from_const <int>::make_debug_string ()
4116 return string::from_printf (m_ctxt,
4117 "(%s)%i",
4118 m_type->get_debug_string (),
4119 m_value);
4122 /* The get_wide_int specialization for <int>. */
4124 template <>
4125 bool
4126 memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const
4128 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4129 return true;
4132 /* The write_reproducer specialization for <int>. */
4134 template <>
4135 void
4136 memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
4138 const char *id = r.make_identifier (this, "rvalue");
4139 r.write (" gcc_jit_rvalue *%s =\n"
4140 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4141 " %s, /* gcc_jit_type *numeric_type */\n"
4142 " %i); /* int value */\n",
4144 r.get_identifier (get_context ()),
4145 r.get_identifier_as_type (m_type),
4146 m_value);
4149 /* The make_debug_string specialization for <long>, rendering it as
4150 (TARGET_TYPE)LITERAL
4151 e.g.
4152 "(long)42". */
4154 template <>
4155 string *
4156 memento_of_new_rvalue_from_const <long>::make_debug_string ()
4158 return string::from_printf (m_ctxt,
4159 "(%s)%li",
4160 m_type->get_debug_string (),
4161 m_value);
4164 /* The get_wide_int specialization for <long>. */
4166 template <>
4167 bool
4168 memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const
4170 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4171 return true;
4174 /* The write_reproducer specialization for <long>. */
4176 template <>
4177 void
4178 recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
4180 const char *id = r.make_identifier (this, "rvalue");
4182 /* We have to special-case LONG_MIN, since e.g.
4183 -9223372036854775808L
4184 is parsed as
4185 -(9223372036854775808L)
4186 and hence we'd get:
4187 error: integer constant is so large that it is unsigned [-Werror]
4188 Workaround this by writing (LONG_MIN + 1) - 1. */
4189 if (m_value == LONG_MIN)
4191 r.write (" gcc_jit_rvalue *%s =\n"
4192 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4193 " %s, /* gcc_jit_type *numeric_type */\n"
4194 " %ldL - 1); /* long value */\n",
4196 r.get_identifier (get_context ()),
4197 r.get_identifier_as_type (m_type),
4198 m_value + 1);;
4199 return;
4202 r.write (" gcc_jit_rvalue *%s =\n"
4203 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4204 " %s, /* gcc_jit_type *numeric_type */\n"
4205 " %ldL); /* long value */\n",
4207 r.get_identifier (get_context ()),
4208 r.get_identifier_as_type (m_type),
4209 m_value);
4212 /* The make_debug_string specialization for <double>, rendering it as
4213 (TARGET_TYPE)LITERAL
4214 e.g.
4215 "(float)42.0". */
4217 template <>
4218 string *
4219 memento_of_new_rvalue_from_const <double>::make_debug_string ()
4221 return string::from_printf (m_ctxt,
4222 "(%s)%f",
4223 m_type->get_debug_string (),
4224 m_value);
4227 /* The get_wide_int specialization for <double>. */
4229 template <>
4230 bool
4231 memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
4233 return false;
4236 /* The write_reproducer specialization for <double>. */
4238 template <>
4239 void
4240 recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
4242 const char *id = r.make_identifier (this, "rvalue");
4243 r.write (" gcc_jit_rvalue *%s =\n"
4244 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4245 " %s, /* gcc_jit_type *numeric_type */\n"
4246 " %f); /* double value */\n",
4248 r.get_identifier (get_context ()),
4249 r.get_identifier_as_type (m_type),
4250 m_value);
4253 /* The make_debug_string specialization for <void *>, rendering it as
4254 (TARGET_TYPE)HEX
4255 e.g.
4256 "(int *)0xdeadbeef"
4258 Zero is rendered as NULL e.g.
4259 "(int *)NULL". */
4261 template <>
4262 string *
4263 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
4265 if (m_value != NULL)
4266 return string::from_printf (m_ctxt,
4267 "(%s)%p",
4268 m_type->get_debug_string (), m_value);
4269 else
4270 return string::from_printf (m_ctxt,
4271 "(%s)NULL",
4272 m_type->get_debug_string ());
4275 /* The get_wide_int specialization for <void *>. */
4277 template <>
4278 bool
4279 memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const
4281 return false;
4284 /* Implementation of recording::memento::write_reproducer for <void *>
4285 values. */
4287 template <>
4288 void
4289 memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
4291 const char *id = r.make_identifier (this, "rvalue");
4292 if (m_value)
4293 r.write (" gcc_jit_rvalue *%s =\n"
4294 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4295 " %s, /* gcc_jit_type *pointer_type */\n"
4296 " (void *)%p); /* void *value */\n",
4298 r.get_identifier (get_context ()),
4299 r.get_identifier_as_type (m_type),
4300 m_value);
4301 else
4302 r.write (" gcc_jit_rvalue *%s =\n"
4303 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4304 " %s); /* gcc_jit_type *pointer_type */\n",
4306 r.get_identifier (get_context ()),
4307 r.get_identifier_as_type (m_type));
4310 /* We're done specializing make_debug_string and write_reproducer, so we
4311 can exit the gcc::jit::recording namespace. */
4313 } // namespace recording
4315 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4317 /* Implementation of pure virtual hook recording::memento::replay_into
4318 for recording::memento_of_new_string_literal. */
4320 void
4321 recording::memento_of_new_string_literal::replay_into (replayer *r)
4323 set_playback_obj (r->new_string_literal (m_value->c_str ()));
4326 /* Implementation of recording::memento::make_debug_string for
4327 string literals. */
4329 recording::string *
4330 recording::memento_of_new_string_literal::make_debug_string ()
4332 return string::from_printf (m_ctxt,
4333 "%s",
4334 m_value->get_debug_string ());
4337 /* Implementation of recording::memento::write_reproducer for string literal
4338 values. */
4340 void
4341 recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
4343 const char *id = r.make_identifier (this, "rvalue");
4344 r.write (" gcc_jit_rvalue *%s =\n"
4345 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4346 " %s); /* const char *value */\n",
4348 r.get_identifier (get_context ()),
4349 m_value->get_debug_string ());
4352 /* The implementation of class gcc::jit::recording::unary_op. */
4354 /* Implementation of pure virtual hook recording::memento::replay_into
4355 for recording::unary_op. */
4357 void
4358 recording::unary_op::replay_into (replayer *r)
4360 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
4361 m_op,
4362 get_type ()->playback_type (),
4363 m_a->playback_rvalue ()));
4366 /* Implementation of pure virtual hook recording::rvalue::visit_children
4367 for recording::unary_op. */
4368 void
4369 recording::unary_op::visit_children (rvalue_visitor *v)
4371 v->visit (m_a);
4374 /* Implementation of recording::memento::make_debug_string for
4375 unary ops. */
4377 static const char * const unary_op_strings[] = {
4378 "-", /* GCC_JIT_UNARY_OP_MINUS */
4379 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4380 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4381 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4384 recording::string *
4385 recording::unary_op::make_debug_string ()
4387 return string::from_printf (m_ctxt,
4388 "%s(%s)",
4389 unary_op_strings[m_op],
4390 m_a->get_debug_string ());
4393 static const char * const unary_op_reproducer_strings[] = {
4394 "GCC_JIT_UNARY_OP_MINUS",
4395 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4396 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4397 "GCC_JIT_UNARY_OP_ABS"
4400 /* Implementation of recording::memento::write_reproducer for unary ops. */
4402 void
4403 recording::unary_op::write_reproducer (reproducer &r)
4405 const char *id = r.make_identifier (this, "rvalue");
4406 r.write (" gcc_jit_rvalue *%s =\n"
4407 " gcc_jit_context_new_unary_op (%s,\n"
4408 " %s, /* gcc_jit_location *loc */\n"
4409 " %s, /* enum gcc_jit_unary_op op */\n"
4410 " %s, /* gcc_jit_type *result_type */\n"
4411 " %s); /* gcc_jit_rvalue *a */\n",
4413 r.get_identifier (get_context ()),
4414 r.get_identifier (m_loc),
4415 unary_op_reproducer_strings[m_op],
4416 r.get_identifier_as_type (get_type ()),
4417 r.get_identifier_as_rvalue (m_a));
4420 /* The implementation of class gcc::jit::recording::binary_op. */
4422 /* Implementation of pure virtual hook recording::memento::replay_into
4423 for recording::binary_op. */
4425 void
4426 recording::binary_op::replay_into (replayer *r)
4428 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
4429 m_op,
4430 get_type ()->playback_type (),
4431 m_a->playback_rvalue (),
4432 m_b->playback_rvalue ()));
4435 /* Implementation of pure virtual hook recording::rvalue::visit_children
4436 for recording::binary_op. */
4437 void
4438 recording::binary_op::visit_children (rvalue_visitor *v)
4440 v->visit (m_a);
4441 v->visit (m_b);
4444 /* Implementation of recording::memento::make_debug_string for
4445 binary ops. */
4447 static const char * const binary_op_strings[] = {
4448 "+", /* GCC_JIT_BINARY_OP_PLUS */
4449 "-", /* GCC_JIT_BINARY_OP_MINUS */
4450 "*", /* GCC_JIT_BINARY_OP_MULT */
4451 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4452 "%", /* GCC_JIT_BINARY_OP_MODULO */
4453 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4454 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4455 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4456 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4457 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4458 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4459 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4462 recording::string *
4463 recording::binary_op::make_debug_string ()
4465 enum precedence prec = get_precedence ();
4466 return string::from_printf (m_ctxt,
4467 "%s %s %s",
4468 m_a->get_debug_string_parens (prec),
4469 binary_op_strings[m_op],
4470 m_b->get_debug_string_parens (prec));
4473 static const char * const binary_op_reproducer_strings[] = {
4474 "GCC_JIT_BINARY_OP_PLUS",
4475 "GCC_JIT_BINARY_OP_MINUS",
4476 "GCC_JIT_BINARY_OP_MULT",
4477 "GCC_JIT_BINARY_OP_DIVIDE",
4478 "GCC_JIT_BINARY_OP_MODULO",
4479 "GCC_JIT_BINARY_OP_BITWISE_AND",
4480 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4481 "GCC_JIT_BINARY_OP_BITWISE_OR",
4482 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4483 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4484 "GCC_JIT_BINARY_OP_LSHIFT",
4485 "GCC_JIT_BINARY_OP_RSHIFT"
4488 /* Implementation of recording::memento::write_reproducer for binary ops. */
4490 void
4491 recording::binary_op::write_reproducer (reproducer &r)
4493 const char *id = r.make_identifier (this, "rvalue");
4494 r.write (" gcc_jit_rvalue *%s =\n"
4495 " gcc_jit_context_new_binary_op (%s,\n"
4496 " %s, /* gcc_jit_location *loc */\n"
4497 " %s, /* enum gcc_jit_binary_op op */\n"
4498 " %s, /* gcc_jit_type *result_type */\n"
4499 " %s, /* gcc_jit_rvalue *a */\n"
4500 " %s); /* gcc_jit_rvalue *b */\n",
4502 r.get_identifier (get_context ()),
4503 r.get_identifier (m_loc),
4504 binary_op_reproducer_strings[m_op],
4505 r.get_identifier_as_type (get_type ()),
4506 r.get_identifier_as_rvalue (m_a),
4507 r.get_identifier_as_rvalue (m_b));
4510 namespace recording {
4511 static const enum precedence binary_op_precedence[] = {
4512 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
4513 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
4515 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
4516 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
4517 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
4519 PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4520 PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4521 PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4522 PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4523 PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4524 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
4525 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
4527 } /* namespace recording */
4529 enum recording::precedence
4530 recording::binary_op::get_precedence () const
4532 return binary_op_precedence[m_op];
4535 /* The implementation of class gcc::jit::recording::comparison. */
4537 /* Implementation of recording::memento::make_debug_string for
4538 comparisons. */
4540 static const char * const comparison_strings[] =
4542 "==", /* GCC_JIT_COMPARISON_EQ */
4543 "!=", /* GCC_JIT_COMPARISON_NE */
4544 "<", /* GCC_JIT_COMPARISON_LT */
4545 "<=", /* GCC_JIT_COMPARISON_LE */
4546 ">", /* GCC_JIT_COMPARISON_GT */
4547 ">=", /* GCC_JIT_COMPARISON_GE */
4550 recording::string *
4551 recording::comparison::make_debug_string ()
4553 enum precedence prec = get_precedence ();
4554 return string::from_printf (m_ctxt,
4555 "%s %s %s",
4556 m_a->get_debug_string_parens (prec),
4557 comparison_strings[m_op],
4558 m_b->get_debug_string_parens (prec));
4561 /* A table of enum gcc_jit_comparison values expressed in string
4562 form. */
4564 static const char * const comparison_reproducer_strings[] =
4566 "GCC_JIT_COMPARISON_EQ",
4567 "GCC_JIT_COMPARISON_NE",
4568 "GCC_JIT_COMPARISON_LT",
4569 "GCC_JIT_COMPARISON_LE",
4570 "GCC_JIT_COMPARISON_GT",
4571 "GCC_JIT_COMPARISON_GE"
4574 /* Implementation of recording::memento::write_reproducer for comparisons. */
4576 void
4577 recording::comparison::write_reproducer (reproducer &r)
4579 const char *id = r.make_identifier (this, "rvalue");
4580 r.write (" gcc_jit_rvalue *%s =\n"
4581 " gcc_jit_context_new_comparison (%s,\n"
4582 " %s, /* gcc_jit_location *loc */\n"
4583 " %s, /* enum gcc_jit_comparison op */\n"
4584 " %s, /* gcc_jit_rvalue *a */\n"
4585 " %s); /* gcc_jit_rvalue *b */\n",
4587 r.get_identifier (get_context ()),
4588 r.get_identifier (m_loc),
4589 comparison_reproducer_strings[m_op],
4590 r.get_identifier_as_rvalue (m_a),
4591 r.get_identifier_as_rvalue (m_b));
4594 /* Implementation of pure virtual hook recording::memento::replay_into
4595 for recording::comparison. */
4597 void
4598 recording::comparison::replay_into (replayer *r)
4600 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
4601 m_op,
4602 m_a->playback_rvalue (),
4603 m_b->playback_rvalue ()));
4606 /* Implementation of pure virtual hook recording::rvalue::visit_children
4607 for recording::comparison. */
4609 void
4610 recording::comparison::visit_children (rvalue_visitor *v)
4612 v->visit (m_a);
4613 v->visit (m_b);
4616 namespace recording {
4617 static const enum precedence comparison_precedence[] =
4619 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
4620 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
4622 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LT */
4623 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
4624 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GT */
4625 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
4627 } /* namespace recording */
4629 enum recording::precedence
4630 recording::comparison::get_precedence () const
4632 return comparison_precedence[m_op];
4635 /* Implementation of pure virtual hook recording::memento::replay_into
4636 for recording::cast. */
4638 void
4639 recording::cast::replay_into (replayer *r)
4641 set_playback_obj (r->new_cast (playback_location (r, m_loc),
4642 m_rvalue->playback_rvalue (),
4643 get_type ()->playback_type ()));
4646 /* Implementation of pure virtual hook recording::rvalue::visit_children
4647 for recording::cast. */
4648 void
4649 recording::cast::visit_children (rvalue_visitor *v)
4651 v->visit (m_rvalue);
4654 /* Implementation of recording::memento::make_debug_string for
4655 casts. */
4657 recording::string *
4658 recording::cast::make_debug_string ()
4660 enum precedence prec = get_precedence ();
4661 return string::from_printf (m_ctxt,
4662 "(%s)%s",
4663 get_type ()->get_debug_string (),
4664 m_rvalue->get_debug_string_parens (prec));
4667 /* Implementation of recording::memento::write_reproducer for casts. */
4669 void
4670 recording::cast::write_reproducer (reproducer &r)
4672 const char *id = r.make_identifier (this, "rvalue");
4673 r.write (" gcc_jit_rvalue *%s =\n"
4674 " gcc_jit_context_new_cast (%s,\n"
4675 " %s, /* gcc_jit_location *loc */\n"
4676 " %s, /* gcc_jit_rvalue *rvalue */\n"
4677 " %s); /* gcc_jit_type *type */\n",
4679 r.get_identifier (get_context ()),
4680 r.get_identifier (m_loc),
4681 r.get_identifier_as_rvalue (m_rvalue),
4682 r.get_identifier_as_type (get_type ()));
4685 /* The implementation of class gcc::jit::recording::call. */
4687 /* The constructor for gcc::jit::recording::call. */
4689 recording::call::call (recording::context *ctxt,
4690 recording::location *loc,
4691 recording::function *func,
4692 int numargs,
4693 rvalue **args)
4694 : rvalue (ctxt, loc, func->get_return_type ()),
4695 m_func (func),
4696 m_args ()
4698 for (int i = 0; i< numargs; i++)
4699 m_args.safe_push (args[i]);
4702 /* Implementation of pure virtual hook recording::memento::replay_into
4703 for recording::call. */
4705 void
4706 recording::call::replay_into (replayer *r)
4708 auto_vec<playback::rvalue *> playback_args;
4709 playback_args.create (m_args.length ());
4710 for (unsigned i = 0; i< m_args.length (); i++)
4711 playback_args.safe_push (m_args[i]->playback_rvalue ());
4713 set_playback_obj (r->new_call (playback_location (r, m_loc),
4714 m_func->playback_function (),
4715 &playback_args));
4718 /* Implementation of pure virtual hook recording::rvalue::visit_children
4719 for recording::call. */
4721 void
4722 recording::call::visit_children (rvalue_visitor *v)
4724 for (unsigned i = 0; i< m_args.length (); i++)
4725 v->visit (m_args[i]);
4728 /* Implementation of recording::memento::make_debug_string for
4729 function calls. */
4731 recording::string *
4732 recording::call::make_debug_string ()
4734 enum precedence prec = get_precedence ();
4735 /* First, build a buffer for the arguments. */
4736 /* Calculate length of said buffer. */
4737 size_t sz = 1; /* nil terminator */
4738 for (unsigned i = 0; i< m_args.length (); i++)
4740 sz += strlen (m_args[i]->get_debug_string_parens (prec));
4741 sz += 2; /* ", " separator */
4744 /* Now allocate and populate the buffer. */
4745 char *argbuf = new char[sz];
4746 size_t len = 0;
4748 for (unsigned i = 0; i< m_args.length (); i++)
4750 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4751 len += strlen (m_args[i]->get_debug_string_parens (prec));
4752 if (i + 1 < m_args.length ())
4754 strcpy (argbuf + len, ", ");
4755 len += 2;
4758 argbuf[len] = '\0';
4760 /* ...and use it to get the string for the call as a whole. */
4761 string *result = string::from_printf (m_ctxt,
4762 "%s (%s)",
4763 m_func->get_debug_string (),
4764 argbuf);
4766 delete[] argbuf;
4768 return result;
4771 void
4772 recording::call::write_reproducer (reproducer &r)
4774 const char *id = r.make_identifier (this, "call");
4775 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4776 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4777 args_id,
4778 m_args.length ());
4779 for (unsigned i = 0; i< m_args.length (); i++)
4780 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4781 r.write (" };\n");
4782 r.write (" gcc_jit_rvalue *%s =\n"
4783 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4784 " %s, /* gcc_jit_location *loc */\n"
4785 " %s, /* gcc_jit_function *func */\n"
4786 " %i, /* int numargs */ \n"
4787 " %s); /* gcc_jit_rvalue **args*/\n",
4789 r.get_identifier (get_context ()),
4790 r.get_identifier (m_loc),
4791 r.get_identifier (m_func),
4792 m_args.length (),
4793 args_id);
4796 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4798 /* The constructor for recording::call_through_ptr. */
4800 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
4801 recording::location *loc,
4802 recording::rvalue *fn_ptr,
4803 int numargs,
4804 rvalue **args)
4805 : rvalue (ctxt, loc,
4806 fn_ptr->get_type ()->dereference ()
4807 ->as_a_function_type ()->get_return_type ()),
4808 m_fn_ptr (fn_ptr),
4809 m_args ()
4811 for (int i = 0; i< numargs; i++)
4812 m_args.safe_push (args[i]);
4815 /* Implementation of pure virtual hook recording::memento::replay_into
4816 for recording::call_through_ptr. */
4818 void
4819 recording::call_through_ptr::replay_into (replayer *r)
4821 auto_vec<playback::rvalue *> playback_args;
4822 playback_args.create (m_args.length ());
4823 for (unsigned i = 0; i< m_args.length (); i++)
4824 playback_args.safe_push (m_args[i]->playback_rvalue ());
4826 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
4827 m_fn_ptr->playback_rvalue (),
4828 &playback_args));
4831 /* Implementation of pure virtual hook recording::rvalue::visit_children
4832 for recording::call_through_ptr. */
4834 void
4835 recording::call_through_ptr::visit_children (rvalue_visitor *v)
4837 v->visit (m_fn_ptr);
4838 for (unsigned i = 0; i< m_args.length (); i++)
4839 v->visit (m_args[i]);
4842 /* Implementation of recording::memento::make_debug_string for
4843 calls through function ptrs. */
4845 recording::string *
4846 recording::call_through_ptr::make_debug_string ()
4848 enum precedence prec = get_precedence ();
4849 /* First, build a buffer for the arguments. */
4850 /* Calculate length of said buffer. */
4851 size_t sz = 1; /* nil terminator */
4852 for (unsigned i = 0; i< m_args.length (); i++)
4854 sz += strlen (m_args[i]->get_debug_string_parens (prec));
4855 sz += 2; /* ", " separator */
4858 /* Now allocate and populate the buffer. */
4859 char *argbuf = new char[sz];
4860 size_t len = 0;
4862 for (unsigned i = 0; i< m_args.length (); i++)
4864 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4865 len += strlen (m_args[i]->get_debug_string_parens (prec));
4866 if (i + 1 < m_args.length ())
4868 strcpy (argbuf + len, ", ");
4869 len += 2;
4872 argbuf[len] = '\0';
4874 /* ...and use it to get the string for the call as a whole. */
4875 string *result = string::from_printf (m_ctxt,
4876 "%s (%s)",
4877 m_fn_ptr->get_debug_string_parens (prec),
4878 argbuf);
4880 delete[] argbuf;
4882 return result;
4885 /* Implementation of recording::memento::write_reproducer for
4886 call_through_ptr. */
4888 void
4889 recording::call_through_ptr::write_reproducer (reproducer &r)
4891 const char *id = r.make_identifier (this, "call");
4892 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4893 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4894 args_id,
4895 m_args.length ());
4896 for (unsigned i = 0; i< m_args.length (); i++)
4897 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4898 r.write (" };\n");
4899 r.write (" gcc_jit_rvalue *%s =\n"
4900 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
4901 " %s, /* gcc_jit_location *loc */\n"
4902 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
4903 " %i, /* int numargs */ \n"
4904 " %s); /* gcc_jit_rvalue **args*/\n",
4906 r.get_identifier (get_context ()),
4907 r.get_identifier (m_loc),
4908 r.get_identifier_as_rvalue (m_fn_ptr),
4909 m_args.length (),
4910 args_id);
4913 /* The implementation of class gcc::jit::recording::array_access. */
4915 /* Implementation of pure virtual hook recording::memento::replay_into
4916 for recording::array_access. */
4918 void
4919 recording::array_access::replay_into (replayer *r)
4921 set_playback_obj (
4922 r->new_array_access (playback_location (r, m_loc),
4923 m_ptr->playback_rvalue (),
4924 m_index->playback_rvalue ()));
4927 /* Implementation of pure virtual hook recording::rvalue::visit_children
4928 for recording::array_access. */
4930 void
4931 recording::array_access::visit_children (rvalue_visitor *v)
4933 v->visit (m_ptr);
4934 v->visit (m_index);
4937 /* Implementation of recording::memento::make_debug_string for
4938 array accesses. */
4940 recording::string *
4941 recording::array_access::make_debug_string ()
4943 enum precedence prec = get_precedence ();
4944 return string::from_printf (m_ctxt,
4945 "%s[%s]",
4946 m_ptr->get_debug_string_parens (prec),
4947 m_index->get_debug_string_parens (prec));
4950 /* Implementation of recording::memento::write_reproducer for
4951 array_access. */
4953 void
4954 recording::array_access::write_reproducer (reproducer &r)
4956 const char *id = r.make_identifier (this, "lvalue");
4957 r.write (" gcc_jit_lvalue *%s = \n"
4958 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
4959 " %s, /*gcc_jit_location *loc */\n"
4960 " %s, /* gcc_jit_rvalue *ptr */\n"
4961 " %s); /* gcc_jit_rvalue *index */\n",
4963 r.get_identifier (get_context ()),
4964 r.get_identifier (m_loc),
4965 r.get_identifier_as_rvalue (m_ptr),
4966 r.get_identifier_as_rvalue (m_index));
4969 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
4971 /* Implementation of pure virtual hook recording::memento::replay_into
4972 for recording::access_field_of_lvalue. */
4974 void
4975 recording::access_field_of_lvalue::replay_into (replayer *r)
4977 set_playback_obj (
4978 m_lvalue->playback_lvalue ()
4979 ->access_field (playback_location (r, m_loc),
4980 m_field->playback_field ()));
4984 /* Implementation of pure virtual hook recording::rvalue::visit_children
4985 for recording::access_field_of_lvalue. */
4987 void
4988 recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
4990 v->visit (m_lvalue);
4993 /* Implementation of recording::memento::make_debug_string for
4994 accessing a field of an lvalue. */
4996 recording::string *
4997 recording::access_field_of_lvalue::make_debug_string ()
4999 enum precedence prec = get_precedence ();
5000 return string::from_printf (m_ctxt,
5001 "%s.%s",
5002 m_lvalue->get_debug_string_parens (prec),
5003 m_field->get_debug_string ());
5006 /* Implementation of recording::memento::write_reproducer for
5007 access_field_of_lvalue. */
5009 void
5010 recording::access_field_of_lvalue::write_reproducer (reproducer &r)
5012 const char *id = r.make_identifier (this, "lvalue");
5013 r.write (" gcc_jit_lvalue *%s = \n"
5014 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5015 " %s, /*gcc_jit_location *loc */\n"
5016 " %s);\n",
5018 r.get_identifier_as_lvalue (m_lvalue),
5019 r.get_identifier (m_loc),
5020 r.get_identifier (m_field));
5023 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
5025 /* Implementation of pure virtual hook recording::memento::replay_into
5026 for recording::access_field_rvalue. */
5028 void
5029 recording::access_field_rvalue::replay_into (replayer *r)
5031 set_playback_obj (
5032 m_rvalue->playback_rvalue ()
5033 ->access_field (playback_location (r, m_loc),
5034 m_field->playback_field ()));
5037 /* Implementation of pure virtual hook recording::rvalue::visit_children
5038 for recording::access_field_rvalue. */
5040 void
5041 recording::access_field_rvalue::visit_children (rvalue_visitor *v)
5043 v->visit (m_rvalue);
5046 /* Implementation of recording::memento::make_debug_string for
5047 accessing a field of an rvalue. */
5049 recording::string *
5050 recording::access_field_rvalue::make_debug_string ()
5052 enum precedence prec = get_precedence ();
5053 return string::from_printf (m_ctxt,
5054 "%s.%s",
5055 m_rvalue->get_debug_string_parens (prec),
5056 m_field->get_debug_string ());
5059 /* Implementation of recording::memento::write_reproducer for
5060 access_field_rvalue. */
5062 void
5063 recording::access_field_rvalue::write_reproducer (reproducer &r)
5065 const char *id = r.make_identifier (this, "rvalue");
5066 r.write (" gcc_jit_rvalue *%s = \n"
5067 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5068 " %s, /*gcc_jit_location *loc */\n"
5069 " %s);\n",
5071 r.get_identifier_as_rvalue (m_rvalue),
5072 r.get_identifier (m_loc),
5073 r.get_identifier (m_field));
5076 /* The implementation of class
5077 gcc::jit::recording::dereference_field_rvalue. */
5079 /* Implementation of pure virtual hook recording::memento::replay_into
5080 for recording::dereference_field_rvalue. */
5082 void
5083 recording::dereference_field_rvalue::replay_into (replayer *r)
5085 set_playback_obj (
5086 m_rvalue->playback_rvalue ()->
5087 dereference_field (playback_location (r, m_loc),
5088 m_field->playback_field ()));
5091 /* Implementation of pure virtual hook recording::rvalue::visit_children
5092 for recording::dereference_field_rvalue. */
5094 void
5095 recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
5097 v->visit (m_rvalue);
5100 /* Implementation of recording::memento::make_debug_string for
5101 dereferencing a field of an rvalue. */
5103 recording::string *
5104 recording::dereference_field_rvalue::make_debug_string ()
5106 enum precedence prec = get_precedence ();
5107 return string::from_printf (m_ctxt,
5108 "%s->%s",
5109 m_rvalue->get_debug_string_parens (prec),
5110 m_field->get_debug_string ());
5113 /* Implementation of recording::memento::write_reproducer for
5114 dereference_field_rvalue. */
5116 void
5117 recording::dereference_field_rvalue::write_reproducer (reproducer &r)
5119 const char *id = r.make_identifier (this, "lvalue");
5120 r.write (" gcc_jit_lvalue *%s=\n"
5121 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5122 " %s, /* gcc_jit_location *loc */\n"
5123 " %s); /* gcc_jit_field *field */\n",
5125 r.get_identifier_as_rvalue (m_rvalue),
5126 r.get_identifier (m_loc),
5127 r.get_identifier (m_field));
5130 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5132 /* Implementation of pure virtual hook recording::memento::replay_into
5133 for recording::dereference_rvalue. */
5135 void
5136 recording::dereference_rvalue::replay_into (replayer *r)
5138 set_playback_obj (
5139 m_rvalue->playback_rvalue ()->
5140 dereference (playback_location (r, m_loc)));
5143 /* Implementation of pure virtual hook recording::rvalue::visit_children
5144 for recording::dereference_rvalue. */
5146 void
5147 recording::dereference_rvalue::visit_children (rvalue_visitor *v)
5149 v->visit (m_rvalue);
5152 /* Implementation of recording::memento::make_debug_string for
5153 dereferencing an rvalue. */
5155 recording::string *
5156 recording::dereference_rvalue::make_debug_string ()
5158 enum precedence prec = get_precedence ();
5159 return string::from_printf (m_ctxt,
5160 "*%s",
5161 m_rvalue->get_debug_string_parens (prec));
5164 /* Implementation of recording::memento::write_reproducer for
5165 dereference_rvalue. */
5167 void
5168 recording::dereference_rvalue::write_reproducer (reproducer &r)
5170 const char *id = r.make_identifier (this, "dereference");
5171 r.write (" gcc_jit_lvalue *%s =\n"
5172 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5173 " %s); /* gcc_jit_location *loc */\n",
5175 r.get_identifier_as_rvalue (m_rvalue),
5176 r.get_identifier (m_loc));
5179 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5181 /* Implementation of pure virtual hook recording::memento::replay_into
5182 for recording::get_address_of_lvalue. */
5184 void
5185 recording::get_address_of_lvalue::replay_into (replayer *r)
5187 set_playback_obj (
5188 m_lvalue->playback_lvalue ()->
5189 get_address (playback_location (r, m_loc)));
5192 /* Implementation of pure virtual hook recording::rvalue::visit_children
5193 for recording::get_address_of_lvalue. */
5195 void
5196 recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
5198 v->visit (m_lvalue);
5201 /* Implementation of recording::memento::make_debug_string for
5202 getting the address of an lvalue. */
5204 recording::string *
5205 recording::get_address_of_lvalue::make_debug_string ()
5207 enum precedence prec = get_precedence ();
5208 return string::from_printf (m_ctxt,
5209 "&%s",
5210 m_lvalue->get_debug_string_parens (prec));
5213 /* Implementation of recording::memento::write_reproducer for
5214 get_address_of_lvalue. */
5216 void
5217 recording::get_address_of_lvalue::write_reproducer (reproducer &r)
5219 const char *id = r.make_identifier (this, "address_of");
5220 r.write (" gcc_jit_rvalue *%s =\n"
5221 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5222 " %s); /* gcc_jit_location *loc */\n",
5224 r.get_identifier_as_lvalue (m_lvalue),
5225 r.get_identifier (m_loc));
5228 /* The implementation of class gcc::jit::recording::local. */
5230 /* Implementation of pure virtual hook recording::memento::replay_into
5231 for recording::local. */
5233 void
5234 recording::local::replay_into (replayer *r)
5236 set_playback_obj (
5237 m_func->playback_function ()
5238 ->new_local (playback_location (r, m_loc),
5239 m_type->playback_type (),
5240 playback_string (m_name)));
5243 /* Override the default implementation of
5244 recording::memento::write_to_dump for locals by writing
5245 TYPE NAME;
5246 for use at the top of the function body as if it were a
5247 declaration. */
5249 void
5250 recording::local::write_to_dump (dump &d)
5252 if (d.update_locations ())
5253 m_loc = d.make_location ();
5254 d.write(" %s %s;\n",
5255 m_type->get_debug_string (),
5256 get_debug_string ());
5259 void
5260 recording::local::write_reproducer (reproducer &r)
5262 const char *id = r.make_identifier (this, "local");
5263 r.write (" gcc_jit_lvalue *%s =\n"
5264 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5265 " %s, /* gcc_jit_location *loc */\n"
5266 " %s, /* gcc_jit_type *type */\n"
5267 " %s); /* const char *name */\n",
5269 r.get_identifier (m_func),
5270 r.get_identifier (m_loc),
5271 r.get_identifier_as_type (m_type),
5272 m_name->get_debug_string ());
5275 /* The implementation of class gcc::jit::recording::statement. */
5277 /* We poison the default implementation of
5278 gcc::jit::recording::statement::get_successor_blocks
5279 since this vfunc must only ever be called on terminator
5280 statements. */
5282 vec <recording::block *>
5283 recording::statement::get_successor_blocks () const
5285 /* The base class implementation is for non-terminating statements,
5286 and thus should never be called. */
5287 gcc_unreachable ();
5288 vec <block *> result;
5289 result.create (0);
5290 return result;
5293 /* Extend the default implementation of
5294 recording::memento::write_to_dump for statements by (if requested)
5295 updating the location of the statement to the current location in
5296 the dumpfile. */
5298 void
5299 recording::statement::write_to_dump (dump &d)
5301 memento::write_to_dump (d);
5302 if (d.update_locations ())
5303 m_loc = d.make_location ();
5306 /* The implementation of class gcc::jit::recording::eval. */
5308 /* Implementation of pure virtual hook recording::memento::replay_into
5309 for recording::eval. */
5311 void
5312 recording::eval::replay_into (replayer *r)
5314 playback_block (get_block ())
5315 ->add_eval (playback_location (r),
5316 m_rvalue->playback_rvalue ());
5319 /* Implementation of recording::memento::make_debug_string for
5320 an eval statement. */
5322 recording::string *
5323 recording::eval::make_debug_string ()
5325 return string::from_printf (m_ctxt,
5326 "(void)%s;",
5327 m_rvalue->get_debug_string ());
5330 /* Implementation of recording::memento::write_reproducer for
5331 eval statements. */
5333 void
5334 recording::eval::write_reproducer (reproducer &r)
5336 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5337 " %s, /* gcc_jit_location *loc */\n"
5338 " %s); /* gcc_jit_rvalue *rvalue */\n",
5339 r.get_identifier (get_block ()),
5340 r.get_identifier (get_loc ()),
5341 r.get_identifier_as_rvalue (m_rvalue));
5344 /* The implementation of class gcc::jit::recording::assignment. */
5346 /* Implementation of pure virtual hook recording::memento::replay_into
5347 for recording::assignment. */
5349 void
5350 recording::assignment::replay_into (replayer *r)
5352 playback_block (get_block ())
5353 ->add_assignment (playback_location (r),
5354 m_lvalue->playback_lvalue (),
5355 m_rvalue->playback_rvalue ());
5358 /* Implementation of recording::memento::make_debug_string for
5359 an assignment statement. */
5361 recording::string *
5362 recording::assignment::make_debug_string ()
5364 return string::from_printf (m_ctxt,
5365 "%s = %s;",
5366 m_lvalue->get_debug_string (),
5367 m_rvalue->get_debug_string ());
5370 /* Implementation of recording::memento::write_reproducer for
5371 assignment statements. */
5373 void
5374 recording::assignment::write_reproducer (reproducer &r)
5376 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5377 " %s, /* gcc_jit_location *loc */\n"
5378 " %s, /* gcc_jit_lvalue *lvalue */\n"
5379 " %s); /* gcc_jit_rvalue *rvalue */\n",
5380 r.get_identifier (get_block ()),
5381 r.get_identifier (get_loc ()),
5382 r.get_identifier_as_lvalue (m_lvalue),
5383 r.get_identifier_as_rvalue (m_rvalue));
5386 /* The implementation of class gcc::jit::recording::assignment_op. */
5388 /* Implementation of pure virtual hook recording::memento::replay_into
5389 for recording::assignment_op. */
5391 void
5392 recording::assignment_op::replay_into (replayer *r)
5394 playback::type *result_type =
5395 m_lvalue->playback_lvalue ()->get_type ();
5397 playback::rvalue *binary_op =
5398 r->new_binary_op (playback_location (r),
5399 m_op,
5400 result_type,
5401 m_lvalue->playback_rvalue (),
5402 m_rvalue->playback_rvalue ());
5404 playback_block (get_block ())
5405 ->add_assignment (playback_location (r),
5406 m_lvalue->playback_lvalue (),
5407 binary_op);
5410 /* Implementation of recording::memento::make_debug_string for
5411 an assignment_op statement. */
5413 recording::string *
5414 recording::assignment_op::make_debug_string ()
5416 return string::from_printf (m_ctxt,
5417 "%s %s= %s;",
5418 m_lvalue->get_debug_string (),
5419 binary_op_strings[m_op],
5420 m_rvalue->get_debug_string ());
5423 /* Implementation of recording::memento::write_reproducer for
5424 assignment_op statements. */
5426 void
5427 recording::assignment_op::write_reproducer (reproducer &r)
5429 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5430 " %s, /* gcc_jit_location *loc */\n"
5431 " %s, /* gcc_jit_lvalue *lvalue */\n"
5432 " %s, /* enum gcc_jit_binary_op op */\n"
5433 " %s); /* gcc_jit_rvalue *rvalue */\n",
5434 r.get_identifier (get_block ()),
5435 r.get_identifier (get_loc ()),
5436 r.get_identifier_as_lvalue (m_lvalue),
5437 binary_op_reproducer_strings[m_op],
5438 r.get_identifier_as_rvalue (m_rvalue));
5441 /* The implementation of class gcc::jit::recording::comment. */
5443 /* Implementation of pure virtual hook recording::memento::replay_into
5444 for recording::comment. */
5446 void
5447 recording::comment::replay_into (replayer *r)
5449 playback_block (get_block ())
5450 ->add_comment (playback_location (r),
5451 m_text->c_str ());
5454 /* Implementation of recording::memento::make_debug_string for
5455 a comment "statement". */
5457 recording::string *
5458 recording::comment::make_debug_string ()
5460 return string::from_printf (m_ctxt,
5461 "/* %s */",
5462 m_text->c_str ());
5465 /* Implementation of recording::memento::write_reproducer for
5466 comments. */
5468 void
5469 recording::comment::write_reproducer (reproducer &r)
5471 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5472 " %s, /* gcc_jit_location *loc */\n"
5473 " %s); /* const char *text */\n",
5474 r.get_identifier (get_block ()),
5475 r.get_identifier (get_loc ()),
5476 m_text->get_debug_string ());
5479 /* The implementation of class gcc::jit::recording::conditional. */
5481 /* Implementation of pure virtual hook recording::memento::replay_into
5482 for recording::conditional. */
5484 void
5485 recording::conditional::replay_into (replayer *r)
5487 playback_block (get_block ())
5488 ->add_conditional (playback_location (r),
5489 m_boolval->playback_rvalue (),
5490 playback_block (m_on_true),
5491 playback_block (m_on_false));
5494 /* Override the poisoned default implementation of
5495 gcc::jit::recording::statement::get_successor_blocks
5497 A conditional jump has 2 successor blocks. */
5499 vec <recording::block *>
5500 recording::conditional::get_successor_blocks () const
5502 vec <block *> result;
5503 result.create (2);
5504 result.quick_push (m_on_true);
5505 result.quick_push (m_on_false);
5506 return result;
5509 /* Implementation of recording::memento::make_debug_string for
5510 a conditional jump statement. */
5512 recording::string *
5513 recording::conditional::make_debug_string ()
5515 if (m_on_false)
5516 return string::from_printf (m_ctxt,
5517 "if (%s) goto %s; else goto %s;",
5518 m_boolval->get_debug_string (),
5519 m_on_true->get_debug_string (),
5520 m_on_false->get_debug_string ());
5521 else
5522 return string::from_printf (m_ctxt,
5523 "if (%s) goto %s;",
5524 m_boolval->get_debug_string (),
5525 m_on_true->get_debug_string ());
5528 /* Implementation of recording::memento::write_reproducer for
5529 conditional statements. */
5531 void
5532 recording::conditional::write_reproducer (reproducer &r)
5534 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5535 " %s, /* gcc_jit_location *loc */\n"
5536 " %s, /* gcc_jit_rvalue *boolval */\n"
5537 " %s, /* gcc_jit_block *on_true */\n"
5538 " %s); /* gcc_jit_block *on_false */\n",
5539 r.get_identifier (get_block ()),
5540 r.get_identifier (get_loc ()),
5541 r.get_identifier_as_rvalue (m_boolval),
5542 r.get_identifier (m_on_true),
5543 r.get_identifier (m_on_false));
5546 /* The implementation of class gcc::jit::recording::jump. */
5548 /* Implementation of pure virtual hook recording::memento::replay_into
5549 for recording::jump. */
5551 void
5552 recording::jump::replay_into (replayer *r)
5554 playback_block (get_block ())
5555 ->add_jump (playback_location (r),
5556 m_target->playback_block ());
5559 /* Override the poisoned default implementation of
5560 gcc::jit::recording::statement::get_successor_blocks
5562 An unconditional jump has 1 successor block. */
5564 vec <recording::block *>
5565 recording::jump::get_successor_blocks () const
5567 vec <block *> result;
5568 result.create (1);
5569 result.quick_push (m_target);
5570 return result;
5573 /* Implementation of recording::memento::make_debug_string for
5574 a unconditional jump statement. */
5576 recording::string *
5577 recording::jump::make_debug_string ()
5579 return string::from_printf (m_ctxt,
5580 "goto %s;",
5581 m_target->get_debug_string ());
5584 /* Implementation of recording::memento::write_reproducer for
5585 jump statements. */
5587 void
5588 recording::jump::write_reproducer (reproducer &r)
5590 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5591 " %s, /* gcc_jit_location *loc */\n"
5592 " %s); /* gcc_jit_block *target */\n",
5593 r.get_identifier (get_block ()),
5594 r.get_identifier (get_loc ()),
5595 r.get_identifier (m_target));
5598 /* The implementation of class gcc::jit::recording::return_. */
5600 /* Implementation of pure virtual hook recording::memento::replay_into
5601 for recording::return_. */
5603 void
5604 recording::return_::replay_into (replayer *r)
5606 playback_block (get_block ())
5607 ->add_return (playback_location (r),
5608 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
5611 /* Override the poisoned default implementation of
5612 gcc::jit::recording::statement::get_successor_blocks
5614 A return statement has no successor block. */
5616 vec <recording::block *>
5617 recording::return_::get_successor_blocks () const
5619 vec <block *> result;
5620 result.create (0);
5621 return result;
5624 /* Implementation of recording::memento::make_debug_string for
5625 a return statement (covers both those with and without rvalues). */
5627 recording::string *
5628 recording::return_::make_debug_string ()
5630 if (m_rvalue)
5631 return string::from_printf (m_ctxt,
5632 "return %s;",
5633 m_rvalue->get_debug_string ());
5634 else
5635 return string::from_printf (m_ctxt,
5636 "return;");
5639 /* Implementation of recording::memento::write_reproducer for
5640 return statements. */
5642 void
5643 recording::return_::write_reproducer (reproducer &r)
5645 if (m_rvalue)
5646 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5647 " %s, /* gcc_jit_location *loc */\n"
5648 " %s); /* gcc_jit_rvalue *rvalue */\n",
5649 r.get_identifier (get_block ()),
5650 r.get_identifier (get_loc ()),
5651 r.get_identifier_as_rvalue (m_rvalue));
5652 else
5653 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5654 " %s); /* gcc_jit_location *loc */\n",
5655 r.get_identifier (get_block ()),
5656 r.get_identifier (get_loc ()));
5659 /* The implementation of class gcc::jit::recording::case_. */
5661 void
5662 recording::case_::write_reproducer (reproducer &r)
5664 const char *id = r.make_identifier (this, "case");
5665 const char *fmt =
5666 " gcc_jit_case *%s = \n"
5667 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
5668 " %s, /* gcc_jit_rvalue *min_value */\n"
5669 " %s, /* gcc_jit_rvalue *max_value */\n"
5670 " %s); /* gcc_jit_block *dest_block */\n";
5671 r.write (fmt,
5673 r.get_identifier (get_context ()),
5674 r.get_identifier_as_rvalue (m_min_value),
5675 r.get_identifier_as_rvalue (m_max_value),
5676 r.get_identifier (m_dest_block));
5679 recording::string *
5680 recording::case_::make_debug_string ()
5682 return string::from_printf (get_context (),
5683 "case %s ... %s: goto %s;",
5684 m_min_value->get_debug_string (),
5685 m_max_value->get_debug_string (),
5686 m_dest_block->get_debug_string ());
5689 /* The implementation of class gcc::jit::recording::switch_. */
5691 /* gcc::jit::recording::switch_'s constructor. */
5693 recording::switch_::switch_ (block *b,
5694 location *loc,
5695 rvalue *expr,
5696 block *default_block,
5697 int num_cases,
5698 case_ **cases)
5699 : statement (b, loc),
5700 m_expr (expr),
5701 m_default_block (default_block)
5703 m_cases.reserve_exact (num_cases);
5704 for (int i = 0; i< num_cases; i++)
5705 m_cases.quick_push (cases[i]);
5708 /* Implementation of pure virtual hook recording::memento::replay_into
5709 for recording::switch_. */
5711 void
5712 recording::switch_::replay_into (replayer *r)
5714 auto_vec <playback::case_> pcases;
5715 int i;
5716 recording::case_ *rcase;
5717 pcases.reserve_exact (m_cases.length ());
5718 FOR_EACH_VEC_ELT (m_cases, i, rcase)
5720 playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (),
5721 rcase->get_max_value ()->playback_rvalue (),
5722 rcase->get_dest_block ()->playback_block ());
5723 pcases.safe_push (pcase);
5725 playback_block (get_block ())
5726 ->add_switch (playback_location (r),
5727 m_expr->playback_rvalue (),
5728 m_default_block->playback_block (),
5729 &pcases);
5732 /* Override the poisoned default implementation of
5733 gcc::jit::recording::statement::get_successor_blocks
5735 A switch statement has (NUM_CASES + 1) successor blocks. */
5737 vec <recording::block *>
5738 recording::switch_::get_successor_blocks () const
5740 vec <block *> result;
5741 result.create (m_cases.length () + 1);
5742 result.quick_push (m_default_block);
5743 int i;
5744 case_ *c;
5745 FOR_EACH_VEC_ELT (m_cases, i, c)
5746 result.quick_push (c->get_dest_block ());
5747 return result;
5750 /* Implementation of recording::memento::make_debug_string for
5751 a switch statement. */
5753 recording::string *
5754 recording::switch_::make_debug_string ()
5756 auto_vec <char> cases_str;
5757 int i;
5758 case_ *c;
5759 FOR_EACH_VEC_ELT (m_cases, i, c)
5761 size_t len = strlen (c->get_debug_string ());
5762 unsigned idx = cases_str.length ();
5763 cases_str.safe_grow (idx + 1 + len);
5764 cases_str[idx] = ' ';
5765 memcpy (&(cases_str[idx + 1]),
5766 c->get_debug_string (),
5767 len);
5769 cases_str.safe_push ('\0');
5771 return string::from_printf (m_ctxt,
5772 "switch (%s) {default: goto %s;%s}",
5773 m_expr->get_debug_string (),
5774 m_default_block->get_debug_string (),
5775 &cases_str[0]);
5778 /* Implementation of recording::memento::write_reproducer for
5779 switch statements. */
5781 void
5782 recording::switch_::write_reproducer (reproducer &r)
5784 r.make_identifier (this, "switch");
5785 int i;
5786 case_ *c;
5787 const char *cases_id =
5788 r.make_tmp_identifier ("cases_for", this);
5789 r.write (" gcc_jit_case *%s[%i] = {\n",
5790 cases_id,
5791 m_cases.length ());
5792 FOR_EACH_VEC_ELT (m_cases, i, c)
5793 r.write (" %s,\n", r.get_identifier (c));
5794 r.write (" };\n");
5795 const char *fmt =
5796 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
5797 " %s, /* gcc_jit_location *loc */\n"
5798 " %s, /* gcc_jit_rvalue *expr */\n"
5799 " %s, /* gcc_jit_block *default_block */\n"
5800 " %i, /* int num_cases */\n"
5801 " %s); /* gcc_jit_case **cases */\n";
5802 r.write (fmt,
5803 r.get_identifier (get_block ()),
5804 r.get_identifier (get_loc ()),
5805 r.get_identifier_as_rvalue (m_expr),
5806 r.get_identifier (m_default_block),
5807 m_cases.length (),
5808 cases_id);
5811 } // namespace gcc::jit
5813 } // namespace gcc