Daily bump.
[official-gcc.git] / gcc / jit / jit-recording.c
blob70bd171a892024a1bd86f2b53adbbbff34fc56b1
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"
28 #include "timevar.h"
30 #include <pthread.h>
32 #include "jit-common.h"
33 #include "jit-builtins.h"
34 #include "jit-logging.h"
35 #include "jit-recording.h"
36 #include "jit-playback.h"
38 namespace gcc {
39 namespace jit {
41 // class dump
43 dump::dump (recording::context &ctxt,
44 const char *filename,
45 bool update_locations)
46 : m_ctxt (ctxt),
47 m_filename (filename),
48 m_update_locations (update_locations),
49 m_line (0),
50 m_column (0)
52 m_file = fopen (filename, "w");
53 if (!m_file)
54 ctxt.add_error (NULL,
55 "error opening dump file %s for writing: %s",
56 filename,
57 xstrerror (errno));
60 dump::~dump ()
62 if (m_file)
64 int err = fclose (m_file);
65 if (err)
66 m_ctxt.add_error (NULL,
67 "error closing dump file %s: %s",
68 m_filename,
69 xstrerror (errno));
73 /* Write the given message to the dump, using printf-formatting
74 conventions, updating the line/column within the dump.
76 Emit an error on the context if a failure occurs. */
78 void
79 dump::write (const char *fmt, ...)
81 int len;
82 va_list ap;
83 char *buf;
85 /* If there was an error opening the file, we've already reported it.
86 Don't attempt further work. */
87 if (!m_file)
88 return;
90 va_start (ap, fmt);
91 len = vasprintf (&buf, fmt, ap);
92 va_end (ap);
94 if (buf == NULL || len < 0)
96 m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
97 m_filename);
98 return;
101 if (fwrite (buf, strlen (buf), 1, m_file) != 1)
102 m_ctxt.add_error (NULL, "error writing to dump file %s",
103 m_filename);
105 /* Flush after each line, to ease debugging crashes. */
106 fflush (m_file);
108 /* Update line/column: */
109 for (const char *ptr = buf; *ptr; ptr++)
111 if ('\n' == *ptr)
113 m_line++;
114 m_column = 0;
116 else
117 m_column++;
120 free (buf);
123 /* Construct a gcc::jit::recording::location instance for the current
124 location within the dump. */
126 recording::location *
127 dump::make_location () const
129 return m_ctxt.new_location (m_filename, m_line, m_column,
130 /* We need to flag such locations as *not*
131 created by the user, so that
132 reproducer::get_identifier can cope with
133 them appearing *after* the memento that
134 refers to them. */
135 false);
138 /* A collection of allocations, all of which can be released together, to
139 avoid needing to track and release them individually. */
141 class allocator
143 public:
144 ~allocator ();
146 char *
147 xstrdup_printf (const char *, ...)
148 ATTRIBUTE_RETURNS_NONNULL
149 GNU_PRINTF(2, 3);
151 char *
152 xstrdup_printf_va (const char *, va_list ap)
153 ATTRIBUTE_RETURNS_NONNULL
154 GNU_PRINTF(2, 0);
156 private:
157 auto_vec <void *> m_buffers;
160 /* allocator's destructor. Call "free" on all of the allocations. */
162 allocator::~allocator ()
164 unsigned i;
165 void *buffer;
166 FOR_EACH_VEC_ELT (m_buffers, i, buffer)
167 free (buffer);
170 /* Formatted printing, allocating to a buffer (or exiting the process if
171 the allocation fails).
173 The buffer exists until the allocator is cleaned up, and is freed at
174 that point, so the caller doesn't need to track the result. */
176 char *
177 allocator::xstrdup_printf (const char *fmt, ...)
179 char *result;
180 va_list ap;
181 va_start (ap, fmt);
182 result = xstrdup_printf_va (fmt, ap);
183 va_end (ap);
184 return result;
187 /* Formatted printing, allocating to a buffer (or exiting the process if
188 the allocation fails).
190 The buffer exists until the allocator is cleaned up, and is freed at
191 that point, so the caller doesn't need to track the result. */
193 char *
194 allocator::xstrdup_printf_va (const char *fmt, va_list ap)
196 char *result = xvasprintf (fmt, ap);
197 m_buffers.safe_push (result);
198 return result;
201 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
202 implementing gcc_jit_context_dump_reproducer_to_file. */
204 class reproducer : public dump
206 public:
207 reproducer (recording::context &ctxt,
208 const char *filename);
210 void
211 write_params (const vec <recording::context *> &contexts);
213 void
214 write_args (const vec <recording::context *> &contexts);
216 const char *
217 make_identifier (recording::memento *m, const char *prefix);
219 const char *
220 make_tmp_identifier (const char *prefix, recording::memento *m);
222 const char *
223 get_identifier (recording::context *ctxt);
225 const char *
226 get_identifier (recording::memento *m);
228 const char *
229 get_identifier_as_rvalue (recording::rvalue *m);
231 const char *
232 get_identifier_as_lvalue (recording::lvalue *m);
234 const char *
235 get_identifier_as_type (recording::type *m);
237 char *
238 xstrdup_printf (const char *, ...)
239 ATTRIBUTE_RETURNS_NONNULL
240 GNU_PRINTF(2, 3);
242 private:
243 hash_map<recording::memento *, const char *> m_identifiers;
244 allocator m_allocator;
247 /* gcc::jit::reproducer's constructor. */
249 reproducer::reproducer (recording::context &ctxt,
250 const char *filename) :
251 dump (ctxt, filename, 0),
252 m_identifiers (),
253 m_allocator ()
257 /* Write out a list of contexts as a set of parameters within a
258 C function declaration. */
260 void
261 reproducer::write_params (const vec <recording::context *> &contexts)
263 unsigned i;
264 recording::context *ctxt;
265 FOR_EACH_VEC_ELT (contexts, i, ctxt)
267 write ("gcc_jit_context *%s",
268 get_identifier (ctxt));
269 if (i < contexts.length () - 1)
270 write (",\n"
271 " ");
275 /* Write out a list of contexts as a set of arguments within a call
276 to a C function. */
278 void
279 reproducer::write_args (const vec <recording::context *> &contexts)
281 unsigned i;
282 recording::context *ctxt;
283 FOR_EACH_VEC_ELT (contexts, i, ctxt)
285 write ("%s",
286 get_identifier (ctxt));
287 if (i < contexts.length () - 1)
288 write (",\n"
289 " ");
293 /* Generate a C identifier for the given memento, associating the generated
294 buffer with the memento (for future calls to get_identifier et al).
296 The reproducer will eventually clean up the buffer in its dtor. */
297 const char *
298 reproducer::make_identifier (recording::memento *m, const char *prefix)
300 char *result;
301 if (strlen (m->get_debug_string ()) < 100)
303 result = m_allocator.xstrdup_printf ("%s_%s_%p",
304 prefix,
305 m->get_debug_string (),
306 (void *) m);
307 for (char *p = result; *p; p++)
308 if (!ISALNUM (*p))
309 *p = '_';
311 else
312 result = m_allocator.xstrdup_printf ("%s_%p",
313 prefix, (void *) m);
314 m_identifiers.put (m, result);
315 return result;
318 /* Generate a C identifier for a temporary variable.
319 The reproducer will eventually clean up the buffer in its dtor. */
321 const char *
322 reproducer::make_tmp_identifier (const char *prefix, recording::memento *m)
324 return m_allocator.xstrdup_printf ("%s_%s",
325 prefix, get_identifier (m));
328 /* Generate a C identifier for the given context.
329 The reproducer will eventually clean up the buffer in its dtor. */
331 const char *
332 reproducer::get_identifier (recording::context *ctxt)
334 return m_allocator.xstrdup_printf ("ctxt_%p",
335 (void *)ctxt);
338 /* Locate the C identifier for the given memento, which is assumed to
339 have already been created via make_identifier. */
341 const char *
342 reproducer::get_identifier (recording::memento *m)
344 if (!m)
345 return "NULL";
347 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
348 and hence these locations appear in the context's memento list
349 out-of-order: they appear in the context's memento list *after*
350 the memento that refers to them. For this case, it's simplest to
351 pretend that they're NULL when writing out the code to recreate the
352 memento that uses them. */
353 if (recording::location *loc = m->dyn_cast_location ())
354 if (!loc->created_by_user ())
355 return "NULL";
357 const char **slot = m_identifiers.get (m);
358 if (!slot)
360 get_context ().add_error (NULL,
361 "unable to find identifier for %p: %s",
362 (void *)m,
363 m->get_debug_string ());
364 gcc_unreachable ();
366 return *slot;
369 /* Locate the C identifier for the given rvalue, wrapping it within
370 a gcc_*_as_rvalue upcast if necessary. */
372 const char *
373 reproducer::get_identifier_as_rvalue (recording::rvalue *m)
375 return m->access_as_rvalue (*this);
378 /* Locate the C identifier for the given lvalue, wrapping it within
379 a gcc_*_as_lvalue upcast if necessary. */
381 const char *
382 reproducer::get_identifier_as_lvalue (recording::lvalue *m)
384 return m->access_as_lvalue (*this);
387 /* Locate the C identifier for the given type, wrapping it within
388 a gcc_*_as_type upcast if necessary. */
390 const char *
391 reproducer::get_identifier_as_type (recording::type *m)
393 return m->access_as_type (*this);
396 /* Formatted printing, allocating to a buffer (or exiting the process if
397 the allocation fails).
399 The buffer exists until the allocator is cleaned up, and is freed at
400 that point, so the caller doesn't need to track the result.
402 Note that we can't use ggc_printf since we're not within the compiler
403 proper (when within gcc_jit_context_dump_reproducer_to_file). */
405 char *
406 reproducer::xstrdup_printf (const char *fmt, ...)
408 char *result;
409 va_list ap;
410 va_start (ap, fmt);
411 result = m_allocator.xstrdup_printf_va (fmt, ap);
412 va_end (ap);
413 return result;
416 /**********************************************************************
417 Recording.
418 **********************************************************************/
420 /* Get the playback::location for the given recording::location,
421 handling a NULL input with a NULL output. */
423 playback::location *
424 recording::playback_location (replayer *r, recording::location *loc)
426 if (loc)
427 return loc->playback_location (r);
428 else
429 return NULL;
432 /* Get a const char * for the given recording::string
433 handling a NULL input with a NULL output. */
435 const char *
436 recording::playback_string (recording::string *str)
438 if (str)
439 return str->c_str ();
440 else
441 return NULL;
444 /* Get the playback::block for the given recording::block,
445 handling a NULL input with a NULL output. */
447 playback::block *
448 recording::playback_block (recording::block *b)
450 if (b)
451 return b->playback_block ();
452 else
453 return NULL;
456 /* Methods of cc::jit::recording::context. */
458 /* The constructor for gcc::jit::recording::context, used by
459 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
461 recording::context::context (context *parent_ctxt)
462 : log_user (NULL),
463 m_parent_ctxt (parent_ctxt),
464 m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this),
465 m_timer (NULL),
466 m_error_count (0),
467 m_first_error_str (NULL),
468 m_owns_first_error_str (false),
469 m_last_error_str (NULL),
470 m_owns_last_error_str (false),
471 m_mementos (),
472 m_compound_types (),
473 m_globals (),
474 m_functions (),
475 m_FILE_type (NULL),
476 m_builtins_manager(NULL)
478 if (parent_ctxt)
480 /* Inherit options from parent. */
481 for (unsigned i = 0;
482 i < sizeof (m_str_options) / sizeof (m_str_options[0]);
483 i++)
485 const char *parent_opt = parent_ctxt->m_str_options[i];
486 m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
488 memcpy (m_int_options,
489 parent_ctxt->m_int_options,
490 sizeof (m_int_options));
491 memcpy (m_bool_options,
492 parent_ctxt->m_bool_options,
493 sizeof (m_bool_options));
494 memcpy (m_inner_bool_options,
495 parent_ctxt->m_inner_bool_options,
496 sizeof (m_inner_bool_options));
497 set_logger (parent_ctxt->get_logger ());
499 else
501 memset (m_str_options, 0, sizeof (m_str_options));
502 memset (m_int_options, 0, sizeof (m_int_options));
503 memset (m_bool_options, 0, sizeof (m_bool_options));
504 memset (m_inner_bool_options, 0, sizeof (m_inner_bool_options));
507 memset (m_basic_types, 0, sizeof (m_basic_types));
510 /* The destructor for gcc::jit::recording::context, implicitly used by
511 gcc_jit_context_release. */
513 recording::context::~context ()
515 JIT_LOG_SCOPE (get_logger ());
516 int i;
517 memento *m;
518 FOR_EACH_VEC_ELT (m_mementos, i, m)
520 delete m;
523 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
524 free (m_str_options[i]);
526 char *optname;
527 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
528 free (optname);
530 if (m_builtins_manager)
531 delete m_builtins_manager;
533 if (m_owns_first_error_str)
534 free (m_first_error_str);
536 if (m_owns_last_error_str)
537 if (m_last_error_str != m_first_error_str)
538 free (m_last_error_str);
541 /* Add the given mememto to the list of those tracked by this
542 gcc::jit::recording::context, so that e.g. it can be deleted
543 when this context is released. */
545 void
546 recording::context::record (memento *m)
548 gcc_assert (m);
550 m_mementos.safe_push (m);
553 /* Replay this context (and any parents) into the given replayer. */
555 void
556 recording::context::replay_into (replayer *r)
558 JIT_LOG_SCOPE (get_logger ());
559 int i;
560 memento *m;
562 /* If we have a parent context, we must replay it. This will
563 recursively walk backwards up the historical tree, then replay things
564 forwards "in historical order", starting with the ultimate parent
565 context, until we reach the "this" context.
567 Note that we fully replay the parent, then fully replay the child,
568 which means that inter-context references can only exist from child
569 to parent, not the other way around.
571 All of this replaying is suboptimal - it would be better to do the
572 work for the parent context *once*, rather than replaying the parent
573 every time we replay each child. However, fixing this requires deep
574 surgery to lifetime-management: we'd need every context family tree
575 to have its own GC heap, and to initialize the GCC code to use that
576 heap (with a mutex on such a heap). */
577 if (m_parent_ctxt)
578 m_parent_ctxt->replay_into (r);
580 if (r->errors_occurred ())
581 return;
583 /* Replay this context's saved operations into r. */
584 FOR_EACH_VEC_ELT (m_mementos, i, m)
586 /* Disabled low-level debugging, here if we need it: print what
587 we're replaying.
588 Note that the calls to get_debug_string might lead to more
589 mementos being created for the strings.
590 This can also be used to exercise the debug_string
591 machinery. */
592 if (0)
593 printf ("context %p replaying (%p): %s\n",
594 (void *)this, (void *)m, m->get_debug_string ());
596 m->replay_into (r);
598 if (r->errors_occurred ())
599 return;
603 /* During a playback, we associate objects from the recording with
604 their counterparts during this playback.
606 For simplicity, we store this within the recording objects.
608 The following method cleans away these associations, to ensure that
609 we never have out-of-date associations lingering on subsequent
610 playbacks (the objects pointed to are GC-managed, but the
611 recording objects don't own refs to them). */
613 void
614 recording::context::disassociate_from_playback ()
616 JIT_LOG_SCOPE (get_logger ());
617 int i;
618 memento *m;
620 if (m_parent_ctxt)
621 m_parent_ctxt->disassociate_from_playback ();
623 FOR_EACH_VEC_ELT (m_mementos, i, m)
625 m->set_playback_obj (NULL);
629 /* Create a recording::string instance and add it to this context's list
630 of mementos.
632 This creates a fresh copy of the given 0-terminated buffer. */
634 recording::string *
635 recording::context::new_string (const char *text)
637 if (!text)
638 return NULL;
640 recording::string *result = new string (this, text);
641 record (result);
642 return result;
645 /* Create a recording::location instance and add it to this context's
646 list of mementos.
648 Implements the post-error-checking part of
649 gcc_jit_context_new_location. */
651 recording::location *
652 recording::context::new_location (const char *filename,
653 int line,
654 int column,
655 bool created_by_user)
657 recording::location *result =
658 new recording::location (this,
659 new_string (filename),
660 line, column,
661 created_by_user);
662 record (result);
663 return result;
666 /* If we haven't seen this enum value yet, create a recording::type
667 instance and add it to this context's list of mementos.
669 If we have seen it before, reuse our cached value, so that repeated
670 calls on the context give the same object.
672 If we have a parent context, the cache is within the ultimate
673 ancestor context.
675 Implements the post-error-checking part of
676 gcc_jit_context_get_type. */
678 recording::type *
679 recording::context::get_type (enum gcc_jit_types kind)
681 if (!m_basic_types[kind])
683 if (m_parent_ctxt)
684 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
685 else
687 recording::type *result = new memento_of_get_type (this, kind);
688 record (result);
689 m_basic_types[kind] = result;
693 return m_basic_types[kind];
696 /* Get a recording::type instance for the given size and signedness.
697 This is implemented in terms of recording::context::get_type
698 above.
700 Implements the post-error-checking part of
701 gcc_jit_context_get_int_type. */
703 recording::type *
704 recording::context::get_int_type (int num_bytes, int is_signed)
706 /* We can't use a switch here since some of the values are macros affected
707 by options; e.g. i386.h has
708 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
709 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
710 are in bits, rather than bytes.
712 const int num_bits = num_bytes * 8;
713 if (num_bits == INT_TYPE_SIZE)
714 return get_type (is_signed
715 ? GCC_JIT_TYPE_INT
716 : GCC_JIT_TYPE_UNSIGNED_INT);
717 if (num_bits == CHAR_TYPE_SIZE)
718 return get_type (is_signed
719 ? GCC_JIT_TYPE_SIGNED_CHAR
720 : GCC_JIT_TYPE_UNSIGNED_CHAR);
721 if (num_bits == SHORT_TYPE_SIZE)
722 return get_type (is_signed
723 ? GCC_JIT_TYPE_SHORT
724 : GCC_JIT_TYPE_UNSIGNED_SHORT);
725 if (num_bits == LONG_TYPE_SIZE)
726 return get_type (is_signed
727 ? GCC_JIT_TYPE_LONG
728 : GCC_JIT_TYPE_UNSIGNED_LONG);
729 if (num_bits == LONG_LONG_TYPE_SIZE)
730 return get_type (is_signed
731 ? GCC_JIT_TYPE_LONG_LONG
732 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
734 /* Some other size, not corresponding to the C int types. */
735 /* To be written: support arbitrary other sizes, sharing by
736 memoizing at the recording::context level? */
737 gcc_unreachable ();
740 /* Create a recording::type instance and add it to this context's list
741 of mementos.
743 Implements the post-error-checking part of
744 gcc_jit_context_new_array_type. */
746 recording::type *
747 recording::context::new_array_type (recording::location *loc,
748 recording::type *element_type,
749 int num_elements)
751 if (struct_ *s = element_type->dyn_cast_struct ())
752 if (!s->get_fields ())
754 add_error (NULL,
755 "cannot create an array of type %s"
756 " until the fields have been set",
757 s->get_name ()->c_str ());
758 return NULL;
760 recording::type *result =
761 new recording::array_type (this, loc, element_type, num_elements);
762 record (result);
763 return result;
766 /* Create a recording::field instance and add it to this context's list
767 of mementos.
769 Implements the post-error-checking part of
770 gcc_jit_context_new_field. */
772 recording::field *
773 recording::context::new_field (recording::location *loc,
774 recording::type *type,
775 const char *name)
777 recording::field *result =
778 new recording::field (this, loc, type, new_string (name));
779 record (result);
780 return result;
783 /* Create a recording::struct_ instance and add it to this context's
784 list of mementos and list of compound types.
786 Implements the post-error-checking part of
787 gcc_jit_context_new_struct_type. */
789 recording::struct_ *
790 recording::context::new_struct_type (recording::location *loc,
791 const char *name)
793 recording::struct_ *result = new struct_ (this, loc, new_string (name));
794 record (result);
795 m_compound_types.safe_push (result);
796 return result;
799 /* Create a recording::union_ instance and add it to this context's
800 list of mementos and list of compound types.
802 Implements the first post-error-checking part of
803 gcc_jit_context_new_union_type. */
805 recording::union_ *
806 recording::context::new_union_type (recording::location *loc,
807 const char *name)
809 recording::union_ *result = new union_ (this, loc, new_string (name));
810 record (result);
811 m_compound_types.safe_push (result);
812 return result;
815 /* Create a recording::function_type instance and add it to this context's
816 list of mementos.
818 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
820 recording::function_type *
821 recording::context::new_function_type (recording::type *return_type,
822 int num_params,
823 recording::type **param_types,
824 int is_variadic)
826 recording::function_type *fn_type
827 = new function_type (this,
828 return_type,
829 num_params,
830 param_types,
831 is_variadic);
832 record (fn_type);
833 return fn_type;
836 /* Create a recording::type instance and add it to this context's list
837 of mementos.
839 Implements the post-error-checking part of
840 gcc_jit_context_new_function_ptr_type. */
842 recording::type *
843 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
844 recording::type *return_type,
845 int num_params,
846 recording::type **param_types,
847 int is_variadic)
849 recording::function_type *fn_type
850 = new_function_type (return_type,
851 num_params,
852 param_types,
853 is_variadic);
855 /* Return a pointer-type to the function type. */
856 return fn_type->get_pointer ();
859 /* Create a recording::param instance and add it to this context's list
860 of mementos.
862 Implements the post-error-checking part of
863 gcc_jit_context_new_param. */
865 recording::param *
866 recording::context::new_param (recording::location *loc,
867 recording::type *type,
868 const char *name)
870 recording::param *result = new recording::param (this, loc, type, new_string (name));
871 record (result);
872 return result;
875 /* Create a recording::function instance and add it to this context's list
876 of mementos and list of functions.
878 Implements the post-error-checking part of
879 gcc_jit_context_new_function. */
881 recording::function *
882 recording::context::new_function (recording::location *loc,
883 enum gcc_jit_function_kind kind,
884 recording::type *return_type,
885 const char *name,
886 int num_params,
887 recording::param **params,
888 int is_variadic,
889 enum built_in_function builtin_id)
891 recording::function *result =
892 new recording::function (this,
893 loc, kind, return_type,
894 new_string (name),
895 num_params, params, is_variadic,
896 builtin_id);
897 record (result);
898 m_functions.safe_push (result);
900 return result;
903 /* Locate the builtins_manager (if any) for this family of contexts,
904 creating it if it doesn't exist already.
906 All of the recording contexts in a family share one builtins_manager:
907 if we have a child context, follow the parent links to get the
908 ultimate ancestor context, and look for it/store it there. */
910 builtins_manager *
911 recording::context::get_builtins_manager ()
913 if (m_parent_ctxt)
914 return m_parent_ctxt->get_builtins_manager ();
916 if (!m_builtins_manager)
917 m_builtins_manager = new builtins_manager (this);
919 return m_builtins_manager;
922 /* Get a recording::function instance, which is lazily-created and added
923 to the context's lists of mementos.
925 Implements the post-error-checking part of
926 gcc_jit_context_get_builtin_function. */
928 recording::function *
929 recording::context::get_builtin_function (const char *name)
931 builtins_manager *bm = get_builtins_manager ();
932 return bm->get_builtin_function (name);
935 /* Create a recording::global instance and add it to this context's list
936 of mementos.
938 Implements the post-error-checking part of
939 gcc_jit_context_new_global. */
941 recording::lvalue *
942 recording::context::new_global (recording::location *loc,
943 enum gcc_jit_global_kind kind,
944 recording::type *type,
945 const char *name)
947 recording::global *result =
948 new recording::global (this, loc, kind, type, new_string (name));
949 record (result);
950 m_globals.safe_push (result);
952 return result;
955 /* Create a recording::memento_of_new_string_literal instance and add it
956 to this context's list of mementos.
958 Implements the post-error-checking part of
959 gcc_jit_context_new_string_literal. */
961 recording::rvalue *
962 recording::context::new_string_literal (const char *value)
964 recording::rvalue *result =
965 new memento_of_new_string_literal (this, NULL, new_string (value));
966 record (result);
967 return result;
970 /* Create a recording::unary_op instance and add it to this context's
971 list of mementos.
973 Implements the post-error-checking part of
974 gcc_jit_context_new_unary_op. */
976 recording::rvalue *
977 recording::context::new_unary_op (recording::location *loc,
978 enum gcc_jit_unary_op op,
979 recording::type *result_type,
980 recording::rvalue *a)
982 recording::rvalue *result =
983 new unary_op (this, loc, op, result_type, a);
984 record (result);
985 return result;
988 /* Create a recording::binary_op instance and add it to this context's
989 list of mementos.
991 Implements the post-error-checking part of
992 gcc_jit_context_new_binary_op. */
994 recording::rvalue *
995 recording::context::new_binary_op (recording::location *loc,
996 enum gcc_jit_binary_op op,
997 recording::type *result_type,
998 recording::rvalue *a,
999 recording::rvalue *b)
1001 recording::rvalue *result =
1002 new binary_op (this, loc, op, result_type, a, b);
1003 record (result);
1004 return result;
1007 /* Create a recording::comparison instance and add it to this context's
1008 list of mementos.
1010 Implements the post-error-checking part of
1011 gcc_jit_context_new_comparison. */
1013 recording::rvalue *
1014 recording::context::new_comparison (recording::location *loc,
1015 enum gcc_jit_comparison op,
1016 recording::rvalue *a,
1017 recording::rvalue *b)
1019 recording::rvalue *result = new comparison (this, loc, op, a, b);
1020 record (result);
1021 return result;
1024 /* Create a recording::cast instance and add it to this context's list
1025 of mementos.
1027 Implements the post-error-checking part of
1028 gcc_jit_context_new_cast. */
1030 recording::rvalue *
1031 recording::context::new_cast (recording::location *loc,
1032 recording::rvalue *expr,
1033 recording::type *type_)
1035 recording::rvalue *result = new cast (this, loc, expr, type_);
1036 record (result);
1037 return result;
1040 /* Create a recording::call instance and add it to this context's list
1041 of mementos.
1043 Implements the post-error-checking part of
1044 gcc_jit_context_new_call. */
1046 recording::rvalue *
1047 recording::context::new_call (recording::location *loc,
1048 function *func,
1049 int numargs , recording::rvalue **args)
1051 recording::rvalue *result = new call (this, loc, func, numargs, args);
1052 record (result);
1053 return result;
1056 /* Create a recording::call_through_ptr instance and add it to this
1057 context's list of mementos.
1059 Implements the post-error-checking part of
1060 gcc_jit_context_new_call_through_ptr. */
1062 recording::rvalue *
1063 recording::context::new_call_through_ptr (recording::location *loc,
1064 recording::rvalue *fn_ptr,
1065 int numargs,
1066 recording::rvalue **args)
1068 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
1069 record (result);
1070 return result;
1073 /* Create a recording::array_access instance and add it to this context's list
1074 of mementos.
1076 Implements the post-error-checking part of
1077 gcc_jit_context_new_array_access. */
1079 recording::lvalue *
1080 recording::context::new_array_access (recording::location *loc,
1081 recording::rvalue *ptr,
1082 recording::rvalue *index)
1084 recording::lvalue *result = new array_access (this, loc, ptr, index);
1085 record (result);
1086 return result;
1089 /* Create a recording::case_ instance and add it to this context's list
1090 of mementos.
1092 Implements the post-error-checking part of
1093 gcc_jit_context_new_case. */
1095 recording::case_ *
1096 recording::context::new_case (recording::rvalue *min_value,
1097 recording::rvalue *max_value,
1098 recording::block *block)
1100 recording::case_ *result = new case_ (this, min_value, max_value, block);
1101 record (result);
1102 return result;
1105 /* Set the given string option for this context, or add an error if
1106 it's not recognized.
1108 Implements the post-error-checking part of
1109 gcc_jit_context_set_str_option. */
1111 void
1112 recording::context::set_str_option (enum gcc_jit_str_option opt,
1113 const char *value)
1115 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
1117 add_error (NULL,
1118 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
1119 return;
1121 free (m_str_options[opt]);
1122 m_str_options[opt] = value ? xstrdup (value) : NULL;
1123 log_str_option (opt);
1126 /* Set the given integer option for this context, or add an error if
1127 it's not recognized.
1129 Implements the post-error-checking part of
1130 gcc_jit_context_set_int_option. */
1132 void
1133 recording::context::set_int_option (enum gcc_jit_int_option opt,
1134 int value)
1136 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
1138 add_error (NULL,
1139 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
1140 return;
1142 m_int_options[opt] = value;
1143 log_int_option (opt);
1146 /* Set the given boolean option for this context, or add an error if
1147 it's not recognized.
1149 Implements the post-error-checking part of
1150 gcc_jit_context_set_bool_option. */
1152 void
1153 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
1154 int value)
1156 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
1158 add_error (NULL,
1159 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
1160 return;
1162 m_bool_options[opt] = value ? true : false;
1163 log_bool_option (opt);
1166 void
1167 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt,
1168 int value)
1170 gcc_assert (inner_opt >= 0 && inner_opt < NUM_INNER_BOOL_OPTIONS);
1171 m_inner_bool_options[inner_opt] = value ? true : false;
1172 log_inner_bool_option (inner_opt);
1176 /* Add the given optname to this context's list of extra options.
1178 Implements the post-error-checking part of
1179 gcc_jit_context_add_command_line_option. */
1181 void
1182 recording::context::add_command_line_option (const char *optname)
1184 m_command_line_options.safe_push (xstrdup (optname));
1187 /* Add any user-provided extra options, starting with any from
1188 parent contexts.
1189 Called by playback::context::make_fake_args. */
1191 void
1192 recording::context::append_command_line_options (vec <char *> *argvec)
1194 if (m_parent_ctxt)
1195 m_parent_ctxt->append_command_line_options (argvec);
1197 int i;
1198 char *optname;
1199 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1200 argvec->safe_push (xstrdup (optname));
1203 /* Add the given dumpname/out_ptr pair to this context's list of requested
1204 dumps.
1206 Implements the post-error-checking part of
1207 gcc_jit_context_enable_dump. */
1209 void
1210 recording::context::enable_dump (const char *dumpname,
1211 char **out_ptr)
1213 requested_dump d;
1214 gcc_assert (dumpname);
1215 gcc_assert (out_ptr);
1217 d.m_dumpname = dumpname;
1218 d.m_out_ptr = out_ptr;
1219 *out_ptr = NULL;
1220 m_requested_dumps.safe_push (d);
1223 /* Validate this context, and if it passes, compile it to memory
1224 (within a mutex).
1226 Implements the post-error-checking part of
1227 gcc_jit_context_compile. */
1229 result *
1230 recording::context::compile ()
1232 JIT_LOG_SCOPE (get_logger ());
1234 log_all_options ();
1236 validate ();
1238 if (errors_occurred ())
1239 return NULL;
1241 /* Set up a compile_to_memory playback context. */
1242 ::gcc::jit::playback::compile_to_memory replayer (this);
1244 /* Use it. */
1245 replayer.compile ();
1247 /* Get the jit::result (or NULL) from the
1248 compile_to_memory playback context. */
1249 return replayer.get_result_obj ();
1252 /* Validate this context, and if it passes, compile it to a file
1253 (within a mutex).
1255 Implements the post-error-checking part of
1256 gcc_jit_context_compile_to_file. */
1258 void
1259 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
1260 const char *output_path)
1262 JIT_LOG_SCOPE (get_logger ());
1264 log_all_options ();
1266 validate ();
1268 if (errors_occurred ())
1269 return;
1271 /* Set up a compile_to_file playback context. */
1272 ::gcc::jit::playback::compile_to_file replayer (this,
1273 output_kind,
1274 output_path);
1276 /* Use it. */
1277 replayer.compile ();
1280 /* Format the given error using printf's conventions, print
1281 it to stderr, and add it to the context. */
1283 void
1284 recording::context::add_error (location *loc, const char *fmt, ...)
1286 va_list ap;
1287 va_start (ap, fmt);
1288 add_error_va (loc, fmt, ap);
1289 va_end (ap);
1292 /* Format the given error using printf's conventions, print
1293 it to stderr, and add it to the context. */
1295 void
1296 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
1298 int len;
1299 char *malloced_msg;
1300 const char *errmsg;
1301 bool has_ownership;
1303 JIT_LOG_SCOPE (get_logger ());
1305 len = vasprintf (&malloced_msg, fmt, ap);
1306 if (malloced_msg == NULL || len < 0)
1308 errmsg = "out of memory generating error message";
1309 has_ownership = false;
1311 else
1313 errmsg = malloced_msg;
1314 has_ownership = true;
1316 if (get_logger ())
1317 get_logger ()->log ("error %i: %s", m_error_count, errmsg);
1319 const char *ctxt_progname =
1320 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
1321 if (!ctxt_progname)
1322 ctxt_progname = "libgccjit.so";
1324 if (loc)
1325 fprintf (stderr, "%s: %s: error: %s\n",
1326 ctxt_progname,
1327 loc->get_debug_string (),
1328 errmsg);
1329 else
1330 fprintf (stderr, "%s: error: %s\n",
1331 ctxt_progname,
1332 errmsg);
1334 if (!m_error_count)
1336 m_first_error_str = const_cast <char *> (errmsg);
1337 m_owns_first_error_str = has_ownership;
1340 if (m_owns_last_error_str)
1341 if (m_last_error_str != m_first_error_str)
1342 free (m_last_error_str);
1343 m_last_error_str = const_cast <char *> (errmsg);
1344 m_owns_last_error_str = has_ownership;
1346 m_error_count++;
1349 /* Get the message for the first error that occurred on this context, or
1350 NULL if no errors have occurred on it.
1352 Implements the post-error-checking part of
1353 gcc_jit_context_get_first_error. */
1355 const char *
1356 recording::context::get_first_error () const
1358 return m_first_error_str;
1361 /* Get the message for the last error that occurred on this context, or
1362 NULL if no errors have occurred on it.
1364 Implements the post-error-checking part of
1365 gcc_jit_context_get_last_error. */
1367 const char *
1368 recording::context::get_last_error () const
1370 return m_last_error_str;
1373 /* Lazily generate and record a recording::type representing an opaque
1374 struct named "FILE".
1376 For use if client code tries to dereference the result of
1377 get_type (GCC_JIT_TYPE_FILE_PTR). */
1379 recording::type *
1380 recording::context::get_opaque_FILE_type ()
1382 if (!m_FILE_type)
1383 m_FILE_type = new_struct_type (NULL, "FILE");
1384 return m_FILE_type;
1387 /* Dump a C-like representation of the given context to the given path.
1388 If UPDATE_LOCATIONS is true, update the locations within the
1389 context's mementos to point to the dumpfile.
1391 Implements the post-error-checking part of
1392 gcc_jit_context_dump_to_file. */
1394 void
1395 recording::context::dump_to_file (const char *path, bool update_locations)
1397 int i;
1398 dump d (*this, path, update_locations);
1400 /* Forward declaration of structs and unions. */
1401 compound_type *st;
1402 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1404 d.write ("%s;\n\n", st->get_debug_string ());
1407 /* Content of structs, where set. */
1408 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1409 if (st->get_fields ())
1411 st->get_fields ()->write_to_dump (d);
1412 d.write ("\n");
1415 /* Globals. */
1416 global *g;
1417 FOR_EACH_VEC_ELT (m_globals, i, g)
1419 g->write_to_dump (d);
1421 if (!m_globals.is_empty ())
1422 d.write ("\n");
1424 function *fn;
1425 FOR_EACH_VEC_ELT (m_functions, i, fn)
1427 fn->write_to_dump (d);
1431 static const char * const
1432 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
1433 "GCC_JIT_STR_OPTION_PROGNAME"
1436 static const char * const
1437 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
1438 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1441 static const char * const
1442 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
1443 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1444 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1445 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1446 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1447 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1448 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1449 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1450 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1453 static const char * const
1454 inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = {
1455 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1456 "gcc_jit_context_set_bool_use_external_driver"
1459 /* Write the current value of all options to the log file (if any). */
1461 void
1462 recording::context::log_all_options () const
1464 int opt_idx;
1466 if (!get_logger ())
1467 return;
1469 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1470 log_str_option ((enum gcc_jit_str_option)opt_idx);
1472 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1473 log_int_option ((enum gcc_jit_int_option)opt_idx);
1475 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1476 log_bool_option ((enum gcc_jit_bool_option)opt_idx);
1477 for (opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1478 log_inner_bool_option ((enum inner_bool_option)opt_idx);
1481 /* Write the current value of the given string option to the
1482 log file (if any). */
1484 void
1485 recording::context::log_str_option (enum gcc_jit_str_option opt) const
1487 gcc_assert (opt < GCC_JIT_NUM_STR_OPTIONS);
1488 if (get_logger ())
1490 if (m_str_options[opt])
1491 log ("%s: \"%s\"",
1492 str_option_reproducer_strings[opt],
1493 m_str_options[opt]);
1494 else
1495 log ("%s: NULL",
1496 str_option_reproducer_strings[opt]);
1500 /* Write the current value of the given int option to the
1501 log file (if any). */
1503 void
1504 recording::context::log_int_option (enum gcc_jit_int_option opt) const
1506 gcc_assert (opt < GCC_JIT_NUM_INT_OPTIONS);
1507 if (get_logger ())
1508 log ("%s: %i",
1509 int_option_reproducer_strings[opt],
1510 m_int_options[opt]);
1513 /* Write the current value of the given bool option to the
1514 log file (if any). */
1516 void
1517 recording::context::log_bool_option (enum gcc_jit_bool_option opt) const
1519 gcc_assert (opt < GCC_JIT_NUM_BOOL_OPTIONS);
1520 if (get_logger ())
1521 log ("%s: %s",
1522 bool_option_reproducer_strings[opt],
1523 m_bool_options[opt] ? "true" : "false");
1526 /* Write the current value of the given "inner" bool option to the
1527 log file (if any). */
1529 void
1530 recording::context::log_inner_bool_option (enum inner_bool_option opt) const
1532 gcc_assert (opt < NUM_INNER_BOOL_OPTIONS);
1533 if (get_logger ())
1534 log ("%s: %s",
1535 inner_bool_option_reproducer_strings[opt],
1536 m_inner_bool_options[opt] ? "true" : "false");
1539 /* Write C source code to PATH that attempts to replay the API
1540 calls made to this context (and its parents), for use in
1541 minimizing test cases for libgccjit.
1543 Implements the post-error-checking part of
1544 gcc_jit_context_dump_reproducer_to_file. */
1546 void
1547 recording::context::dump_reproducer_to_file (const char *path)
1549 JIT_LOG_SCOPE (get_logger ());
1550 reproducer r (*this, path);
1552 /* Generate the "ancestry" of this context, as a list. */
1553 auto_vec <context *> ascending_contexts;
1554 for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
1555 ascending_contexts.safe_push (ctxt);
1557 /* Reverse the list, giving a list of contexts from
1558 top-most parent context down through to youngest child context.
1559 We will use this list as the parameters of the functions in
1560 our generated file. */
1561 unsigned num_ctxts = ascending_contexts.length ();
1562 auto_vec <context *> contexts (num_ctxts);
1563 for (unsigned i = 0; i < num_ctxts; i++)
1564 contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
1566 /* contexts[0] should be the top-level context. */
1567 gcc_assert (contexts[0]);
1568 gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
1570 /* The final element in contexts should be "this". */
1571 gcc_assert (contexts[contexts.length () - 1] == this);
1572 gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
1573 == contexts[0]);
1575 r.write ("/* This code was autogenerated by"
1576 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1577 print_version (r.get_file (), " ", false);
1578 r.write ("*/\n");
1579 r.write ("#include <libgccjit.h>\n\n");
1580 r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1581 r.write ("static void\nset_options (");
1582 r.write_params (contexts);
1583 r.write (");\n\n");
1584 r.write ("static void\ncreate_code (");
1585 r.write_params (contexts);
1586 r.write (");\n\n");
1587 r.write ("int\nmain (int argc, const char **argv)\n");
1588 r.write ("{\n");
1589 for (unsigned i = 0; i < num_ctxts; i++)
1590 r.write (" gcc_jit_context *%s;\n",
1591 r.get_identifier (contexts[i]));
1592 r.write (" gcc_jit_result *result;\n"
1593 "\n");
1595 /* Create the contexts.
1596 The top-level context is acquired from a clean slate, the others as
1597 children of the prior context. */
1598 r.write (" %s = gcc_jit_context_acquire ();\n",
1599 r.get_identifier (contexts[0]));
1600 for (unsigned i = 1; i < num_ctxts; i++)
1601 r.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1602 r.get_identifier (contexts[i]),
1603 r.get_identifier (contexts[i - 1]));
1604 r.write (" set_options (");
1605 r.write_args (contexts);
1606 r.write (");\n");
1607 r.write (" create_code (");
1608 r.write_args (contexts);
1609 r.write (");\n");
1611 r.write (" result = gcc_jit_context_compile (%s);\n",
1612 r.get_identifier (this));
1614 for (unsigned i = num_ctxts; i > 0; i--)
1615 r.write (" gcc_jit_context_release (%s);\n",
1616 r.get_identifier (contexts[i - 1]));
1618 r.write (" gcc_jit_result_release (result);\n"
1619 " return 0;\n"
1620 "}\n\n");
1622 /* Define (char *) variables for use in calls to
1623 gcc_jit_context_enable_dump. */
1624 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1626 if (m_requested_dumps.length ())
1628 r.write ("/* Requested dumps for %s. */\n",
1629 r.get_identifier (contexts[ctxt_idx]));
1630 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1631 r.write ("static char *dump_%p;\n",
1632 (void *)&m_requested_dumps[i]);
1633 r.write ("\n");
1637 /* Write out values of options. */
1638 r.write ("static void\nset_options (");
1639 r.write_params (contexts);
1640 r.write (")\n{\n");
1641 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1643 if (ctxt_idx > 0)
1644 r.write ("\n");
1646 r.write (" /* Set options for %s. */\n",
1647 r.get_identifier (contexts[ctxt_idx]));
1649 r.write (" /* String options. */\n");
1650 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1652 r.write (" gcc_jit_context_set_str_option (%s,\n"
1653 " %s,\n",
1654 r.get_identifier (contexts[ctxt_idx]),
1655 str_option_reproducer_strings[opt_idx]);
1656 if (m_str_options[opt_idx])
1657 r.write (" \"%s\");\n",
1658 m_str_options[opt_idx]);
1659 else
1660 r.write (" NULL);\n");
1662 r.write (" /* Int options. */\n");
1663 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1664 r.write (" gcc_jit_context_set_int_option (%s,\n"
1665 " %s,\n"
1666 " %i);\n",
1667 r.get_identifier (contexts[ctxt_idx]),
1668 int_option_reproducer_strings[opt_idx],
1669 m_int_options[opt_idx]);
1670 r.write (" /* Boolean options. */\n");
1671 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1672 r.write (" gcc_jit_context_set_bool_option (%s,\n"
1673 " %s,\n"
1674 " %i);\n",
1675 r.get_identifier (contexts[ctxt_idx]),
1676 bool_option_reproducer_strings[opt_idx],
1677 m_bool_options[opt_idx]);
1678 for (int opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1679 r.write (" %s (%s, %i);\n",
1680 inner_bool_option_reproducer_strings[opt_idx],
1681 r.get_identifier (contexts[ctxt_idx]),
1682 m_inner_bool_options[opt_idx]);
1684 if (!m_command_line_options.is_empty ())
1686 int i;
1687 char *optname;
1688 r.write (" /* User-provided command-line options. */\n");
1689 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1690 r.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1691 r.get_identifier (contexts[ctxt_idx]),
1692 optname);
1695 if (m_requested_dumps.length ())
1697 r.write (" /* Requested dumps. */\n");
1698 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1699 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1701 r.write (" gcc_jit_context_enable_dump (%s,\n"
1702 " \"%s\",\n"
1703 " &dump_%p);\n",
1704 r.get_identifier (contexts[ctxt_idx]),
1705 m_requested_dumps[i].m_dumpname,
1706 (void *)&m_requested_dumps[i]);
1710 r.write ("}\n\n");
1712 r.write ("static void\ncreate_code (");
1713 r.write_params (contexts);
1714 r.write (")\n"
1715 "{\n");
1716 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1718 memento *m;
1719 int i;
1720 if (ctxt_idx > 0)
1721 r.write ("\n\n");
1723 r.write (" /* Replay of API calls for %s. */\n",
1724 r.get_identifier (contexts[ctxt_idx]));
1725 FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
1726 m->write_reproducer (r);
1728 r.write ("}\n");
1731 /* Copy the requested dumps within this context and all ancestors into
1732 OUT. */
1734 void
1735 recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
1737 if (m_parent_ctxt)
1738 m_parent_ctxt->get_all_requested_dumps (out);
1740 out->reserve (m_requested_dumps.length ());
1741 out->splice (m_requested_dumps);
1744 /* This is a pre-compilation check for the context (and any parents).
1746 Detect errors within the context, adding errors if any are found. */
1748 void
1749 recording::context::validate ()
1751 JIT_LOG_SCOPE (get_logger ());
1753 if (m_parent_ctxt)
1754 m_parent_ctxt->validate ();
1756 int i;
1757 function *fn;
1758 FOR_EACH_VEC_ELT (m_functions, i, fn)
1759 fn->validate ();
1762 /* The implementation of class gcc::jit::recording::memento. */
1764 /* Get a (const char *) debug description of the given memento, by
1765 calling the pure-virtual make_debug_string hook, caching the
1766 result.
1768 It is intended that this should only be called in debugging and
1769 error-handling paths, so this doesn't need to be particularly
1770 optimized. */
1772 const char *
1773 recording::memento::get_debug_string ()
1775 if (!m_debug_string)
1776 m_debug_string = make_debug_string ();
1777 return m_debug_string->c_str ();
1780 /* Default implementation of recording::memento::write_to_dump, writing
1781 an indented form of the memento's debug string to the dump. */
1783 void
1784 recording::memento::write_to_dump (dump &d)
1786 d.write(" %s\n", get_debug_string ());
1789 /* The implementation of class gcc::jit::recording::string. */
1791 /* Constructor for gcc::jit::recording::string::string, allocating a
1792 copy of the given text using new char[]. */
1794 recording::string::string (context *ctxt, const char *text)
1795 : memento (ctxt)
1797 m_len = strlen (text);
1798 m_buffer = new char[m_len + 1];
1799 strcpy (m_buffer, text);
1802 /* Destructor for gcc::jit::recording::string::string. */
1804 recording::string::~string ()
1806 delete[] m_buffer;
1809 /* Function for making gcc::jit::recording::string instances on a
1810 context via printf-style formatting.
1812 It is intended that this should only be called in debugging and
1813 error-handling paths, so this doesn't need to be particularly
1814 optimized, hence the double-copy of the string is acceptable. */
1816 recording::string *
1817 recording::string::from_printf (context *ctxt, const char *fmt, ...)
1819 int len;
1820 va_list ap;
1821 char *buf;
1822 recording::string *result;
1824 va_start (ap, fmt);
1825 len = vasprintf (&buf, fmt, ap);
1826 va_end (ap);
1828 if (buf == NULL || len < 0)
1830 ctxt->add_error (NULL, "malloc failure");
1831 return NULL;
1834 result = ctxt->new_string (buf);
1835 free (buf);
1836 return result;
1839 /* Implementation of recording::memento::make_debug_string for strings,
1840 wrapping the given string in quotes and escaping as necessary. */
1842 recording::string *
1843 recording::string::make_debug_string ()
1845 /* Hack to avoid infinite recursion into strings when logging all
1846 mementos: don't re-escape strings: */
1847 if (m_buffer[0] == '"')
1848 return this;
1850 /* Wrap in quotes and do escaping etc */
1852 size_t sz = (1 /* opening quote */
1853 + (m_len * 2) /* each char might get escaped */
1854 + 1 /* closing quote */
1855 + 1); /* nil termintator */
1856 char *tmp = new char[sz];
1857 size_t len = 0;
1859 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1860 APPEND('"'); /* opening quote */
1861 for (size_t i = 0; i < m_len ; i++)
1863 char ch = m_buffer[i];
1864 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
1865 APPEND('\\');
1866 APPEND(ch);
1868 APPEND('"'); /* closing quote */
1869 #undef APPEND
1870 tmp[len] = '\0'; /* nil termintator */
1872 string *result = m_ctxt->new_string (tmp);
1874 delete[] tmp;
1875 return result;
1878 /* Implementation of recording::memento::write_reproducer for strings. */
1880 void
1881 recording::string::write_reproducer (reproducer &)
1883 /* Empty. */
1886 /* The implementation of class gcc::jit::recording::location. */
1888 /* Implementation of recording::memento::replay_into for locations.
1890 Create a new playback::location and store it into the
1891 recording::location's m_playback_obj field. */
1893 void
1894 recording::location::replay_into (replayer *r)
1896 m_playback_obj = r->new_location (this,
1897 m_filename->c_str (),
1898 m_line,
1899 m_column);
1902 /* Implementation of recording::memento::make_debug_string for locations,
1903 turning them into the usual form:
1904 FILENAME:LINE:COLUMN
1905 like we do when emitting diagnostics. */
1907 recording::string *
1908 recording::location::make_debug_string ()
1910 return string::from_printf (m_ctxt,
1911 "%s:%i:%i",
1912 m_filename->c_str (), m_line, m_column);
1915 /* Implementation of recording::memento::write_reproducer for locations. */
1917 void
1918 recording::location::write_reproducer (reproducer &r)
1920 const char *id = r.make_identifier (this, "loc");
1921 r.write (" gcc_jit_location *%s =\n"
1922 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1923 " %s, /* const char *filename */\n"
1924 " %i, /* int line */\n"
1925 " %i);/* int column */\n",
1927 r.get_identifier (get_context ()),
1928 m_filename->get_debug_string (),
1929 m_line, m_column);
1932 /* The implementation of class gcc::jit::recording::type. */
1934 /* Given a type T, get the type T*.
1936 If this doesn't already exist, generate a new memento_of_get_pointer
1937 instance and add it to this type's context's list of mementos.
1939 Otherwise, use the cached type.
1941 Implements the post-error-checking part of
1942 gcc_jit_type_get_pointer. */
1944 recording::type *
1945 recording::type::get_pointer ()
1947 if (!m_pointer_to_this_type)
1949 m_pointer_to_this_type = new memento_of_get_pointer (this);
1950 m_ctxt->record (m_pointer_to_this_type);
1952 return m_pointer_to_this_type;
1955 /* Given a type T, get the type const T.
1957 Implements the post-error-checking part of
1958 gcc_jit_type_get_const. */
1960 recording::type *
1961 recording::type::get_const ()
1963 recording::type *result = new memento_of_get_const (this);
1964 m_ctxt->record (result);
1965 return result;
1968 /* Given a type T, get the type volatile T.
1970 Implements the post-error-checking part of
1971 gcc_jit_type_get_volatile. */
1973 recording::type *
1974 recording::type::get_volatile ()
1976 recording::type *result = new memento_of_get_volatile (this);
1977 m_ctxt->record (result);
1978 return result;
1981 const char *
1982 recording::type::access_as_type (reproducer &r)
1984 return r.get_identifier (this);
1987 /* Implementation of pure virtual hook recording::type::dereference for
1988 recording::memento_of_get_type. */
1990 recording::type *
1991 recording::memento_of_get_type::dereference ()
1993 switch (m_kind)
1995 default: gcc_unreachable ();
1997 case GCC_JIT_TYPE_VOID:
1998 return NULL;
2000 case GCC_JIT_TYPE_VOID_PTR:
2001 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
2003 case GCC_JIT_TYPE_BOOL:
2004 case GCC_JIT_TYPE_CHAR:
2005 case GCC_JIT_TYPE_SIGNED_CHAR:
2006 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2007 case GCC_JIT_TYPE_SHORT:
2008 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2009 case GCC_JIT_TYPE_INT:
2010 case GCC_JIT_TYPE_UNSIGNED_INT:
2011 case GCC_JIT_TYPE_LONG:
2012 case GCC_JIT_TYPE_UNSIGNED_LONG:
2013 case GCC_JIT_TYPE_LONG_LONG:
2014 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2015 case GCC_JIT_TYPE_FLOAT:
2016 case GCC_JIT_TYPE_DOUBLE:
2017 case GCC_JIT_TYPE_LONG_DOUBLE:
2018 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2019 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2020 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2021 /* Not a pointer: */
2022 return NULL;
2024 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2025 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
2027 case GCC_JIT_TYPE_SIZE_T:
2028 /* Not a pointer: */
2029 return NULL;
2031 case GCC_JIT_TYPE_FILE_PTR:
2032 /* Give the client code back an opaque "struct FILE". */
2033 return m_ctxt->get_opaque_FILE_type ();
2037 /* Implementation of pure virtual hook recording::type::is_int for
2038 recording::memento_of_get_type. */
2040 bool
2041 recording::memento_of_get_type::is_int () const
2043 switch (m_kind)
2045 default: gcc_unreachable ();
2047 case GCC_JIT_TYPE_VOID:
2048 return false;
2050 case GCC_JIT_TYPE_VOID_PTR:
2051 return false;
2053 case GCC_JIT_TYPE_BOOL:
2054 return false;
2056 case GCC_JIT_TYPE_CHAR:
2057 case GCC_JIT_TYPE_SIGNED_CHAR:
2058 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2059 case GCC_JIT_TYPE_SHORT:
2060 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2061 case GCC_JIT_TYPE_INT:
2062 case GCC_JIT_TYPE_UNSIGNED_INT:
2063 case GCC_JIT_TYPE_LONG:
2064 case GCC_JIT_TYPE_UNSIGNED_LONG:
2065 case GCC_JIT_TYPE_LONG_LONG:
2066 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2067 return true;
2069 case GCC_JIT_TYPE_FLOAT:
2070 case GCC_JIT_TYPE_DOUBLE:
2071 case GCC_JIT_TYPE_LONG_DOUBLE:
2072 return false;
2074 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2075 return false;
2077 case GCC_JIT_TYPE_SIZE_T:
2078 return true;
2080 case GCC_JIT_TYPE_FILE_PTR:
2081 return false;
2083 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2084 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2085 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2086 return false;
2090 /* Implementation of pure virtual hook recording::type::is_float for
2091 recording::memento_of_get_type. */
2093 bool
2094 recording::memento_of_get_type::is_float () const
2096 switch (m_kind)
2098 default: gcc_unreachable ();
2100 case GCC_JIT_TYPE_VOID:
2101 return false;
2103 case GCC_JIT_TYPE_VOID_PTR:
2104 return false;
2106 case GCC_JIT_TYPE_BOOL:
2107 return false;
2109 case GCC_JIT_TYPE_CHAR:
2110 case GCC_JIT_TYPE_SIGNED_CHAR:
2111 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2112 case GCC_JIT_TYPE_SHORT:
2113 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2114 case GCC_JIT_TYPE_INT:
2115 case GCC_JIT_TYPE_UNSIGNED_INT:
2116 case GCC_JIT_TYPE_LONG:
2117 case GCC_JIT_TYPE_UNSIGNED_LONG:
2118 case GCC_JIT_TYPE_LONG_LONG:
2119 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2120 return false;
2122 case GCC_JIT_TYPE_FLOAT:
2123 case GCC_JIT_TYPE_DOUBLE:
2124 case GCC_JIT_TYPE_LONG_DOUBLE:
2125 return true;
2127 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2128 return false;
2130 case GCC_JIT_TYPE_SIZE_T:
2131 return false;
2133 case GCC_JIT_TYPE_FILE_PTR:
2134 return false;
2136 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2137 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2138 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2139 return true;
2143 /* Implementation of pure virtual hook recording::type::is_bool for
2144 recording::memento_of_get_type. */
2146 bool
2147 recording::memento_of_get_type::is_bool () const
2149 switch (m_kind)
2151 default: gcc_unreachable ();
2153 case GCC_JIT_TYPE_VOID:
2154 return false;
2156 case GCC_JIT_TYPE_VOID_PTR:
2157 return false;
2159 case GCC_JIT_TYPE_BOOL:
2160 return true;
2162 case GCC_JIT_TYPE_CHAR:
2163 case GCC_JIT_TYPE_SIGNED_CHAR:
2164 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2165 case GCC_JIT_TYPE_SHORT:
2166 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2167 case GCC_JIT_TYPE_INT:
2168 case GCC_JIT_TYPE_UNSIGNED_INT:
2169 case GCC_JIT_TYPE_LONG:
2170 case GCC_JIT_TYPE_UNSIGNED_LONG:
2171 case GCC_JIT_TYPE_LONG_LONG:
2172 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2173 return false;
2175 case GCC_JIT_TYPE_FLOAT:
2176 case GCC_JIT_TYPE_DOUBLE:
2177 case GCC_JIT_TYPE_LONG_DOUBLE:
2178 return false;
2180 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2181 return false;
2183 case GCC_JIT_TYPE_SIZE_T:
2184 return false;
2186 case GCC_JIT_TYPE_FILE_PTR:
2187 return false;
2189 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2190 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2191 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2192 return false;
2196 /* Implementation of pure virtual hook recording::memento::replay_into
2197 for recording::memento_of_get_type. */
2199 void
2200 recording::memento_of_get_type::replay_into (replayer *r)
2202 set_playback_obj (r->get_type (m_kind));
2205 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2207 /* Descriptive strings for each of enum gcc_jit_types. */
2209 static const char * const get_type_strings[] = {
2210 "void", /* GCC_JIT_TYPE_VOID */
2211 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2213 "bool", /* GCC_JIT_TYPE_BOOL */
2215 "char", /* GCC_JIT_TYPE_CHAR */
2216 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2217 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2219 "short", /* GCC_JIT_TYPE_SHORT */
2220 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2222 "int", /* GCC_JIT_TYPE_INT */
2223 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2225 "long", /* GCC_JIT_TYPE_LONG */
2226 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2228 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2229 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2231 "float", /* GCC_JIT_TYPE_FLOAT */
2232 "double", /* GCC_JIT_TYPE_DOUBLE */
2233 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2235 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2237 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2239 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2241 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2242 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2243 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2247 /* Implementation of recording::memento::make_debug_string for
2248 results of get_type, using a simple table of type names. */
2250 recording::string *
2251 recording::memento_of_get_type::make_debug_string ()
2253 return m_ctxt->new_string (get_type_strings[m_kind]);
2256 static const char * const get_type_enum_strings[] = {
2257 "GCC_JIT_TYPE_VOID",
2258 "GCC_JIT_TYPE_VOID_PTR",
2259 "GCC_JIT_TYPE_BOOL",
2260 "GCC_JIT_TYPE_CHAR",
2261 "GCC_JIT_TYPE_SIGNED_CHAR",
2262 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2263 "GCC_JIT_TYPE_SHORT",
2264 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2265 "GCC_JIT_TYPE_INT",
2266 "GCC_JIT_TYPE_UNSIGNED_INT",
2267 "GCC_JIT_TYPE_LONG",
2268 "GCC_JIT_TYPE_UNSIGNED_LONG",
2269 "GCC_JIT_TYPE_LONG_LONG",
2270 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2271 "GCC_JIT_TYPE_FLOAT",
2272 "GCC_JIT_TYPE_DOUBLE",
2273 "GCC_JIT_TYPE_LONG_DOUBLE",
2274 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2275 "GCC_JIT_TYPE_SIZE_T",
2276 "GCC_JIT_TYPE_FILE_PTR",
2277 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2278 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2279 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2282 void
2283 recording::memento_of_get_type::write_reproducer (reproducer &r)
2285 const char *id = r.make_identifier (this, "type");
2286 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2288 r.get_identifier (get_context ()),
2289 get_type_enum_strings[m_kind]);
2292 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2294 /* Override of default implementation of
2295 recording::type::accepts_writes_from for get_pointer.
2297 Require a pointer type, and allowing writes to
2298 (const T *) from a (T*), but not the other way around. */
2300 bool
2301 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2303 /* Must be a pointer type: */
2304 type *rtype_points_to = rtype->is_pointer ();
2305 if (!rtype_points_to)
2306 return false;
2308 /* It's OK to assign to a (const T *) from a (T *). */
2309 return m_other_type->unqualified ()
2310 ->accepts_writes_from (rtype_points_to);
2313 /* Implementation of pure virtual hook recording::memento::replay_into
2314 for recording::memento_of_get_pointer. */
2316 void
2317 recording::memento_of_get_pointer::replay_into (replayer *)
2319 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2322 /* Implementation of recording::memento::make_debug_string for
2323 results of get_pointer, adding " *" to the underlying type,
2324 with special-casing to handle function pointer types. */
2326 recording::string *
2327 recording::memento_of_get_pointer::make_debug_string ()
2329 /* Special-case function pointer types, to put the "*" in parens between
2330 the return type and the params (for one level of dereferencing, at
2331 least). */
2332 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2333 return fn_type->make_debug_string_with_ptr ();
2335 return string::from_printf (m_ctxt,
2336 "%s *", m_other_type->get_debug_string ());
2339 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2341 void
2342 recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2344 /* We need to special-case function pointer types; see the notes in
2345 recording::function_type::write_deferred_reproducer. */
2346 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2348 fn_type->write_deferred_reproducer (r, this);
2349 return;
2352 const char *id = r.make_identifier (this, "type");
2353 r.write (" gcc_jit_type *%s =\n"
2354 " gcc_jit_type_get_pointer (%s);\n",
2356 r.get_identifier_as_type (m_other_type));
2359 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2361 /* Implementation of pure virtual hook recording::memento::replay_into
2362 for recording::memento_of_get_const. */
2364 void
2365 recording::memento_of_get_const::replay_into (replayer *)
2367 set_playback_obj (m_other_type->playback_type ()->get_const ());
2370 /* Implementation of recording::memento::make_debug_string for
2371 results of get_const, prepending "const ". */
2373 recording::string *
2374 recording::memento_of_get_const::make_debug_string ()
2376 return string::from_printf (m_ctxt,
2377 "const %s", m_other_type->get_debug_string ());
2380 /* Implementation of recording::memento::write_reproducer for const types. */
2382 void
2383 recording::memento_of_get_const::write_reproducer (reproducer &r)
2385 const char *id = r.make_identifier (this, "type");
2386 r.write (" gcc_jit_type *%s =\n"
2387 " gcc_jit_type_get_const (%s);\n",
2389 r.get_identifier_as_type (m_other_type));
2392 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2394 /* Implementation of pure virtual hook recording::memento::replay_into
2395 for recording::memento_of_get_volatile. */
2397 void
2398 recording::memento_of_get_volatile::replay_into (replayer *)
2400 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2403 /* Implementation of recording::memento::make_debug_string for
2404 results of get_volatile, prepending "volatile ". */
2406 recording::string *
2407 recording::memento_of_get_volatile::make_debug_string ()
2409 return string::from_printf (m_ctxt,
2410 "volatile %s", m_other_type->get_debug_string ());
2413 /* Implementation of recording::memento::write_reproducer for volatile
2414 types. */
2416 void
2417 recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2419 const char *id = r.make_identifier (this, "type");
2420 r.write (" gcc_jit_type *%s =\n"
2421 " gcc_jit_type_get_volatile (%s);\n",
2423 r.get_identifier_as_type (m_other_type));
2426 /* The implementation of class gcc::jit::recording::array_type */
2428 /* Implementation of pure virtual hook recording::type::dereference for
2429 recording::array_type. */
2431 recording::type *
2432 recording::array_type::dereference ()
2434 return m_element_type;
2437 /* Implementation of pure virtual hook recording::memento::replay_into
2438 for recording::array_type. */
2440 void
2441 recording::array_type::replay_into (replayer *r)
2443 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
2444 m_element_type->playback_type (),
2445 m_num_elements));
2448 /* Implementation of recording::memento::make_debug_string for
2449 results of new_array_type. */
2451 recording::string *
2452 recording::array_type::make_debug_string ()
2454 return string::from_printf (m_ctxt,
2455 "%s[%d]",
2456 m_element_type->get_debug_string (),
2457 m_num_elements);
2460 /* Implementation of recording::memento::write_reproducer for array
2461 types. */
2463 void
2464 recording::array_type::write_reproducer (reproducer &r)
2466 const char *id = r.make_identifier (this, "array_type");
2467 r.write (" gcc_jit_type *%s =\n"
2468 " gcc_jit_context_new_array_type (%s,\n"
2469 " %s, /* gcc_jit_location *loc */\n"
2470 " %s, /* gcc_jit_type *element_type */\n"
2471 " %i); /* int num_elements */\n",
2473 r.get_identifier (get_context ()),
2474 r.get_identifier (m_loc),
2475 r.get_identifier_as_type (m_element_type),
2476 m_num_elements);
2479 /* The implementation of class gcc::jit::recording::function_type */
2481 /* Constructor for gcc::jit::recording::function_type. */
2483 recording::function_type::function_type (context *ctxt,
2484 type *return_type,
2485 int num_params,
2486 type **param_types,
2487 int is_variadic)
2488 : type (ctxt),
2489 m_return_type (return_type),
2490 m_param_types (),
2491 m_is_variadic (is_variadic)
2493 for (int i = 0; i< num_params; i++)
2494 m_param_types.safe_push (param_types[i]);
2497 /* Implementation of pure virtual hook recording::type::dereference for
2498 recording::function_type. */
2500 recording::type *
2501 recording::function_type::dereference ()
2503 return NULL;
2506 /* Implementation of pure virtual hook recording::memento::replay_into
2507 for recording::function_type. */
2509 void
2510 recording::function_type::replay_into (replayer *r)
2512 /* Convert m_param_types to a vec of playback type. */
2513 auto_vec <playback::type *> param_types;
2514 int i;
2515 recording::type *type;
2516 param_types.create (m_param_types.length ());
2517 FOR_EACH_VEC_ELT (m_param_types, i, type)
2518 param_types.safe_push (type->playback_type ());
2520 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
2521 &param_types,
2522 m_is_variadic));
2525 /* Special-casing for make_debug_string for get_pointer results for
2526 handling (one level) of pointers to functions. */
2528 recording::string *
2529 recording::function_type::make_debug_string_with_ptr ()
2531 return make_debug_string_with ("(*) ");
2534 /* Implementation of recording::memento::make_debug_string for
2535 results of new_function_type. */
2537 recording::string *
2538 recording::function_type::make_debug_string ()
2540 return make_debug_string_with ("");
2543 /* Build a debug string representation of the form:
2545 RESULT_TYPE INSERT (PARAM_TYPES)
2547 for use when handling 0 and 1 level of indirection to this
2548 function type. */
2550 recording::string *
2551 recording::function_type::make_debug_string_with (const char *insert)
2553 /* First, build a buffer for the arguments. */
2554 /* Calculate length of said buffer. */
2555 size_t sz = 1; /* nil terminator */
2556 for (unsigned i = 0; i< m_param_types.length (); i++)
2558 sz += strlen (m_param_types[i]->get_debug_string ());
2559 sz += 2; /* ", " separator */
2561 if (m_is_variadic)
2562 sz += 5; /* ", ..." separator and ellipsis */
2564 /* Now allocate and populate the buffer. */
2565 char *argbuf = new char[sz];
2566 size_t len = 0;
2568 for (unsigned i = 0; i< m_param_types.length (); i++)
2570 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
2571 len += strlen (m_param_types[i]->get_debug_string ());
2572 if (i + 1 < m_param_types.length ())
2574 strcpy (argbuf + len, ", ");
2575 len += 2;
2578 if (m_is_variadic)
2580 if (m_param_types.length ())
2582 strcpy (argbuf + len, ", ");
2583 len += 2;
2585 strcpy (argbuf + len, "...");
2586 len += 3;
2588 argbuf[len] = '\0';
2590 /* ...and use it to get the string for the call as a whole. */
2591 string *result = string::from_printf (m_ctxt,
2592 "%s %s(%s)",
2593 m_return_type->get_debug_string (),
2594 insert,
2595 argbuf);
2597 delete[] argbuf;
2599 return result;
2602 /* Implementation of recording::memento::write_reproducer for function
2603 types. */
2605 void
2606 recording::function_type::write_reproducer (reproducer &)
2608 /* see notes below. */
2611 /* There's a get_pointer within context::new_function_ptr_type:
2612 the type received by client code isn't the memento for the
2613 function_type, but instead the result of get_pointer on it.
2615 Hence we can't directly write a reproducer that gives function_type.
2616 Instead we special-case things within get_pointer, detecting this
2617 case, calling the following function. */
2619 void
2620 recording::function_type::write_deferred_reproducer (reproducer &r,
2621 memento *ptr_type)
2623 gcc_assert (ptr_type);
2624 r.make_identifier (this, "function_type");
2625 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
2626 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
2627 r.write (" gcc_jit_type *%s[%i] = {\n",
2628 param_types_id,
2629 m_param_types.length ());
2630 int i;
2631 type *param_type;
2632 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2633 r.write (" %s,\n", r.get_identifier_as_type (param_type));
2634 r.write (" };\n");
2635 r.write (" gcc_jit_type *%s =\n"
2636 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2637 " %s, /* gcc_jit_location *loc */\n"
2638 " %s, /* gcc_jit_type *return_type */\n"
2639 " %i, /* int num_params */\n"
2640 " %s, /* gcc_jit_type **param_types */\n"
2641 " %i); /* int is_variadic */\n",
2642 ptr_id,
2643 r.get_identifier (get_context ()),
2644 "NULL", /* location is not stored */
2645 r.get_identifier_as_type (m_return_type),
2646 m_param_types.length (),
2647 param_types_id,
2648 m_is_variadic);
2651 /* The implementation of class gcc::jit::recording::field. */
2653 /* Implementation of pure virtual hook recording::memento::replay_into
2654 for recording::field. */
2656 void
2657 recording::field::replay_into (replayer *r)
2659 set_playback_obj (r->new_field (playback_location (r, m_loc),
2660 m_type->playback_type (),
2661 playback_string (m_name)));
2664 /* Override the default implementation of
2665 recording::memento::write_to_dump. Dump each field
2666 by dumping a line of the form:
2667 TYPE NAME;
2668 so that we can build up a struct/union field-byfield. */
2670 void
2671 recording::field::write_to_dump (dump &d)
2673 d.write (" %s %s;\n",
2674 m_type->get_debug_string (),
2675 m_name->c_str ());
2678 /* Implementation of recording::memento::make_debug_string for
2679 results of new_field. */
2681 recording::string *
2682 recording::field::make_debug_string ()
2684 return m_name;
2687 /* Implementation of recording::memento::write_reproducer for fields. */
2689 void
2690 recording::field::write_reproducer (reproducer &r)
2692 const char *id = r.make_identifier (this, "field");
2693 r.write(" gcc_jit_field *%s =\n"
2694 " gcc_jit_context_new_field (%s,\n"
2695 " %s, /* gcc_jit_location *loc */\n"
2696 " %s, /* gcc_jit_type *type, */\n"
2697 " %s); /* const char *name */\n",
2699 r.get_identifier (get_context ()),
2700 r.get_identifier (m_loc),
2701 r.get_identifier_as_type (m_type),
2702 m_name->get_debug_string ());
2705 /* The implementation of class gcc::jit::recording::compound_type */
2707 /* The constructor for gcc::jit::recording::compound_type. */
2709 recording::compound_type::compound_type (context *ctxt,
2710 location *loc,
2711 string *name)
2712 : type (ctxt),
2713 m_loc (loc),
2714 m_name (name),
2715 m_fields (NULL)
2719 /* Set the fields of a compound type.
2721 Implements the post-error-checking part of
2722 gcc_jit_struct_set_fields, and is also used by
2723 gcc_jit_context_new_union_type. */
2725 void
2726 recording::compound_type::set_fields (location *loc,
2727 int num_fields,
2728 field **field_array)
2730 m_loc = loc;
2731 gcc_assert (NULL == m_fields);
2733 m_fields = new fields (this, num_fields, field_array);
2734 m_ctxt->record (m_fields);
2737 /* Implementation of pure virtual hook recording::type::dereference for
2738 recording::compound_type. */
2740 recording::type *
2741 recording::compound_type::dereference ()
2743 return NULL; /* not a pointer */
2746 /* The implementation of class gcc::jit::recording::struct_. */
2748 /* The constructor for gcc::jit::recording::struct_. */
2750 recording::struct_::struct_ (context *ctxt,
2751 location *loc,
2752 string *name)
2753 : compound_type (ctxt, loc, name)
2757 /* Implementation of pure virtual hook recording::memento::replay_into
2758 for recording::struct_. */
2760 void
2761 recording::struct_::replay_into (replayer *r)
2763 set_playback_obj (
2764 r->new_compound_type (playback_location (r, get_loc ()),
2765 get_name ()->c_str (),
2766 true /* is_struct */));
2769 const char *
2770 recording::struct_::access_as_type (reproducer &r)
2772 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2773 r.get_identifier (this));
2776 /* Implementation of recording::memento::make_debug_string for
2777 structs. */
2779 recording::string *
2780 recording::struct_::make_debug_string ()
2782 return string::from_printf (m_ctxt,
2783 "struct %s", get_name ()->c_str ());
2786 void
2787 recording::struct_::write_reproducer (reproducer &r)
2789 const char *id = r.make_identifier (this, "struct");
2790 r.write (" gcc_jit_struct *%s =\n"
2791 " gcc_jit_context_new_opaque_struct (%s,\n"
2792 " %s, /* gcc_jit_location *loc */\n"
2793 " %s); /* const char *name */\n",
2795 r.get_identifier (get_context ()),
2796 r.get_identifier (get_loc ()),
2797 get_name ()->get_debug_string ());
2800 /* The implementation of class gcc::jit::recording::union_. */
2802 /* The constructor for gcc::jit::recording::union_. */
2804 recording::union_::union_ (context *ctxt,
2805 location *loc,
2806 string *name)
2807 : compound_type (ctxt, loc, name)
2811 /* Implementation of pure virtual hook recording::memento::replay_into
2812 for recording::union_. */
2814 void
2815 recording::union_::replay_into (replayer *r)
2817 set_playback_obj (
2818 r->new_compound_type (playback_location (r, get_loc ()),
2819 get_name ()->c_str (),
2820 false /* is_struct */));
2823 /* Implementation of recording::memento::make_debug_string for
2824 unions. */
2826 recording::string *
2827 recording::union_::make_debug_string ()
2829 return string::from_printf (m_ctxt,
2830 "union %s", get_name ()->c_str ());
2833 /* Implementation of recording::memento::write_reproducer for unions. */
2835 void
2836 recording::union_::write_reproducer (reproducer &r)
2838 const char *id = r.make_identifier (this, "union");
2840 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
2841 r.write (" gcc_jit_field *%s[%i] = {\n",
2842 fields_id,
2843 get_fields ()->length ());
2844 for (int i = 0; i < get_fields ()->length (); i++)
2845 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
2846 r.write (" };\n");
2848 r.write (" gcc_jit_type *%s =\n"
2849 " gcc_jit_context_new_union_type (%s,\n"
2850 " %s, /* gcc_jit_location *loc */\n"
2851 " %s, /* const char *name */\n"
2852 " %i, /* int num_fields */\n"
2853 " %s); /* gcc_jit_field **fields */\n",
2855 r.get_identifier (get_context ()),
2856 r.get_identifier (get_loc ()),
2857 get_name ()->get_debug_string (),
2858 get_fields ()->length (),
2859 fields_id);
2862 /* The implementation of class gcc::jit::recording::fields. */
2864 /* The constructor for gcc::jit::recording::fields. */
2866 recording::fields::fields (compound_type *struct_or_union,
2867 int num_fields,
2868 field **fields)
2869 : memento (struct_or_union->m_ctxt),
2870 m_struct_or_union (struct_or_union),
2871 m_fields ()
2873 for (int i = 0; i < num_fields; i++)
2875 gcc_assert (fields[i]->get_container () == NULL);
2876 fields[i]->set_container (m_struct_or_union);
2877 m_fields.safe_push (fields[i]);
2881 /* Implementation of pure virtual hook recording::memento::replay_into
2882 for recording::fields. */
2884 void
2885 recording::fields::replay_into (replayer *)
2887 auto_vec<playback::field *> playback_fields;
2888 playback_fields.create (m_fields.length ());
2889 for (unsigned i = 0; i < m_fields.length (); i++)
2890 playback_fields.safe_push (m_fields[i]->playback_field ());
2891 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
2894 /* Override the default implementation of
2895 recording::memento::write_to_dump by writing a union/struct
2896 declaration of this form:
2898 struct/union NAME {
2899 TYPE_1 NAME_1;
2900 TYPE_2 NAME_2;
2901 ....
2902 TYPE_N NAME_N;
2905 to the dump. */
2907 void
2908 recording::fields::write_to_dump (dump &d)
2910 int i;
2911 field *f;
2913 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
2914 FOR_EACH_VEC_ELT (m_fields, i, f)
2915 f->write_to_dump (d);
2916 d.write ("};\n");
2919 /* Implementation of recording::memento::write_reproducer for the fields
2920 subclass. */
2922 void
2923 recording::fields::write_reproducer (reproducer &r)
2925 if (m_struct_or_union)
2926 if (NULL == m_struct_or_union->dyn_cast_struct ())
2927 /* We have a union; the fields have already been written by
2928 union::write_reproducer. */
2929 return;
2931 const char *fields_id = r.make_identifier (this, "fields");
2932 r.write (" gcc_jit_field *%s[%i] = {\n",
2933 fields_id,
2934 m_fields.length ());
2935 int i;
2936 field *field;
2937 FOR_EACH_VEC_ELT (m_fields, i, field)
2938 r.write (" %s,\n", r.get_identifier (field));
2939 r.write (" };\n");
2941 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
2942 " %s, /* gcc_jit_location *loc */\n"
2943 " %i, /* int num_fields */\n"
2944 " %s); /* gcc_jit_field **fields */\n",
2945 r.get_identifier (m_struct_or_union),
2946 r.get_identifier ((memento *)NULL),
2947 m_fields.length (),
2948 fields_id);
2951 /* Implementation of recording::memento::make_debug_string for
2952 field tables. */
2954 recording::string *
2955 recording::fields::make_debug_string ()
2957 return string::from_printf (m_ctxt,
2958 "fields");
2961 /* The implementation of class gcc::jit::recording::rvalue. */
2963 /* Create a recording::access_field_rvalue instance and add it to
2964 the rvalue's context's list of mementos.
2966 Implements the post-error-checking part of
2967 gcc_jit_rvalue_access_field. */
2969 recording::rvalue *
2970 recording::rvalue::access_field (recording::location *loc,
2971 field *field)
2973 recording::rvalue *result =
2974 new access_field_rvalue (m_ctxt, loc, this, field);
2975 m_ctxt->record (result);
2976 return result;
2979 /* Create a recording::dereference_field_rvalue instance and add it to
2980 the rvalue's context's list of mementos.
2982 Implements the post-error-checking part of
2983 gcc_jit_rvalue_dereference_field. */
2985 recording::lvalue *
2986 recording::rvalue::dereference_field (recording::location *loc,
2987 field *field)
2989 recording::lvalue *result =
2990 new dereference_field_rvalue (m_ctxt, loc, this, field);
2991 m_ctxt->record (result);
2992 return result;
2995 /* Create a recording::dereference_rvalue instance and add it to the
2996 rvalue's context's list of mementos.
2998 Implements the post-error-checking part of
2999 gcc_jit_rvalue_dereference. */
3001 recording::lvalue *
3002 recording::rvalue::dereference (recording::location *loc)
3004 recording::lvalue *result =
3005 new dereference_rvalue (m_ctxt, loc, this);
3006 m_ctxt->record (result);
3007 return result;
3010 /* An rvalue visitor, for validating that every rvalue within an expression
3011 trees within "STMT" has the correct scope (e.g. no access to locals
3012 of a different function). */
3014 class rvalue_usage_validator : public recording::rvalue_visitor
3016 public:
3017 rvalue_usage_validator (const char *api_funcname,
3018 recording::context *ctxt,
3019 recording::statement *stmt);
3021 void
3022 visit (recording::rvalue *rvalue);
3024 private:
3025 const char *m_api_funcname;
3026 recording::context *m_ctxt;
3027 recording::statement *m_stmt;
3030 /* The trivial constructor for rvalue_usage_validator. */
3032 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
3033 recording::context *ctxt,
3034 recording::statement *stmt)
3035 : m_api_funcname (api_funcname),
3036 m_ctxt (ctxt),
3037 m_stmt (stmt)
3041 /* Verify that the given rvalue is in the correct scope. */
3043 void
3044 rvalue_usage_validator::visit (recording::rvalue *rvalue)
3046 gcc_assert (m_stmt->get_block ());
3047 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
3049 /* Most rvalues don't have a scope (only locals and params). */
3050 if (rvalue->get_scope ())
3052 if (rvalue->get_scope () != stmt_scope)
3053 m_ctxt->add_error
3054 (rvalue->get_loc (),
3055 "%s:"
3056 " rvalue %s (type: %s)"
3057 " has scope limited to function %s"
3058 " but was used within function %s"
3059 " (in statement: %s)",
3060 m_api_funcname,
3061 rvalue->get_debug_string (),
3062 rvalue->get_type ()->get_debug_string (),
3063 rvalue->get_scope ()->get_debug_string (),
3064 stmt_scope->get_debug_string (),
3065 m_stmt->get_debug_string ());
3067 else
3069 if (rvalue->dyn_cast_param ())
3070 m_ctxt->add_error
3071 (rvalue->get_loc (),
3072 "%s:"
3073 " param %s (type: %s)"
3074 " was used within function %s"
3075 " (in statement: %s)"
3076 " but is not associated with any function",
3077 m_api_funcname,
3078 rvalue->get_debug_string (),
3079 rvalue->get_type ()->get_debug_string (),
3080 stmt_scope->get_debug_string (),
3081 m_stmt->get_debug_string ());
3085 /* Verify that it's valid to use this rvalue (and all expressions
3086 in the tree below it) within the given statement.
3088 For example, we must reject attempts to use a local from one
3089 function within a different function here, or we'll get
3090 an ICE deep inside toplev::main. */
3092 void
3093 recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
3095 rvalue_usage_validator v (api_funcname,
3096 s->get_context (),
3099 /* Verify that it's OK to use this rvalue within s. */
3100 v.visit (this);
3102 /* Traverse the expression tree below "this", verifying all rvalues
3103 within it. */
3104 visit_children (&v);
3107 /* Set the scope of this rvalue to be the given function. This can only
3108 be done once on a given rvalue. */
3110 void
3111 recording::rvalue::set_scope (function *scope)
3113 gcc_assert (scope);
3114 gcc_assert (NULL == m_scope);
3115 m_scope = scope;
3119 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3120 themselves.
3121 Instances of rvalue don't need an upcast call. */
3123 const char *
3124 recording::rvalue::access_as_rvalue (reproducer &r)
3126 return r.get_identifier (this);
3129 /* Return a debug string for the given rvalue, wrapping it in parentheses
3130 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3131 stronger precedence that this rvalue's precedence.
3133 For example, given:
3135 MULT
3137 PLUS MINUS
3138 / \ / \
3139 A B C D
3141 we want to emit:
3143 (A + B) * (C - D)
3145 since MULT has strong precedence than PLUS and MINUS, whereas for:
3147 PLUS
3149 MULT DIVIDE
3150 / \ / \
3151 A B C D
3153 we can simply emit:
3155 A * B + C / D
3157 since PLUS has weaker precedence than MULT and DIVIDE. */
3159 const char *
3160 recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
3162 enum precedence this_prec = get_precedence ();
3164 /* If this_prec has stronger precedence than outer_prec, we don't
3165 need to wrap this in parens within the outer debug string.
3166 Stronger precedences occur earlier than weaker within the enum,
3167 so this is a less than test. Equal precedences don't need
3168 parentheses. */
3169 if (this_prec <= outer_prec)
3170 return get_debug_string();
3172 /* Otherwise, we need parentheses. */
3174 /* Lazily-build and cache m_parenthesized_string. */
3175 if (!m_parenthesized_string)
3177 const char *debug_string = get_debug_string ();
3178 m_parenthesized_string = string::from_printf (get_context (),
3179 "(%s)",
3180 debug_string);
3182 gcc_assert (m_parenthesized_string);
3183 return m_parenthesized_string->c_str ();
3187 /* The implementation of class gcc::jit::recording::lvalue. */
3189 /* Create a recording::new_access_field_of_lvalue instance and add it to
3190 the lvalue's context's list of mementos.
3192 Implements the post-error-checking part of
3193 gcc_jit_lvalue_access_field. */
3195 recording::lvalue *
3196 recording::lvalue::access_field (recording::location *loc,
3197 field *field)
3199 recording::lvalue *result =
3200 new access_field_of_lvalue (m_ctxt, loc, this, field);
3201 m_ctxt->record (result);
3202 return result;
3205 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3206 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3207 upcast call. */
3209 const char *
3210 recording::lvalue::access_as_rvalue (reproducer &r)
3212 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3213 r.get_identifier (this));
3216 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3217 Instances of lvalue don't need to be upcast. */
3219 const char *
3220 recording::lvalue::access_as_lvalue (reproducer &r)
3222 return r.get_identifier (this);
3225 /* Create a recording::get_address_of_lvalue instance and add it to
3226 the lvalue's context's list of mementos.
3228 Implements the post-error-checking part of
3229 gcc_jit_lvalue_get_address. */
3231 recording::rvalue *
3232 recording::lvalue::get_address (recording::location *loc)
3234 recording::rvalue *result =
3235 new get_address_of_lvalue (m_ctxt, loc, this);
3236 m_ctxt->record (result);
3237 return result;
3240 /* The implementation of class gcc::jit::recording::param. */
3242 /* Implementation of pure virtual hook recording::memento::replay_into
3243 for recording::param. */
3245 void
3246 recording::param::replay_into (replayer *r)
3248 set_playback_obj (r->new_param (playback_location (r, m_loc),
3249 m_type->playback_type (),
3250 m_name->c_str ()));
3253 /* Implementation of recording::rvalue::access_as_rvalue for params.
3254 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3255 upcast call. */
3257 const char *
3258 recording::param::access_as_rvalue (reproducer &r)
3260 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3261 r.get_identifier (this));
3264 /* Implementation of recording::lvalue::access_as_lvalue for params.
3265 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3266 upcast call. */
3268 const char *
3269 recording::param::access_as_lvalue (reproducer &r)
3271 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3272 r.get_identifier (this));
3275 /* Implementation of recording::memento::write_reproducer for params. */
3277 void
3278 recording::param::write_reproducer (reproducer &r)
3280 const char *id = r.make_identifier (this, "param");
3281 r.write (" gcc_jit_param *%s =\n"
3282 " gcc_jit_context_new_param (%s,\n"
3283 " %s, /* gcc_jit_location *loc */\n"
3284 " %s, /*gcc_jit_type *type */\n"
3285 " %s); /* const char *name */\n",
3287 r.get_identifier (get_context ()),
3288 r.get_identifier (m_loc),
3289 r.get_identifier_as_type (m_type),
3290 m_name->get_debug_string ());
3293 /* The implementation of class gcc::jit::recording::function. */
3295 /* gcc::jit::recording::function's constructor. */
3297 recording::function::function (context *ctxt,
3298 recording::location *loc,
3299 enum gcc_jit_function_kind kind,
3300 type *return_type,
3301 recording::string *name,
3302 int num_params,
3303 recording::param **params,
3304 int is_variadic,
3305 enum built_in_function builtin_id)
3306 : memento (ctxt),
3307 m_loc (loc),
3308 m_kind (kind),
3309 m_return_type (return_type),
3310 m_name (name),
3311 m_params (),
3312 m_is_variadic (is_variadic),
3313 m_builtin_id (builtin_id),
3314 m_locals (),
3315 m_blocks ()
3317 for (int i = 0; i< num_params; i++)
3319 param *param = params[i];
3320 gcc_assert (param);
3322 /* Associate each param with this function.
3324 Verify that the param doesn't already have a function. */
3325 if (param->get_scope ())
3327 /* We've already rejected attempts to reuse a param between
3328 different functions (within gcc_jit_context_new_function), so
3329 if the param *does* already have a function, it must be being
3330 reused within the params array for this function. We must
3331 produce an error for this reuse (blocking the compile), since
3332 otherwise we'd have an ICE later on. */
3333 gcc_assert (this == param->get_scope ());
3334 ctxt->add_error
3335 (loc,
3336 "gcc_jit_context_new_function:"
3337 " parameter %s (type: %s)"
3338 " is used more than once when creating function %s",
3339 param->get_debug_string (),
3340 param->get_type ()->get_debug_string (),
3341 name->c_str ());
3343 else
3345 /* The normal, non-error case: associate this function with the
3346 param. */
3347 param->set_scope (this);
3350 m_params.safe_push (param);
3354 /* Implementation of pure virtual hook recording::memento::replay_into
3355 for recording::function. */
3357 void
3358 recording::function::replay_into (replayer *r)
3360 /* Convert m_params to a vec of playback param. */
3361 auto_vec <playback::param *> params;
3362 int i;
3363 recording::param *param;
3364 params.create (m_params.length ());
3365 FOR_EACH_VEC_ELT (m_params, i, param)
3366 params.safe_push (param->playback_param ());
3368 set_playback_obj (r->new_function (playback_location (r, m_loc),
3369 m_kind,
3370 m_return_type->playback_type (),
3371 m_name->c_str (),
3372 &params,
3373 m_is_variadic,
3374 m_builtin_id));
3377 /* Create a recording::local instance and add it to
3378 the functions's context's list of mementos, and to the function's
3379 list of locals.
3381 Implements the post-error-checking part of
3382 gcc_jit_function_new_local. */
3384 recording::lvalue *
3385 recording::function::new_local (recording::location *loc,
3386 type *type,
3387 const char *name)
3389 local *result = new local (this, loc, type, new_string (name));
3390 m_ctxt->record (result);
3391 m_locals.safe_push (result);
3392 return result;
3395 /* Create a recording::block instance and add it to
3396 the functions's context's list of mementos, and to the function's
3397 list of blocks.
3399 Implements the post-error-checking part of
3400 gcc_jit_function_new_block. */
3402 recording::block*
3403 recording::function::new_block (const char *name)
3405 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
3407 recording::block *result =
3408 new recording::block (this, m_blocks.length (), new_string (name));
3409 m_ctxt->record (result);
3410 m_blocks.safe_push (result);
3411 return result;
3414 /* Override the default implementation of
3415 recording::memento::write_to_dump by dumping a C-like
3416 representation of the function; either like a prototype
3417 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3418 all other kinds of function. */
3420 void
3421 recording::function::write_to_dump (dump &d)
3423 switch (m_kind)
3425 default: gcc_unreachable ();
3426 case GCC_JIT_FUNCTION_EXPORTED:
3427 case GCC_JIT_FUNCTION_IMPORTED:
3428 d.write ("extern ");
3429 break;
3430 case GCC_JIT_FUNCTION_INTERNAL:
3431 d.write ("static ");
3432 break;
3433 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
3434 d.write ("static inline ");
3435 break;
3437 d.write ("%s\n", m_return_type->get_debug_string ());
3439 if (d.update_locations ())
3440 m_loc = d.make_location ();
3442 d.write ("%s (", get_debug_string ());
3444 int i;
3445 recording::param *param;
3446 FOR_EACH_VEC_ELT (m_params, i, param)
3448 if (i > 0)
3449 d.write (", ");
3450 d.write ("%s %s",
3451 param->get_type ()->get_debug_string (),
3452 param->get_debug_string ());
3454 d.write (")");
3455 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
3457 d.write ("; /* (imported) */\n\n");
3459 else
3461 int i;
3462 local *var = NULL;
3463 block *b;
3464 d.write ("\n{\n");
3466 /* Write locals: */
3467 FOR_EACH_VEC_ELT (m_locals, i, var)
3468 var->write_to_dump (d);
3469 if (m_locals.length ())
3470 d.write ("\n");
3472 /* Write each block: */
3473 FOR_EACH_VEC_ELT (m_blocks, i, b)
3475 if (i > 0)
3476 d.write ("\n");
3477 b->write_to_dump (d);
3480 d.write ("}\n\n");
3484 /* Pre-compilation validation of a function, for those things we can't
3485 check until the context is (supposedly) fully-populated. */
3487 void
3488 recording::function::validate ()
3490 /* Complain about empty functions with non-void return type. */
3491 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
3492 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
3493 if (0 == m_blocks.length ())
3494 m_ctxt->add_error (m_loc,
3495 "function %s returns non-void (type: %s)"
3496 " but has no blocks",
3497 get_debug_string (),
3498 m_return_type->get_debug_string ());
3500 /* Check that all blocks are terminated. */
3501 int num_invalid_blocks = 0;
3503 int i;
3504 block *b;
3506 FOR_EACH_VEC_ELT (m_blocks, i, b)
3507 if (!b->validate ())
3508 num_invalid_blocks++;
3511 /* Check that all blocks are reachable. */
3512 if (!m_ctxt->get_inner_bool_option
3513 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
3514 && m_blocks.length () > 0 && 0 == num_invalid_blocks)
3516 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3517 flag, starting at the initial block. */
3518 auto_vec<block *> worklist (m_blocks.length ());
3519 worklist.safe_push (m_blocks[0]);
3520 while (worklist.length () > 0)
3522 block *b = worklist.pop ();
3523 b->m_is_reachable = true;
3525 /* Add successor blocks that aren't yet marked to the worklist. */
3526 /* We checked that each block has a terminating statement above . */
3527 vec <block *> successors = b->get_successor_blocks ();
3528 int i;
3529 block *succ;
3530 FOR_EACH_VEC_ELT (successors, i, succ)
3531 if (!succ->m_is_reachable)
3532 worklist.safe_push (succ);
3533 successors.release ();
3536 /* Now complain about any blocks that haven't been marked. */
3538 int i;
3539 block *b;
3540 FOR_EACH_VEC_ELT (m_blocks, i, b)
3541 if (!b->m_is_reachable)
3542 m_ctxt->add_error (b->get_loc (),
3543 "unreachable block: %s",
3544 b->get_debug_string ());
3549 /* Implements the post-error-checking part of
3550 gcc_jit_function_dump_to_dot. */
3552 void
3553 recording::function::dump_to_dot (const char *path)
3555 FILE *fp = fopen (path, "w");
3556 if (!fp)
3557 return;
3559 pretty_printer the_pp;
3560 the_pp.buffer->stream = fp;
3562 pretty_printer *pp = &the_pp;
3564 pp_printf (pp,
3565 "digraph %s {\n", get_debug_string ());
3567 /* Blocks: */
3569 int i;
3570 block *b;
3571 FOR_EACH_VEC_ELT (m_blocks, i, b)
3572 b->dump_to_dot (pp);
3575 /* Edges: */
3577 int i;
3578 block *b;
3579 FOR_EACH_VEC_ELT (m_blocks, i, b)
3580 b->dump_edges_to_dot (pp);
3583 pp_printf (pp, "}\n");
3584 pp_flush (pp);
3585 fclose (fp);
3588 /* Implementation of recording::memento::make_debug_string for
3589 functions. */
3591 recording::string *
3592 recording::function::make_debug_string ()
3594 return m_name;
3597 /* A table of enum gcc_jit_function_kind values expressed in string
3598 form. */
3600 static const char * const names_of_function_kinds[] = {
3601 "GCC_JIT_FUNCTION_EXPORTED",
3602 "GCC_JIT_FUNCTION_INTERNAL",
3603 "GCC_JIT_FUNCTION_IMPORTED",
3604 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3607 /* Implementation of recording::memento::write_reproducer for functions. */
3609 void
3610 recording::function::write_reproducer (reproducer &r)
3612 const char *id = r.make_identifier (this, "func");
3614 if (m_builtin_id)
3616 r.write (" gcc_jit_function *%s =\n"
3617 " gcc_jit_context_get_builtin_function (%s,\n"
3618 " %s);\n",
3620 r.get_identifier (get_context ()),
3621 m_name->get_debug_string ());
3622 return;
3624 const char *params_id = r.make_tmp_identifier ("params_for", this);
3625 r.write (" gcc_jit_param *%s[%i] = {\n",
3626 params_id,
3627 m_params.length ());
3628 int i;
3629 param *param;
3630 FOR_EACH_VEC_ELT (m_params, i, param)
3631 r.write (" %s,\n", r.get_identifier (param));
3632 r.write (" };\n");
3633 r.write (" gcc_jit_function *%s =\n"
3634 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3635 " %s, /* gcc_jit_location *loc */\n"
3636 " %s, /* enum gcc_jit_function_kind kind */\n"
3637 " %s, /* gcc_jit_type *return_type */\n"
3638 " %s, /* const char *name */\n"
3639 " %i, /* int num_params */\n"
3640 " %s, /* gcc_jit_param **params */\n"
3641 " %i); /* int is_variadic */\n",
3643 r.get_identifier (get_context ()),
3644 r.get_identifier (m_loc),
3645 names_of_function_kinds[m_kind],
3646 r.get_identifier_as_type (m_return_type),
3647 m_name->get_debug_string (),
3648 m_params.length (),
3649 params_id,
3650 m_is_variadic);
3654 /* The implementation of class gcc::jit::recording::block. */
3656 /* Create a recording::eval instance and add it to
3657 the block's context's list of mementos, and to the block's
3658 list of statements.
3660 Implements the heart of gcc_jit_block_add_eval. */
3662 recording::statement *
3663 recording::block::add_eval (recording::location *loc,
3664 recording::rvalue *rvalue)
3666 statement *result = new eval (this, loc, rvalue);
3667 m_ctxt->record (result);
3668 m_statements.safe_push (result);
3669 return result;
3672 /* Create a recording::assignment instance and add it to
3673 the block's context's list of mementos, and to the block's
3674 list of statements.
3676 Implements the heart of gcc_jit_block_add_assignment. */
3678 recording::statement *
3679 recording::block::add_assignment (recording::location *loc,
3680 recording::lvalue *lvalue,
3681 recording::rvalue *rvalue)
3683 statement *result = new assignment (this, loc, lvalue, rvalue);
3684 m_ctxt->record (result);
3685 m_statements.safe_push (result);
3686 return result;
3689 /* Create a recording::assignment_op instance and add it to
3690 the block's context's list of mementos, and to the block's
3691 list of statements.
3693 Implements the heart of gcc_jit_block_add_assignment_op. */
3695 recording::statement *
3696 recording::block::add_assignment_op (recording::location *loc,
3697 recording::lvalue *lvalue,
3698 enum gcc_jit_binary_op op,
3699 recording::rvalue *rvalue)
3701 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
3702 m_ctxt->record (result);
3703 m_statements.safe_push (result);
3704 return result;
3707 /* Create a recording::comment instance and add it to
3708 the block's context's list of mementos, and to the block's
3709 list of statements.
3711 Implements the heart of gcc_jit_block_add_comment. */
3713 recording::statement *
3714 recording::block::add_comment (recording::location *loc,
3715 const char *text)
3717 statement *result = new comment (this, loc, new_string (text));
3718 m_ctxt->record (result);
3719 m_statements.safe_push (result);
3720 return result;
3723 /* Create a recording::end_with_conditional instance and add it to
3724 the block's context's list of mementos, and to the block's
3725 list of statements.
3727 Implements the heart of gcc_jit_block_end_with_conditional. */
3729 recording::statement *
3730 recording::block::end_with_conditional (recording::location *loc,
3731 recording::rvalue *boolval,
3732 recording::block *on_true,
3733 recording::block *on_false)
3735 statement *result = new conditional (this, loc, boolval, on_true, on_false);
3736 m_ctxt->record (result);
3737 m_statements.safe_push (result);
3738 m_has_been_terminated = true;
3739 return result;
3742 /* Create a recording::end_with_jump instance and add it to
3743 the block's context's list of mementos, and to the block's
3744 list of statements.
3746 Implements the heart of gcc_jit_block_end_with_jump. */
3748 recording::statement *
3749 recording::block::end_with_jump (recording::location *loc,
3750 recording::block *target)
3752 statement *result = new jump (this, loc, target);
3753 m_ctxt->record (result);
3754 m_statements.safe_push (result);
3755 m_has_been_terminated = true;
3756 return result;
3759 /* Create a recording::end_with_return instance and add it to
3760 the block's context's list of mementos, and to the block's
3761 list of statements.
3763 Implements the post-error-checking parts of
3764 gcc_jit_block_end_with_return and
3765 gcc_jit_block_end_with_void_return. */
3767 recording::statement *
3768 recording::block::end_with_return (recording::location *loc,
3769 recording::rvalue *rvalue)
3771 /* This is used by both gcc_jit_function_add_return and
3772 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3773 the former and NULL for the latter. */
3774 statement *result = new return_ (this, loc, rvalue);
3775 m_ctxt->record (result);
3776 m_statements.safe_push (result);
3777 m_has_been_terminated = true;
3778 return result;
3781 /* Create a recording::switch_ instance and add it to
3782 the block's context's list of mementos, and to the block's
3783 list of statements.
3785 Implements the heart of gcc_jit_block_end_with_switch. */
3787 recording::statement *
3788 recording::block::end_with_switch (recording::location *loc,
3789 recording::rvalue *expr,
3790 recording::block *default_block,
3791 int num_cases,
3792 recording::case_ **cases)
3794 statement *result = new switch_ (this, loc,
3795 expr,
3796 default_block,
3797 num_cases,
3798 cases);
3799 m_ctxt->record (result);
3800 m_statements.safe_push (result);
3801 m_has_been_terminated = true;
3802 return result;
3805 /* Override the default implementation of
3806 recording::memento::write_to_dump for blocks by writing
3807 an unindented block name as a label, followed by the indented
3808 statements:
3810 BLOCK_NAME:
3811 STATEMENT_1;
3812 STATEMENT_2;
3814 STATEMENT_N; */
3816 void
3817 recording::block::write_to_dump (dump &d)
3819 d.write ("%s:\n", get_debug_string ());
3821 int i;
3822 statement *s;
3823 FOR_EACH_VEC_ELT (m_statements, i, s)
3824 s->write_to_dump (d);
3827 /* Validate a block by ensuring that it has been terminated. */
3829 bool
3830 recording::block::validate ()
3832 /* Check for termination. */
3833 if (!has_been_terminated ())
3835 statement *stmt = get_last_statement ();
3836 location *loc = stmt ? stmt->get_loc () : NULL;
3837 m_func->get_context ()->add_error (loc,
3838 "unterminated block in %s: %s",
3839 m_func->get_debug_string (),
3840 get_debug_string ());
3841 return false;
3844 return true;
3847 /* Get the source-location of a block by using that of the first
3848 statement within it, if any. */
3850 recording::location *
3851 recording::block::get_loc () const
3853 recording::statement *stmt = get_first_statement ();
3854 if (stmt)
3855 return stmt->get_loc ();
3856 else
3857 return NULL;
3860 /* Get the first statement within a block, if any. */
3862 recording::statement *
3863 recording::block::get_first_statement () const
3865 if (m_statements.length ())
3866 return m_statements[0];
3867 else
3868 return NULL;
3871 /* Get the last statement within a block, if any. */
3873 recording::statement *
3874 recording::block::get_last_statement () const
3876 if (m_statements.length ())
3877 return m_statements[m_statements.length () - 1];
3878 else
3879 return NULL;
3882 /* Assuming that this block has been terminated, get the successor blocks
3883 as a vector. Ownership of the vector transfers to the caller, which
3884 must call its release () method.
3886 Used when validating functions, and when dumping dot representations
3887 of them. */
3889 vec <recording::block *>
3890 recording::block::get_successor_blocks () const
3892 gcc_assert (m_has_been_terminated);
3893 statement *last_statement = get_last_statement ();
3894 gcc_assert (last_statement);
3895 return last_statement->get_successor_blocks ();
3898 /* Implementation of pure virtual hook recording::memento::replay_into
3899 for recording::block. */
3901 void
3902 recording::block::replay_into (replayer *)
3904 set_playback_obj (m_func->playback_function ()
3905 ->new_block (playback_string (m_name)));
3908 /* Implementation of recording::memento::make_debug_string for
3909 blocks. */
3911 recording::string *
3912 recording::block::make_debug_string ()
3914 if (m_name)
3915 return m_name;
3916 else
3917 return string::from_printf (m_ctxt,
3918 "<UNNAMED BLOCK %p>",
3919 (void *)this);
3922 /* Implementation of recording::memento::write_reproducer for blocks. */
3924 void
3925 recording::block::write_reproducer (reproducer &r)
3927 const char *id = r.make_identifier (this, "block");
3928 r.write (" gcc_jit_block *%s =\n"
3929 " gcc_jit_function_new_block (%s, %s);\n",
3931 r.get_identifier (m_func),
3932 m_name ? m_name->get_debug_string () : "NULL");
3935 /* Dump a block in graphviz form into PP, capturing the block name (if
3936 any) and the statements. */
3938 void
3939 recording::block::dump_to_dot (pretty_printer *pp)
3941 pp_printf (pp,
3942 ("\tblock_%d "
3943 "[shape=record,style=filled,fillcolor=white,label=\"{"),
3944 m_index);
3945 pp_write_text_to_stream (pp);
3946 if (m_name)
3948 pp_string (pp, m_name->c_str ());
3949 pp_string (pp, ":");
3950 pp_newline (pp);
3951 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3954 int i;
3955 statement *s;
3956 FOR_EACH_VEC_ELT (m_statements, i, s)
3958 pp_string (pp, s->get_debug_string ());
3959 pp_newline (pp);
3960 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3963 pp_printf (pp,
3964 "}\"];\n\n");
3965 pp_flush (pp);
3968 /* Dump the out-edges of the block in graphviz form into PP. */
3970 void
3971 recording::block::dump_edges_to_dot (pretty_printer *pp)
3973 vec <block *> successors = get_successor_blocks ();
3974 int i;
3975 block *succ;
3976 FOR_EACH_VEC_ELT (successors, i, succ)
3977 pp_printf (pp,
3978 "\tblock_%d:s -> block_%d:n;\n",
3979 m_index, succ->m_index);
3980 successors.release ();
3983 /* The implementation of class gcc::jit::recording::global. */
3985 /* Implementation of pure virtual hook recording::memento::replay_into
3986 for recording::global. */
3988 void
3989 recording::global::replay_into (replayer *r)
3991 set_playback_obj (r->new_global (playback_location (r, m_loc),
3992 m_kind,
3993 m_type->playback_type (),
3994 playback_string (m_name)));
3997 /* Override the default implementation of
3998 recording::memento::write_to_dump for globals.
3999 This will be of the form:
4001 GCC_JIT_GLOBAL_EXPORTED:
4002 "TYPE NAME;"
4003 e.g. "int foo;"
4005 GCC_JIT_GLOBAL_INTERNAL:
4006 "static TYPE NAME;"
4007 e.g. "static int foo;"
4009 GCC_JIT_GLOBAL_IMPORTED:
4010 "extern TYPE NAME;"
4011 e.g. "extern int foo;"
4013 These are written to the top of the dump by
4014 recording::context::dump_to_file. */
4016 void
4017 recording::global::write_to_dump (dump &d)
4019 if (d.update_locations ())
4020 m_loc = d.make_location ();
4022 switch (m_kind)
4024 default:
4025 gcc_unreachable ();
4027 case GCC_JIT_GLOBAL_EXPORTED:
4028 break;
4030 case GCC_JIT_GLOBAL_INTERNAL:
4031 d.write ("static ");
4032 break;
4034 case GCC_JIT_GLOBAL_IMPORTED:
4035 d.write ("extern ");
4036 break;
4038 d.write ("%s %s;\n",
4039 m_type->get_debug_string (),
4040 get_debug_string ());
4043 /* A table of enum gcc_jit_global_kind values expressed in string
4044 form. */
4046 static const char * const global_kind_reproducer_strings[] = {
4047 "GCC_JIT_GLOBAL_EXPORTED",
4048 "GCC_JIT_GLOBAL_INTERNAL",
4049 "GCC_JIT_GLOBAL_IMPORTED"
4052 /* Implementation of recording::memento::write_reproducer for globals. */
4054 void
4055 recording::global::write_reproducer (reproducer &r)
4057 const char *id = r.make_identifier (this, "block");
4058 r.write (" gcc_jit_lvalue *%s =\n"
4059 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4060 " %s, /* gcc_jit_location *loc */\n"
4061 " %s, /* enum gcc_jit_global_kind kind */\n"
4062 " %s, /* gcc_jit_type *type */\n"
4063 " %s); /* const char *name */\n",
4065 r.get_identifier (get_context ()),
4066 r.get_identifier (m_loc),
4067 global_kind_reproducer_strings[m_kind],
4068 r.get_identifier_as_type (get_type ()),
4069 m_name->get_debug_string ());
4072 /* The implementation of the various const-handling classes:
4073 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4075 /* Explicit specialization of the various mementos we're interested in. */
4076 template class recording::memento_of_new_rvalue_from_const <int>;
4077 template class recording::memento_of_new_rvalue_from_const <long>;
4078 template class recording::memento_of_new_rvalue_from_const <double>;
4079 template class recording::memento_of_new_rvalue_from_const <void *>;
4081 /* Implementation of the pure virtual hook recording::memento::replay_into
4082 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4084 template <typename HOST_TYPE>
4085 void
4086 recording::
4087 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
4089 set_playback_obj
4090 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
4091 m_value));
4094 /* The make_debug_string and write_reproducer methods vary between the
4095 various
4096 memento_of_new_rvalue_from_const <HOST_TYPE>
4097 classes, so we explicitly write specializations of them.
4099 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4100 namespaces are written out explicitly, which is why most of this file
4101 doesn't abbreviate things by entering the "recording" namespace.
4103 However, these specializations are required to be in the same namespace
4104 as the template, hence we now have to enter the gcc::jit::recording
4105 namespace. */
4107 namespace recording
4110 /* The make_debug_string specialization for <int>, which renders it as
4111 (TARGET_TYPE)LITERAL
4112 e.g.
4113 "(int)42". */
4115 template <>
4116 string *
4117 memento_of_new_rvalue_from_const <int>::make_debug_string ()
4119 return string::from_printf (m_ctxt,
4120 "(%s)%i",
4121 m_type->get_debug_string (),
4122 m_value);
4125 /* The get_wide_int specialization for <int>. */
4127 template <>
4128 bool
4129 memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const
4131 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4132 return true;
4135 /* The write_reproducer specialization for <int>. */
4137 template <>
4138 void
4139 memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
4141 const char *id = r.make_identifier (this, "rvalue");
4142 r.write (" gcc_jit_rvalue *%s =\n"
4143 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4144 " %s, /* gcc_jit_type *numeric_type */\n"
4145 " %i); /* int value */\n",
4147 r.get_identifier (get_context ()),
4148 r.get_identifier_as_type (m_type),
4149 m_value);
4152 /* The make_debug_string specialization for <long>, rendering it as
4153 (TARGET_TYPE)LITERAL
4154 e.g.
4155 "(long)42". */
4157 template <>
4158 string *
4159 memento_of_new_rvalue_from_const <long>::make_debug_string ()
4161 return string::from_printf (m_ctxt,
4162 "(%s)%li",
4163 m_type->get_debug_string (),
4164 m_value);
4167 /* The get_wide_int specialization for <long>. */
4169 template <>
4170 bool
4171 memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const
4173 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4174 return true;
4177 /* The write_reproducer specialization for <long>. */
4179 template <>
4180 void
4181 recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
4183 const char *id = r.make_identifier (this, "rvalue");
4185 /* We have to special-case LONG_MIN, since e.g.
4186 -9223372036854775808L
4187 is parsed as
4188 -(9223372036854775808L)
4189 and hence we'd get:
4190 error: integer constant is so large that it is unsigned [-Werror]
4191 Workaround this by writing (LONG_MIN + 1) - 1. */
4192 if (m_value == LONG_MIN)
4194 r.write (" gcc_jit_rvalue *%s =\n"
4195 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4196 " %s, /* gcc_jit_type *numeric_type */\n"
4197 " %ldL - 1); /* long value */\n",
4199 r.get_identifier (get_context ()),
4200 r.get_identifier_as_type (m_type),
4201 m_value + 1);;
4202 return;
4205 r.write (" gcc_jit_rvalue *%s =\n"
4206 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4207 " %s, /* gcc_jit_type *numeric_type */\n"
4208 " %ldL); /* long value */\n",
4210 r.get_identifier (get_context ()),
4211 r.get_identifier_as_type (m_type),
4212 m_value);
4215 /* The make_debug_string specialization for <double>, rendering it as
4216 (TARGET_TYPE)LITERAL
4217 e.g.
4218 "(float)42.0". */
4220 template <>
4221 string *
4222 memento_of_new_rvalue_from_const <double>::make_debug_string ()
4224 return string::from_printf (m_ctxt,
4225 "(%s)%f",
4226 m_type->get_debug_string (),
4227 m_value);
4230 /* The get_wide_int specialization for <double>. */
4232 template <>
4233 bool
4234 memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
4236 return false;
4239 /* The write_reproducer specialization for <double>. */
4241 template <>
4242 void
4243 recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
4245 const char *id = r.make_identifier (this, "rvalue");
4246 r.write (" gcc_jit_rvalue *%s =\n"
4247 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4248 " %s, /* gcc_jit_type *numeric_type */\n"
4249 " %f); /* double value */\n",
4251 r.get_identifier (get_context ()),
4252 r.get_identifier_as_type (m_type),
4253 m_value);
4256 /* The make_debug_string specialization for <void *>, rendering it as
4257 (TARGET_TYPE)HEX
4258 e.g.
4259 "(int *)0xdeadbeef"
4261 Zero is rendered as NULL e.g.
4262 "(int *)NULL". */
4264 template <>
4265 string *
4266 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
4268 if (m_value != NULL)
4269 return string::from_printf (m_ctxt,
4270 "(%s)%p",
4271 m_type->get_debug_string (), m_value);
4272 else
4273 return string::from_printf (m_ctxt,
4274 "(%s)NULL",
4275 m_type->get_debug_string ());
4278 /* The get_wide_int specialization for <void *>. */
4280 template <>
4281 bool
4282 memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const
4284 return false;
4287 /* Implementation of recording::memento::write_reproducer for <void *>
4288 values. */
4290 template <>
4291 void
4292 memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
4294 const char *id = r.make_identifier (this, "rvalue");
4295 if (m_value)
4296 r.write (" gcc_jit_rvalue *%s =\n"
4297 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4298 " %s, /* gcc_jit_type *pointer_type */\n"
4299 " (void *)%p); /* void *value */\n",
4301 r.get_identifier (get_context ()),
4302 r.get_identifier_as_type (m_type),
4303 m_value);
4304 else
4305 r.write (" gcc_jit_rvalue *%s =\n"
4306 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4307 " %s); /* gcc_jit_type *pointer_type */\n",
4309 r.get_identifier (get_context ()),
4310 r.get_identifier_as_type (m_type));
4313 /* We're done specializing make_debug_string and write_reproducer, so we
4314 can exit the gcc::jit::recording namespace. */
4316 } // namespace recording
4318 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4320 /* Implementation of pure virtual hook recording::memento::replay_into
4321 for recording::memento_of_new_string_literal. */
4323 void
4324 recording::memento_of_new_string_literal::replay_into (replayer *r)
4326 set_playback_obj (r->new_string_literal (m_value->c_str ()));
4329 /* Implementation of recording::memento::make_debug_string for
4330 string literals. */
4332 recording::string *
4333 recording::memento_of_new_string_literal::make_debug_string ()
4335 return string::from_printf (m_ctxt,
4336 "%s",
4337 m_value->get_debug_string ());
4340 /* Implementation of recording::memento::write_reproducer for string literal
4341 values. */
4343 void
4344 recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
4346 const char *id = r.make_identifier (this, "rvalue");
4347 r.write (" gcc_jit_rvalue *%s =\n"
4348 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4349 " %s); /* const char *value */\n",
4351 r.get_identifier (get_context ()),
4352 m_value->get_debug_string ());
4355 /* The implementation of class gcc::jit::recording::unary_op. */
4357 /* Implementation of pure virtual hook recording::memento::replay_into
4358 for recording::unary_op. */
4360 void
4361 recording::unary_op::replay_into (replayer *r)
4363 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
4364 m_op,
4365 get_type ()->playback_type (),
4366 m_a->playback_rvalue ()));
4369 /* Implementation of pure virtual hook recording::rvalue::visit_children
4370 for recording::unary_op. */
4371 void
4372 recording::unary_op::visit_children (rvalue_visitor *v)
4374 v->visit (m_a);
4377 /* Implementation of recording::memento::make_debug_string for
4378 unary ops. */
4380 static const char * const unary_op_strings[] = {
4381 "-", /* GCC_JIT_UNARY_OP_MINUS */
4382 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4383 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4384 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4387 recording::string *
4388 recording::unary_op::make_debug_string ()
4390 return string::from_printf (m_ctxt,
4391 "%s(%s)",
4392 unary_op_strings[m_op],
4393 m_a->get_debug_string ());
4396 static const char * const unary_op_reproducer_strings[] = {
4397 "GCC_JIT_UNARY_OP_MINUS",
4398 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4399 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4400 "GCC_JIT_UNARY_OP_ABS"
4403 /* Implementation of recording::memento::write_reproducer for unary ops. */
4405 void
4406 recording::unary_op::write_reproducer (reproducer &r)
4408 const char *id = r.make_identifier (this, "rvalue");
4409 r.write (" gcc_jit_rvalue *%s =\n"
4410 " gcc_jit_context_new_unary_op (%s,\n"
4411 " %s, /* gcc_jit_location *loc */\n"
4412 " %s, /* enum gcc_jit_unary_op op */\n"
4413 " %s, /* gcc_jit_type *result_type */\n"
4414 " %s); /* gcc_jit_rvalue *a */\n",
4416 r.get_identifier (get_context ()),
4417 r.get_identifier (m_loc),
4418 unary_op_reproducer_strings[m_op],
4419 r.get_identifier_as_type (get_type ()),
4420 r.get_identifier_as_rvalue (m_a));
4423 /* The implementation of class gcc::jit::recording::binary_op. */
4425 /* Implementation of pure virtual hook recording::memento::replay_into
4426 for recording::binary_op. */
4428 void
4429 recording::binary_op::replay_into (replayer *r)
4431 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
4432 m_op,
4433 get_type ()->playback_type (),
4434 m_a->playback_rvalue (),
4435 m_b->playback_rvalue ()));
4438 /* Implementation of pure virtual hook recording::rvalue::visit_children
4439 for recording::binary_op. */
4440 void
4441 recording::binary_op::visit_children (rvalue_visitor *v)
4443 v->visit (m_a);
4444 v->visit (m_b);
4447 /* Implementation of recording::memento::make_debug_string for
4448 binary ops. */
4450 static const char * const binary_op_strings[] = {
4451 "+", /* GCC_JIT_BINARY_OP_PLUS */
4452 "-", /* GCC_JIT_BINARY_OP_MINUS */
4453 "*", /* GCC_JIT_BINARY_OP_MULT */
4454 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4455 "%", /* GCC_JIT_BINARY_OP_MODULO */
4456 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4457 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4458 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4459 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4460 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4461 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4462 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4465 recording::string *
4466 recording::binary_op::make_debug_string ()
4468 enum precedence prec = get_precedence ();
4469 return string::from_printf (m_ctxt,
4470 "%s %s %s",
4471 m_a->get_debug_string_parens (prec),
4472 binary_op_strings[m_op],
4473 m_b->get_debug_string_parens (prec));
4476 static const char * const binary_op_reproducer_strings[] = {
4477 "GCC_JIT_BINARY_OP_PLUS",
4478 "GCC_JIT_BINARY_OP_MINUS",
4479 "GCC_JIT_BINARY_OP_MULT",
4480 "GCC_JIT_BINARY_OP_DIVIDE",
4481 "GCC_JIT_BINARY_OP_MODULO",
4482 "GCC_JIT_BINARY_OP_BITWISE_AND",
4483 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4484 "GCC_JIT_BINARY_OP_BITWISE_OR",
4485 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4486 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4487 "GCC_JIT_BINARY_OP_LSHIFT",
4488 "GCC_JIT_BINARY_OP_RSHIFT"
4491 /* Implementation of recording::memento::write_reproducer for binary ops. */
4493 void
4494 recording::binary_op::write_reproducer (reproducer &r)
4496 const char *id = r.make_identifier (this, "rvalue");
4497 r.write (" gcc_jit_rvalue *%s =\n"
4498 " gcc_jit_context_new_binary_op (%s,\n"
4499 " %s, /* gcc_jit_location *loc */\n"
4500 " %s, /* enum gcc_jit_binary_op op */\n"
4501 " %s, /* gcc_jit_type *result_type */\n"
4502 " %s, /* gcc_jit_rvalue *a */\n"
4503 " %s); /* gcc_jit_rvalue *b */\n",
4505 r.get_identifier (get_context ()),
4506 r.get_identifier (m_loc),
4507 binary_op_reproducer_strings[m_op],
4508 r.get_identifier_as_type (get_type ()),
4509 r.get_identifier_as_rvalue (m_a),
4510 r.get_identifier_as_rvalue (m_b));
4513 namespace recording {
4514 static const enum precedence binary_op_precedence[] = {
4515 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
4516 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
4518 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
4519 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
4520 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
4522 PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4523 PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4524 PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4525 PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4526 PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4527 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
4528 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
4530 } /* namespace recording */
4532 enum recording::precedence
4533 recording::binary_op::get_precedence () const
4535 return binary_op_precedence[m_op];
4538 /* The implementation of class gcc::jit::recording::comparison. */
4540 /* Implementation of recording::memento::make_debug_string for
4541 comparisons. */
4543 static const char * const comparison_strings[] =
4545 "==", /* GCC_JIT_COMPARISON_EQ */
4546 "!=", /* GCC_JIT_COMPARISON_NE */
4547 "<", /* GCC_JIT_COMPARISON_LT */
4548 "<=", /* GCC_JIT_COMPARISON_LE */
4549 ">", /* GCC_JIT_COMPARISON_GT */
4550 ">=", /* GCC_JIT_COMPARISON_GE */
4553 recording::string *
4554 recording::comparison::make_debug_string ()
4556 enum precedence prec = get_precedence ();
4557 return string::from_printf (m_ctxt,
4558 "%s %s %s",
4559 m_a->get_debug_string_parens (prec),
4560 comparison_strings[m_op],
4561 m_b->get_debug_string_parens (prec));
4564 /* A table of enum gcc_jit_comparison values expressed in string
4565 form. */
4567 static const char * const comparison_reproducer_strings[] =
4569 "GCC_JIT_COMPARISON_EQ",
4570 "GCC_JIT_COMPARISON_NE",
4571 "GCC_JIT_COMPARISON_LT",
4572 "GCC_JIT_COMPARISON_LE",
4573 "GCC_JIT_COMPARISON_GT",
4574 "GCC_JIT_COMPARISON_GE"
4577 /* Implementation of recording::memento::write_reproducer for comparisons. */
4579 void
4580 recording::comparison::write_reproducer (reproducer &r)
4582 const char *id = r.make_identifier (this, "rvalue");
4583 r.write (" gcc_jit_rvalue *%s =\n"
4584 " gcc_jit_context_new_comparison (%s,\n"
4585 " %s, /* gcc_jit_location *loc */\n"
4586 " %s, /* enum gcc_jit_comparison op */\n"
4587 " %s, /* gcc_jit_rvalue *a */\n"
4588 " %s); /* gcc_jit_rvalue *b */\n",
4590 r.get_identifier (get_context ()),
4591 r.get_identifier (m_loc),
4592 comparison_reproducer_strings[m_op],
4593 r.get_identifier_as_rvalue (m_a),
4594 r.get_identifier_as_rvalue (m_b));
4597 /* Implementation of pure virtual hook recording::memento::replay_into
4598 for recording::comparison. */
4600 void
4601 recording::comparison::replay_into (replayer *r)
4603 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
4604 m_op,
4605 m_a->playback_rvalue (),
4606 m_b->playback_rvalue ()));
4609 /* Implementation of pure virtual hook recording::rvalue::visit_children
4610 for recording::comparison. */
4612 void
4613 recording::comparison::visit_children (rvalue_visitor *v)
4615 v->visit (m_a);
4616 v->visit (m_b);
4619 namespace recording {
4620 static const enum precedence comparison_precedence[] =
4622 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
4623 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
4625 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LT */
4626 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
4627 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GT */
4628 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
4630 } /* namespace recording */
4632 enum recording::precedence
4633 recording::comparison::get_precedence () const
4635 return comparison_precedence[m_op];
4638 /* Implementation of pure virtual hook recording::memento::replay_into
4639 for recording::cast. */
4641 void
4642 recording::cast::replay_into (replayer *r)
4644 set_playback_obj (r->new_cast (playback_location (r, m_loc),
4645 m_rvalue->playback_rvalue (),
4646 get_type ()->playback_type ()));
4649 /* Implementation of pure virtual hook recording::rvalue::visit_children
4650 for recording::cast. */
4651 void
4652 recording::cast::visit_children (rvalue_visitor *v)
4654 v->visit (m_rvalue);
4657 /* Implementation of recording::memento::make_debug_string for
4658 casts. */
4660 recording::string *
4661 recording::cast::make_debug_string ()
4663 enum precedence prec = get_precedence ();
4664 return string::from_printf (m_ctxt,
4665 "(%s)%s",
4666 get_type ()->get_debug_string (),
4667 m_rvalue->get_debug_string_parens (prec));
4670 /* Implementation of recording::memento::write_reproducer for casts. */
4672 void
4673 recording::cast::write_reproducer (reproducer &r)
4675 const char *id = r.make_identifier (this, "rvalue");
4676 r.write (" gcc_jit_rvalue *%s =\n"
4677 " gcc_jit_context_new_cast (%s,\n"
4678 " %s, /* gcc_jit_location *loc */\n"
4679 " %s, /* gcc_jit_rvalue *rvalue */\n"
4680 " %s); /* gcc_jit_type *type */\n",
4682 r.get_identifier (get_context ()),
4683 r.get_identifier (m_loc),
4684 r.get_identifier_as_rvalue (m_rvalue),
4685 r.get_identifier_as_type (get_type ()));
4688 /* The implementation of class gcc::jit::recording::call. */
4690 /* The constructor for gcc::jit::recording::call. */
4692 recording::call::call (recording::context *ctxt,
4693 recording::location *loc,
4694 recording::function *func,
4695 int numargs,
4696 rvalue **args)
4697 : rvalue (ctxt, loc, func->get_return_type ()),
4698 m_func (func),
4699 m_args ()
4701 for (int i = 0; i< numargs; i++)
4702 m_args.safe_push (args[i]);
4705 /* Implementation of pure virtual hook recording::memento::replay_into
4706 for recording::call. */
4708 void
4709 recording::call::replay_into (replayer *r)
4711 auto_vec<playback::rvalue *> playback_args;
4712 playback_args.create (m_args.length ());
4713 for (unsigned i = 0; i< m_args.length (); i++)
4714 playback_args.safe_push (m_args[i]->playback_rvalue ());
4716 set_playback_obj (r->new_call (playback_location (r, m_loc),
4717 m_func->playback_function (),
4718 &playback_args));
4721 /* Implementation of pure virtual hook recording::rvalue::visit_children
4722 for recording::call. */
4724 void
4725 recording::call::visit_children (rvalue_visitor *v)
4727 for (unsigned i = 0; i< m_args.length (); i++)
4728 v->visit (m_args[i]);
4731 /* Implementation of recording::memento::make_debug_string for
4732 function calls. */
4734 recording::string *
4735 recording::call::make_debug_string ()
4737 enum precedence prec = get_precedence ();
4738 /* First, build a buffer for the arguments. */
4739 /* Calculate length of said buffer. */
4740 size_t sz = 1; /* nil terminator */
4741 for (unsigned i = 0; i< m_args.length (); i++)
4743 sz += strlen (m_args[i]->get_debug_string_parens (prec));
4744 sz += 2; /* ", " separator */
4747 /* Now allocate and populate the buffer. */
4748 char *argbuf = new char[sz];
4749 size_t len = 0;
4751 for (unsigned i = 0; i< m_args.length (); i++)
4753 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4754 len += strlen (m_args[i]->get_debug_string_parens (prec));
4755 if (i + 1 < m_args.length ())
4757 strcpy (argbuf + len, ", ");
4758 len += 2;
4761 argbuf[len] = '\0';
4763 /* ...and use it to get the string for the call as a whole. */
4764 string *result = string::from_printf (m_ctxt,
4765 "%s (%s)",
4766 m_func->get_debug_string (),
4767 argbuf);
4769 delete[] argbuf;
4771 return result;
4774 void
4775 recording::call::write_reproducer (reproducer &r)
4777 const char *id = r.make_identifier (this, "call");
4778 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4779 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4780 args_id,
4781 m_args.length ());
4782 for (unsigned i = 0; i< m_args.length (); i++)
4783 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4784 r.write (" };\n");
4785 r.write (" gcc_jit_rvalue *%s =\n"
4786 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4787 " %s, /* gcc_jit_location *loc */\n"
4788 " %s, /* gcc_jit_function *func */\n"
4789 " %i, /* int numargs */ \n"
4790 " %s); /* gcc_jit_rvalue **args*/\n",
4792 r.get_identifier (get_context ()),
4793 r.get_identifier (m_loc),
4794 r.get_identifier (m_func),
4795 m_args.length (),
4796 args_id);
4799 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4801 /* The constructor for recording::call_through_ptr. */
4803 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
4804 recording::location *loc,
4805 recording::rvalue *fn_ptr,
4806 int numargs,
4807 rvalue **args)
4808 : rvalue (ctxt, loc,
4809 fn_ptr->get_type ()->dereference ()
4810 ->as_a_function_type ()->get_return_type ()),
4811 m_fn_ptr (fn_ptr),
4812 m_args ()
4814 for (int i = 0; i< numargs; i++)
4815 m_args.safe_push (args[i]);
4818 /* Implementation of pure virtual hook recording::memento::replay_into
4819 for recording::call_through_ptr. */
4821 void
4822 recording::call_through_ptr::replay_into (replayer *r)
4824 auto_vec<playback::rvalue *> playback_args;
4825 playback_args.create (m_args.length ());
4826 for (unsigned i = 0; i< m_args.length (); i++)
4827 playback_args.safe_push (m_args[i]->playback_rvalue ());
4829 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
4830 m_fn_ptr->playback_rvalue (),
4831 &playback_args));
4834 /* Implementation of pure virtual hook recording::rvalue::visit_children
4835 for recording::call_through_ptr. */
4837 void
4838 recording::call_through_ptr::visit_children (rvalue_visitor *v)
4840 v->visit (m_fn_ptr);
4841 for (unsigned i = 0; i< m_args.length (); i++)
4842 v->visit (m_args[i]);
4845 /* Implementation of recording::memento::make_debug_string for
4846 calls through function ptrs. */
4848 recording::string *
4849 recording::call_through_ptr::make_debug_string ()
4851 enum precedence prec = get_precedence ();
4852 /* First, build a buffer for the arguments. */
4853 /* Calculate length of said buffer. */
4854 size_t sz = 1; /* nil terminator */
4855 for (unsigned i = 0; i< m_args.length (); i++)
4857 sz += strlen (m_args[i]->get_debug_string_parens (prec));
4858 sz += 2; /* ", " separator */
4861 /* Now allocate and populate the buffer. */
4862 char *argbuf = new char[sz];
4863 size_t len = 0;
4865 for (unsigned i = 0; i< m_args.length (); i++)
4867 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4868 len += strlen (m_args[i]->get_debug_string_parens (prec));
4869 if (i + 1 < m_args.length ())
4871 strcpy (argbuf + len, ", ");
4872 len += 2;
4875 argbuf[len] = '\0';
4877 /* ...and use it to get the string for the call as a whole. */
4878 string *result = string::from_printf (m_ctxt,
4879 "%s (%s)",
4880 m_fn_ptr->get_debug_string_parens (prec),
4881 argbuf);
4883 delete[] argbuf;
4885 return result;
4888 /* Implementation of recording::memento::write_reproducer for
4889 call_through_ptr. */
4891 void
4892 recording::call_through_ptr::write_reproducer (reproducer &r)
4894 const char *id = r.make_identifier (this, "call");
4895 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4896 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4897 args_id,
4898 m_args.length ());
4899 for (unsigned i = 0; i< m_args.length (); i++)
4900 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4901 r.write (" };\n");
4902 r.write (" gcc_jit_rvalue *%s =\n"
4903 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
4904 " %s, /* gcc_jit_location *loc */\n"
4905 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
4906 " %i, /* int numargs */ \n"
4907 " %s); /* gcc_jit_rvalue **args*/\n",
4909 r.get_identifier (get_context ()),
4910 r.get_identifier (m_loc),
4911 r.get_identifier_as_rvalue (m_fn_ptr),
4912 m_args.length (),
4913 args_id);
4916 /* The implementation of class gcc::jit::recording::array_access. */
4918 /* Implementation of pure virtual hook recording::memento::replay_into
4919 for recording::array_access. */
4921 void
4922 recording::array_access::replay_into (replayer *r)
4924 set_playback_obj (
4925 r->new_array_access (playback_location (r, m_loc),
4926 m_ptr->playback_rvalue (),
4927 m_index->playback_rvalue ()));
4930 /* Implementation of pure virtual hook recording::rvalue::visit_children
4931 for recording::array_access. */
4933 void
4934 recording::array_access::visit_children (rvalue_visitor *v)
4936 v->visit (m_ptr);
4937 v->visit (m_index);
4940 /* Implementation of recording::memento::make_debug_string for
4941 array accesses. */
4943 recording::string *
4944 recording::array_access::make_debug_string ()
4946 enum precedence prec = get_precedence ();
4947 return string::from_printf (m_ctxt,
4948 "%s[%s]",
4949 m_ptr->get_debug_string_parens (prec),
4950 m_index->get_debug_string_parens (prec));
4953 /* Implementation of recording::memento::write_reproducer for
4954 array_access. */
4956 void
4957 recording::array_access::write_reproducer (reproducer &r)
4959 const char *id = r.make_identifier (this, "lvalue");
4960 r.write (" gcc_jit_lvalue *%s = \n"
4961 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
4962 " %s, /*gcc_jit_location *loc */\n"
4963 " %s, /* gcc_jit_rvalue *ptr */\n"
4964 " %s); /* gcc_jit_rvalue *index */\n",
4966 r.get_identifier (get_context ()),
4967 r.get_identifier (m_loc),
4968 r.get_identifier_as_rvalue (m_ptr),
4969 r.get_identifier_as_rvalue (m_index));
4972 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
4974 /* Implementation of pure virtual hook recording::memento::replay_into
4975 for recording::access_field_of_lvalue. */
4977 void
4978 recording::access_field_of_lvalue::replay_into (replayer *r)
4980 set_playback_obj (
4981 m_lvalue->playback_lvalue ()
4982 ->access_field (playback_location (r, m_loc),
4983 m_field->playback_field ()));
4987 /* Implementation of pure virtual hook recording::rvalue::visit_children
4988 for recording::access_field_of_lvalue. */
4990 void
4991 recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
4993 v->visit (m_lvalue);
4996 /* Implementation of recording::memento::make_debug_string for
4997 accessing a field of an lvalue. */
4999 recording::string *
5000 recording::access_field_of_lvalue::make_debug_string ()
5002 enum precedence prec = get_precedence ();
5003 return string::from_printf (m_ctxt,
5004 "%s.%s",
5005 m_lvalue->get_debug_string_parens (prec),
5006 m_field->get_debug_string ());
5009 /* Implementation of recording::memento::write_reproducer for
5010 access_field_of_lvalue. */
5012 void
5013 recording::access_field_of_lvalue::write_reproducer (reproducer &r)
5015 const char *id = r.make_identifier (this, "lvalue");
5016 r.write (" gcc_jit_lvalue *%s = \n"
5017 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5018 " %s, /*gcc_jit_location *loc */\n"
5019 " %s);\n",
5021 r.get_identifier_as_lvalue (m_lvalue),
5022 r.get_identifier (m_loc),
5023 r.get_identifier (m_field));
5026 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
5028 /* Implementation of pure virtual hook recording::memento::replay_into
5029 for recording::access_field_rvalue. */
5031 void
5032 recording::access_field_rvalue::replay_into (replayer *r)
5034 set_playback_obj (
5035 m_rvalue->playback_rvalue ()
5036 ->access_field (playback_location (r, m_loc),
5037 m_field->playback_field ()));
5040 /* Implementation of pure virtual hook recording::rvalue::visit_children
5041 for recording::access_field_rvalue. */
5043 void
5044 recording::access_field_rvalue::visit_children (rvalue_visitor *v)
5046 v->visit (m_rvalue);
5049 /* Implementation of recording::memento::make_debug_string for
5050 accessing a field of an rvalue. */
5052 recording::string *
5053 recording::access_field_rvalue::make_debug_string ()
5055 enum precedence prec = get_precedence ();
5056 return string::from_printf (m_ctxt,
5057 "%s.%s",
5058 m_rvalue->get_debug_string_parens (prec),
5059 m_field->get_debug_string ());
5062 /* Implementation of recording::memento::write_reproducer for
5063 access_field_rvalue. */
5065 void
5066 recording::access_field_rvalue::write_reproducer (reproducer &r)
5068 const char *id = r.make_identifier (this, "rvalue");
5069 r.write (" gcc_jit_rvalue *%s = \n"
5070 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5071 " %s, /*gcc_jit_location *loc */\n"
5072 " %s);\n",
5074 r.get_identifier_as_rvalue (m_rvalue),
5075 r.get_identifier (m_loc),
5076 r.get_identifier (m_field));
5079 /* The implementation of class
5080 gcc::jit::recording::dereference_field_rvalue. */
5082 /* Implementation of pure virtual hook recording::memento::replay_into
5083 for recording::dereference_field_rvalue. */
5085 void
5086 recording::dereference_field_rvalue::replay_into (replayer *r)
5088 set_playback_obj (
5089 m_rvalue->playback_rvalue ()->
5090 dereference_field (playback_location (r, m_loc),
5091 m_field->playback_field ()));
5094 /* Implementation of pure virtual hook recording::rvalue::visit_children
5095 for recording::dereference_field_rvalue. */
5097 void
5098 recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
5100 v->visit (m_rvalue);
5103 /* Implementation of recording::memento::make_debug_string for
5104 dereferencing a field of an rvalue. */
5106 recording::string *
5107 recording::dereference_field_rvalue::make_debug_string ()
5109 enum precedence prec = get_precedence ();
5110 return string::from_printf (m_ctxt,
5111 "%s->%s",
5112 m_rvalue->get_debug_string_parens (prec),
5113 m_field->get_debug_string ());
5116 /* Implementation of recording::memento::write_reproducer for
5117 dereference_field_rvalue. */
5119 void
5120 recording::dereference_field_rvalue::write_reproducer (reproducer &r)
5122 const char *id = r.make_identifier (this, "lvalue");
5123 r.write (" gcc_jit_lvalue *%s=\n"
5124 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5125 " %s, /* gcc_jit_location *loc */\n"
5126 " %s); /* gcc_jit_field *field */\n",
5128 r.get_identifier_as_rvalue (m_rvalue),
5129 r.get_identifier (m_loc),
5130 r.get_identifier (m_field));
5133 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5135 /* Implementation of pure virtual hook recording::memento::replay_into
5136 for recording::dereference_rvalue. */
5138 void
5139 recording::dereference_rvalue::replay_into (replayer *r)
5141 set_playback_obj (
5142 m_rvalue->playback_rvalue ()->
5143 dereference (playback_location (r, m_loc)));
5146 /* Implementation of pure virtual hook recording::rvalue::visit_children
5147 for recording::dereference_rvalue. */
5149 void
5150 recording::dereference_rvalue::visit_children (rvalue_visitor *v)
5152 v->visit (m_rvalue);
5155 /* Implementation of recording::memento::make_debug_string for
5156 dereferencing an rvalue. */
5158 recording::string *
5159 recording::dereference_rvalue::make_debug_string ()
5161 enum precedence prec = get_precedence ();
5162 return string::from_printf (m_ctxt,
5163 "*%s",
5164 m_rvalue->get_debug_string_parens (prec));
5167 /* Implementation of recording::memento::write_reproducer for
5168 dereference_rvalue. */
5170 void
5171 recording::dereference_rvalue::write_reproducer (reproducer &r)
5173 const char *id = r.make_identifier (this, "dereference");
5174 r.write (" gcc_jit_lvalue *%s =\n"
5175 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5176 " %s); /* gcc_jit_location *loc */\n",
5178 r.get_identifier_as_rvalue (m_rvalue),
5179 r.get_identifier (m_loc));
5182 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5184 /* Implementation of pure virtual hook recording::memento::replay_into
5185 for recording::get_address_of_lvalue. */
5187 void
5188 recording::get_address_of_lvalue::replay_into (replayer *r)
5190 set_playback_obj (
5191 m_lvalue->playback_lvalue ()->
5192 get_address (playback_location (r, m_loc)));
5195 /* Implementation of pure virtual hook recording::rvalue::visit_children
5196 for recording::get_address_of_lvalue. */
5198 void
5199 recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
5201 v->visit (m_lvalue);
5204 /* Implementation of recording::memento::make_debug_string for
5205 getting the address of an lvalue. */
5207 recording::string *
5208 recording::get_address_of_lvalue::make_debug_string ()
5210 enum precedence prec = get_precedence ();
5211 return string::from_printf (m_ctxt,
5212 "&%s",
5213 m_lvalue->get_debug_string_parens (prec));
5216 /* Implementation of recording::memento::write_reproducer for
5217 get_address_of_lvalue. */
5219 void
5220 recording::get_address_of_lvalue::write_reproducer (reproducer &r)
5222 const char *id = r.make_identifier (this, "address_of");
5223 r.write (" gcc_jit_rvalue *%s =\n"
5224 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5225 " %s); /* gcc_jit_location *loc */\n",
5227 r.get_identifier_as_lvalue (m_lvalue),
5228 r.get_identifier (m_loc));
5231 /* The implementation of class gcc::jit::recording::local. */
5233 /* Implementation of pure virtual hook recording::memento::replay_into
5234 for recording::local. */
5236 void
5237 recording::local::replay_into (replayer *r)
5239 set_playback_obj (
5240 m_func->playback_function ()
5241 ->new_local (playback_location (r, m_loc),
5242 m_type->playback_type (),
5243 playback_string (m_name)));
5246 /* Override the default implementation of
5247 recording::memento::write_to_dump for locals by writing
5248 TYPE NAME;
5249 for use at the top of the function body as if it were a
5250 declaration. */
5252 void
5253 recording::local::write_to_dump (dump &d)
5255 if (d.update_locations ())
5256 m_loc = d.make_location ();
5257 d.write(" %s %s;\n",
5258 m_type->get_debug_string (),
5259 get_debug_string ());
5262 void
5263 recording::local::write_reproducer (reproducer &r)
5265 const char *id = r.make_identifier (this, "local");
5266 r.write (" gcc_jit_lvalue *%s =\n"
5267 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5268 " %s, /* gcc_jit_location *loc */\n"
5269 " %s, /* gcc_jit_type *type */\n"
5270 " %s); /* const char *name */\n",
5272 r.get_identifier (m_func),
5273 r.get_identifier (m_loc),
5274 r.get_identifier_as_type (m_type),
5275 m_name->get_debug_string ());
5278 /* The implementation of class gcc::jit::recording::statement. */
5280 /* We poison the default implementation of
5281 gcc::jit::recording::statement::get_successor_blocks
5282 since this vfunc must only ever be called on terminator
5283 statements. */
5285 vec <recording::block *>
5286 recording::statement::get_successor_blocks () const
5288 /* The base class implementation is for non-terminating statements,
5289 and thus should never be called. */
5290 gcc_unreachable ();
5291 vec <block *> result;
5292 result.create (0);
5293 return result;
5296 /* Extend the default implementation of
5297 recording::memento::write_to_dump for statements by (if requested)
5298 updating the location of the statement to the current location in
5299 the dumpfile. */
5301 void
5302 recording::statement::write_to_dump (dump &d)
5304 memento::write_to_dump (d);
5305 if (d.update_locations ())
5306 m_loc = d.make_location ();
5309 /* The implementation of class gcc::jit::recording::eval. */
5311 /* Implementation of pure virtual hook recording::memento::replay_into
5312 for recording::eval. */
5314 void
5315 recording::eval::replay_into (replayer *r)
5317 playback_block (get_block ())
5318 ->add_eval (playback_location (r),
5319 m_rvalue->playback_rvalue ());
5322 /* Implementation of recording::memento::make_debug_string for
5323 an eval statement. */
5325 recording::string *
5326 recording::eval::make_debug_string ()
5328 return string::from_printf (m_ctxt,
5329 "(void)%s;",
5330 m_rvalue->get_debug_string ());
5333 /* Implementation of recording::memento::write_reproducer for
5334 eval statements. */
5336 void
5337 recording::eval::write_reproducer (reproducer &r)
5339 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5340 " %s, /* gcc_jit_location *loc */\n"
5341 " %s); /* gcc_jit_rvalue *rvalue */\n",
5342 r.get_identifier (get_block ()),
5343 r.get_identifier (get_loc ()),
5344 r.get_identifier_as_rvalue (m_rvalue));
5347 /* The implementation of class gcc::jit::recording::assignment. */
5349 /* Implementation of pure virtual hook recording::memento::replay_into
5350 for recording::assignment. */
5352 void
5353 recording::assignment::replay_into (replayer *r)
5355 playback_block (get_block ())
5356 ->add_assignment (playback_location (r),
5357 m_lvalue->playback_lvalue (),
5358 m_rvalue->playback_rvalue ());
5361 /* Implementation of recording::memento::make_debug_string for
5362 an assignment statement. */
5364 recording::string *
5365 recording::assignment::make_debug_string ()
5367 return string::from_printf (m_ctxt,
5368 "%s = %s;",
5369 m_lvalue->get_debug_string (),
5370 m_rvalue->get_debug_string ());
5373 /* Implementation of recording::memento::write_reproducer for
5374 assignment statements. */
5376 void
5377 recording::assignment::write_reproducer (reproducer &r)
5379 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5380 " %s, /* gcc_jit_location *loc */\n"
5381 " %s, /* gcc_jit_lvalue *lvalue */\n"
5382 " %s); /* gcc_jit_rvalue *rvalue */\n",
5383 r.get_identifier (get_block ()),
5384 r.get_identifier (get_loc ()),
5385 r.get_identifier_as_lvalue (m_lvalue),
5386 r.get_identifier_as_rvalue (m_rvalue));
5389 /* The implementation of class gcc::jit::recording::assignment_op. */
5391 /* Implementation of pure virtual hook recording::memento::replay_into
5392 for recording::assignment_op. */
5394 void
5395 recording::assignment_op::replay_into (replayer *r)
5397 playback::type *result_type =
5398 m_lvalue->playback_lvalue ()->get_type ();
5400 playback::rvalue *binary_op =
5401 r->new_binary_op (playback_location (r),
5402 m_op,
5403 result_type,
5404 m_lvalue->playback_rvalue (),
5405 m_rvalue->playback_rvalue ());
5407 playback_block (get_block ())
5408 ->add_assignment (playback_location (r),
5409 m_lvalue->playback_lvalue (),
5410 binary_op);
5413 /* Implementation of recording::memento::make_debug_string for
5414 an assignment_op statement. */
5416 recording::string *
5417 recording::assignment_op::make_debug_string ()
5419 return string::from_printf (m_ctxt,
5420 "%s %s= %s;",
5421 m_lvalue->get_debug_string (),
5422 binary_op_strings[m_op],
5423 m_rvalue->get_debug_string ());
5426 /* Implementation of recording::memento::write_reproducer for
5427 assignment_op statements. */
5429 void
5430 recording::assignment_op::write_reproducer (reproducer &r)
5432 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5433 " %s, /* gcc_jit_location *loc */\n"
5434 " %s, /* gcc_jit_lvalue *lvalue */\n"
5435 " %s, /* enum gcc_jit_binary_op op */\n"
5436 " %s); /* gcc_jit_rvalue *rvalue */\n",
5437 r.get_identifier (get_block ()),
5438 r.get_identifier (get_loc ()),
5439 r.get_identifier_as_lvalue (m_lvalue),
5440 binary_op_reproducer_strings[m_op],
5441 r.get_identifier_as_rvalue (m_rvalue));
5444 /* The implementation of class gcc::jit::recording::comment. */
5446 /* Implementation of pure virtual hook recording::memento::replay_into
5447 for recording::comment. */
5449 void
5450 recording::comment::replay_into (replayer *r)
5452 playback_block (get_block ())
5453 ->add_comment (playback_location (r),
5454 m_text->c_str ());
5457 /* Implementation of recording::memento::make_debug_string for
5458 a comment "statement". */
5460 recording::string *
5461 recording::comment::make_debug_string ()
5463 return string::from_printf (m_ctxt,
5464 "/* %s */",
5465 m_text->c_str ());
5468 /* Implementation of recording::memento::write_reproducer for
5469 comments. */
5471 void
5472 recording::comment::write_reproducer (reproducer &r)
5474 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5475 " %s, /* gcc_jit_location *loc */\n"
5476 " %s); /* const char *text */\n",
5477 r.get_identifier (get_block ()),
5478 r.get_identifier (get_loc ()),
5479 m_text->get_debug_string ());
5482 /* The implementation of class gcc::jit::recording::conditional. */
5484 /* Implementation of pure virtual hook recording::memento::replay_into
5485 for recording::conditional. */
5487 void
5488 recording::conditional::replay_into (replayer *r)
5490 playback_block (get_block ())
5491 ->add_conditional (playback_location (r),
5492 m_boolval->playback_rvalue (),
5493 playback_block (m_on_true),
5494 playback_block (m_on_false));
5497 /* Override the poisoned default implementation of
5498 gcc::jit::recording::statement::get_successor_blocks
5500 A conditional jump has 2 successor blocks. */
5502 vec <recording::block *>
5503 recording::conditional::get_successor_blocks () const
5505 vec <block *> result;
5506 result.create (2);
5507 result.quick_push (m_on_true);
5508 result.quick_push (m_on_false);
5509 return result;
5512 /* Implementation of recording::memento::make_debug_string for
5513 a conditional jump statement. */
5515 recording::string *
5516 recording::conditional::make_debug_string ()
5518 if (m_on_false)
5519 return string::from_printf (m_ctxt,
5520 "if (%s) goto %s; else goto %s;",
5521 m_boolval->get_debug_string (),
5522 m_on_true->get_debug_string (),
5523 m_on_false->get_debug_string ());
5524 else
5525 return string::from_printf (m_ctxt,
5526 "if (%s) goto %s;",
5527 m_boolval->get_debug_string (),
5528 m_on_true->get_debug_string ());
5531 /* Implementation of recording::memento::write_reproducer for
5532 conditional statements. */
5534 void
5535 recording::conditional::write_reproducer (reproducer &r)
5537 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5538 " %s, /* gcc_jit_location *loc */\n"
5539 " %s, /* gcc_jit_rvalue *boolval */\n"
5540 " %s, /* gcc_jit_block *on_true */\n"
5541 " %s); /* gcc_jit_block *on_false */\n",
5542 r.get_identifier (get_block ()),
5543 r.get_identifier (get_loc ()),
5544 r.get_identifier_as_rvalue (m_boolval),
5545 r.get_identifier (m_on_true),
5546 r.get_identifier (m_on_false));
5549 /* The implementation of class gcc::jit::recording::jump. */
5551 /* Implementation of pure virtual hook recording::memento::replay_into
5552 for recording::jump. */
5554 void
5555 recording::jump::replay_into (replayer *r)
5557 playback_block (get_block ())
5558 ->add_jump (playback_location (r),
5559 m_target->playback_block ());
5562 /* Override the poisoned default implementation of
5563 gcc::jit::recording::statement::get_successor_blocks
5565 An unconditional jump has 1 successor block. */
5567 vec <recording::block *>
5568 recording::jump::get_successor_blocks () const
5570 vec <block *> result;
5571 result.create (1);
5572 result.quick_push (m_target);
5573 return result;
5576 /* Implementation of recording::memento::make_debug_string for
5577 a unconditional jump statement. */
5579 recording::string *
5580 recording::jump::make_debug_string ()
5582 return string::from_printf (m_ctxt,
5583 "goto %s;",
5584 m_target->get_debug_string ());
5587 /* Implementation of recording::memento::write_reproducer for
5588 jump statements. */
5590 void
5591 recording::jump::write_reproducer (reproducer &r)
5593 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5594 " %s, /* gcc_jit_location *loc */\n"
5595 " %s); /* gcc_jit_block *target */\n",
5596 r.get_identifier (get_block ()),
5597 r.get_identifier (get_loc ()),
5598 r.get_identifier (m_target));
5601 /* The implementation of class gcc::jit::recording::return_. */
5603 /* Implementation of pure virtual hook recording::memento::replay_into
5604 for recording::return_. */
5606 void
5607 recording::return_::replay_into (replayer *r)
5609 playback_block (get_block ())
5610 ->add_return (playback_location (r),
5611 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
5614 /* Override the poisoned default implementation of
5615 gcc::jit::recording::statement::get_successor_blocks
5617 A return statement has no successor block. */
5619 vec <recording::block *>
5620 recording::return_::get_successor_blocks () const
5622 vec <block *> result;
5623 result.create (0);
5624 return result;
5627 /* Implementation of recording::memento::make_debug_string for
5628 a return statement (covers both those with and without rvalues). */
5630 recording::string *
5631 recording::return_::make_debug_string ()
5633 if (m_rvalue)
5634 return string::from_printf (m_ctxt,
5635 "return %s;",
5636 m_rvalue->get_debug_string ());
5637 else
5638 return string::from_printf (m_ctxt,
5639 "return;");
5642 /* Implementation of recording::memento::write_reproducer for
5643 return statements. */
5645 void
5646 recording::return_::write_reproducer (reproducer &r)
5648 if (m_rvalue)
5649 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5650 " %s, /* gcc_jit_location *loc */\n"
5651 " %s); /* gcc_jit_rvalue *rvalue */\n",
5652 r.get_identifier (get_block ()),
5653 r.get_identifier (get_loc ()),
5654 r.get_identifier_as_rvalue (m_rvalue));
5655 else
5656 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5657 " %s); /* gcc_jit_location *loc */\n",
5658 r.get_identifier (get_block ()),
5659 r.get_identifier (get_loc ()));
5662 /* The implementation of class gcc::jit::recording::case_. */
5664 void
5665 recording::case_::write_reproducer (reproducer &r)
5667 const char *id = r.make_identifier (this, "case");
5668 const char *fmt =
5669 " gcc_jit_case *%s = \n"
5670 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
5671 " %s, /* gcc_jit_rvalue *min_value */\n"
5672 " %s, /* gcc_jit_rvalue *max_value */\n"
5673 " %s); /* gcc_jit_block *dest_block */\n";
5674 r.write (fmt,
5676 r.get_identifier (get_context ()),
5677 r.get_identifier_as_rvalue (m_min_value),
5678 r.get_identifier_as_rvalue (m_max_value),
5679 r.get_identifier (m_dest_block));
5682 recording::string *
5683 recording::case_::make_debug_string ()
5685 return string::from_printf (get_context (),
5686 "case %s ... %s: goto %s;",
5687 m_min_value->get_debug_string (),
5688 m_max_value->get_debug_string (),
5689 m_dest_block->get_debug_string ());
5692 /* The implementation of class gcc::jit::recording::switch_. */
5694 /* gcc::jit::recording::switch_'s constructor. */
5696 recording::switch_::switch_ (block *b,
5697 location *loc,
5698 rvalue *expr,
5699 block *default_block,
5700 int num_cases,
5701 case_ **cases)
5702 : statement (b, loc),
5703 m_expr (expr),
5704 m_default_block (default_block)
5706 m_cases.reserve_exact (num_cases);
5707 for (int i = 0; i< num_cases; i++)
5708 m_cases.quick_push (cases[i]);
5711 /* Implementation of pure virtual hook recording::memento::replay_into
5712 for recording::switch_. */
5714 void
5715 recording::switch_::replay_into (replayer *r)
5717 auto_vec <playback::case_> pcases;
5718 int i;
5719 recording::case_ *rcase;
5720 pcases.reserve_exact (m_cases.length ());
5721 FOR_EACH_VEC_ELT (m_cases, i, rcase)
5723 playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (),
5724 rcase->get_max_value ()->playback_rvalue (),
5725 rcase->get_dest_block ()->playback_block ());
5726 pcases.safe_push (pcase);
5728 playback_block (get_block ())
5729 ->add_switch (playback_location (r),
5730 m_expr->playback_rvalue (),
5731 m_default_block->playback_block (),
5732 &pcases);
5735 /* Override the poisoned default implementation of
5736 gcc::jit::recording::statement::get_successor_blocks
5738 A switch statement has (NUM_CASES + 1) successor blocks. */
5740 vec <recording::block *>
5741 recording::switch_::get_successor_blocks () const
5743 vec <block *> result;
5744 result.create (m_cases.length () + 1);
5745 result.quick_push (m_default_block);
5746 int i;
5747 case_ *c;
5748 FOR_EACH_VEC_ELT (m_cases, i, c)
5749 result.quick_push (c->get_dest_block ());
5750 return result;
5753 /* Implementation of recording::memento::make_debug_string for
5754 a switch statement. */
5756 recording::string *
5757 recording::switch_::make_debug_string ()
5759 auto_vec <char> cases_str;
5760 int i;
5761 case_ *c;
5762 FOR_EACH_VEC_ELT (m_cases, i, c)
5764 size_t len = strlen (c->get_debug_string ());
5765 unsigned idx = cases_str.length ();
5766 cases_str.safe_grow (idx + 1 + len);
5767 cases_str[idx] = ' ';
5768 memcpy (&(cases_str[idx + 1]),
5769 c->get_debug_string (),
5770 len);
5772 cases_str.safe_push ('\0');
5774 return string::from_printf (m_ctxt,
5775 "switch (%s) {default: goto %s;%s}",
5776 m_expr->get_debug_string (),
5777 m_default_block->get_debug_string (),
5778 &cases_str[0]);
5781 /* Implementation of recording::memento::write_reproducer for
5782 switch statements. */
5784 void
5785 recording::switch_::write_reproducer (reproducer &r)
5787 r.make_identifier (this, "switch");
5788 int i;
5789 case_ *c;
5790 const char *cases_id =
5791 r.make_tmp_identifier ("cases_for", this);
5792 r.write (" gcc_jit_case *%s[%i] = {\n",
5793 cases_id,
5794 m_cases.length ());
5795 FOR_EACH_VEC_ELT (m_cases, i, c)
5796 r.write (" %s,\n", r.get_identifier (c));
5797 r.write (" };\n");
5798 const char *fmt =
5799 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
5800 " %s, /* gcc_jit_location *loc */\n"
5801 " %s, /* gcc_jit_rvalue *expr */\n"
5802 " %s, /* gcc_jit_block *default_block */\n"
5803 " %i, /* int num_cases */\n"
5804 " %s); /* gcc_jit_case **cases */\n";
5805 r.write (fmt,
5806 r.get_identifier (get_block ()),
5807 r.get_identifier (get_loc ()),
5808 r.get_identifier_as_rvalue (m_expr),
5809 r.get_identifier (m_default_block),
5810 m_cases.length (),
5811 cases_id);
5814 } // namespace gcc::jit
5816 } // namespace gcc