jit: add gcc_jit_type_get_vector
[official-gcc.git] / gcc / jit / jit-recording.c
blobea4ebb124959c916fbb7553a7b138ed4a1e13994
1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2017 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "pretty-print.h"
26 #include "toplev.h"
28 #include <pthread.h>
30 #include "jit-builtins.h"
31 #include "jit-recording.h"
32 #include "jit-playback.h"
34 namespace gcc {
35 namespace jit {
37 // class dump
39 dump::dump (recording::context &ctxt,
40 const char *filename,
41 bool update_locations)
42 : m_ctxt (ctxt),
43 m_filename (filename),
44 m_update_locations (update_locations),
45 m_line (0),
46 m_column (0)
48 m_file = fopen (filename, "w");
49 if (!m_file)
50 ctxt.add_error (NULL,
51 "error opening dump file %s for writing: %s",
52 filename,
53 xstrerror (errno));
56 dump::~dump ()
58 if (m_file)
60 int err = fclose (m_file);
61 if (err)
62 m_ctxt.add_error (NULL,
63 "error closing dump file %s: %s",
64 m_filename,
65 xstrerror (errno));
69 /* Write the given message to the dump, using printf-formatting
70 conventions, updating the line/column within the dump.
72 Emit an error on the context if a failure occurs. */
74 void
75 dump::write (const char *fmt, ...)
77 int len;
78 va_list ap;
79 char *buf;
81 /* If there was an error opening the file, we've already reported it.
82 Don't attempt further work. */
83 if (!m_file)
84 return;
86 va_start (ap, fmt);
87 len = vasprintf (&buf, fmt, ap);
88 va_end (ap);
90 if (buf == NULL || len < 0)
92 m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
93 m_filename);
94 return;
97 if (fwrite (buf, strlen (buf), 1, m_file) != 1)
98 m_ctxt.add_error (NULL, "error writing to dump file %s",
99 m_filename);
101 /* Flush after each line, to ease debugging crashes. */
102 fflush (m_file);
104 /* Update line/column: */
105 for (const char *ptr = buf; *ptr; ptr++)
107 if ('\n' == *ptr)
109 m_line++;
110 m_column = 0;
112 else
113 m_column++;
116 free (buf);
119 /* Construct a gcc::jit::recording::location instance for the current
120 location within the dump. */
122 recording::location *
123 dump::make_location () const
125 return m_ctxt.new_location (m_filename, m_line, m_column,
126 /* We need to flag such locations as *not*
127 created by the user, so that
128 reproducer::get_identifier can cope with
129 them appearing *after* the memento that
130 refers to them. */
131 false);
134 /* A collection of allocations, all of which can be released together, to
135 avoid needing to track and release them individually. */
137 class allocator
139 public:
140 ~allocator ();
142 char *
143 xstrdup_printf (const char *, ...)
144 ATTRIBUTE_RETURNS_NONNULL
145 GNU_PRINTF(2, 3);
147 char *
148 xstrdup_printf_va (const char *, va_list ap)
149 ATTRIBUTE_RETURNS_NONNULL
150 GNU_PRINTF(2, 0);
152 private:
153 auto_vec <void *> m_buffers;
156 /* allocator's destructor. Call "free" on all of the allocations. */
158 allocator::~allocator ()
160 unsigned i;
161 void *buffer;
162 FOR_EACH_VEC_ELT (m_buffers, i, buffer)
163 free (buffer);
166 /* Formatted printing, allocating to a buffer (or exiting the process if
167 the allocation fails).
169 The buffer exists until the allocator is cleaned up, and is freed at
170 that point, so the caller doesn't need to track the result. */
172 char *
173 allocator::xstrdup_printf (const char *fmt, ...)
175 char *result;
176 va_list ap;
177 va_start (ap, fmt);
178 result = xstrdup_printf_va (fmt, ap);
179 va_end (ap);
180 return result;
183 /* Formatted printing, allocating to a buffer (or exiting the process if
184 the allocation fails).
186 The buffer exists until the allocator is cleaned up, and is freed at
187 that point, so the caller doesn't need to track the result. */
189 char *
190 allocator::xstrdup_printf_va (const char *fmt, va_list ap)
192 char *result = xvasprintf (fmt, ap);
193 m_buffers.safe_push (result);
194 return result;
197 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
198 implementing gcc_jit_context_dump_reproducer_to_file. */
200 class reproducer : public dump
202 public:
203 reproducer (recording::context &ctxt,
204 const char *filename);
206 void
207 write_params (const vec <recording::context *> &contexts);
209 void
210 write_args (const vec <recording::context *> &contexts);
212 const char *
213 make_identifier (recording::memento *m, const char *prefix);
215 const char *
216 make_tmp_identifier (const char *prefix, recording::memento *m);
218 const char *
219 get_identifier (recording::context *ctxt);
221 const char *
222 get_identifier (recording::memento *m);
224 const char *
225 get_identifier_as_rvalue (recording::rvalue *m);
227 const char *
228 get_identifier_as_lvalue (recording::lvalue *m);
230 const char *
231 get_identifier_as_type (recording::type *m);
233 char *
234 xstrdup_printf (const char *, ...)
235 ATTRIBUTE_RETURNS_NONNULL
236 GNU_PRINTF(2, 3);
238 private:
239 hash_map<recording::memento *, const char *> m_identifiers;
240 allocator m_allocator;
243 /* gcc::jit::reproducer's constructor. */
245 reproducer::reproducer (recording::context &ctxt,
246 const char *filename) :
247 dump (ctxt, filename, 0),
248 m_identifiers (),
249 m_allocator ()
253 /* Write out a list of contexts as a set of parameters within a
254 C function declaration. */
256 void
257 reproducer::write_params (const vec <recording::context *> &contexts)
259 unsigned i;
260 recording::context *ctxt;
261 FOR_EACH_VEC_ELT (contexts, i, ctxt)
263 write ("gcc_jit_context *%s",
264 get_identifier (ctxt));
265 if (i < contexts.length () - 1)
266 write (",\n"
267 " ");
271 /* Write out a list of contexts as a set of arguments within a call
272 to a C function. */
274 void
275 reproducer::write_args (const vec <recording::context *> &contexts)
277 unsigned i;
278 recording::context *ctxt;
279 FOR_EACH_VEC_ELT (contexts, i, ctxt)
281 write ("%s",
282 get_identifier (ctxt));
283 if (i < contexts.length () - 1)
284 write (",\n"
285 " ");
289 /* Generate a C identifier for the given memento, associating the generated
290 buffer with the memento (for future calls to get_identifier et al).
292 The reproducer will eventually clean up the buffer in its dtor. */
293 const char *
294 reproducer::make_identifier (recording::memento *m, const char *prefix)
296 char *result;
297 if (strlen (m->get_debug_string ()) < 100)
299 result = m_allocator.xstrdup_printf ("%s_%s_%p",
300 prefix,
301 m->get_debug_string (),
302 (void *) m);
303 for (char *p = result; *p; p++)
304 if (!ISALNUM (*p))
305 *p = '_';
307 else
308 result = m_allocator.xstrdup_printf ("%s_%p",
309 prefix, (void *) m);
310 m_identifiers.put (m, result);
311 return result;
314 /* Generate a C identifier for a temporary variable.
315 The reproducer will eventually clean up the buffer in its dtor. */
317 const char *
318 reproducer::make_tmp_identifier (const char *prefix, recording::memento *m)
320 return m_allocator.xstrdup_printf ("%s_%s",
321 prefix, get_identifier (m));
324 /* Generate a C identifier for the given context.
325 The reproducer will eventually clean up the buffer in its dtor. */
327 const char *
328 reproducer::get_identifier (recording::context *ctxt)
330 return m_allocator.xstrdup_printf ("ctxt_%p",
331 (void *)ctxt);
334 /* Locate the C identifier for the given memento, which is assumed to
335 have already been created via make_identifier. */
337 const char *
338 reproducer::get_identifier (recording::memento *m)
340 if (!m)
341 return "NULL";
343 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
344 and hence these locations appear in the context's memento list
345 out-of-order: they appear in the context's memento list *after*
346 the memento that refers to them. For this case, it's simplest to
347 pretend that they're NULL when writing out the code to recreate the
348 memento that uses them. */
349 if (recording::location *loc = m->dyn_cast_location ())
350 if (!loc->created_by_user ())
351 return "NULL";
353 const char **slot = m_identifiers.get (m);
354 if (!slot)
356 get_context ().add_error (NULL,
357 "unable to find identifier for %p: %s",
358 (void *)m,
359 m->get_debug_string ());
360 gcc_unreachable ();
362 return *slot;
365 /* Locate the C identifier for the given rvalue, wrapping it within
366 a gcc_*_as_rvalue upcast if necessary. */
368 const char *
369 reproducer::get_identifier_as_rvalue (recording::rvalue *m)
371 return m->access_as_rvalue (*this);
374 /* Locate the C identifier for the given lvalue, wrapping it within
375 a gcc_*_as_lvalue upcast if necessary. */
377 const char *
378 reproducer::get_identifier_as_lvalue (recording::lvalue *m)
380 return m->access_as_lvalue (*this);
383 /* Locate the C identifier for the given type, wrapping it within
384 a gcc_*_as_type upcast if necessary. */
386 const char *
387 reproducer::get_identifier_as_type (recording::type *m)
389 return m->access_as_type (*this);
392 /* Formatted printing, allocating to a buffer (or exiting the process if
393 the allocation fails).
395 The buffer exists until the allocator is cleaned up, and is freed at
396 that point, so the caller doesn't need to track the result.
398 Note that we can't use ggc_printf since we're not within the compiler
399 proper (when within gcc_jit_context_dump_reproducer_to_file). */
401 char *
402 reproducer::xstrdup_printf (const char *fmt, ...)
404 char *result;
405 va_list ap;
406 va_start (ap, fmt);
407 result = m_allocator.xstrdup_printf_va (fmt, ap);
408 va_end (ap);
409 return result;
412 /**********************************************************************
413 Recording.
414 **********************************************************************/
416 /* Get the playback::location for the given recording::location,
417 handling a NULL input with a NULL output. */
419 playback::location *
420 recording::playback_location (replayer *r, recording::location *loc)
422 if (loc)
423 return loc->playback_location (r);
424 else
425 return NULL;
428 /* Get a const char * for the given recording::string
429 handling a NULL input with a NULL output. */
431 const char *
432 recording::playback_string (recording::string *str)
434 if (str)
435 return str->c_str ();
436 else
437 return NULL;
440 /* Get the playback::block for the given recording::block,
441 handling a NULL input with a NULL output. */
443 playback::block *
444 recording::playback_block (recording::block *b)
446 if (b)
447 return b->playback_block ();
448 else
449 return NULL;
452 /* Methods of cc::jit::recording::context. */
454 /* The constructor for gcc::jit::recording::context, used by
455 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
457 recording::context::context (context *parent_ctxt)
458 : log_user (NULL),
459 m_parent_ctxt (parent_ctxt),
460 m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this),
461 m_timer (NULL),
462 m_error_count (0),
463 m_first_error_str (NULL),
464 m_owns_first_error_str (false),
465 m_last_error_str (NULL),
466 m_owns_last_error_str (false),
467 m_mementos (),
468 m_compound_types (),
469 m_globals (),
470 m_functions (),
471 m_FILE_type (NULL),
472 m_builtins_manager(NULL)
474 if (parent_ctxt)
476 /* Inherit options from parent. */
477 for (unsigned i = 0;
478 i < sizeof (m_str_options) / sizeof (m_str_options[0]);
479 i++)
481 const char *parent_opt = parent_ctxt->m_str_options[i];
482 m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
484 memcpy (m_int_options,
485 parent_ctxt->m_int_options,
486 sizeof (m_int_options));
487 memcpy (m_bool_options,
488 parent_ctxt->m_bool_options,
489 sizeof (m_bool_options));
490 memcpy (m_inner_bool_options,
491 parent_ctxt->m_inner_bool_options,
492 sizeof (m_inner_bool_options));
493 set_logger (parent_ctxt->get_logger ());
495 else
497 memset (m_str_options, 0, sizeof (m_str_options));
498 memset (m_int_options, 0, sizeof (m_int_options));
499 memset (m_bool_options, 0, sizeof (m_bool_options));
500 memset (m_inner_bool_options, 0, sizeof (m_inner_bool_options));
503 memset (m_basic_types, 0, sizeof (m_basic_types));
506 /* The destructor for gcc::jit::recording::context, implicitly used by
507 gcc_jit_context_release. */
509 recording::context::~context ()
511 JIT_LOG_SCOPE (get_logger ());
512 int i;
513 memento *m;
514 FOR_EACH_VEC_ELT (m_mementos, i, m)
516 delete m;
519 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
520 free (m_str_options[i]);
522 char *optname;
523 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
524 free (optname);
526 if (m_builtins_manager)
527 delete m_builtins_manager;
529 if (m_owns_first_error_str)
530 free (m_first_error_str);
532 if (m_owns_last_error_str)
533 if (m_last_error_str != m_first_error_str)
534 free (m_last_error_str);
537 /* Add the given mememto to the list of those tracked by this
538 gcc::jit::recording::context, so that e.g. it can be deleted
539 when this context is released. */
541 void
542 recording::context::record (memento *m)
544 gcc_assert (m);
546 m_mementos.safe_push (m);
549 /* Replay this context (and any parents) into the given replayer. */
551 void
552 recording::context::replay_into (replayer *r)
554 JIT_LOG_SCOPE (get_logger ());
555 int i;
556 memento *m;
558 /* If we have a parent context, we must replay it. This will
559 recursively walk backwards up the historical tree, then replay things
560 forwards "in historical order", starting with the ultimate parent
561 context, until we reach the "this" context.
563 Note that we fully replay the parent, then fully replay the child,
564 which means that inter-context references can only exist from child
565 to parent, not the other way around.
567 All of this replaying is suboptimal - it would be better to do the
568 work for the parent context *once*, rather than replaying the parent
569 every time we replay each child. However, fixing this requires deep
570 surgery to lifetime-management: we'd need every context family tree
571 to have its own GC heap, and to initialize the GCC code to use that
572 heap (with a mutex on such a heap). */
573 if (m_parent_ctxt)
574 m_parent_ctxt->replay_into (r);
576 if (r->errors_occurred ())
577 return;
579 /* Replay this context's saved operations into r. */
580 FOR_EACH_VEC_ELT (m_mementos, i, m)
582 /* Disabled low-level debugging, here if we need it: print what
583 we're replaying.
584 Note that the calls to get_debug_string might lead to more
585 mementos being created for the strings.
586 This can also be used to exercise the debug_string
587 machinery. */
588 if (0)
589 printf ("context %p replaying (%p): %s\n",
590 (void *)this, (void *)m, m->get_debug_string ());
592 m->replay_into (r);
594 if (r->errors_occurred ())
595 return;
599 /* During a playback, we associate objects from the recording with
600 their counterparts during this playback.
602 For simplicity, we store this within the recording objects.
604 The following method cleans away these associations, to ensure that
605 we never have out-of-date associations lingering on subsequent
606 playbacks (the objects pointed to are GC-managed, but the
607 recording objects don't own refs to them). */
609 void
610 recording::context::disassociate_from_playback ()
612 JIT_LOG_SCOPE (get_logger ());
613 int i;
614 memento *m;
616 if (m_parent_ctxt)
617 m_parent_ctxt->disassociate_from_playback ();
619 FOR_EACH_VEC_ELT (m_mementos, i, m)
621 m->set_playback_obj (NULL);
625 /* Create a recording::string instance and add it to this context's list
626 of mementos.
628 This creates a fresh copy of the given 0-terminated buffer. */
630 recording::string *
631 recording::context::new_string (const char *text)
633 if (!text)
634 return NULL;
636 recording::string *result = new string (this, text);
637 record (result);
638 return result;
641 /* Create a recording::location instance and add it to this context's
642 list of mementos.
644 Implements the post-error-checking part of
645 gcc_jit_context_new_location. */
647 recording::location *
648 recording::context::new_location (const char *filename,
649 int line,
650 int column,
651 bool created_by_user)
653 recording::location *result =
654 new recording::location (this,
655 new_string (filename),
656 line, column,
657 created_by_user);
658 record (result);
659 return result;
662 /* If we haven't seen this enum value yet, create a recording::type
663 instance and add it to this context's list of mementos.
665 If we have seen it before, reuse our cached value, so that repeated
666 calls on the context give the same object.
668 If we have a parent context, the cache is within the ultimate
669 ancestor context.
671 Implements the post-error-checking part of
672 gcc_jit_context_get_type. */
674 recording::type *
675 recording::context::get_type (enum gcc_jit_types kind)
677 if (!m_basic_types[kind])
679 if (m_parent_ctxt)
680 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
681 else
683 recording::type *result = new memento_of_get_type (this, kind);
684 record (result);
685 m_basic_types[kind] = result;
689 return m_basic_types[kind];
692 /* Get a recording::type instance for the given size and signedness.
693 This is implemented in terms of recording::context::get_type
694 above.
696 Implements the post-error-checking part of
697 gcc_jit_context_get_int_type. */
699 recording::type *
700 recording::context::get_int_type (int num_bytes, int is_signed)
702 /* We can't use a switch here since some of the values are macros affected
703 by options; e.g. i386.h has
704 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
705 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
706 are in bits, rather than bytes.
708 const int num_bits = num_bytes * 8;
709 if (num_bits == INT_TYPE_SIZE)
710 return get_type (is_signed
711 ? GCC_JIT_TYPE_INT
712 : GCC_JIT_TYPE_UNSIGNED_INT);
713 if (num_bits == CHAR_TYPE_SIZE)
714 return get_type (is_signed
715 ? GCC_JIT_TYPE_SIGNED_CHAR
716 : GCC_JIT_TYPE_UNSIGNED_CHAR);
717 if (num_bits == SHORT_TYPE_SIZE)
718 return get_type (is_signed
719 ? GCC_JIT_TYPE_SHORT
720 : GCC_JIT_TYPE_UNSIGNED_SHORT);
721 if (num_bits == LONG_TYPE_SIZE)
722 return get_type (is_signed
723 ? GCC_JIT_TYPE_LONG
724 : GCC_JIT_TYPE_UNSIGNED_LONG);
725 if (num_bits == LONG_LONG_TYPE_SIZE)
726 return get_type (is_signed
727 ? GCC_JIT_TYPE_LONG_LONG
728 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
730 /* Some other size, not corresponding to the C int types. */
731 /* To be written: support arbitrary other sizes, sharing by
732 memoizing at the recording::context level? */
733 gcc_unreachable ();
736 /* Create a recording::type instance and add it to this context's list
737 of mementos.
739 Implements the post-error-checking part of
740 gcc_jit_context_new_array_type. */
742 recording::type *
743 recording::context::new_array_type (recording::location *loc,
744 recording::type *element_type,
745 int num_elements)
747 if (struct_ *s = element_type->dyn_cast_struct ())
748 if (!s->get_fields ())
750 add_error (NULL,
751 "cannot create an array of type %s"
752 " until the fields have been set",
753 s->get_name ()->c_str ());
754 return NULL;
756 recording::type *result =
757 new recording::array_type (this, loc, element_type, num_elements);
758 record (result);
759 return result;
762 /* Create a recording::field instance and add it to this context's list
763 of mementos.
765 Implements the post-error-checking part of
766 gcc_jit_context_new_field. */
768 recording::field *
769 recording::context::new_field (recording::location *loc,
770 recording::type *type,
771 const char *name)
773 recording::field *result =
774 new recording::field (this, loc, type, new_string (name));
775 record (result);
776 return result;
779 /* Create a recording::struct_ instance and add it to this context's
780 list of mementos and list of compound types.
782 Implements the post-error-checking part of
783 gcc_jit_context_new_struct_type. */
785 recording::struct_ *
786 recording::context::new_struct_type (recording::location *loc,
787 const char *name)
789 recording::struct_ *result = new struct_ (this, loc, new_string (name));
790 record (result);
791 m_compound_types.safe_push (result);
792 return result;
795 /* Create a recording::union_ instance and add it to this context's
796 list of mementos and list of compound types.
798 Implements the first post-error-checking part of
799 gcc_jit_context_new_union_type. */
801 recording::union_ *
802 recording::context::new_union_type (recording::location *loc,
803 const char *name)
805 recording::union_ *result = new union_ (this, loc, new_string (name));
806 record (result);
807 m_compound_types.safe_push (result);
808 return result;
811 /* Create a recording::function_type instance and add it to this context's
812 list of mementos.
814 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
816 recording::function_type *
817 recording::context::new_function_type (recording::type *return_type,
818 int num_params,
819 recording::type **param_types,
820 int is_variadic)
822 recording::function_type *fn_type
823 = new function_type (this,
824 return_type,
825 num_params,
826 param_types,
827 is_variadic);
828 record (fn_type);
829 return fn_type;
832 /* Create a recording::type instance and add it to this context's list
833 of mementos.
835 Implements the post-error-checking part of
836 gcc_jit_context_new_function_ptr_type. */
838 recording::type *
839 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
840 recording::type *return_type,
841 int num_params,
842 recording::type **param_types,
843 int is_variadic)
845 recording::function_type *fn_type
846 = new_function_type (return_type,
847 num_params,
848 param_types,
849 is_variadic);
851 /* Return a pointer-type to the function type. */
852 return fn_type->get_pointer ();
855 /* Create a recording::param instance and add it to this context's list
856 of mementos.
858 Implements the post-error-checking part of
859 gcc_jit_context_new_param. */
861 recording::param *
862 recording::context::new_param (recording::location *loc,
863 recording::type *type,
864 const char *name)
866 recording::param *result = new recording::param (this, loc, type, new_string (name));
867 record (result);
868 return result;
871 /* Create a recording::function instance and add it to this context's list
872 of mementos and list of functions.
874 Implements the post-error-checking part of
875 gcc_jit_context_new_function. */
877 recording::function *
878 recording::context::new_function (recording::location *loc,
879 enum gcc_jit_function_kind kind,
880 recording::type *return_type,
881 const char *name,
882 int num_params,
883 recording::param **params,
884 int is_variadic,
885 enum built_in_function builtin_id)
887 recording::function *result =
888 new recording::function (this,
889 loc, kind, return_type,
890 new_string (name),
891 num_params, params, is_variadic,
892 builtin_id);
893 record (result);
894 m_functions.safe_push (result);
896 return result;
899 /* Locate the builtins_manager (if any) for this family of contexts,
900 creating it if it doesn't exist already.
902 All of the recording contexts in a family share one builtins_manager:
903 if we have a child context, follow the parent links to get the
904 ultimate ancestor context, and look for it/store it there. */
906 builtins_manager *
907 recording::context::get_builtins_manager ()
909 if (m_parent_ctxt)
910 return m_parent_ctxt->get_builtins_manager ();
912 if (!m_builtins_manager)
913 m_builtins_manager = new builtins_manager (this);
915 return m_builtins_manager;
918 /* Get a recording::function instance, which is lazily-created and added
919 to the context's lists of mementos.
921 Implements the post-error-checking part of
922 gcc_jit_context_get_builtin_function. */
924 recording::function *
925 recording::context::get_builtin_function (const char *name)
927 builtins_manager *bm = get_builtins_manager ();
928 return bm->get_builtin_function (name);
931 /* Create a recording::global instance and add it to this context's list
932 of mementos.
934 Implements the post-error-checking part of
935 gcc_jit_context_new_global. */
937 recording::lvalue *
938 recording::context::new_global (recording::location *loc,
939 enum gcc_jit_global_kind kind,
940 recording::type *type,
941 const char *name)
943 recording::global *result =
944 new recording::global (this, loc, kind, type, new_string (name));
945 record (result);
946 m_globals.safe_push (result);
948 return result;
951 /* Create a recording::memento_of_new_string_literal instance and add it
952 to this context's list of mementos.
954 Implements the post-error-checking part of
955 gcc_jit_context_new_string_literal. */
957 recording::rvalue *
958 recording::context::new_string_literal (const char *value)
960 recording::rvalue *result =
961 new memento_of_new_string_literal (this, NULL, new_string (value));
962 record (result);
963 return result;
966 /* Create a recording::unary_op instance and add it to this context's
967 list of mementos.
969 Implements the post-error-checking part of
970 gcc_jit_context_new_unary_op. */
972 recording::rvalue *
973 recording::context::new_unary_op (recording::location *loc,
974 enum gcc_jit_unary_op op,
975 recording::type *result_type,
976 recording::rvalue *a)
978 recording::rvalue *result =
979 new unary_op (this, loc, op, result_type, a);
980 record (result);
981 return result;
984 /* Create a recording::binary_op instance and add it to this context's
985 list of mementos.
987 Implements the post-error-checking part of
988 gcc_jit_context_new_binary_op. */
990 recording::rvalue *
991 recording::context::new_binary_op (recording::location *loc,
992 enum gcc_jit_binary_op op,
993 recording::type *result_type,
994 recording::rvalue *a,
995 recording::rvalue *b)
997 recording::rvalue *result =
998 new binary_op (this, loc, op, result_type, a, b);
999 record (result);
1000 return result;
1003 /* Create a recording::comparison instance and add it to this context's
1004 list of mementos.
1006 Implements the post-error-checking part of
1007 gcc_jit_context_new_comparison. */
1009 recording::rvalue *
1010 recording::context::new_comparison (recording::location *loc,
1011 enum gcc_jit_comparison op,
1012 recording::rvalue *a,
1013 recording::rvalue *b)
1015 recording::rvalue *result = new comparison (this, loc, op, a, b);
1016 record (result);
1017 return result;
1020 /* Create a recording::cast instance and add it to this context's list
1021 of mementos.
1023 Implements the post-error-checking part of
1024 gcc_jit_context_new_cast. */
1026 recording::rvalue *
1027 recording::context::new_cast (recording::location *loc,
1028 recording::rvalue *expr,
1029 recording::type *type_)
1031 recording::rvalue *result = new cast (this, loc, expr, type_);
1032 record (result);
1033 return result;
1036 /* Create a recording::call instance and add it to this context's list
1037 of mementos.
1039 Implements the post-error-checking part of
1040 gcc_jit_context_new_call. */
1042 recording::rvalue *
1043 recording::context::new_call (recording::location *loc,
1044 function *func,
1045 int numargs , recording::rvalue **args)
1047 recording::rvalue *result = new call (this, loc, func, numargs, args);
1048 record (result);
1049 return result;
1052 /* Create a recording::call_through_ptr instance and add it to this
1053 context's list of mementos.
1055 Implements the post-error-checking part of
1056 gcc_jit_context_new_call_through_ptr. */
1058 recording::rvalue *
1059 recording::context::new_call_through_ptr (recording::location *loc,
1060 recording::rvalue *fn_ptr,
1061 int numargs,
1062 recording::rvalue **args)
1064 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
1065 record (result);
1066 return result;
1069 /* Create a recording::array_access instance and add it to this context's list
1070 of mementos.
1072 Implements the post-error-checking part of
1073 gcc_jit_context_new_array_access. */
1075 recording::lvalue *
1076 recording::context::new_array_access (recording::location *loc,
1077 recording::rvalue *ptr,
1078 recording::rvalue *index)
1080 recording::lvalue *result = new array_access (this, loc, ptr, index);
1081 record (result);
1082 return result;
1085 /* Create a recording::case_ instance and add it to this context's list
1086 of mementos.
1088 Implements the post-error-checking part of
1089 gcc_jit_context_new_case. */
1091 recording::case_ *
1092 recording::context::new_case (recording::rvalue *min_value,
1093 recording::rvalue *max_value,
1094 recording::block *block)
1096 recording::case_ *result = new case_ (this, min_value, max_value, block);
1097 record (result);
1098 return result;
1101 /* Set the given string option for this context, or add an error if
1102 it's not recognized.
1104 Implements the post-error-checking part of
1105 gcc_jit_context_set_str_option. */
1107 void
1108 recording::context::set_str_option (enum gcc_jit_str_option opt,
1109 const char *value)
1111 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
1113 add_error (NULL,
1114 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
1115 return;
1117 free (m_str_options[opt]);
1118 m_str_options[opt] = value ? xstrdup (value) : NULL;
1119 log_str_option (opt);
1122 /* Set the given integer option for this context, or add an error if
1123 it's not recognized.
1125 Implements the post-error-checking part of
1126 gcc_jit_context_set_int_option. */
1128 void
1129 recording::context::set_int_option (enum gcc_jit_int_option opt,
1130 int value)
1132 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
1134 add_error (NULL,
1135 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
1136 return;
1138 m_int_options[opt] = value;
1139 log_int_option (opt);
1142 /* Set the given boolean option for this context, or add an error if
1143 it's not recognized.
1145 Implements the post-error-checking part of
1146 gcc_jit_context_set_bool_option. */
1148 void
1149 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
1150 int value)
1152 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
1154 add_error (NULL,
1155 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
1156 return;
1158 m_bool_options[opt] = value ? true : false;
1159 log_bool_option (opt);
1162 void
1163 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt,
1164 int value)
1166 gcc_assert (inner_opt >= 0 && inner_opt < NUM_INNER_BOOL_OPTIONS);
1167 m_inner_bool_options[inner_opt] = value ? true : false;
1168 log_inner_bool_option (inner_opt);
1172 /* Add the given optname to this context's list of extra options.
1174 Implements the post-error-checking part of
1175 gcc_jit_context_add_command_line_option. */
1177 void
1178 recording::context::add_command_line_option (const char *optname)
1180 m_command_line_options.safe_push (xstrdup (optname));
1183 /* Add any user-provided extra options, starting with any from
1184 parent contexts.
1185 Called by playback::context::make_fake_args. */
1187 void
1188 recording::context::append_command_line_options (vec <char *> *argvec)
1190 if (m_parent_ctxt)
1191 m_parent_ctxt->append_command_line_options (argvec);
1193 int i;
1194 char *optname;
1195 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1196 argvec->safe_push (xstrdup (optname));
1199 /* Add the given dumpname/out_ptr pair to this context's list of requested
1200 dumps.
1202 Implements the post-error-checking part of
1203 gcc_jit_context_enable_dump. */
1205 void
1206 recording::context::enable_dump (const char *dumpname,
1207 char **out_ptr)
1209 requested_dump d;
1210 gcc_assert (dumpname);
1211 gcc_assert (out_ptr);
1213 d.m_dumpname = dumpname;
1214 d.m_out_ptr = out_ptr;
1215 *out_ptr = NULL;
1216 m_requested_dumps.safe_push (d);
1219 /* Validate this context, and if it passes, compile it to memory
1220 (within a mutex).
1222 Implements the post-error-checking part of
1223 gcc_jit_context_compile. */
1225 result *
1226 recording::context::compile ()
1228 JIT_LOG_SCOPE (get_logger ());
1230 log_all_options ();
1232 validate ();
1234 if (errors_occurred ())
1235 return NULL;
1237 /* Set up a compile_to_memory playback context. */
1238 ::gcc::jit::playback::compile_to_memory replayer (this);
1240 /* Use it. */
1241 replayer.compile ();
1243 /* Get the jit::result (or NULL) from the
1244 compile_to_memory playback context. */
1245 return replayer.get_result_obj ();
1248 /* Validate this context, and if it passes, compile it to a file
1249 (within a mutex).
1251 Implements the post-error-checking part of
1252 gcc_jit_context_compile_to_file. */
1254 void
1255 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
1256 const char *output_path)
1258 JIT_LOG_SCOPE (get_logger ());
1260 log_all_options ();
1262 validate ();
1264 if (errors_occurred ())
1265 return;
1267 /* Set up a compile_to_file playback context. */
1268 ::gcc::jit::playback::compile_to_file replayer (this,
1269 output_kind,
1270 output_path);
1272 /* Use it. */
1273 replayer.compile ();
1276 /* Format the given error using printf's conventions, print
1277 it to stderr, and add it to the context. */
1279 void
1280 recording::context::add_error (location *loc, const char *fmt, ...)
1282 va_list ap;
1283 va_start (ap, fmt);
1284 add_error_va (loc, fmt, ap);
1285 va_end (ap);
1288 /* Format the given error using printf's conventions, print
1289 it to stderr, and add it to the context. */
1291 void
1292 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
1294 int len;
1295 char *malloced_msg;
1296 const char *errmsg;
1297 bool has_ownership;
1299 JIT_LOG_SCOPE (get_logger ());
1301 len = vasprintf (&malloced_msg, fmt, ap);
1302 if (malloced_msg == NULL || len < 0)
1304 errmsg = "out of memory generating error message";
1305 has_ownership = false;
1307 else
1309 errmsg = malloced_msg;
1310 has_ownership = true;
1312 if (get_logger ())
1313 get_logger ()->log ("error %i: %s", m_error_count, errmsg);
1315 const char *ctxt_progname =
1316 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
1317 if (!ctxt_progname)
1318 ctxt_progname = "libgccjit.so";
1320 if (loc)
1321 fprintf (stderr, "%s: %s: error: %s\n",
1322 ctxt_progname,
1323 loc->get_debug_string (),
1324 errmsg);
1325 else
1326 fprintf (stderr, "%s: error: %s\n",
1327 ctxt_progname,
1328 errmsg);
1330 if (!m_error_count)
1332 m_first_error_str = const_cast <char *> (errmsg);
1333 m_owns_first_error_str = has_ownership;
1336 if (m_owns_last_error_str)
1337 if (m_last_error_str != m_first_error_str)
1338 free (m_last_error_str);
1339 m_last_error_str = const_cast <char *> (errmsg);
1340 m_owns_last_error_str = has_ownership;
1342 m_error_count++;
1345 /* Get the message for the first error that occurred on this context, or
1346 NULL if no errors have occurred on it.
1348 Implements the post-error-checking part of
1349 gcc_jit_context_get_first_error. */
1351 const char *
1352 recording::context::get_first_error () const
1354 return m_first_error_str;
1357 /* Get the message for the last error that occurred on this context, or
1358 NULL if no errors have occurred on it.
1360 Implements the post-error-checking part of
1361 gcc_jit_context_get_last_error. */
1363 const char *
1364 recording::context::get_last_error () const
1366 return m_last_error_str;
1369 /* Lazily generate and record a recording::type representing an opaque
1370 struct named "FILE".
1372 For use if client code tries to dereference the result of
1373 get_type (GCC_JIT_TYPE_FILE_PTR). */
1375 recording::type *
1376 recording::context::get_opaque_FILE_type ()
1378 if (!m_FILE_type)
1379 m_FILE_type = new_struct_type (NULL, "FILE");
1380 return m_FILE_type;
1383 /* Dump a C-like representation of the given context to the given path.
1384 If UPDATE_LOCATIONS is true, update the locations within the
1385 context's mementos to point to the dumpfile.
1387 Implements the post-error-checking part of
1388 gcc_jit_context_dump_to_file. */
1390 void
1391 recording::context::dump_to_file (const char *path, bool update_locations)
1393 int i;
1394 dump d (*this, path, update_locations);
1396 /* Forward declaration of structs and unions. */
1397 compound_type *st;
1398 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1400 d.write ("%s;\n\n", st->get_debug_string ());
1403 /* Content of structs, where set. */
1404 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1405 if (st->get_fields ())
1407 st->get_fields ()->write_to_dump (d);
1408 d.write ("\n");
1411 /* Globals. */
1412 global *g;
1413 FOR_EACH_VEC_ELT (m_globals, i, g)
1415 g->write_to_dump (d);
1417 if (!m_globals.is_empty ())
1418 d.write ("\n");
1420 function *fn;
1421 FOR_EACH_VEC_ELT (m_functions, i, fn)
1423 fn->write_to_dump (d);
1427 static const char * const
1428 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
1429 "GCC_JIT_STR_OPTION_PROGNAME"
1432 static const char * const
1433 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
1434 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1437 static const char * const
1438 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
1439 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1440 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1441 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1442 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1443 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1444 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1445 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1446 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1449 static const char * const
1450 inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = {
1451 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1452 "gcc_jit_context_set_bool_use_external_driver"
1455 /* Write the current value of all options to the log file (if any). */
1457 void
1458 recording::context::log_all_options () const
1460 int opt_idx;
1462 if (!get_logger ())
1463 return;
1465 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1466 log_str_option ((enum gcc_jit_str_option)opt_idx);
1468 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1469 log_int_option ((enum gcc_jit_int_option)opt_idx);
1471 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1472 log_bool_option ((enum gcc_jit_bool_option)opt_idx);
1473 for (opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1474 log_inner_bool_option ((enum inner_bool_option)opt_idx);
1477 /* Write the current value of the given string option to the
1478 log file (if any). */
1480 void
1481 recording::context::log_str_option (enum gcc_jit_str_option opt) const
1483 gcc_assert (opt < GCC_JIT_NUM_STR_OPTIONS);
1484 if (get_logger ())
1486 if (m_str_options[opt])
1487 log ("%s: \"%s\"",
1488 str_option_reproducer_strings[opt],
1489 m_str_options[opt]);
1490 else
1491 log ("%s: NULL",
1492 str_option_reproducer_strings[opt]);
1496 /* Write the current value of the given int option to the
1497 log file (if any). */
1499 void
1500 recording::context::log_int_option (enum gcc_jit_int_option opt) const
1502 gcc_assert (opt < GCC_JIT_NUM_INT_OPTIONS);
1503 if (get_logger ())
1504 log ("%s: %i",
1505 int_option_reproducer_strings[opt],
1506 m_int_options[opt]);
1509 /* Write the current value of the given bool option to the
1510 log file (if any). */
1512 void
1513 recording::context::log_bool_option (enum gcc_jit_bool_option opt) const
1515 gcc_assert (opt < GCC_JIT_NUM_BOOL_OPTIONS);
1516 if (get_logger ())
1517 log ("%s: %s",
1518 bool_option_reproducer_strings[opt],
1519 m_bool_options[opt] ? "true" : "false");
1522 /* Write the current value of the given "inner" bool option to the
1523 log file (if any). */
1525 void
1526 recording::context::log_inner_bool_option (enum inner_bool_option opt) const
1528 gcc_assert (opt < NUM_INNER_BOOL_OPTIONS);
1529 if (get_logger ())
1530 log ("%s: %s",
1531 inner_bool_option_reproducer_strings[opt],
1532 m_inner_bool_options[opt] ? "true" : "false");
1535 /* Write C source code to PATH that attempts to replay the API
1536 calls made to this context (and its parents), for use in
1537 minimizing test cases for libgccjit.
1539 Implements the post-error-checking part of
1540 gcc_jit_context_dump_reproducer_to_file. */
1542 void
1543 recording::context::dump_reproducer_to_file (const char *path)
1545 JIT_LOG_SCOPE (get_logger ());
1546 reproducer r (*this, path);
1548 /* Generate the "ancestry" of this context, as a list. */
1549 auto_vec <context *> ascending_contexts;
1550 for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
1551 ascending_contexts.safe_push (ctxt);
1553 /* Reverse the list, giving a list of contexts from
1554 top-most parent context down through to youngest child context.
1555 We will use this list as the parameters of the functions in
1556 our generated file. */
1557 unsigned num_ctxts = ascending_contexts.length ();
1558 auto_vec <context *> contexts (num_ctxts);
1559 for (unsigned i = 0; i < num_ctxts; i++)
1560 contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
1562 /* contexts[0] should be the top-level context. */
1563 gcc_assert (contexts[0]);
1564 gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
1566 /* The final element in contexts should be "this". */
1567 gcc_assert (contexts[contexts.length () - 1] == this);
1568 gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
1569 == contexts[0]);
1571 r.write ("/* This code was autogenerated by"
1572 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1573 print_version (r.get_file (), " ", false);
1574 r.write ("*/\n");
1575 r.write ("#include <libgccjit.h>\n\n");
1576 r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1577 r.write ("static void\nset_options (");
1578 r.write_params (contexts);
1579 r.write (");\n\n");
1580 r.write ("static void\ncreate_code (");
1581 r.write_params (contexts);
1582 r.write (");\n\n");
1583 r.write ("int\nmain (int argc, const char **argv)\n");
1584 r.write ("{\n");
1585 for (unsigned i = 0; i < num_ctxts; i++)
1586 r.write (" gcc_jit_context *%s;\n",
1587 r.get_identifier (contexts[i]));
1588 r.write (" gcc_jit_result *result;\n"
1589 "\n");
1591 /* Create the contexts.
1592 The top-level context is acquired from a clean slate, the others as
1593 children of the prior context. */
1594 r.write (" %s = gcc_jit_context_acquire ();\n",
1595 r.get_identifier (contexts[0]));
1596 for (unsigned i = 1; i < num_ctxts; i++)
1597 r.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1598 r.get_identifier (contexts[i]),
1599 r.get_identifier (contexts[i - 1]));
1600 r.write (" set_options (");
1601 r.write_args (contexts);
1602 r.write (");\n");
1603 r.write (" create_code (");
1604 r.write_args (contexts);
1605 r.write (");\n");
1607 r.write (" result = gcc_jit_context_compile (%s);\n",
1608 r.get_identifier (this));
1610 for (unsigned i = num_ctxts; i > 0; i--)
1611 r.write (" gcc_jit_context_release (%s);\n",
1612 r.get_identifier (contexts[i - 1]));
1614 r.write (" gcc_jit_result_release (result);\n"
1615 " return 0;\n"
1616 "}\n\n");
1618 /* Define (char *) variables for use in calls to
1619 gcc_jit_context_enable_dump. */
1620 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1622 if (m_requested_dumps.length ())
1624 r.write ("/* Requested dumps for %s. */\n",
1625 r.get_identifier (contexts[ctxt_idx]));
1626 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1627 r.write ("static char *dump_%p;\n",
1628 (void *)&m_requested_dumps[i]);
1629 r.write ("\n");
1633 /* Write out values of options. */
1634 r.write ("static void\nset_options (");
1635 r.write_params (contexts);
1636 r.write (")\n{\n");
1637 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1639 if (ctxt_idx > 0)
1640 r.write ("\n");
1642 r.write (" /* Set options for %s. */\n",
1643 r.get_identifier (contexts[ctxt_idx]));
1645 r.write (" /* String options. */\n");
1646 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1648 r.write (" gcc_jit_context_set_str_option (%s,\n"
1649 " %s,\n",
1650 r.get_identifier (contexts[ctxt_idx]),
1651 str_option_reproducer_strings[opt_idx]);
1652 if (m_str_options[opt_idx])
1653 r.write (" \"%s\");\n",
1654 m_str_options[opt_idx]);
1655 else
1656 r.write (" NULL);\n");
1658 r.write (" /* Int options. */\n");
1659 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1660 r.write (" gcc_jit_context_set_int_option (%s,\n"
1661 " %s,\n"
1662 " %i);\n",
1663 r.get_identifier (contexts[ctxt_idx]),
1664 int_option_reproducer_strings[opt_idx],
1665 m_int_options[opt_idx]);
1666 r.write (" /* Boolean options. */\n");
1667 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1668 r.write (" gcc_jit_context_set_bool_option (%s,\n"
1669 " %s,\n"
1670 " %i);\n",
1671 r.get_identifier (contexts[ctxt_idx]),
1672 bool_option_reproducer_strings[opt_idx],
1673 m_bool_options[opt_idx]);
1674 for (int opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1675 r.write (" %s (%s, %i);\n",
1676 inner_bool_option_reproducer_strings[opt_idx],
1677 r.get_identifier (contexts[ctxt_idx]),
1678 m_inner_bool_options[opt_idx]);
1680 if (!m_command_line_options.is_empty ())
1682 int i;
1683 char *optname;
1684 r.write (" /* User-provided command-line options. */\n");
1685 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1686 r.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1687 r.get_identifier (contexts[ctxt_idx]),
1688 optname);
1691 if (m_requested_dumps.length ())
1693 r.write (" /* Requested dumps. */\n");
1694 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1695 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1697 r.write (" gcc_jit_context_enable_dump (%s,\n"
1698 " \"%s\",\n"
1699 " &dump_%p);\n",
1700 r.get_identifier (contexts[ctxt_idx]),
1701 m_requested_dumps[i].m_dumpname,
1702 (void *)&m_requested_dumps[i]);
1706 r.write ("}\n\n");
1708 r.write ("static void\ncreate_code (");
1709 r.write_params (contexts);
1710 r.write (")\n"
1711 "{\n");
1712 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1714 memento *m;
1715 int i;
1716 if (ctxt_idx > 0)
1717 r.write ("\n\n");
1719 r.write (" /* Replay of API calls for %s. */\n",
1720 r.get_identifier (contexts[ctxt_idx]));
1721 FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
1722 m->write_reproducer (r);
1724 r.write ("}\n");
1727 /* Copy the requested dumps within this context and all ancestors into
1728 OUT. */
1730 void
1731 recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
1733 if (m_parent_ctxt)
1734 m_parent_ctxt->get_all_requested_dumps (out);
1736 out->reserve (m_requested_dumps.length ());
1737 out->splice (m_requested_dumps);
1740 /* This is a pre-compilation check for the context (and any parents).
1742 Detect errors within the context, adding errors if any are found. */
1744 void
1745 recording::context::validate ()
1747 JIT_LOG_SCOPE (get_logger ());
1749 if (m_parent_ctxt)
1750 m_parent_ctxt->validate ();
1752 int i;
1753 function *fn;
1754 FOR_EACH_VEC_ELT (m_functions, i, fn)
1755 fn->validate ();
1758 /* The implementation of class gcc::jit::recording::memento. */
1760 /* Get a (const char *) debug description of the given memento, by
1761 calling the pure-virtual make_debug_string hook, caching the
1762 result.
1764 It is intended that this should only be called in debugging and
1765 error-handling paths, so this doesn't need to be particularly
1766 optimized. */
1768 const char *
1769 recording::memento::get_debug_string ()
1771 if (!m_debug_string)
1772 m_debug_string = make_debug_string ();
1773 return m_debug_string->c_str ();
1776 /* Default implementation of recording::memento::write_to_dump, writing
1777 an indented form of the memento's debug string to the dump. */
1779 void
1780 recording::memento::write_to_dump (dump &d)
1782 d.write(" %s\n", get_debug_string ());
1785 /* The implementation of class gcc::jit::recording::string. */
1787 /* Constructor for gcc::jit::recording::string::string, allocating a
1788 copy of the given text using new char[]. */
1790 recording::string::string (context *ctxt, const char *text)
1791 : memento (ctxt)
1793 m_len = strlen (text);
1794 m_buffer = new char[m_len + 1];
1795 strcpy (m_buffer, text);
1798 /* Destructor for gcc::jit::recording::string::string. */
1800 recording::string::~string ()
1802 delete[] m_buffer;
1805 /* Function for making gcc::jit::recording::string instances on a
1806 context via printf-style formatting.
1808 It is intended that this should only be called in debugging and
1809 error-handling paths, so this doesn't need to be particularly
1810 optimized, hence the double-copy of the string is acceptable. */
1812 recording::string *
1813 recording::string::from_printf (context *ctxt, const char *fmt, ...)
1815 int len;
1816 va_list ap;
1817 char *buf;
1818 recording::string *result;
1820 va_start (ap, fmt);
1821 len = vasprintf (&buf, fmt, ap);
1822 va_end (ap);
1824 if (buf == NULL || len < 0)
1826 ctxt->add_error (NULL, "malloc failure");
1827 return NULL;
1830 result = ctxt->new_string (buf);
1831 free (buf);
1832 return result;
1835 /* Implementation of recording::memento::make_debug_string for strings,
1836 wrapping the given string in quotes and escaping as necessary. */
1838 recording::string *
1839 recording::string::make_debug_string ()
1841 /* Hack to avoid infinite recursion into strings when logging all
1842 mementos: don't re-escape strings: */
1843 if (m_buffer[0] == '"')
1844 return this;
1846 /* Wrap in quotes and do escaping etc */
1848 size_t sz = (1 /* opening quote */
1849 + (m_len * 2) /* each char might get escaped */
1850 + 1 /* closing quote */
1851 + 1); /* nil termintator */
1852 char *tmp = new char[sz];
1853 size_t len = 0;
1855 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1856 APPEND('"'); /* opening quote */
1857 for (size_t i = 0; i < m_len ; i++)
1859 char ch = m_buffer[i];
1860 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
1861 APPEND('\\');
1862 APPEND(ch);
1864 APPEND('"'); /* closing quote */
1865 #undef APPEND
1866 tmp[len] = '\0'; /* nil termintator */
1868 string *result = m_ctxt->new_string (tmp);
1870 delete[] tmp;
1871 return result;
1874 /* Implementation of recording::memento::write_reproducer for strings. */
1876 void
1877 recording::string::write_reproducer (reproducer &)
1879 /* Empty. */
1882 /* The implementation of class gcc::jit::recording::location. */
1884 /* Implementation of recording::memento::replay_into for locations.
1886 Create a new playback::location and store it into the
1887 recording::location's m_playback_obj field. */
1889 void
1890 recording::location::replay_into (replayer *r)
1892 m_playback_obj = r->new_location (this,
1893 m_filename->c_str (),
1894 m_line,
1895 m_column);
1898 /* Implementation of recording::memento::make_debug_string for locations,
1899 turning them into the usual form:
1900 FILENAME:LINE:COLUMN
1901 like we do when emitting diagnostics. */
1903 recording::string *
1904 recording::location::make_debug_string ()
1906 return string::from_printf (m_ctxt,
1907 "%s:%i:%i",
1908 m_filename->c_str (), m_line, m_column);
1911 /* Implementation of recording::memento::write_reproducer for locations. */
1913 void
1914 recording::location::write_reproducer (reproducer &r)
1916 const char *id = r.make_identifier (this, "loc");
1917 r.write (" gcc_jit_location *%s =\n"
1918 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1919 " %s, /* const char *filename */\n"
1920 " %i, /* int line */\n"
1921 " %i);/* int column */\n",
1923 r.get_identifier (get_context ()),
1924 m_filename->get_debug_string (),
1925 m_line, m_column);
1928 /* The implementation of class gcc::jit::recording::type. */
1930 /* Given a type T, get the type T*.
1932 If this doesn't already exist, generate a new memento_of_get_pointer
1933 instance and add it to this type's context's list of mementos.
1935 Otherwise, use the cached type.
1937 Implements the post-error-checking part of
1938 gcc_jit_type_get_pointer. */
1940 recording::type *
1941 recording::type::get_pointer ()
1943 if (!m_pointer_to_this_type)
1945 m_pointer_to_this_type = new memento_of_get_pointer (this);
1946 m_ctxt->record (m_pointer_to_this_type);
1948 return m_pointer_to_this_type;
1951 /* Given a type T, get the type const T.
1953 Implements the post-error-checking part of
1954 gcc_jit_type_get_const. */
1956 recording::type *
1957 recording::type::get_const ()
1959 recording::type *result = new memento_of_get_const (this);
1960 m_ctxt->record (result);
1961 return result;
1964 /* Given a type T, get the type volatile T.
1966 Implements the post-error-checking part of
1967 gcc_jit_type_get_volatile. */
1969 recording::type *
1970 recording::type::get_volatile ()
1972 recording::type *result = new memento_of_get_volatile (this);
1973 m_ctxt->record (result);
1974 return result;
1977 /* Given a type, get an aligned version of the type.
1979 Implements the post-error-checking part of
1980 gcc_jit_type_get_aligned. */
1982 recording::type *
1983 recording::type::get_aligned (size_t alignment_in_bytes)
1985 recording::type *result
1986 = new memento_of_get_aligned (this, alignment_in_bytes);
1987 m_ctxt->record (result);
1988 return result;
1991 /* Given a type, get a vector version of the type.
1993 Implements the post-error-checking part of
1994 gcc_jit_type_get_vector. */
1996 recording::type *
1997 recording::type::get_vector (size_t num_units)
1999 recording::type *result
2000 = new memento_of_get_vector (this, num_units);
2001 m_ctxt->record (result);
2002 return result;
2005 const char *
2006 recording::type::access_as_type (reproducer &r)
2008 return r.get_identifier (this);
2011 /* Implementation of pure virtual hook recording::type::dereference for
2012 recording::memento_of_get_type. */
2014 recording::type *
2015 recording::memento_of_get_type::dereference ()
2017 switch (m_kind)
2019 default: gcc_unreachable ();
2021 case GCC_JIT_TYPE_VOID:
2022 return NULL;
2024 case GCC_JIT_TYPE_VOID_PTR:
2025 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
2027 case GCC_JIT_TYPE_BOOL:
2028 case GCC_JIT_TYPE_CHAR:
2029 case GCC_JIT_TYPE_SIGNED_CHAR:
2030 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2031 case GCC_JIT_TYPE_SHORT:
2032 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2033 case GCC_JIT_TYPE_INT:
2034 case GCC_JIT_TYPE_UNSIGNED_INT:
2035 case GCC_JIT_TYPE_LONG:
2036 case GCC_JIT_TYPE_UNSIGNED_LONG:
2037 case GCC_JIT_TYPE_LONG_LONG:
2038 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2039 case GCC_JIT_TYPE_FLOAT:
2040 case GCC_JIT_TYPE_DOUBLE:
2041 case GCC_JIT_TYPE_LONG_DOUBLE:
2042 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2043 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2044 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2045 /* Not a pointer: */
2046 return NULL;
2048 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2049 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
2051 case GCC_JIT_TYPE_SIZE_T:
2052 /* Not a pointer: */
2053 return NULL;
2055 case GCC_JIT_TYPE_FILE_PTR:
2056 /* Give the client code back an opaque "struct FILE". */
2057 return m_ctxt->get_opaque_FILE_type ();
2061 /* Implementation of pure virtual hook recording::type::is_int for
2062 recording::memento_of_get_type. */
2064 bool
2065 recording::memento_of_get_type::is_int () const
2067 switch (m_kind)
2069 default: gcc_unreachable ();
2071 case GCC_JIT_TYPE_VOID:
2072 return false;
2074 case GCC_JIT_TYPE_VOID_PTR:
2075 return false;
2077 case GCC_JIT_TYPE_BOOL:
2078 return false;
2080 case GCC_JIT_TYPE_CHAR:
2081 case GCC_JIT_TYPE_SIGNED_CHAR:
2082 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2083 case GCC_JIT_TYPE_SHORT:
2084 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2085 case GCC_JIT_TYPE_INT:
2086 case GCC_JIT_TYPE_UNSIGNED_INT:
2087 case GCC_JIT_TYPE_LONG:
2088 case GCC_JIT_TYPE_UNSIGNED_LONG:
2089 case GCC_JIT_TYPE_LONG_LONG:
2090 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2091 return true;
2093 case GCC_JIT_TYPE_FLOAT:
2094 case GCC_JIT_TYPE_DOUBLE:
2095 case GCC_JIT_TYPE_LONG_DOUBLE:
2096 return false;
2098 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2099 return false;
2101 case GCC_JIT_TYPE_SIZE_T:
2102 return true;
2104 case GCC_JIT_TYPE_FILE_PTR:
2105 return false;
2107 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2108 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2109 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2110 return false;
2114 /* Implementation of pure virtual hook recording::type::is_float for
2115 recording::memento_of_get_type. */
2117 bool
2118 recording::memento_of_get_type::is_float () const
2120 switch (m_kind)
2122 default: gcc_unreachable ();
2124 case GCC_JIT_TYPE_VOID:
2125 return false;
2127 case GCC_JIT_TYPE_VOID_PTR:
2128 return false;
2130 case GCC_JIT_TYPE_BOOL:
2131 return false;
2133 case GCC_JIT_TYPE_CHAR:
2134 case GCC_JIT_TYPE_SIGNED_CHAR:
2135 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2136 case GCC_JIT_TYPE_SHORT:
2137 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2138 case GCC_JIT_TYPE_INT:
2139 case GCC_JIT_TYPE_UNSIGNED_INT:
2140 case GCC_JIT_TYPE_LONG:
2141 case GCC_JIT_TYPE_UNSIGNED_LONG:
2142 case GCC_JIT_TYPE_LONG_LONG:
2143 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2144 return false;
2146 case GCC_JIT_TYPE_FLOAT:
2147 case GCC_JIT_TYPE_DOUBLE:
2148 case GCC_JIT_TYPE_LONG_DOUBLE:
2149 return true;
2151 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2152 return false;
2154 case GCC_JIT_TYPE_SIZE_T:
2155 return false;
2157 case GCC_JIT_TYPE_FILE_PTR:
2158 return false;
2160 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2161 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2162 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2163 return true;
2167 /* Implementation of pure virtual hook recording::type::is_bool for
2168 recording::memento_of_get_type. */
2170 bool
2171 recording::memento_of_get_type::is_bool () const
2173 switch (m_kind)
2175 default: gcc_unreachable ();
2177 case GCC_JIT_TYPE_VOID:
2178 return false;
2180 case GCC_JIT_TYPE_VOID_PTR:
2181 return false;
2183 case GCC_JIT_TYPE_BOOL:
2184 return true;
2186 case GCC_JIT_TYPE_CHAR:
2187 case GCC_JIT_TYPE_SIGNED_CHAR:
2188 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2189 case GCC_JIT_TYPE_SHORT:
2190 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2191 case GCC_JIT_TYPE_INT:
2192 case GCC_JIT_TYPE_UNSIGNED_INT:
2193 case GCC_JIT_TYPE_LONG:
2194 case GCC_JIT_TYPE_UNSIGNED_LONG:
2195 case GCC_JIT_TYPE_LONG_LONG:
2196 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2197 return false;
2199 case GCC_JIT_TYPE_FLOAT:
2200 case GCC_JIT_TYPE_DOUBLE:
2201 case GCC_JIT_TYPE_LONG_DOUBLE:
2202 return false;
2204 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2205 return false;
2207 case GCC_JIT_TYPE_SIZE_T:
2208 return false;
2210 case GCC_JIT_TYPE_FILE_PTR:
2211 return false;
2213 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2214 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2215 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2216 return false;
2220 /* Implementation of pure virtual hook recording::memento::replay_into
2221 for recording::memento_of_get_type. */
2223 void
2224 recording::memento_of_get_type::replay_into (replayer *r)
2226 set_playback_obj (r->get_type (m_kind));
2229 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2231 /* Descriptive strings for each of enum gcc_jit_types. */
2233 static const char * const get_type_strings[] = {
2234 "void", /* GCC_JIT_TYPE_VOID */
2235 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2237 "bool", /* GCC_JIT_TYPE_BOOL */
2239 "char", /* GCC_JIT_TYPE_CHAR */
2240 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2241 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2243 "short", /* GCC_JIT_TYPE_SHORT */
2244 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2246 "int", /* GCC_JIT_TYPE_INT */
2247 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2249 "long", /* GCC_JIT_TYPE_LONG */
2250 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2252 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2253 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2255 "float", /* GCC_JIT_TYPE_FLOAT */
2256 "double", /* GCC_JIT_TYPE_DOUBLE */
2257 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2259 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2261 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2263 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2265 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2266 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2267 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2271 /* Implementation of recording::memento::make_debug_string for
2272 results of get_type, using a simple table of type names. */
2274 recording::string *
2275 recording::memento_of_get_type::make_debug_string ()
2277 return m_ctxt->new_string (get_type_strings[m_kind]);
2280 static const char * const get_type_enum_strings[] = {
2281 "GCC_JIT_TYPE_VOID",
2282 "GCC_JIT_TYPE_VOID_PTR",
2283 "GCC_JIT_TYPE_BOOL",
2284 "GCC_JIT_TYPE_CHAR",
2285 "GCC_JIT_TYPE_SIGNED_CHAR",
2286 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2287 "GCC_JIT_TYPE_SHORT",
2288 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2289 "GCC_JIT_TYPE_INT",
2290 "GCC_JIT_TYPE_UNSIGNED_INT",
2291 "GCC_JIT_TYPE_LONG",
2292 "GCC_JIT_TYPE_UNSIGNED_LONG",
2293 "GCC_JIT_TYPE_LONG_LONG",
2294 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2295 "GCC_JIT_TYPE_FLOAT",
2296 "GCC_JIT_TYPE_DOUBLE",
2297 "GCC_JIT_TYPE_LONG_DOUBLE",
2298 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2299 "GCC_JIT_TYPE_SIZE_T",
2300 "GCC_JIT_TYPE_FILE_PTR",
2301 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2302 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2303 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2306 void
2307 recording::memento_of_get_type::write_reproducer (reproducer &r)
2309 const char *id = r.make_identifier (this, "type");
2310 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2312 r.get_identifier (get_context ()),
2313 get_type_enum_strings[m_kind]);
2316 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2318 /* Override of default implementation of
2319 recording::type::accepts_writes_from for get_pointer.
2321 Require a pointer type, and allowing writes to
2322 (const T *) from a (T*), but not the other way around. */
2324 bool
2325 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2327 /* Must be a pointer type: */
2328 type *rtype_points_to = rtype->is_pointer ();
2329 if (!rtype_points_to)
2330 return false;
2332 /* It's OK to assign to a (const T *) from a (T *). */
2333 return m_other_type->unqualified ()
2334 ->accepts_writes_from (rtype_points_to);
2337 /* Implementation of pure virtual hook recording::memento::replay_into
2338 for recording::memento_of_get_pointer. */
2340 void
2341 recording::memento_of_get_pointer::replay_into (replayer *)
2343 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2346 /* Implementation of recording::memento::make_debug_string for
2347 results of get_pointer, adding " *" to the underlying type,
2348 with special-casing to handle function pointer types. */
2350 recording::string *
2351 recording::memento_of_get_pointer::make_debug_string ()
2353 /* Special-case function pointer types, to put the "*" in parens between
2354 the return type and the params (for one level of dereferencing, at
2355 least). */
2356 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2357 return fn_type->make_debug_string_with_ptr ();
2359 return string::from_printf (m_ctxt,
2360 "%s *", m_other_type->get_debug_string ());
2363 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2365 void
2366 recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2368 /* We need to special-case function pointer types; see the notes in
2369 recording::function_type::write_deferred_reproducer. */
2370 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2372 fn_type->write_deferred_reproducer (r, this);
2373 return;
2376 const char *id = r.make_identifier (this, "type");
2377 r.write (" gcc_jit_type *%s =\n"
2378 " gcc_jit_type_get_pointer (%s);\n",
2380 r.get_identifier_as_type (m_other_type));
2383 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2385 /* Implementation of pure virtual hook recording::memento::replay_into
2386 for recording::memento_of_get_const. */
2388 void
2389 recording::memento_of_get_const::replay_into (replayer *)
2391 set_playback_obj (m_other_type->playback_type ()->get_const ());
2394 /* Implementation of recording::memento::make_debug_string for
2395 results of get_const, prepending "const ". */
2397 recording::string *
2398 recording::memento_of_get_const::make_debug_string ()
2400 return string::from_printf (m_ctxt,
2401 "const %s", m_other_type->get_debug_string ());
2404 /* Implementation of recording::memento::write_reproducer for const types. */
2406 void
2407 recording::memento_of_get_const::write_reproducer (reproducer &r)
2409 const char *id = r.make_identifier (this, "type");
2410 r.write (" gcc_jit_type *%s =\n"
2411 " gcc_jit_type_get_const (%s);\n",
2413 r.get_identifier_as_type (m_other_type));
2416 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2418 /* Implementation of pure virtual hook recording::memento::replay_into
2419 for recording::memento_of_get_volatile. */
2421 void
2422 recording::memento_of_get_volatile::replay_into (replayer *)
2424 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2427 /* Implementation of recording::memento::make_debug_string for
2428 results of get_volatile, prepending "volatile ". */
2430 recording::string *
2431 recording::memento_of_get_volatile::make_debug_string ()
2433 return string::from_printf (m_ctxt,
2434 "volatile %s", m_other_type->get_debug_string ());
2437 /* Implementation of recording::memento::write_reproducer for volatile
2438 types. */
2440 void
2441 recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2443 const char *id = r.make_identifier (this, "type");
2444 r.write (" gcc_jit_type *%s =\n"
2445 " gcc_jit_type_get_volatile (%s);\n",
2447 r.get_identifier_as_type (m_other_type));
2450 /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
2452 /* Implementation of pure virtual hook recording::memento::replay_into
2453 for recording::memento_of_get_aligned. */
2455 void
2456 recording::memento_of_get_aligned::replay_into (replayer *)
2458 set_playback_obj
2459 (m_other_type->playback_type ()->get_aligned (m_alignment_in_bytes));
2462 /* Implementation of recording::memento::make_debug_string for
2463 results of get_aligned. */
2465 recording::string *
2466 recording::memento_of_get_aligned::make_debug_string ()
2468 return string::from_printf (m_ctxt,
2469 "%s __attribute__((aligned(%zi)))",
2470 m_other_type->get_debug_string (),
2471 m_alignment_in_bytes);
2474 /* Implementation of recording::memento::write_reproducer for aligned
2475 types. */
2477 void
2478 recording::memento_of_get_aligned::write_reproducer (reproducer &r)
2480 const char *id = r.make_identifier (this, "type");
2481 r.write (" gcc_jit_type *%s =\n"
2482 " gcc_jit_type_get_aligned (%s, %zi);\n",
2484 r.get_identifier_as_type (m_other_type),
2485 m_alignment_in_bytes);
2488 /* The implementation of class gcc::jit::recording::memento_of_get_vector. */
2490 /* Implementation of pure virtual hook recording::memento::replay_into
2491 for recording::memento_of_get_vector. */
2493 void
2494 recording::memento_of_get_vector::replay_into (replayer *)
2496 set_playback_obj
2497 (m_other_type->playback_type ()->get_vector (m_num_units));
2500 /* Implementation of recording::memento::make_debug_string for
2501 results of get_vector. */
2503 recording::string *
2504 recording::memento_of_get_vector::make_debug_string ()
2506 return string::from_printf
2507 (m_ctxt,
2508 "%s __attribute__((vector_size(sizeof (%s) * %zi)))",
2509 m_other_type->get_debug_string (),
2510 m_other_type->get_debug_string (),
2511 m_num_units);
2514 /* Implementation of recording::memento::write_reproducer for volatile
2515 types. */
2517 void
2518 recording::memento_of_get_vector::write_reproducer (reproducer &r)
2520 const char *id = r.make_identifier (this, "type");
2521 r.write (" gcc_jit_type *%s =\n"
2522 " gcc_jit_type_get_vector (%s, %zi);\n",
2524 r.get_identifier_as_type (m_other_type),
2525 m_num_units);
2528 /* The implementation of class gcc::jit::recording::array_type */
2530 /* Implementation of pure virtual hook recording::type::dereference for
2531 recording::array_type. */
2533 recording::type *
2534 recording::array_type::dereference ()
2536 return m_element_type;
2539 /* Implementation of pure virtual hook recording::memento::replay_into
2540 for recording::array_type. */
2542 void
2543 recording::array_type::replay_into (replayer *r)
2545 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
2546 m_element_type->playback_type (),
2547 m_num_elements));
2550 /* Implementation of recording::memento::make_debug_string for
2551 results of new_array_type. */
2553 recording::string *
2554 recording::array_type::make_debug_string ()
2556 return string::from_printf (m_ctxt,
2557 "%s[%d]",
2558 m_element_type->get_debug_string (),
2559 m_num_elements);
2562 /* Implementation of recording::memento::write_reproducer for array
2563 types. */
2565 void
2566 recording::array_type::write_reproducer (reproducer &r)
2568 const char *id = r.make_identifier (this, "array_type");
2569 r.write (" gcc_jit_type *%s =\n"
2570 " gcc_jit_context_new_array_type (%s,\n"
2571 " %s, /* gcc_jit_location *loc */\n"
2572 " %s, /* gcc_jit_type *element_type */\n"
2573 " %i); /* int num_elements */\n",
2575 r.get_identifier (get_context ()),
2576 r.get_identifier (m_loc),
2577 r.get_identifier_as_type (m_element_type),
2578 m_num_elements);
2581 /* The implementation of class gcc::jit::recording::function_type */
2583 /* Constructor for gcc::jit::recording::function_type. */
2585 recording::function_type::function_type (context *ctxt,
2586 type *return_type,
2587 int num_params,
2588 type **param_types,
2589 int is_variadic)
2590 : type (ctxt),
2591 m_return_type (return_type),
2592 m_param_types (),
2593 m_is_variadic (is_variadic)
2595 for (int i = 0; i< num_params; i++)
2596 m_param_types.safe_push (param_types[i]);
2599 /* Implementation of pure virtual hook recording::type::dereference for
2600 recording::function_type. */
2602 recording::type *
2603 recording::function_type::dereference ()
2605 return NULL;
2608 /* Implementation of pure virtual hook recording::memento::replay_into
2609 for recording::function_type. */
2611 void
2612 recording::function_type::replay_into (replayer *r)
2614 /* Convert m_param_types to a vec of playback type. */
2615 auto_vec <playback::type *> param_types;
2616 int i;
2617 recording::type *type;
2618 param_types.create (m_param_types.length ());
2619 FOR_EACH_VEC_ELT (m_param_types, i, type)
2620 param_types.safe_push (type->playback_type ());
2622 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
2623 &param_types,
2624 m_is_variadic));
2627 /* Special-casing for make_debug_string for get_pointer results for
2628 handling (one level) of pointers to functions. */
2630 recording::string *
2631 recording::function_type::make_debug_string_with_ptr ()
2633 return make_debug_string_with ("(*) ");
2636 /* Implementation of recording::memento::make_debug_string for
2637 results of new_function_type. */
2639 recording::string *
2640 recording::function_type::make_debug_string ()
2642 return make_debug_string_with ("");
2645 /* Build a debug string representation of the form:
2647 RESULT_TYPE INSERT (PARAM_TYPES)
2649 for use when handling 0 and 1 level of indirection to this
2650 function type. */
2652 recording::string *
2653 recording::function_type::make_debug_string_with (const char *insert)
2655 /* First, build a buffer for the arguments. */
2656 /* Calculate length of said buffer. */
2657 size_t sz = 1; /* nil terminator */
2658 for (unsigned i = 0; i< m_param_types.length (); i++)
2660 sz += strlen (m_param_types[i]->get_debug_string ());
2661 sz += 2; /* ", " separator */
2663 if (m_is_variadic)
2664 sz += 5; /* ", ..." separator and ellipsis */
2666 /* Now allocate and populate the buffer. */
2667 char *argbuf = new char[sz];
2668 size_t len = 0;
2670 for (unsigned i = 0; i< m_param_types.length (); i++)
2672 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
2673 len += strlen (m_param_types[i]->get_debug_string ());
2674 if (i + 1 < m_param_types.length ())
2676 strcpy (argbuf + len, ", ");
2677 len += 2;
2680 if (m_is_variadic)
2682 if (m_param_types.length ())
2684 strcpy (argbuf + len, ", ");
2685 len += 2;
2687 strcpy (argbuf + len, "...");
2688 len += 3;
2690 argbuf[len] = '\0';
2692 /* ...and use it to get the string for the call as a whole. */
2693 string *result = string::from_printf (m_ctxt,
2694 "%s %s(%s)",
2695 m_return_type->get_debug_string (),
2696 insert,
2697 argbuf);
2699 delete[] argbuf;
2701 return result;
2704 /* Implementation of recording::memento::write_reproducer for function
2705 types. */
2707 void
2708 recording::function_type::write_reproducer (reproducer &)
2710 /* see notes below. */
2713 /* There's a get_pointer within context::new_function_ptr_type:
2714 the type received by client code isn't the memento for the
2715 function_type, but instead the result of get_pointer on it.
2717 Hence we can't directly write a reproducer that gives function_type.
2718 Instead we special-case things within get_pointer, detecting this
2719 case, calling the following function. */
2721 void
2722 recording::function_type::write_deferred_reproducer (reproducer &r,
2723 memento *ptr_type)
2725 gcc_assert (ptr_type);
2726 r.make_identifier (this, "function_type");
2727 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
2728 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
2729 r.write (" gcc_jit_type *%s[%i] = {\n",
2730 param_types_id,
2731 m_param_types.length ());
2732 int i;
2733 type *param_type;
2734 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2735 r.write (" %s,\n", r.get_identifier_as_type (param_type));
2736 r.write (" };\n");
2737 r.write (" gcc_jit_type *%s =\n"
2738 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2739 " %s, /* gcc_jit_location *loc */\n"
2740 " %s, /* gcc_jit_type *return_type */\n"
2741 " %i, /* int num_params */\n"
2742 " %s, /* gcc_jit_type **param_types */\n"
2743 " %i); /* int is_variadic */\n",
2744 ptr_id,
2745 r.get_identifier (get_context ()),
2746 "NULL", /* location is not stored */
2747 r.get_identifier_as_type (m_return_type),
2748 m_param_types.length (),
2749 param_types_id,
2750 m_is_variadic);
2753 /* The implementation of class gcc::jit::recording::field. */
2755 /* Implementation of pure virtual hook recording::memento::replay_into
2756 for recording::field. */
2758 void
2759 recording::field::replay_into (replayer *r)
2761 set_playback_obj (r->new_field (playback_location (r, m_loc),
2762 m_type->playback_type (),
2763 playback_string (m_name)));
2766 /* Override the default implementation of
2767 recording::memento::write_to_dump. Dump each field
2768 by dumping a line of the form:
2769 TYPE NAME;
2770 so that we can build up a struct/union field-byfield. */
2772 void
2773 recording::field::write_to_dump (dump &d)
2775 d.write (" %s %s;\n",
2776 m_type->get_debug_string (),
2777 m_name->c_str ());
2780 /* Implementation of recording::memento::make_debug_string for
2781 results of new_field. */
2783 recording::string *
2784 recording::field::make_debug_string ()
2786 return m_name;
2789 /* Implementation of recording::memento::write_reproducer for fields. */
2791 void
2792 recording::field::write_reproducer (reproducer &r)
2794 const char *id = r.make_identifier (this, "field");
2795 r.write(" gcc_jit_field *%s =\n"
2796 " gcc_jit_context_new_field (%s,\n"
2797 " %s, /* gcc_jit_location *loc */\n"
2798 " %s, /* gcc_jit_type *type, */\n"
2799 " %s); /* const char *name */\n",
2801 r.get_identifier (get_context ()),
2802 r.get_identifier (m_loc),
2803 r.get_identifier_as_type (m_type),
2804 m_name->get_debug_string ());
2807 /* The implementation of class gcc::jit::recording::compound_type */
2809 /* The constructor for gcc::jit::recording::compound_type. */
2811 recording::compound_type::compound_type (context *ctxt,
2812 location *loc,
2813 string *name)
2814 : type (ctxt),
2815 m_loc (loc),
2816 m_name (name),
2817 m_fields (NULL)
2821 /* Set the fields of a compound type.
2823 Implements the post-error-checking part of
2824 gcc_jit_struct_set_fields, and is also used by
2825 gcc_jit_context_new_union_type. */
2827 void
2828 recording::compound_type::set_fields (location *loc,
2829 int num_fields,
2830 field **field_array)
2832 m_loc = loc;
2833 gcc_assert (NULL == m_fields);
2835 m_fields = new fields (this, num_fields, field_array);
2836 m_ctxt->record (m_fields);
2839 /* Implementation of pure virtual hook recording::type::dereference for
2840 recording::compound_type. */
2842 recording::type *
2843 recording::compound_type::dereference ()
2845 return NULL; /* not a pointer */
2848 /* The implementation of class gcc::jit::recording::struct_. */
2850 /* The constructor for gcc::jit::recording::struct_. */
2852 recording::struct_::struct_ (context *ctxt,
2853 location *loc,
2854 string *name)
2855 : compound_type (ctxt, loc, name)
2859 /* Implementation of pure virtual hook recording::memento::replay_into
2860 for recording::struct_. */
2862 void
2863 recording::struct_::replay_into (replayer *r)
2865 set_playback_obj (
2866 r->new_compound_type (playback_location (r, get_loc ()),
2867 get_name ()->c_str (),
2868 true /* is_struct */));
2871 const char *
2872 recording::struct_::access_as_type (reproducer &r)
2874 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2875 r.get_identifier (this));
2878 /* Implementation of recording::memento::make_debug_string for
2879 structs. */
2881 recording::string *
2882 recording::struct_::make_debug_string ()
2884 return string::from_printf (m_ctxt,
2885 "struct %s", get_name ()->c_str ());
2888 void
2889 recording::struct_::write_reproducer (reproducer &r)
2891 const char *id = r.make_identifier (this, "struct");
2892 r.write (" gcc_jit_struct *%s =\n"
2893 " gcc_jit_context_new_opaque_struct (%s,\n"
2894 " %s, /* gcc_jit_location *loc */\n"
2895 " %s); /* const char *name */\n",
2897 r.get_identifier (get_context ()),
2898 r.get_identifier (get_loc ()),
2899 get_name ()->get_debug_string ());
2902 /* The implementation of class gcc::jit::recording::union_. */
2904 /* The constructor for gcc::jit::recording::union_. */
2906 recording::union_::union_ (context *ctxt,
2907 location *loc,
2908 string *name)
2909 : compound_type (ctxt, loc, name)
2913 /* Implementation of pure virtual hook recording::memento::replay_into
2914 for recording::union_. */
2916 void
2917 recording::union_::replay_into (replayer *r)
2919 set_playback_obj (
2920 r->new_compound_type (playback_location (r, get_loc ()),
2921 get_name ()->c_str (),
2922 false /* is_struct */));
2925 /* Implementation of recording::memento::make_debug_string for
2926 unions. */
2928 recording::string *
2929 recording::union_::make_debug_string ()
2931 return string::from_printf (m_ctxt,
2932 "union %s", get_name ()->c_str ());
2935 /* Implementation of recording::memento::write_reproducer for unions. */
2937 void
2938 recording::union_::write_reproducer (reproducer &r)
2940 const char *id = r.make_identifier (this, "union");
2942 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
2943 r.write (" gcc_jit_field *%s[%i] = {\n",
2944 fields_id,
2945 get_fields ()->length ());
2946 for (int i = 0; i < get_fields ()->length (); i++)
2947 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
2948 r.write (" };\n");
2950 r.write (" gcc_jit_type *%s =\n"
2951 " gcc_jit_context_new_union_type (%s,\n"
2952 " %s, /* gcc_jit_location *loc */\n"
2953 " %s, /* const char *name */\n"
2954 " %i, /* int num_fields */\n"
2955 " %s); /* gcc_jit_field **fields */\n",
2957 r.get_identifier (get_context ()),
2958 r.get_identifier (get_loc ()),
2959 get_name ()->get_debug_string (),
2960 get_fields ()->length (),
2961 fields_id);
2964 /* The implementation of class gcc::jit::recording::fields. */
2966 /* The constructor for gcc::jit::recording::fields. */
2968 recording::fields::fields (compound_type *struct_or_union,
2969 int num_fields,
2970 field **fields)
2971 : memento (struct_or_union->m_ctxt),
2972 m_struct_or_union (struct_or_union),
2973 m_fields ()
2975 for (int i = 0; i < num_fields; i++)
2977 gcc_assert (fields[i]->get_container () == NULL);
2978 fields[i]->set_container (m_struct_or_union);
2979 m_fields.safe_push (fields[i]);
2983 /* Implementation of pure virtual hook recording::memento::replay_into
2984 for recording::fields. */
2986 void
2987 recording::fields::replay_into (replayer *)
2989 auto_vec<playback::field *> playback_fields;
2990 playback_fields.create (m_fields.length ());
2991 for (unsigned i = 0; i < m_fields.length (); i++)
2992 playback_fields.safe_push (m_fields[i]->playback_field ());
2993 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
2996 /* Override the default implementation of
2997 recording::memento::write_to_dump by writing a union/struct
2998 declaration of this form:
3000 struct/union NAME {
3001 TYPE_1 NAME_1;
3002 TYPE_2 NAME_2;
3003 ....
3004 TYPE_N NAME_N;
3007 to the dump. */
3009 void
3010 recording::fields::write_to_dump (dump &d)
3012 int i;
3013 field *f;
3015 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
3016 FOR_EACH_VEC_ELT (m_fields, i, f)
3017 f->write_to_dump (d);
3018 d.write ("};\n");
3021 /* Implementation of recording::memento::write_reproducer for the fields
3022 subclass. */
3024 void
3025 recording::fields::write_reproducer (reproducer &r)
3027 if (m_struct_or_union)
3028 if (NULL == m_struct_or_union->dyn_cast_struct ())
3029 /* We have a union; the fields have already been written by
3030 union::write_reproducer. */
3031 return;
3033 const char *fields_id = r.make_identifier (this, "fields");
3034 r.write (" gcc_jit_field *%s[%i] = {\n",
3035 fields_id,
3036 m_fields.length ());
3037 int i;
3038 field *field;
3039 FOR_EACH_VEC_ELT (m_fields, i, field)
3040 r.write (" %s,\n", r.get_identifier (field));
3041 r.write (" };\n");
3043 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
3044 " %s, /* gcc_jit_location *loc */\n"
3045 " %i, /* int num_fields */\n"
3046 " %s); /* gcc_jit_field **fields */\n",
3047 r.get_identifier (m_struct_or_union),
3048 r.get_identifier ((memento *)NULL),
3049 m_fields.length (),
3050 fields_id);
3053 /* Implementation of recording::memento::make_debug_string for
3054 field tables. */
3056 recording::string *
3057 recording::fields::make_debug_string ()
3059 return string::from_printf (m_ctxt,
3060 "fields");
3063 /* The implementation of class gcc::jit::recording::rvalue. */
3065 /* Create a recording::access_field_rvalue instance and add it to
3066 the rvalue's context's list of mementos.
3068 Implements the post-error-checking part of
3069 gcc_jit_rvalue_access_field. */
3071 recording::rvalue *
3072 recording::rvalue::access_field (recording::location *loc,
3073 field *field)
3075 recording::rvalue *result =
3076 new access_field_rvalue (m_ctxt, loc, this, field);
3077 m_ctxt->record (result);
3078 return result;
3081 /* Create a recording::dereference_field_rvalue instance and add it to
3082 the rvalue's context's list of mementos.
3084 Implements the post-error-checking part of
3085 gcc_jit_rvalue_dereference_field. */
3087 recording::lvalue *
3088 recording::rvalue::dereference_field (recording::location *loc,
3089 field *field)
3091 recording::lvalue *result =
3092 new dereference_field_rvalue (m_ctxt, loc, this, field);
3093 m_ctxt->record (result);
3094 return result;
3097 /* Create a recording::dereference_rvalue instance and add it to the
3098 rvalue's context's list of mementos.
3100 Implements the post-error-checking part of
3101 gcc_jit_rvalue_dereference. */
3103 recording::lvalue *
3104 recording::rvalue::dereference (recording::location *loc)
3106 recording::lvalue *result =
3107 new dereference_rvalue (m_ctxt, loc, this);
3108 m_ctxt->record (result);
3109 return result;
3112 /* An rvalue visitor, for validating that every rvalue within an expression
3113 trees within "STMT" has the correct scope (e.g. no access to locals
3114 of a different function). */
3116 class rvalue_usage_validator : public recording::rvalue_visitor
3118 public:
3119 rvalue_usage_validator (const char *api_funcname,
3120 recording::context *ctxt,
3121 recording::statement *stmt);
3123 void
3124 visit (recording::rvalue *rvalue) FINAL OVERRIDE;
3126 private:
3127 const char *m_api_funcname;
3128 recording::context *m_ctxt;
3129 recording::statement *m_stmt;
3132 /* The trivial constructor for rvalue_usage_validator. */
3134 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
3135 recording::context *ctxt,
3136 recording::statement *stmt)
3137 : m_api_funcname (api_funcname),
3138 m_ctxt (ctxt),
3139 m_stmt (stmt)
3143 /* Verify that the given rvalue is in the correct scope. */
3145 void
3146 rvalue_usage_validator::visit (recording::rvalue *rvalue)
3148 gcc_assert (m_stmt->get_block ());
3149 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
3151 /* Most rvalues don't have a scope (only locals and params). */
3152 if (rvalue->get_scope ())
3154 if (rvalue->get_scope () != stmt_scope)
3155 m_ctxt->add_error
3156 (rvalue->get_loc (),
3157 "%s:"
3158 " rvalue %s (type: %s)"
3159 " has scope limited to function %s"
3160 " but was used within function %s"
3161 " (in statement: %s)",
3162 m_api_funcname,
3163 rvalue->get_debug_string (),
3164 rvalue->get_type ()->get_debug_string (),
3165 rvalue->get_scope ()->get_debug_string (),
3166 stmt_scope->get_debug_string (),
3167 m_stmt->get_debug_string ());
3169 else
3171 if (rvalue->dyn_cast_param ())
3172 m_ctxt->add_error
3173 (rvalue->get_loc (),
3174 "%s:"
3175 " param %s (type: %s)"
3176 " was used within function %s"
3177 " (in statement: %s)"
3178 " but is not associated with any function",
3179 m_api_funcname,
3180 rvalue->get_debug_string (),
3181 rvalue->get_type ()->get_debug_string (),
3182 stmt_scope->get_debug_string (),
3183 m_stmt->get_debug_string ());
3187 /* Verify that it's valid to use this rvalue (and all expressions
3188 in the tree below it) within the given statement.
3190 For example, we must reject attempts to use a local from one
3191 function within a different function here, or we'll get
3192 an ICE deep inside toplev::main. */
3194 void
3195 recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
3197 rvalue_usage_validator v (api_funcname,
3198 s->get_context (),
3201 /* Verify that it's OK to use this rvalue within s. */
3202 v.visit (this);
3204 /* Traverse the expression tree below "this", verifying all rvalues
3205 within it. */
3206 visit_children (&v);
3209 /* Set the scope of this rvalue to be the given function. This can only
3210 be done once on a given rvalue. */
3212 void
3213 recording::rvalue::set_scope (function *scope)
3215 gcc_assert (scope);
3216 gcc_assert (NULL == m_scope);
3217 m_scope = scope;
3221 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3222 themselves.
3223 Instances of rvalue don't need an upcast call. */
3225 const char *
3226 recording::rvalue::access_as_rvalue (reproducer &r)
3228 return r.get_identifier (this);
3231 /* Return a debug string for the given rvalue, wrapping it in parentheses
3232 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3233 stronger precedence that this rvalue's precedence.
3235 For example, given:
3237 MULT
3239 PLUS MINUS
3240 / \ / \
3241 A B C D
3243 we want to emit:
3245 (A + B) * (C - D)
3247 since MULT has strong precedence than PLUS and MINUS, whereas for:
3249 PLUS
3251 MULT DIVIDE
3252 / \ / \
3253 A B C D
3255 we can simply emit:
3257 A * B + C / D
3259 since PLUS has weaker precedence than MULT and DIVIDE. */
3261 const char *
3262 recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
3264 enum precedence this_prec = get_precedence ();
3266 /* If this_prec has stronger precedence than outer_prec, we don't
3267 need to wrap this in parens within the outer debug string.
3268 Stronger precedences occur earlier than weaker within the enum,
3269 so this is a less than test. Equal precedences don't need
3270 parentheses. */
3271 if (this_prec <= outer_prec)
3272 return get_debug_string();
3274 /* Otherwise, we need parentheses. */
3276 /* Lazily-build and cache m_parenthesized_string. */
3277 if (!m_parenthesized_string)
3279 const char *debug_string = get_debug_string ();
3280 m_parenthesized_string = string::from_printf (get_context (),
3281 "(%s)",
3282 debug_string);
3284 gcc_assert (m_parenthesized_string);
3285 return m_parenthesized_string->c_str ();
3289 /* The implementation of class gcc::jit::recording::lvalue. */
3291 /* Create a recording::new_access_field_of_lvalue instance and add it to
3292 the lvalue's context's list of mementos.
3294 Implements the post-error-checking part of
3295 gcc_jit_lvalue_access_field. */
3297 recording::lvalue *
3298 recording::lvalue::access_field (recording::location *loc,
3299 field *field)
3301 recording::lvalue *result =
3302 new access_field_of_lvalue (m_ctxt, loc, this, field);
3303 m_ctxt->record (result);
3304 return result;
3307 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3308 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3309 upcast call. */
3311 const char *
3312 recording::lvalue::access_as_rvalue (reproducer &r)
3314 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3315 r.get_identifier (this));
3318 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3319 Instances of lvalue don't need to be upcast. */
3321 const char *
3322 recording::lvalue::access_as_lvalue (reproducer &r)
3324 return r.get_identifier (this);
3327 /* Create a recording::get_address_of_lvalue instance and add it to
3328 the lvalue's context's list of mementos.
3330 Implements the post-error-checking part of
3331 gcc_jit_lvalue_get_address. */
3333 recording::rvalue *
3334 recording::lvalue::get_address (recording::location *loc)
3336 recording::rvalue *result =
3337 new get_address_of_lvalue (m_ctxt, loc, this);
3338 m_ctxt->record (result);
3339 return result;
3342 /* The implementation of class gcc::jit::recording::param. */
3344 /* Implementation of pure virtual hook recording::memento::replay_into
3345 for recording::param. */
3347 void
3348 recording::param::replay_into (replayer *r)
3350 set_playback_obj (r->new_param (playback_location (r, m_loc),
3351 m_type->playback_type (),
3352 m_name->c_str ()));
3355 /* Implementation of recording::rvalue::access_as_rvalue for params.
3356 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3357 upcast call. */
3359 const char *
3360 recording::param::access_as_rvalue (reproducer &r)
3362 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3363 r.get_identifier (this));
3366 /* Implementation of recording::lvalue::access_as_lvalue for params.
3367 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3368 upcast call. */
3370 const char *
3371 recording::param::access_as_lvalue (reproducer &r)
3373 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3374 r.get_identifier (this));
3377 /* Implementation of recording::memento::write_reproducer for params. */
3379 void
3380 recording::param::write_reproducer (reproducer &r)
3382 const char *id = r.make_identifier (this, "param");
3383 r.write (" gcc_jit_param *%s =\n"
3384 " gcc_jit_context_new_param (%s,\n"
3385 " %s, /* gcc_jit_location *loc */\n"
3386 " %s, /*gcc_jit_type *type */\n"
3387 " %s); /* const char *name */\n",
3389 r.get_identifier (get_context ()),
3390 r.get_identifier (m_loc),
3391 r.get_identifier_as_type (m_type),
3392 m_name->get_debug_string ());
3395 /* The implementation of class gcc::jit::recording::function. */
3397 /* gcc::jit::recording::function's constructor. */
3399 recording::function::function (context *ctxt,
3400 recording::location *loc,
3401 enum gcc_jit_function_kind kind,
3402 type *return_type,
3403 recording::string *name,
3404 int num_params,
3405 recording::param **params,
3406 int is_variadic,
3407 enum built_in_function builtin_id)
3408 : memento (ctxt),
3409 m_loc (loc),
3410 m_kind (kind),
3411 m_return_type (return_type),
3412 m_name (name),
3413 m_params (),
3414 m_is_variadic (is_variadic),
3415 m_builtin_id (builtin_id),
3416 m_locals (),
3417 m_blocks ()
3419 for (int i = 0; i< num_params; i++)
3421 param *param = params[i];
3422 gcc_assert (param);
3424 /* Associate each param with this function.
3426 Verify that the param doesn't already have a function. */
3427 if (param->get_scope ())
3429 /* We've already rejected attempts to reuse a param between
3430 different functions (within gcc_jit_context_new_function), so
3431 if the param *does* already have a function, it must be being
3432 reused within the params array for this function. We must
3433 produce an error for this reuse (blocking the compile), since
3434 otherwise we'd have an ICE later on. */
3435 gcc_assert (this == param->get_scope ());
3436 ctxt->add_error
3437 (loc,
3438 "gcc_jit_context_new_function:"
3439 " parameter %s (type: %s)"
3440 " is used more than once when creating function %s",
3441 param->get_debug_string (),
3442 param->get_type ()->get_debug_string (),
3443 name->c_str ());
3445 else
3447 /* The normal, non-error case: associate this function with the
3448 param. */
3449 param->set_scope (this);
3452 m_params.safe_push (param);
3456 /* Implementation of pure virtual hook recording::memento::replay_into
3457 for recording::function. */
3459 void
3460 recording::function::replay_into (replayer *r)
3462 /* Convert m_params to a vec of playback param. */
3463 auto_vec <playback::param *> params;
3464 int i;
3465 recording::param *param;
3466 params.create (m_params.length ());
3467 FOR_EACH_VEC_ELT (m_params, i, param)
3468 params.safe_push (param->playback_param ());
3470 set_playback_obj (r->new_function (playback_location (r, m_loc),
3471 m_kind,
3472 m_return_type->playback_type (),
3473 m_name->c_str (),
3474 &params,
3475 m_is_variadic,
3476 m_builtin_id));
3479 /* Create a recording::local instance and add it to
3480 the functions's context's list of mementos, and to the function's
3481 list of locals.
3483 Implements the post-error-checking part of
3484 gcc_jit_function_new_local. */
3486 recording::lvalue *
3487 recording::function::new_local (recording::location *loc,
3488 type *type,
3489 const char *name)
3491 local *result = new local (this, loc, type, new_string (name));
3492 m_ctxt->record (result);
3493 m_locals.safe_push (result);
3494 return result;
3497 /* Create a recording::block instance and add it to
3498 the functions's context's list of mementos, and to the function's
3499 list of blocks.
3501 Implements the post-error-checking part of
3502 gcc_jit_function_new_block. */
3504 recording::block*
3505 recording::function::new_block (const char *name)
3507 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
3509 recording::block *result =
3510 new recording::block (this, m_blocks.length (), new_string (name));
3511 m_ctxt->record (result);
3512 m_blocks.safe_push (result);
3513 return result;
3516 /* Override the default implementation of
3517 recording::memento::write_to_dump by dumping a C-like
3518 representation of the function; either like a prototype
3519 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3520 all other kinds of function. */
3522 void
3523 recording::function::write_to_dump (dump &d)
3525 switch (m_kind)
3527 default: gcc_unreachable ();
3528 case GCC_JIT_FUNCTION_EXPORTED:
3529 case GCC_JIT_FUNCTION_IMPORTED:
3530 d.write ("extern ");
3531 break;
3532 case GCC_JIT_FUNCTION_INTERNAL:
3533 d.write ("static ");
3534 break;
3535 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
3536 d.write ("static inline ");
3537 break;
3539 d.write ("%s\n", m_return_type->get_debug_string ());
3541 if (d.update_locations ())
3542 m_loc = d.make_location ();
3544 d.write ("%s (", get_debug_string ());
3546 int i;
3547 recording::param *param;
3548 FOR_EACH_VEC_ELT (m_params, i, param)
3550 if (i > 0)
3551 d.write (", ");
3552 d.write ("%s %s",
3553 param->get_type ()->get_debug_string (),
3554 param->get_debug_string ());
3556 d.write (")");
3557 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
3559 d.write ("; /* (imported) */\n\n");
3561 else
3563 int i;
3564 local *var = NULL;
3565 block *b;
3566 d.write ("\n{\n");
3568 /* Write locals: */
3569 FOR_EACH_VEC_ELT (m_locals, i, var)
3570 var->write_to_dump (d);
3571 if (m_locals.length ())
3572 d.write ("\n");
3574 /* Write each block: */
3575 FOR_EACH_VEC_ELT (m_blocks, i, b)
3577 if (i > 0)
3578 d.write ("\n");
3579 b->write_to_dump (d);
3582 d.write ("}\n\n");
3586 /* Pre-compilation validation of a function, for those things we can't
3587 check until the context is (supposedly) fully-populated. */
3589 void
3590 recording::function::validate ()
3592 /* Complain about empty functions with non-void return type. */
3593 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
3594 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
3595 if (0 == m_blocks.length ())
3596 m_ctxt->add_error (m_loc,
3597 "function %s returns non-void (type: %s)"
3598 " but has no blocks",
3599 get_debug_string (),
3600 m_return_type->get_debug_string ());
3602 /* Check that all blocks are terminated. */
3603 int num_invalid_blocks = 0;
3605 int i;
3606 block *b;
3608 FOR_EACH_VEC_ELT (m_blocks, i, b)
3609 if (!b->validate ())
3610 num_invalid_blocks++;
3613 /* Check that all blocks are reachable. */
3614 if (!m_ctxt->get_inner_bool_option
3615 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
3616 && m_blocks.length () > 0 && 0 == num_invalid_blocks)
3618 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3619 flag, starting at the initial block. */
3620 auto_vec<block *> worklist (m_blocks.length ());
3621 worklist.safe_push (m_blocks[0]);
3622 while (worklist.length () > 0)
3624 block *b = worklist.pop ();
3625 b->m_is_reachable = true;
3627 /* Add successor blocks that aren't yet marked to the worklist. */
3628 /* We checked that each block has a terminating statement above . */
3629 vec <block *> successors = b->get_successor_blocks ();
3630 int i;
3631 block *succ;
3632 FOR_EACH_VEC_ELT (successors, i, succ)
3633 if (!succ->m_is_reachable)
3634 worklist.safe_push (succ);
3635 successors.release ();
3638 /* Now complain about any blocks that haven't been marked. */
3640 int i;
3641 block *b;
3642 FOR_EACH_VEC_ELT (m_blocks, i, b)
3643 if (!b->m_is_reachable)
3644 m_ctxt->add_error (b->get_loc (),
3645 "unreachable block: %s",
3646 b->get_debug_string ());
3651 /* Implements the post-error-checking part of
3652 gcc_jit_function_dump_to_dot. */
3654 void
3655 recording::function::dump_to_dot (const char *path)
3657 FILE *fp = fopen (path, "w");
3658 if (!fp)
3659 return;
3661 pretty_printer the_pp;
3662 the_pp.buffer->stream = fp;
3664 pretty_printer *pp = &the_pp;
3666 pp_printf (pp,
3667 "digraph %s {\n", get_debug_string ());
3669 /* Blocks: */
3671 int i;
3672 block *b;
3673 FOR_EACH_VEC_ELT (m_blocks, i, b)
3674 b->dump_to_dot (pp);
3677 /* Edges: */
3679 int i;
3680 block *b;
3681 FOR_EACH_VEC_ELT (m_blocks, i, b)
3682 b->dump_edges_to_dot (pp);
3685 pp_printf (pp, "}\n");
3686 pp_flush (pp);
3687 fclose (fp);
3690 /* Implementation of recording::memento::make_debug_string for
3691 functions. */
3693 recording::string *
3694 recording::function::make_debug_string ()
3696 return m_name;
3699 /* A table of enum gcc_jit_function_kind values expressed in string
3700 form. */
3702 static const char * const names_of_function_kinds[] = {
3703 "GCC_JIT_FUNCTION_EXPORTED",
3704 "GCC_JIT_FUNCTION_INTERNAL",
3705 "GCC_JIT_FUNCTION_IMPORTED",
3706 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3709 /* Implementation of recording::memento::write_reproducer for functions. */
3711 void
3712 recording::function::write_reproducer (reproducer &r)
3714 const char *id = r.make_identifier (this, "func");
3716 if (m_builtin_id)
3718 r.write (" gcc_jit_function *%s =\n"
3719 " gcc_jit_context_get_builtin_function (%s,\n"
3720 " %s);\n",
3722 r.get_identifier (get_context ()),
3723 m_name->get_debug_string ());
3724 return;
3726 const char *params_id = r.make_tmp_identifier ("params_for", this);
3727 r.write (" gcc_jit_param *%s[%i] = {\n",
3728 params_id,
3729 m_params.length ());
3730 int i;
3731 param *param;
3732 FOR_EACH_VEC_ELT (m_params, i, param)
3733 r.write (" %s,\n", r.get_identifier (param));
3734 r.write (" };\n");
3735 r.write (" gcc_jit_function *%s =\n"
3736 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3737 " %s, /* gcc_jit_location *loc */\n"
3738 " %s, /* enum gcc_jit_function_kind kind */\n"
3739 " %s, /* gcc_jit_type *return_type */\n"
3740 " %s, /* const char *name */\n"
3741 " %i, /* int num_params */\n"
3742 " %s, /* gcc_jit_param **params */\n"
3743 " %i); /* int is_variadic */\n",
3745 r.get_identifier (get_context ()),
3746 r.get_identifier (m_loc),
3747 names_of_function_kinds[m_kind],
3748 r.get_identifier_as_type (m_return_type),
3749 m_name->get_debug_string (),
3750 m_params.length (),
3751 params_id,
3752 m_is_variadic);
3756 /* The implementation of class gcc::jit::recording::block. */
3758 /* Create a recording::eval instance and add it to
3759 the block's context's list of mementos, and to the block's
3760 list of statements.
3762 Implements the heart of gcc_jit_block_add_eval. */
3764 recording::statement *
3765 recording::block::add_eval (recording::location *loc,
3766 recording::rvalue *rvalue)
3768 statement *result = new eval (this, loc, rvalue);
3769 m_ctxt->record (result);
3770 m_statements.safe_push (result);
3771 return result;
3774 /* Create a recording::assignment instance and add it to
3775 the block's context's list of mementos, and to the block's
3776 list of statements.
3778 Implements the heart of gcc_jit_block_add_assignment. */
3780 recording::statement *
3781 recording::block::add_assignment (recording::location *loc,
3782 recording::lvalue *lvalue,
3783 recording::rvalue *rvalue)
3785 statement *result = new assignment (this, loc, lvalue, rvalue);
3786 m_ctxt->record (result);
3787 m_statements.safe_push (result);
3788 return result;
3791 /* Create a recording::assignment_op instance and add it to
3792 the block's context's list of mementos, and to the block's
3793 list of statements.
3795 Implements the heart of gcc_jit_block_add_assignment_op. */
3797 recording::statement *
3798 recording::block::add_assignment_op (recording::location *loc,
3799 recording::lvalue *lvalue,
3800 enum gcc_jit_binary_op op,
3801 recording::rvalue *rvalue)
3803 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
3804 m_ctxt->record (result);
3805 m_statements.safe_push (result);
3806 return result;
3809 /* Create a recording::comment instance and add it to
3810 the block's context's list of mementos, and to the block's
3811 list of statements.
3813 Implements the heart of gcc_jit_block_add_comment. */
3815 recording::statement *
3816 recording::block::add_comment (recording::location *loc,
3817 const char *text)
3819 statement *result = new comment (this, loc, new_string (text));
3820 m_ctxt->record (result);
3821 m_statements.safe_push (result);
3822 return result;
3825 /* Create a recording::end_with_conditional instance and add it to
3826 the block's context's list of mementos, and to the block's
3827 list of statements.
3829 Implements the heart of gcc_jit_block_end_with_conditional. */
3831 recording::statement *
3832 recording::block::end_with_conditional (recording::location *loc,
3833 recording::rvalue *boolval,
3834 recording::block *on_true,
3835 recording::block *on_false)
3837 statement *result = new conditional (this, loc, boolval, on_true, on_false);
3838 m_ctxt->record (result);
3839 m_statements.safe_push (result);
3840 m_has_been_terminated = true;
3841 return result;
3844 /* Create a recording::end_with_jump instance and add it to
3845 the block's context's list of mementos, and to the block's
3846 list of statements.
3848 Implements the heart of gcc_jit_block_end_with_jump. */
3850 recording::statement *
3851 recording::block::end_with_jump (recording::location *loc,
3852 recording::block *target)
3854 statement *result = new jump (this, loc, target);
3855 m_ctxt->record (result);
3856 m_statements.safe_push (result);
3857 m_has_been_terminated = true;
3858 return result;
3861 /* Create a recording::end_with_return instance and add it to
3862 the block's context's list of mementos, and to the block's
3863 list of statements.
3865 Implements the post-error-checking parts of
3866 gcc_jit_block_end_with_return and
3867 gcc_jit_block_end_with_void_return. */
3869 recording::statement *
3870 recording::block::end_with_return (recording::location *loc,
3871 recording::rvalue *rvalue)
3873 /* This is used by both gcc_jit_function_add_return and
3874 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3875 the former and NULL for the latter. */
3876 statement *result = new return_ (this, loc, rvalue);
3877 m_ctxt->record (result);
3878 m_statements.safe_push (result);
3879 m_has_been_terminated = true;
3880 return result;
3883 /* Create a recording::switch_ instance and add it to
3884 the block's context's list of mementos, and to the block's
3885 list of statements.
3887 Implements the heart of gcc_jit_block_end_with_switch. */
3889 recording::statement *
3890 recording::block::end_with_switch (recording::location *loc,
3891 recording::rvalue *expr,
3892 recording::block *default_block,
3893 int num_cases,
3894 recording::case_ **cases)
3896 statement *result = new switch_ (this, loc,
3897 expr,
3898 default_block,
3899 num_cases,
3900 cases);
3901 m_ctxt->record (result);
3902 m_statements.safe_push (result);
3903 m_has_been_terminated = true;
3904 return result;
3907 /* Override the default implementation of
3908 recording::memento::write_to_dump for blocks by writing
3909 an unindented block name as a label, followed by the indented
3910 statements:
3912 BLOCK_NAME:
3913 STATEMENT_1;
3914 STATEMENT_2;
3916 STATEMENT_N; */
3918 void
3919 recording::block::write_to_dump (dump &d)
3921 d.write ("%s:\n", get_debug_string ());
3923 int i;
3924 statement *s;
3925 FOR_EACH_VEC_ELT (m_statements, i, s)
3926 s->write_to_dump (d);
3929 /* Validate a block by ensuring that it has been terminated. */
3931 bool
3932 recording::block::validate ()
3934 /* Check for termination. */
3935 if (!has_been_terminated ())
3937 statement *stmt = get_last_statement ();
3938 location *loc = stmt ? stmt->get_loc () : NULL;
3939 m_func->get_context ()->add_error (loc,
3940 "unterminated block in %s: %s",
3941 m_func->get_debug_string (),
3942 get_debug_string ());
3943 return false;
3946 return true;
3949 /* Get the source-location of a block by using that of the first
3950 statement within it, if any. */
3952 recording::location *
3953 recording::block::get_loc () const
3955 recording::statement *stmt = get_first_statement ();
3956 if (stmt)
3957 return stmt->get_loc ();
3958 else
3959 return NULL;
3962 /* Get the first statement within a block, if any. */
3964 recording::statement *
3965 recording::block::get_first_statement () const
3967 if (m_statements.length ())
3968 return m_statements[0];
3969 else
3970 return NULL;
3973 /* Get the last statement within a block, if any. */
3975 recording::statement *
3976 recording::block::get_last_statement () const
3978 if (m_statements.length ())
3979 return m_statements[m_statements.length () - 1];
3980 else
3981 return NULL;
3984 /* Assuming that this block has been terminated, get the successor blocks
3985 as a vector. Ownership of the vector transfers to the caller, which
3986 must call its release () method.
3988 Used when validating functions, and when dumping dot representations
3989 of them. */
3991 vec <recording::block *>
3992 recording::block::get_successor_blocks () const
3994 gcc_assert (m_has_been_terminated);
3995 statement *last_statement = get_last_statement ();
3996 gcc_assert (last_statement);
3997 return last_statement->get_successor_blocks ();
4000 /* Implementation of pure virtual hook recording::memento::replay_into
4001 for recording::block. */
4003 void
4004 recording::block::replay_into (replayer *)
4006 set_playback_obj (m_func->playback_function ()
4007 ->new_block (playback_string (m_name)));
4010 /* Implementation of recording::memento::make_debug_string for
4011 blocks. */
4013 recording::string *
4014 recording::block::make_debug_string ()
4016 if (m_name)
4017 return m_name;
4018 else
4019 return string::from_printf (m_ctxt,
4020 "<UNNAMED BLOCK %p>",
4021 (void *)this);
4024 /* Implementation of recording::memento::write_reproducer for blocks. */
4026 void
4027 recording::block::write_reproducer (reproducer &r)
4029 const char *id = r.make_identifier (this, "block");
4030 r.write (" gcc_jit_block *%s =\n"
4031 " gcc_jit_function_new_block (%s, %s);\n",
4033 r.get_identifier (m_func),
4034 m_name ? m_name->get_debug_string () : "NULL");
4037 /* Dump a block in graphviz form into PP, capturing the block name (if
4038 any) and the statements. */
4040 void
4041 recording::block::dump_to_dot (pretty_printer *pp)
4043 pp_printf (pp,
4044 ("\tblock_%d "
4045 "[shape=record,style=filled,fillcolor=white,label=\"{"),
4046 m_index);
4047 pp_write_text_to_stream (pp);
4048 if (m_name)
4050 pp_string (pp, m_name->c_str ());
4051 pp_string (pp, ":");
4052 pp_newline (pp);
4053 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4056 int i;
4057 statement *s;
4058 FOR_EACH_VEC_ELT (m_statements, i, s)
4060 pp_string (pp, s->get_debug_string ());
4061 pp_newline (pp);
4062 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4065 pp_printf (pp,
4066 "}\"];\n\n");
4067 pp_flush (pp);
4070 /* Dump the out-edges of the block in graphviz form into PP. */
4072 void
4073 recording::block::dump_edges_to_dot (pretty_printer *pp)
4075 vec <block *> successors = get_successor_blocks ();
4076 int i;
4077 block *succ;
4078 FOR_EACH_VEC_ELT (successors, i, succ)
4079 pp_printf (pp,
4080 "\tblock_%d:s -> block_%d:n;\n",
4081 m_index, succ->m_index);
4082 successors.release ();
4085 /* The implementation of class gcc::jit::recording::global. */
4087 /* Implementation of pure virtual hook recording::memento::replay_into
4088 for recording::global. */
4090 void
4091 recording::global::replay_into (replayer *r)
4093 set_playback_obj (r->new_global (playback_location (r, m_loc),
4094 m_kind,
4095 m_type->playback_type (),
4096 playback_string (m_name)));
4099 /* Override the default implementation of
4100 recording::memento::write_to_dump for globals.
4101 This will be of the form:
4103 GCC_JIT_GLOBAL_EXPORTED:
4104 "TYPE NAME;"
4105 e.g. "int foo;"
4107 GCC_JIT_GLOBAL_INTERNAL:
4108 "static TYPE NAME;"
4109 e.g. "static int foo;"
4111 GCC_JIT_GLOBAL_IMPORTED:
4112 "extern TYPE NAME;"
4113 e.g. "extern int foo;"
4115 These are written to the top of the dump by
4116 recording::context::dump_to_file. */
4118 void
4119 recording::global::write_to_dump (dump &d)
4121 if (d.update_locations ())
4122 m_loc = d.make_location ();
4124 switch (m_kind)
4126 default:
4127 gcc_unreachable ();
4129 case GCC_JIT_GLOBAL_EXPORTED:
4130 break;
4132 case GCC_JIT_GLOBAL_INTERNAL:
4133 d.write ("static ");
4134 break;
4136 case GCC_JIT_GLOBAL_IMPORTED:
4137 d.write ("extern ");
4138 break;
4140 d.write ("%s %s;\n",
4141 m_type->get_debug_string (),
4142 get_debug_string ());
4145 /* A table of enum gcc_jit_global_kind values expressed in string
4146 form. */
4148 static const char * const global_kind_reproducer_strings[] = {
4149 "GCC_JIT_GLOBAL_EXPORTED",
4150 "GCC_JIT_GLOBAL_INTERNAL",
4151 "GCC_JIT_GLOBAL_IMPORTED"
4154 /* Implementation of recording::memento::write_reproducer for globals. */
4156 void
4157 recording::global::write_reproducer (reproducer &r)
4159 const char *id = r.make_identifier (this, "block");
4160 r.write (" gcc_jit_lvalue *%s =\n"
4161 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4162 " %s, /* gcc_jit_location *loc */\n"
4163 " %s, /* enum gcc_jit_global_kind kind */\n"
4164 " %s, /* gcc_jit_type *type */\n"
4165 " %s); /* const char *name */\n",
4167 r.get_identifier (get_context ()),
4168 r.get_identifier (m_loc),
4169 global_kind_reproducer_strings[m_kind],
4170 r.get_identifier_as_type (get_type ()),
4171 m_name->get_debug_string ());
4174 /* The implementation of the various const-handling classes:
4175 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4177 /* Explicit specialization of the various mementos we're interested in. */
4178 template class recording::memento_of_new_rvalue_from_const <int>;
4179 template class recording::memento_of_new_rvalue_from_const <long>;
4180 template class recording::memento_of_new_rvalue_from_const <double>;
4181 template class recording::memento_of_new_rvalue_from_const <void *>;
4183 /* Implementation of the pure virtual hook recording::memento::replay_into
4184 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4186 template <typename HOST_TYPE>
4187 void
4188 recording::
4189 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
4191 set_playback_obj
4192 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
4193 m_value));
4196 /* The make_debug_string and write_reproducer methods vary between the
4197 various
4198 memento_of_new_rvalue_from_const <HOST_TYPE>
4199 classes, so we explicitly write specializations of them.
4201 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4202 namespaces are written out explicitly, which is why most of this file
4203 doesn't abbreviate things by entering the "recording" namespace.
4205 However, these specializations are required to be in the same namespace
4206 as the template, hence we now have to enter the gcc::jit::recording
4207 namespace. */
4209 namespace recording
4212 /* The make_debug_string specialization for <int>, which renders it as
4213 (TARGET_TYPE)LITERAL
4214 e.g.
4215 "(int)42". */
4217 template <>
4218 string *
4219 memento_of_new_rvalue_from_const <int>::make_debug_string ()
4221 return string::from_printf (m_ctxt,
4222 "(%s)%i",
4223 m_type->get_debug_string (),
4224 m_value);
4227 /* The get_wide_int specialization for <int>. */
4229 template <>
4230 bool
4231 memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const
4233 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4234 return true;
4237 /* The write_reproducer specialization for <int>. */
4239 template <>
4240 void
4241 memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
4243 const char *id = r.make_identifier (this, "rvalue");
4244 r.write (" gcc_jit_rvalue *%s =\n"
4245 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4246 " %s, /* gcc_jit_type *numeric_type */\n"
4247 " %i); /* int value */\n",
4249 r.get_identifier (get_context ()),
4250 r.get_identifier_as_type (m_type),
4251 m_value);
4254 /* The make_debug_string specialization for <long>, rendering it as
4255 (TARGET_TYPE)LITERAL
4256 e.g.
4257 "(long)42". */
4259 template <>
4260 string *
4261 memento_of_new_rvalue_from_const <long>::make_debug_string ()
4263 return string::from_printf (m_ctxt,
4264 "(%s)%li",
4265 m_type->get_debug_string (),
4266 m_value);
4269 /* The get_wide_int specialization for <long>. */
4271 template <>
4272 bool
4273 memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const
4275 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4276 return true;
4279 /* The write_reproducer specialization for <long>. */
4281 template <>
4282 void
4283 recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
4285 const char *id = r.make_identifier (this, "rvalue");
4287 /* We have to special-case LONG_MIN, since e.g.
4288 -9223372036854775808L
4289 is parsed as
4290 -(9223372036854775808L)
4291 and hence we'd get:
4292 error: integer constant is so large that it is unsigned [-Werror]
4293 Workaround this by writing (LONG_MIN + 1) - 1. */
4294 if (m_value == LONG_MIN)
4296 r.write (" gcc_jit_rvalue *%s =\n"
4297 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4298 " %s, /* gcc_jit_type *numeric_type */\n"
4299 " %ldL - 1); /* long value */\n",
4301 r.get_identifier (get_context ()),
4302 r.get_identifier_as_type (m_type),
4303 m_value + 1);;
4304 return;
4307 r.write (" gcc_jit_rvalue *%s =\n"
4308 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4309 " %s, /* gcc_jit_type *numeric_type */\n"
4310 " %ldL); /* long value */\n",
4312 r.get_identifier (get_context ()),
4313 r.get_identifier_as_type (m_type),
4314 m_value);
4317 /* The make_debug_string specialization for <double>, rendering it as
4318 (TARGET_TYPE)LITERAL
4319 e.g.
4320 "(float)42.0". */
4322 template <>
4323 string *
4324 memento_of_new_rvalue_from_const <double>::make_debug_string ()
4326 return string::from_printf (m_ctxt,
4327 "(%s)%f",
4328 m_type->get_debug_string (),
4329 m_value);
4332 /* The get_wide_int specialization for <double>. */
4334 template <>
4335 bool
4336 memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
4338 return false;
4341 /* The write_reproducer specialization for <double>. */
4343 template <>
4344 void
4345 recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
4347 const char *id = r.make_identifier (this, "rvalue");
4348 r.write (" gcc_jit_rvalue *%s =\n"
4349 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4350 " %s, /* gcc_jit_type *numeric_type */\n"
4351 " %f); /* double value */\n",
4353 r.get_identifier (get_context ()),
4354 r.get_identifier_as_type (m_type),
4355 m_value);
4358 /* The make_debug_string specialization for <void *>, rendering it as
4359 (TARGET_TYPE)HEX
4360 e.g.
4361 "(int *)0xdeadbeef"
4363 Zero is rendered as NULL e.g.
4364 "(int *)NULL". */
4366 template <>
4367 string *
4368 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
4370 if (m_value != NULL)
4371 return string::from_printf (m_ctxt,
4372 "(%s)%p",
4373 m_type->get_debug_string (), m_value);
4374 else
4375 return string::from_printf (m_ctxt,
4376 "(%s)NULL",
4377 m_type->get_debug_string ());
4380 /* The get_wide_int specialization for <void *>. */
4382 template <>
4383 bool
4384 memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const
4386 return false;
4389 /* Implementation of recording::memento::write_reproducer for <void *>
4390 values. */
4392 template <>
4393 void
4394 memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
4396 const char *id = r.make_identifier (this, "rvalue");
4397 if (m_value)
4398 r.write (" gcc_jit_rvalue *%s =\n"
4399 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4400 " %s, /* gcc_jit_type *pointer_type */\n"
4401 " (void *)%p); /* void *value */\n",
4403 r.get_identifier (get_context ()),
4404 r.get_identifier_as_type (m_type),
4405 m_value);
4406 else
4407 r.write (" gcc_jit_rvalue *%s =\n"
4408 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4409 " %s); /* gcc_jit_type *pointer_type */\n",
4411 r.get_identifier (get_context ()),
4412 r.get_identifier_as_type (m_type));
4415 /* We're done specializing make_debug_string and write_reproducer, so we
4416 can exit the gcc::jit::recording namespace. */
4418 } // namespace recording
4420 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4422 /* Implementation of pure virtual hook recording::memento::replay_into
4423 for recording::memento_of_new_string_literal. */
4425 void
4426 recording::memento_of_new_string_literal::replay_into (replayer *r)
4428 set_playback_obj (r->new_string_literal (m_value->c_str ()));
4431 /* Implementation of recording::memento::make_debug_string for
4432 string literals. */
4434 recording::string *
4435 recording::memento_of_new_string_literal::make_debug_string ()
4437 return string::from_printf (m_ctxt,
4438 "%s",
4439 m_value->get_debug_string ());
4442 /* Implementation of recording::memento::write_reproducer for string literal
4443 values. */
4445 void
4446 recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
4448 const char *id = r.make_identifier (this, "rvalue");
4449 r.write (" gcc_jit_rvalue *%s =\n"
4450 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4451 " %s); /* const char *value */\n",
4453 r.get_identifier (get_context ()),
4454 m_value->get_debug_string ());
4457 /* The implementation of class gcc::jit::recording::unary_op. */
4459 /* Implementation of pure virtual hook recording::memento::replay_into
4460 for recording::unary_op. */
4462 void
4463 recording::unary_op::replay_into (replayer *r)
4465 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
4466 m_op,
4467 get_type ()->playback_type (),
4468 m_a->playback_rvalue ()));
4471 /* Implementation of pure virtual hook recording::rvalue::visit_children
4472 for recording::unary_op. */
4473 void
4474 recording::unary_op::visit_children (rvalue_visitor *v)
4476 v->visit (m_a);
4479 /* Implementation of recording::memento::make_debug_string for
4480 unary ops. */
4482 static const char * const unary_op_strings[] = {
4483 "-", /* GCC_JIT_UNARY_OP_MINUS */
4484 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4485 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4486 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4489 recording::string *
4490 recording::unary_op::make_debug_string ()
4492 return string::from_printf (m_ctxt,
4493 "%s(%s)",
4494 unary_op_strings[m_op],
4495 m_a->get_debug_string ());
4498 static const char * const unary_op_reproducer_strings[] = {
4499 "GCC_JIT_UNARY_OP_MINUS",
4500 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4501 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4502 "GCC_JIT_UNARY_OP_ABS"
4505 /* Implementation of recording::memento::write_reproducer for unary ops. */
4507 void
4508 recording::unary_op::write_reproducer (reproducer &r)
4510 const char *id = r.make_identifier (this, "rvalue");
4511 r.write (" gcc_jit_rvalue *%s =\n"
4512 " gcc_jit_context_new_unary_op (%s,\n"
4513 " %s, /* gcc_jit_location *loc */\n"
4514 " %s, /* enum gcc_jit_unary_op op */\n"
4515 " %s, /* gcc_jit_type *result_type */\n"
4516 " %s); /* gcc_jit_rvalue *a */\n",
4518 r.get_identifier (get_context ()),
4519 r.get_identifier (m_loc),
4520 unary_op_reproducer_strings[m_op],
4521 r.get_identifier_as_type (get_type ()),
4522 r.get_identifier_as_rvalue (m_a));
4525 /* The implementation of class gcc::jit::recording::binary_op. */
4527 /* Implementation of pure virtual hook recording::memento::replay_into
4528 for recording::binary_op. */
4530 void
4531 recording::binary_op::replay_into (replayer *r)
4533 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
4534 m_op,
4535 get_type ()->playback_type (),
4536 m_a->playback_rvalue (),
4537 m_b->playback_rvalue ()));
4540 /* Implementation of pure virtual hook recording::rvalue::visit_children
4541 for recording::binary_op. */
4542 void
4543 recording::binary_op::visit_children (rvalue_visitor *v)
4545 v->visit (m_a);
4546 v->visit (m_b);
4549 /* Implementation of recording::memento::make_debug_string for
4550 binary ops. */
4552 static const char * const binary_op_strings[] = {
4553 "+", /* GCC_JIT_BINARY_OP_PLUS */
4554 "-", /* GCC_JIT_BINARY_OP_MINUS */
4555 "*", /* GCC_JIT_BINARY_OP_MULT */
4556 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4557 "%", /* GCC_JIT_BINARY_OP_MODULO */
4558 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4559 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4560 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4561 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4562 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4563 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4564 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4567 recording::string *
4568 recording::binary_op::make_debug_string ()
4570 enum precedence prec = get_precedence ();
4571 return string::from_printf (m_ctxt,
4572 "%s %s %s",
4573 m_a->get_debug_string_parens (prec),
4574 binary_op_strings[m_op],
4575 m_b->get_debug_string_parens (prec));
4578 static const char * const binary_op_reproducer_strings[] = {
4579 "GCC_JIT_BINARY_OP_PLUS",
4580 "GCC_JIT_BINARY_OP_MINUS",
4581 "GCC_JIT_BINARY_OP_MULT",
4582 "GCC_JIT_BINARY_OP_DIVIDE",
4583 "GCC_JIT_BINARY_OP_MODULO",
4584 "GCC_JIT_BINARY_OP_BITWISE_AND",
4585 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4586 "GCC_JIT_BINARY_OP_BITWISE_OR",
4587 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4588 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4589 "GCC_JIT_BINARY_OP_LSHIFT",
4590 "GCC_JIT_BINARY_OP_RSHIFT"
4593 /* Implementation of recording::memento::write_reproducer for binary ops. */
4595 void
4596 recording::binary_op::write_reproducer (reproducer &r)
4598 const char *id = r.make_identifier (this, "rvalue");
4599 r.write (" gcc_jit_rvalue *%s =\n"
4600 " gcc_jit_context_new_binary_op (%s,\n"
4601 " %s, /* gcc_jit_location *loc */\n"
4602 " %s, /* enum gcc_jit_binary_op op */\n"
4603 " %s, /* gcc_jit_type *result_type */\n"
4604 " %s, /* gcc_jit_rvalue *a */\n"
4605 " %s); /* gcc_jit_rvalue *b */\n",
4607 r.get_identifier (get_context ()),
4608 r.get_identifier (m_loc),
4609 binary_op_reproducer_strings[m_op],
4610 r.get_identifier_as_type (get_type ()),
4611 r.get_identifier_as_rvalue (m_a),
4612 r.get_identifier_as_rvalue (m_b));
4615 namespace recording {
4616 static const enum precedence binary_op_precedence[] = {
4617 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
4618 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
4620 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
4621 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
4622 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
4624 PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4625 PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4626 PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4627 PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4628 PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4629 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
4630 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
4632 } /* namespace recording */
4634 enum recording::precedence
4635 recording::binary_op::get_precedence () const
4637 return binary_op_precedence[m_op];
4640 /* The implementation of class gcc::jit::recording::comparison. */
4642 /* Implementation of recording::memento::make_debug_string for
4643 comparisons. */
4645 static const char * const comparison_strings[] =
4647 "==", /* GCC_JIT_COMPARISON_EQ */
4648 "!=", /* GCC_JIT_COMPARISON_NE */
4649 "<", /* GCC_JIT_COMPARISON_LT */
4650 "<=", /* GCC_JIT_COMPARISON_LE */
4651 ">", /* GCC_JIT_COMPARISON_GT */
4652 ">=", /* GCC_JIT_COMPARISON_GE */
4655 recording::string *
4656 recording::comparison::make_debug_string ()
4658 enum precedence prec = get_precedence ();
4659 return string::from_printf (m_ctxt,
4660 "%s %s %s",
4661 m_a->get_debug_string_parens (prec),
4662 comparison_strings[m_op],
4663 m_b->get_debug_string_parens (prec));
4666 /* A table of enum gcc_jit_comparison values expressed in string
4667 form. */
4669 static const char * const comparison_reproducer_strings[] =
4671 "GCC_JIT_COMPARISON_EQ",
4672 "GCC_JIT_COMPARISON_NE",
4673 "GCC_JIT_COMPARISON_LT",
4674 "GCC_JIT_COMPARISON_LE",
4675 "GCC_JIT_COMPARISON_GT",
4676 "GCC_JIT_COMPARISON_GE"
4679 /* Implementation of recording::memento::write_reproducer for comparisons. */
4681 void
4682 recording::comparison::write_reproducer (reproducer &r)
4684 const char *id = r.make_identifier (this, "rvalue");
4685 r.write (" gcc_jit_rvalue *%s =\n"
4686 " gcc_jit_context_new_comparison (%s,\n"
4687 " %s, /* gcc_jit_location *loc */\n"
4688 " %s, /* enum gcc_jit_comparison op */\n"
4689 " %s, /* gcc_jit_rvalue *a */\n"
4690 " %s); /* gcc_jit_rvalue *b */\n",
4692 r.get_identifier (get_context ()),
4693 r.get_identifier (m_loc),
4694 comparison_reproducer_strings[m_op],
4695 r.get_identifier_as_rvalue (m_a),
4696 r.get_identifier_as_rvalue (m_b));
4699 /* Implementation of pure virtual hook recording::memento::replay_into
4700 for recording::comparison. */
4702 void
4703 recording::comparison::replay_into (replayer *r)
4705 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
4706 m_op,
4707 m_a->playback_rvalue (),
4708 m_b->playback_rvalue ()));
4711 /* Implementation of pure virtual hook recording::rvalue::visit_children
4712 for recording::comparison. */
4714 void
4715 recording::comparison::visit_children (rvalue_visitor *v)
4717 v->visit (m_a);
4718 v->visit (m_b);
4721 namespace recording {
4722 static const enum precedence comparison_precedence[] =
4724 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
4725 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
4727 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LT */
4728 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
4729 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GT */
4730 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
4732 } /* namespace recording */
4734 enum recording::precedence
4735 recording::comparison::get_precedence () const
4737 return comparison_precedence[m_op];
4740 /* Implementation of pure virtual hook recording::memento::replay_into
4741 for recording::cast. */
4743 void
4744 recording::cast::replay_into (replayer *r)
4746 set_playback_obj (r->new_cast (playback_location (r, m_loc),
4747 m_rvalue->playback_rvalue (),
4748 get_type ()->playback_type ()));
4751 /* Implementation of pure virtual hook recording::rvalue::visit_children
4752 for recording::cast. */
4753 void
4754 recording::cast::visit_children (rvalue_visitor *v)
4756 v->visit (m_rvalue);
4759 /* Implementation of recording::memento::make_debug_string for
4760 casts. */
4762 recording::string *
4763 recording::cast::make_debug_string ()
4765 enum precedence prec = get_precedence ();
4766 return string::from_printf (m_ctxt,
4767 "(%s)%s",
4768 get_type ()->get_debug_string (),
4769 m_rvalue->get_debug_string_parens (prec));
4772 /* Implementation of recording::memento::write_reproducer for casts. */
4774 void
4775 recording::cast::write_reproducer (reproducer &r)
4777 const char *id = r.make_identifier (this, "rvalue");
4778 r.write (" gcc_jit_rvalue *%s =\n"
4779 " gcc_jit_context_new_cast (%s,\n"
4780 " %s, /* gcc_jit_location *loc */\n"
4781 " %s, /* gcc_jit_rvalue *rvalue */\n"
4782 " %s); /* gcc_jit_type *type */\n",
4784 r.get_identifier (get_context ()),
4785 r.get_identifier (m_loc),
4786 r.get_identifier_as_rvalue (m_rvalue),
4787 r.get_identifier_as_type (get_type ()));
4790 /* The implementation of class gcc::jit::recording::base_call. */
4792 /* The constructor for gcc::jit::recording::base_call. */
4794 recording::base_call::base_call (context *ctxt,
4795 location *loc,
4796 type *type_,
4797 int numargs,
4798 rvalue **args)
4799 : rvalue (ctxt, loc, type_),
4800 m_args (),
4801 m_require_tail_call (0)
4803 for (int i = 0; i< numargs; i++)
4804 m_args.safe_push (args[i]);
4807 /* Subroutine for use by call and call_though_ptr's write_reproducer
4808 methods. */
4810 void
4811 recording::base_call::write_reproducer_tail_call (reproducer &r,
4812 const char *id)
4814 if (m_require_tail_call)
4816 r.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
4817 " %i); /* int require_tail_call*/\n",
4823 /* The implementation of class gcc::jit::recording::call. */
4825 /* The constructor for gcc::jit::recording::call. */
4827 recording::call::call (recording::context *ctxt,
4828 recording::location *loc,
4829 recording::function *func,
4830 int numargs,
4831 rvalue **args)
4832 : base_call (ctxt, loc, func->get_return_type (), numargs, args),
4833 m_func (func)
4837 /* Implementation of pure virtual hook recording::memento::replay_into
4838 for recording::call. */
4840 void
4841 recording::call::replay_into (replayer *r)
4843 auto_vec<playback::rvalue *> playback_args;
4844 playback_args.create (m_args.length ());
4845 for (unsigned i = 0; i< m_args.length (); i++)
4846 playback_args.safe_push (m_args[i]->playback_rvalue ());
4848 set_playback_obj (r->new_call (playback_location (r, m_loc),
4849 m_func->playback_function (),
4850 &playback_args,
4851 m_require_tail_call));
4854 /* Implementation of pure virtual hook recording::rvalue::visit_children
4855 for recording::call. */
4857 void
4858 recording::call::visit_children (rvalue_visitor *v)
4860 for (unsigned i = 0; i< m_args.length (); i++)
4861 v->visit (m_args[i]);
4864 /* Implementation of recording::memento::make_debug_string for
4865 function calls. */
4867 recording::string *
4868 recording::call::make_debug_string ()
4870 enum precedence prec = get_precedence ();
4871 /* First, build a buffer for the arguments. */
4872 /* Calculate length of said buffer. */
4873 size_t sz = 1; /* nil terminator */
4874 for (unsigned i = 0; i< m_args.length (); i++)
4876 sz += strlen (m_args[i]->get_debug_string_parens (prec));
4877 sz += 2; /* ", " separator */
4880 /* Now allocate and populate the buffer. */
4881 char *argbuf = new char[sz];
4882 size_t len = 0;
4884 for (unsigned i = 0; i< m_args.length (); i++)
4886 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4887 len += strlen (m_args[i]->get_debug_string_parens (prec));
4888 if (i + 1 < m_args.length ())
4890 strcpy (argbuf + len, ", ");
4891 len += 2;
4894 argbuf[len] = '\0';
4896 /* ...and use it to get the string for the call as a whole. */
4897 string *result = string::from_printf (m_ctxt,
4898 "%s (%s)",
4899 m_func->get_debug_string (),
4900 argbuf);
4902 delete[] argbuf;
4904 return result;
4907 void
4908 recording::call::write_reproducer (reproducer &r)
4910 const char *id = r.make_identifier (this, "call");
4911 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4912 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4913 args_id,
4914 m_args.length ());
4915 for (unsigned i = 0; i< m_args.length (); i++)
4916 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4917 r.write (" };\n");
4918 r.write (" gcc_jit_rvalue *%s =\n"
4919 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4920 " %s, /* gcc_jit_location *loc */\n"
4921 " %s, /* gcc_jit_function *func */\n"
4922 " %i, /* int numargs */ \n"
4923 " %s); /* gcc_jit_rvalue **args*/\n",
4925 r.get_identifier (get_context ()),
4926 r.get_identifier (m_loc),
4927 r.get_identifier (m_func),
4928 m_args.length (),
4929 args_id);
4930 write_reproducer_tail_call (r, id);
4933 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4935 /* The constructor for recording::call_through_ptr. */
4937 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
4938 recording::location *loc,
4939 recording::rvalue *fn_ptr,
4940 int numargs,
4941 rvalue **args)
4942 : base_call (ctxt, loc,
4943 fn_ptr->get_type ()->dereference ()
4944 ->as_a_function_type ()->get_return_type (),
4945 numargs, args),
4946 m_fn_ptr (fn_ptr)
4950 /* Implementation of pure virtual hook recording::memento::replay_into
4951 for recording::call_through_ptr. */
4953 void
4954 recording::call_through_ptr::replay_into (replayer *r)
4956 auto_vec<playback::rvalue *> playback_args;
4957 playback_args.create (m_args.length ());
4958 for (unsigned i = 0; i< m_args.length (); i++)
4959 playback_args.safe_push (m_args[i]->playback_rvalue ());
4961 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
4962 m_fn_ptr->playback_rvalue (),
4963 &playback_args,
4964 m_require_tail_call));
4967 /* Implementation of pure virtual hook recording::rvalue::visit_children
4968 for recording::call_through_ptr. */
4970 void
4971 recording::call_through_ptr::visit_children (rvalue_visitor *v)
4973 v->visit (m_fn_ptr);
4974 for (unsigned i = 0; i< m_args.length (); i++)
4975 v->visit (m_args[i]);
4978 /* Implementation of recording::memento::make_debug_string for
4979 calls through function ptrs. */
4981 recording::string *
4982 recording::call_through_ptr::make_debug_string ()
4984 enum precedence prec = get_precedence ();
4985 /* First, build a buffer for the arguments. */
4986 /* Calculate length of said buffer. */
4987 size_t sz = 1; /* nil terminator */
4988 for (unsigned i = 0; i< m_args.length (); i++)
4990 sz += strlen (m_args[i]->get_debug_string_parens (prec));
4991 sz += 2; /* ", " separator */
4994 /* Now allocate and populate the buffer. */
4995 char *argbuf = new char[sz];
4996 size_t len = 0;
4998 for (unsigned i = 0; i< m_args.length (); i++)
5000 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
5001 len += strlen (m_args[i]->get_debug_string_parens (prec));
5002 if (i + 1 < m_args.length ())
5004 strcpy (argbuf + len, ", ");
5005 len += 2;
5008 argbuf[len] = '\0';
5010 /* ...and use it to get the string for the call as a whole. */
5011 string *result = string::from_printf (m_ctxt,
5012 "%s (%s)",
5013 m_fn_ptr->get_debug_string_parens (prec),
5014 argbuf);
5016 delete[] argbuf;
5018 return result;
5021 /* Implementation of recording::memento::write_reproducer for
5022 call_through_ptr. */
5024 void
5025 recording::call_through_ptr::write_reproducer (reproducer &r)
5027 const char *id = r.make_identifier (this, "call");
5028 const char *args_id = r.make_tmp_identifier ("args_for_", this);
5029 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
5030 args_id,
5031 m_args.length ());
5032 for (unsigned i = 0; i< m_args.length (); i++)
5033 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
5034 r.write (" };\n");
5035 r.write (" gcc_jit_rvalue *%s =\n"
5036 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
5037 " %s, /* gcc_jit_location *loc */\n"
5038 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
5039 " %i, /* int numargs */ \n"
5040 " %s); /* gcc_jit_rvalue **args*/\n",
5042 r.get_identifier (get_context ()),
5043 r.get_identifier (m_loc),
5044 r.get_identifier_as_rvalue (m_fn_ptr),
5045 m_args.length (),
5046 args_id);
5047 write_reproducer_tail_call (r, id);
5050 /* The implementation of class gcc::jit::recording::array_access. */
5052 /* Implementation of pure virtual hook recording::memento::replay_into
5053 for recording::array_access. */
5055 void
5056 recording::array_access::replay_into (replayer *r)
5058 set_playback_obj (
5059 r->new_array_access (playback_location (r, m_loc),
5060 m_ptr->playback_rvalue (),
5061 m_index->playback_rvalue ()));
5064 /* Implementation of pure virtual hook recording::rvalue::visit_children
5065 for recording::array_access. */
5067 void
5068 recording::array_access::visit_children (rvalue_visitor *v)
5070 v->visit (m_ptr);
5071 v->visit (m_index);
5074 /* Implementation of recording::memento::make_debug_string for
5075 array accesses. */
5077 recording::string *
5078 recording::array_access::make_debug_string ()
5080 enum precedence prec = get_precedence ();
5081 return string::from_printf (m_ctxt,
5082 "%s[%s]",
5083 m_ptr->get_debug_string_parens (prec),
5084 m_index->get_debug_string_parens (prec));
5087 /* Implementation of recording::memento::write_reproducer for
5088 array_access. */
5090 void
5091 recording::array_access::write_reproducer (reproducer &r)
5093 const char *id = r.make_identifier (this, "lvalue");
5094 r.write (" gcc_jit_lvalue *%s = \n"
5095 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
5096 " %s, /*gcc_jit_location *loc */\n"
5097 " %s, /* gcc_jit_rvalue *ptr */\n"
5098 " %s); /* gcc_jit_rvalue *index */\n",
5100 r.get_identifier (get_context ()),
5101 r.get_identifier (m_loc),
5102 r.get_identifier_as_rvalue (m_ptr),
5103 r.get_identifier_as_rvalue (m_index));
5106 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
5108 /* Implementation of pure virtual hook recording::memento::replay_into
5109 for recording::access_field_of_lvalue. */
5111 void
5112 recording::access_field_of_lvalue::replay_into (replayer *r)
5114 set_playback_obj (
5115 m_lvalue->playback_lvalue ()
5116 ->access_field (playback_location (r, m_loc),
5117 m_field->playback_field ()));
5121 /* Implementation of pure virtual hook recording::rvalue::visit_children
5122 for recording::access_field_of_lvalue. */
5124 void
5125 recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
5127 v->visit (m_lvalue);
5130 /* Implementation of recording::memento::make_debug_string for
5131 accessing a field of an lvalue. */
5133 recording::string *
5134 recording::access_field_of_lvalue::make_debug_string ()
5136 enum precedence prec = get_precedence ();
5137 return string::from_printf (m_ctxt,
5138 "%s.%s",
5139 m_lvalue->get_debug_string_parens (prec),
5140 m_field->get_debug_string ());
5143 /* Implementation of recording::memento::write_reproducer for
5144 access_field_of_lvalue. */
5146 void
5147 recording::access_field_of_lvalue::write_reproducer (reproducer &r)
5149 const char *id = r.make_identifier (this, "lvalue");
5150 r.write (" gcc_jit_lvalue *%s = \n"
5151 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5152 " %s, /*gcc_jit_location *loc */\n"
5153 " %s);\n",
5155 r.get_identifier_as_lvalue (m_lvalue),
5156 r.get_identifier (m_loc),
5157 r.get_identifier (m_field));
5160 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
5162 /* Implementation of pure virtual hook recording::memento::replay_into
5163 for recording::access_field_rvalue. */
5165 void
5166 recording::access_field_rvalue::replay_into (replayer *r)
5168 set_playback_obj (
5169 m_rvalue->playback_rvalue ()
5170 ->access_field (playback_location (r, m_loc),
5171 m_field->playback_field ()));
5174 /* Implementation of pure virtual hook recording::rvalue::visit_children
5175 for recording::access_field_rvalue. */
5177 void
5178 recording::access_field_rvalue::visit_children (rvalue_visitor *v)
5180 v->visit (m_rvalue);
5183 /* Implementation of recording::memento::make_debug_string for
5184 accessing a field of an rvalue. */
5186 recording::string *
5187 recording::access_field_rvalue::make_debug_string ()
5189 enum precedence prec = get_precedence ();
5190 return string::from_printf (m_ctxt,
5191 "%s.%s",
5192 m_rvalue->get_debug_string_parens (prec),
5193 m_field->get_debug_string ());
5196 /* Implementation of recording::memento::write_reproducer for
5197 access_field_rvalue. */
5199 void
5200 recording::access_field_rvalue::write_reproducer (reproducer &r)
5202 const char *id = r.make_identifier (this, "rvalue");
5203 r.write (" gcc_jit_rvalue *%s = \n"
5204 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5205 " %s, /*gcc_jit_location *loc */\n"
5206 " %s);\n",
5208 r.get_identifier_as_rvalue (m_rvalue),
5209 r.get_identifier (m_loc),
5210 r.get_identifier (m_field));
5213 /* The implementation of class
5214 gcc::jit::recording::dereference_field_rvalue. */
5216 /* Implementation of pure virtual hook recording::memento::replay_into
5217 for recording::dereference_field_rvalue. */
5219 void
5220 recording::dereference_field_rvalue::replay_into (replayer *r)
5222 set_playback_obj (
5223 m_rvalue->playback_rvalue ()->
5224 dereference_field (playback_location (r, m_loc),
5225 m_field->playback_field ()));
5228 /* Implementation of pure virtual hook recording::rvalue::visit_children
5229 for recording::dereference_field_rvalue. */
5231 void
5232 recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
5234 v->visit (m_rvalue);
5237 /* Implementation of recording::memento::make_debug_string for
5238 dereferencing a field of an rvalue. */
5240 recording::string *
5241 recording::dereference_field_rvalue::make_debug_string ()
5243 enum precedence prec = get_precedence ();
5244 return string::from_printf (m_ctxt,
5245 "%s->%s",
5246 m_rvalue->get_debug_string_parens (prec),
5247 m_field->get_debug_string ());
5250 /* Implementation of recording::memento::write_reproducer for
5251 dereference_field_rvalue. */
5253 void
5254 recording::dereference_field_rvalue::write_reproducer (reproducer &r)
5256 const char *id = r.make_identifier (this, "lvalue");
5257 r.write (" gcc_jit_lvalue *%s=\n"
5258 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5259 " %s, /* gcc_jit_location *loc */\n"
5260 " %s); /* gcc_jit_field *field */\n",
5262 r.get_identifier_as_rvalue (m_rvalue),
5263 r.get_identifier (m_loc),
5264 r.get_identifier (m_field));
5267 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5269 /* Implementation of pure virtual hook recording::memento::replay_into
5270 for recording::dereference_rvalue. */
5272 void
5273 recording::dereference_rvalue::replay_into (replayer *r)
5275 set_playback_obj (
5276 m_rvalue->playback_rvalue ()->
5277 dereference (playback_location (r, m_loc)));
5280 /* Implementation of pure virtual hook recording::rvalue::visit_children
5281 for recording::dereference_rvalue. */
5283 void
5284 recording::dereference_rvalue::visit_children (rvalue_visitor *v)
5286 v->visit (m_rvalue);
5289 /* Implementation of recording::memento::make_debug_string for
5290 dereferencing an rvalue. */
5292 recording::string *
5293 recording::dereference_rvalue::make_debug_string ()
5295 enum precedence prec = get_precedence ();
5296 return string::from_printf (m_ctxt,
5297 "*%s",
5298 m_rvalue->get_debug_string_parens (prec));
5301 /* Implementation of recording::memento::write_reproducer for
5302 dereference_rvalue. */
5304 void
5305 recording::dereference_rvalue::write_reproducer (reproducer &r)
5307 const char *id = r.make_identifier (this, "dereference");
5308 r.write (" gcc_jit_lvalue *%s =\n"
5309 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5310 " %s); /* gcc_jit_location *loc */\n",
5312 r.get_identifier_as_rvalue (m_rvalue),
5313 r.get_identifier (m_loc));
5316 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5318 /* Implementation of pure virtual hook recording::memento::replay_into
5319 for recording::get_address_of_lvalue. */
5321 void
5322 recording::get_address_of_lvalue::replay_into (replayer *r)
5324 set_playback_obj (
5325 m_lvalue->playback_lvalue ()->
5326 get_address (playback_location (r, m_loc)));
5329 /* Implementation of pure virtual hook recording::rvalue::visit_children
5330 for recording::get_address_of_lvalue. */
5332 void
5333 recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
5335 v->visit (m_lvalue);
5338 /* Implementation of recording::memento::make_debug_string for
5339 getting the address of an lvalue. */
5341 recording::string *
5342 recording::get_address_of_lvalue::make_debug_string ()
5344 enum precedence prec = get_precedence ();
5345 return string::from_printf (m_ctxt,
5346 "&%s",
5347 m_lvalue->get_debug_string_parens (prec));
5350 /* Implementation of recording::memento::write_reproducer for
5351 get_address_of_lvalue. */
5353 void
5354 recording::get_address_of_lvalue::write_reproducer (reproducer &r)
5356 const char *id = r.make_identifier (this, "address_of");
5357 r.write (" gcc_jit_rvalue *%s =\n"
5358 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5359 " %s); /* gcc_jit_location *loc */\n",
5361 r.get_identifier_as_lvalue (m_lvalue),
5362 r.get_identifier (m_loc));
5365 /* The implementation of class gcc::jit::recording::local. */
5367 /* Implementation of pure virtual hook recording::memento::replay_into
5368 for recording::local. */
5370 void
5371 recording::local::replay_into (replayer *r)
5373 set_playback_obj (
5374 m_func->playback_function ()
5375 ->new_local (playback_location (r, m_loc),
5376 m_type->playback_type (),
5377 playback_string (m_name)));
5380 /* Override the default implementation of
5381 recording::memento::write_to_dump for locals by writing
5382 TYPE NAME;
5383 for use at the top of the function body as if it were a
5384 declaration. */
5386 void
5387 recording::local::write_to_dump (dump &d)
5389 if (d.update_locations ())
5390 m_loc = d.make_location ();
5391 d.write(" %s %s;\n",
5392 m_type->get_debug_string (),
5393 get_debug_string ());
5396 void
5397 recording::local::write_reproducer (reproducer &r)
5399 const char *id = r.make_identifier (this, "local");
5400 r.write (" gcc_jit_lvalue *%s =\n"
5401 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5402 " %s, /* gcc_jit_location *loc */\n"
5403 " %s, /* gcc_jit_type *type */\n"
5404 " %s); /* const char *name */\n",
5406 r.get_identifier (m_func),
5407 r.get_identifier (m_loc),
5408 r.get_identifier_as_type (m_type),
5409 m_name->get_debug_string ());
5412 /* The implementation of class gcc::jit::recording::statement. */
5414 /* We poison the default implementation of
5415 gcc::jit::recording::statement::get_successor_blocks
5416 since this vfunc must only ever be called on terminator
5417 statements. */
5419 vec <recording::block *>
5420 recording::statement::get_successor_blocks () const
5422 /* The base class implementation is for non-terminating statements,
5423 and thus should never be called. */
5424 gcc_unreachable ();
5425 vec <block *> result;
5426 result.create (0);
5427 return result;
5430 /* Extend the default implementation of
5431 recording::memento::write_to_dump for statements by (if requested)
5432 updating the location of the statement to the current location in
5433 the dumpfile. */
5435 void
5436 recording::statement::write_to_dump (dump &d)
5438 memento::write_to_dump (d);
5439 if (d.update_locations ())
5440 m_loc = d.make_location ();
5443 /* The implementation of class gcc::jit::recording::eval. */
5445 /* Implementation of pure virtual hook recording::memento::replay_into
5446 for recording::eval. */
5448 void
5449 recording::eval::replay_into (replayer *r)
5451 playback_block (get_block ())
5452 ->add_eval (playback_location (r),
5453 m_rvalue->playback_rvalue ());
5456 /* Implementation of recording::memento::make_debug_string for
5457 an eval statement. */
5459 recording::string *
5460 recording::eval::make_debug_string ()
5462 return string::from_printf (m_ctxt,
5463 "(void)%s;",
5464 m_rvalue->get_debug_string ());
5467 /* Implementation of recording::memento::write_reproducer for
5468 eval statements. */
5470 void
5471 recording::eval::write_reproducer (reproducer &r)
5473 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5474 " %s, /* gcc_jit_location *loc */\n"
5475 " %s); /* gcc_jit_rvalue *rvalue */\n",
5476 r.get_identifier (get_block ()),
5477 r.get_identifier (get_loc ()),
5478 r.get_identifier_as_rvalue (m_rvalue));
5481 /* The implementation of class gcc::jit::recording::assignment. */
5483 /* Implementation of pure virtual hook recording::memento::replay_into
5484 for recording::assignment. */
5486 void
5487 recording::assignment::replay_into (replayer *r)
5489 playback_block (get_block ())
5490 ->add_assignment (playback_location (r),
5491 m_lvalue->playback_lvalue (),
5492 m_rvalue->playback_rvalue ());
5495 /* Implementation of recording::memento::make_debug_string for
5496 an assignment statement. */
5498 recording::string *
5499 recording::assignment::make_debug_string ()
5501 return string::from_printf (m_ctxt,
5502 "%s = %s;",
5503 m_lvalue->get_debug_string (),
5504 m_rvalue->get_debug_string ());
5507 /* Implementation of recording::memento::write_reproducer for
5508 assignment statements. */
5510 void
5511 recording::assignment::write_reproducer (reproducer &r)
5513 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5514 " %s, /* gcc_jit_location *loc */\n"
5515 " %s, /* gcc_jit_lvalue *lvalue */\n"
5516 " %s); /* gcc_jit_rvalue *rvalue */\n",
5517 r.get_identifier (get_block ()),
5518 r.get_identifier (get_loc ()),
5519 r.get_identifier_as_lvalue (m_lvalue),
5520 r.get_identifier_as_rvalue (m_rvalue));
5523 /* The implementation of class gcc::jit::recording::assignment_op. */
5525 /* Implementation of pure virtual hook recording::memento::replay_into
5526 for recording::assignment_op. */
5528 void
5529 recording::assignment_op::replay_into (replayer *r)
5531 playback::type *result_type =
5532 m_lvalue->playback_lvalue ()->get_type ();
5534 playback::rvalue *binary_op =
5535 r->new_binary_op (playback_location (r),
5536 m_op,
5537 result_type,
5538 m_lvalue->playback_rvalue (),
5539 m_rvalue->playback_rvalue ());
5541 playback_block (get_block ())
5542 ->add_assignment (playback_location (r),
5543 m_lvalue->playback_lvalue (),
5544 binary_op);
5547 /* Implementation of recording::memento::make_debug_string for
5548 an assignment_op statement. */
5550 recording::string *
5551 recording::assignment_op::make_debug_string ()
5553 return string::from_printf (m_ctxt,
5554 "%s %s= %s;",
5555 m_lvalue->get_debug_string (),
5556 binary_op_strings[m_op],
5557 m_rvalue->get_debug_string ());
5560 /* Implementation of recording::memento::write_reproducer for
5561 assignment_op statements. */
5563 void
5564 recording::assignment_op::write_reproducer (reproducer &r)
5566 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5567 " %s, /* gcc_jit_location *loc */\n"
5568 " %s, /* gcc_jit_lvalue *lvalue */\n"
5569 " %s, /* enum gcc_jit_binary_op op */\n"
5570 " %s); /* gcc_jit_rvalue *rvalue */\n",
5571 r.get_identifier (get_block ()),
5572 r.get_identifier (get_loc ()),
5573 r.get_identifier_as_lvalue (m_lvalue),
5574 binary_op_reproducer_strings[m_op],
5575 r.get_identifier_as_rvalue (m_rvalue));
5578 /* The implementation of class gcc::jit::recording::comment. */
5580 /* Implementation of pure virtual hook recording::memento::replay_into
5581 for recording::comment. */
5583 void
5584 recording::comment::replay_into (replayer *r)
5586 playback_block (get_block ())
5587 ->add_comment (playback_location (r),
5588 m_text->c_str ());
5591 /* Implementation of recording::memento::make_debug_string for
5592 a comment "statement". */
5594 recording::string *
5595 recording::comment::make_debug_string ()
5597 return string::from_printf (m_ctxt,
5598 "/* %s */",
5599 m_text->c_str ());
5602 /* Implementation of recording::memento::write_reproducer for
5603 comments. */
5605 void
5606 recording::comment::write_reproducer (reproducer &r)
5608 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5609 " %s, /* gcc_jit_location *loc */\n"
5610 " %s); /* const char *text */\n",
5611 r.get_identifier (get_block ()),
5612 r.get_identifier (get_loc ()),
5613 m_text->get_debug_string ());
5616 /* The implementation of class gcc::jit::recording::conditional. */
5618 /* Implementation of pure virtual hook recording::memento::replay_into
5619 for recording::conditional. */
5621 void
5622 recording::conditional::replay_into (replayer *r)
5624 playback_block (get_block ())
5625 ->add_conditional (playback_location (r),
5626 m_boolval->playback_rvalue (),
5627 playback_block (m_on_true),
5628 playback_block (m_on_false));
5631 /* Override the poisoned default implementation of
5632 gcc::jit::recording::statement::get_successor_blocks
5634 A conditional jump has 2 successor blocks. */
5636 vec <recording::block *>
5637 recording::conditional::get_successor_blocks () const
5639 vec <block *> result;
5640 result.create (2);
5641 result.quick_push (m_on_true);
5642 result.quick_push (m_on_false);
5643 return result;
5646 /* Implementation of recording::memento::make_debug_string for
5647 a conditional jump statement. */
5649 recording::string *
5650 recording::conditional::make_debug_string ()
5652 if (m_on_false)
5653 return string::from_printf (m_ctxt,
5654 "if (%s) goto %s; else goto %s;",
5655 m_boolval->get_debug_string (),
5656 m_on_true->get_debug_string (),
5657 m_on_false->get_debug_string ());
5658 else
5659 return string::from_printf (m_ctxt,
5660 "if (%s) goto %s;",
5661 m_boolval->get_debug_string (),
5662 m_on_true->get_debug_string ());
5665 /* Implementation of recording::memento::write_reproducer for
5666 conditional statements. */
5668 void
5669 recording::conditional::write_reproducer (reproducer &r)
5671 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5672 " %s, /* gcc_jit_location *loc */\n"
5673 " %s, /* gcc_jit_rvalue *boolval */\n"
5674 " %s, /* gcc_jit_block *on_true */\n"
5675 " %s); /* gcc_jit_block *on_false */\n",
5676 r.get_identifier (get_block ()),
5677 r.get_identifier (get_loc ()),
5678 r.get_identifier_as_rvalue (m_boolval),
5679 r.get_identifier (m_on_true),
5680 r.get_identifier (m_on_false));
5683 /* The implementation of class gcc::jit::recording::jump. */
5685 /* Implementation of pure virtual hook recording::memento::replay_into
5686 for recording::jump. */
5688 void
5689 recording::jump::replay_into (replayer *r)
5691 playback_block (get_block ())
5692 ->add_jump (playback_location (r),
5693 m_target->playback_block ());
5696 /* Override the poisoned default implementation of
5697 gcc::jit::recording::statement::get_successor_blocks
5699 An unconditional jump has 1 successor block. */
5701 vec <recording::block *>
5702 recording::jump::get_successor_blocks () const
5704 vec <block *> result;
5705 result.create (1);
5706 result.quick_push (m_target);
5707 return result;
5710 /* Implementation of recording::memento::make_debug_string for
5711 a unconditional jump statement. */
5713 recording::string *
5714 recording::jump::make_debug_string ()
5716 return string::from_printf (m_ctxt,
5717 "goto %s;",
5718 m_target->get_debug_string ());
5721 /* Implementation of recording::memento::write_reproducer for
5722 jump statements. */
5724 void
5725 recording::jump::write_reproducer (reproducer &r)
5727 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5728 " %s, /* gcc_jit_location *loc */\n"
5729 " %s); /* gcc_jit_block *target */\n",
5730 r.get_identifier (get_block ()),
5731 r.get_identifier (get_loc ()),
5732 r.get_identifier (m_target));
5735 /* The implementation of class gcc::jit::recording::return_. */
5737 /* Implementation of pure virtual hook recording::memento::replay_into
5738 for recording::return_. */
5740 void
5741 recording::return_::replay_into (replayer *r)
5743 playback_block (get_block ())
5744 ->add_return (playback_location (r),
5745 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
5748 /* Override the poisoned default implementation of
5749 gcc::jit::recording::statement::get_successor_blocks
5751 A return statement has no successor block. */
5753 vec <recording::block *>
5754 recording::return_::get_successor_blocks () const
5756 vec <block *> result;
5757 result.create (0);
5758 return result;
5761 /* Implementation of recording::memento::make_debug_string for
5762 a return statement (covers both those with and without rvalues). */
5764 recording::string *
5765 recording::return_::make_debug_string ()
5767 if (m_rvalue)
5768 return string::from_printf (m_ctxt,
5769 "return %s;",
5770 m_rvalue->get_debug_string ());
5771 else
5772 return string::from_printf (m_ctxt,
5773 "return;");
5776 /* Implementation of recording::memento::write_reproducer for
5777 return statements. */
5779 void
5780 recording::return_::write_reproducer (reproducer &r)
5782 if (m_rvalue)
5783 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5784 " %s, /* gcc_jit_location *loc */\n"
5785 " %s); /* gcc_jit_rvalue *rvalue */\n",
5786 r.get_identifier (get_block ()),
5787 r.get_identifier (get_loc ()),
5788 r.get_identifier_as_rvalue (m_rvalue));
5789 else
5790 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5791 " %s); /* gcc_jit_location *loc */\n",
5792 r.get_identifier (get_block ()),
5793 r.get_identifier (get_loc ()));
5796 /* The implementation of class gcc::jit::recording::case_. */
5798 void
5799 recording::case_::write_reproducer (reproducer &r)
5801 const char *id = r.make_identifier (this, "case");
5802 const char *fmt =
5803 " gcc_jit_case *%s = \n"
5804 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
5805 " %s, /* gcc_jit_rvalue *min_value */\n"
5806 " %s, /* gcc_jit_rvalue *max_value */\n"
5807 " %s); /* gcc_jit_block *dest_block */\n";
5808 r.write (fmt,
5810 r.get_identifier (get_context ()),
5811 r.get_identifier_as_rvalue (m_min_value),
5812 r.get_identifier_as_rvalue (m_max_value),
5813 r.get_identifier (m_dest_block));
5816 recording::string *
5817 recording::case_::make_debug_string ()
5819 return string::from_printf (get_context (),
5820 "case %s ... %s: goto %s;",
5821 m_min_value->get_debug_string (),
5822 m_max_value->get_debug_string (),
5823 m_dest_block->get_debug_string ());
5826 /* The implementation of class gcc::jit::recording::switch_. */
5828 /* gcc::jit::recording::switch_'s constructor. */
5830 recording::switch_::switch_ (block *b,
5831 location *loc,
5832 rvalue *expr,
5833 block *default_block,
5834 int num_cases,
5835 case_ **cases)
5836 : statement (b, loc),
5837 m_expr (expr),
5838 m_default_block (default_block)
5840 m_cases.reserve_exact (num_cases);
5841 for (int i = 0; i< num_cases; i++)
5842 m_cases.quick_push (cases[i]);
5845 /* Implementation of pure virtual hook recording::memento::replay_into
5846 for recording::switch_. */
5848 void
5849 recording::switch_::replay_into (replayer *r)
5851 auto_vec <playback::case_> pcases;
5852 int i;
5853 recording::case_ *rcase;
5854 pcases.reserve_exact (m_cases.length ());
5855 FOR_EACH_VEC_ELT (m_cases, i, rcase)
5857 playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (),
5858 rcase->get_max_value ()->playback_rvalue (),
5859 rcase->get_dest_block ()->playback_block ());
5860 pcases.safe_push (pcase);
5862 playback_block (get_block ())
5863 ->add_switch (playback_location (r),
5864 m_expr->playback_rvalue (),
5865 m_default_block->playback_block (),
5866 &pcases);
5869 /* Override the poisoned default implementation of
5870 gcc::jit::recording::statement::get_successor_blocks
5872 A switch statement has (NUM_CASES + 1) successor blocks. */
5874 vec <recording::block *>
5875 recording::switch_::get_successor_blocks () const
5877 vec <block *> result;
5878 result.create (m_cases.length () + 1);
5879 result.quick_push (m_default_block);
5880 int i;
5881 case_ *c;
5882 FOR_EACH_VEC_ELT (m_cases, i, c)
5883 result.quick_push (c->get_dest_block ());
5884 return result;
5887 /* Implementation of recording::memento::make_debug_string for
5888 a switch statement. */
5890 recording::string *
5891 recording::switch_::make_debug_string ()
5893 auto_vec <char> cases_str;
5894 int i;
5895 case_ *c;
5896 FOR_EACH_VEC_ELT (m_cases, i, c)
5898 size_t len = strlen (c->get_debug_string ());
5899 unsigned idx = cases_str.length ();
5900 cases_str.safe_grow (idx + 1 + len);
5901 cases_str[idx] = ' ';
5902 memcpy (&(cases_str[idx + 1]),
5903 c->get_debug_string (),
5904 len);
5906 cases_str.safe_push ('\0');
5908 return string::from_printf (m_ctxt,
5909 "switch (%s) {default: goto %s;%s}",
5910 m_expr->get_debug_string (),
5911 m_default_block->get_debug_string (),
5912 &cases_str[0]);
5915 /* Implementation of recording::memento::write_reproducer for
5916 switch statements. */
5918 void
5919 recording::switch_::write_reproducer (reproducer &r)
5921 r.make_identifier (this, "switch");
5922 int i;
5923 case_ *c;
5924 const char *cases_id =
5925 r.make_tmp_identifier ("cases_for", this);
5926 r.write (" gcc_jit_case *%s[%i] = {\n",
5927 cases_id,
5928 m_cases.length ());
5929 FOR_EACH_VEC_ELT (m_cases, i, c)
5930 r.write (" %s,\n", r.get_identifier (c));
5931 r.write (" };\n");
5932 const char *fmt =
5933 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
5934 " %s, /* gcc_jit_location *loc */\n"
5935 " %s, /* gcc_jit_rvalue *expr */\n"
5936 " %s, /* gcc_jit_block *default_block */\n"
5937 " %i, /* int num_cases */\n"
5938 " %s); /* gcc_jit_case **cases */\n";
5939 r.write (fmt,
5940 r.get_identifier (get_block ()),
5941 r.get_identifier (get_loc ()),
5942 r.get_identifier_as_rvalue (m_expr),
5943 r.get_identifier (m_default_block),
5944 m_cases.length (),
5945 cases_id);
5948 } // namespace gcc::jit
5950 } // namespace gcc