jit: make simpler reproducers
[official-gcc.git] / gcc / jit / jit-recording.c
blob0e7f46e0ccadf07416ff23df6089830c4e367a4a
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 const char * ensure_identifier_is_unique (const char *candidate, void *ptr);
241 private:
242 hash_map<recording::memento *, const char *> m_map_memento_to_identifier;
244 struct hash_traits : public string_hash
246 static void remove (const char *) {}
248 hash_set<const char *, hash_traits> m_set_identifiers;
249 allocator m_allocator;
252 /* gcc::jit::reproducer's constructor. */
254 reproducer::reproducer (recording::context &ctxt,
255 const char *filename) :
256 dump (ctxt, filename, 0),
257 m_map_memento_to_identifier (),
258 m_set_identifiers (),
259 m_allocator ()
263 /* Write out a list of contexts as a set of parameters within a
264 C function declaration. */
266 void
267 reproducer::write_params (const vec <recording::context *> &contexts)
269 unsigned i;
270 recording::context *ctxt;
271 FOR_EACH_VEC_ELT (contexts, i, ctxt)
273 write ("gcc_jit_context *%s",
274 get_identifier (ctxt));
275 if (i < contexts.length () - 1)
276 write (",\n"
277 " ");
281 /* Write out a list of contexts as a set of arguments within a call
282 to a C function. */
284 void
285 reproducer::write_args (const vec <recording::context *> &contexts)
287 unsigned i;
288 recording::context *ctxt;
289 FOR_EACH_VEC_ELT (contexts, i, ctxt)
291 write ("%s",
292 get_identifier (ctxt));
293 if (i < contexts.length () - 1)
294 write (",\n"
295 " ");
299 /* Ensure that STR is a valid C identifier by overwriting
300 any invalid chars in-place with underscores.
302 This doesn't special-case the first character. */
304 static void
305 convert_to_identifier (char *str)
307 for (char *p = str; *p; p++)
308 if (!ISALNUM (*p))
309 *p = '_';
312 /* Given CANDIDATE, a possible C identifier for use in a reproducer,
313 ensure that it is unique within the generated source file by
314 appending PTR to it if necessary. Return the resulting string.
316 The reproducer will eventually clean up the buffer in its dtor. */
318 const char *
319 reproducer::ensure_identifier_is_unique (const char *candidate, void *ptr)
321 if (m_set_identifiers.contains (candidate))
322 candidate = m_allocator.xstrdup_printf ("%s_%p", candidate, ptr);
323 gcc_assert (!m_set_identifiers.contains (candidate));
324 m_set_identifiers.add (candidate);
325 return candidate;
328 /* Generate a C identifier for the given memento, associating the generated
329 buffer with the memento (for future calls to get_identifier et al).
331 The reproducer will eventually clean up the buffer in its dtor. */
332 const char *
333 reproducer::make_identifier (recording::memento *m, const char *prefix)
335 const char *result;
336 if (strlen (m->get_debug_string ()) < 100)
338 char *buf = m_allocator.xstrdup_printf ("%s_%s",
339 prefix,
340 m->get_debug_string ());
341 convert_to_identifier (buf);
342 result = buf;
344 else
345 result = m_allocator.xstrdup_printf ("%s_%p",
346 prefix, (void *) m);
347 result = ensure_identifier_is_unique (result, m);
348 m_map_memento_to_identifier.put (m, result);
349 return result;
352 /* Generate a C identifier for a temporary variable.
353 The reproducer will eventually clean up the buffer in its dtor. */
355 const char *
356 reproducer::make_tmp_identifier (const char *prefix, recording::memento *m)
358 return m_allocator.xstrdup_printf ("%s_%s",
359 prefix, get_identifier (m));
362 /* Generate a C identifier for the given context.
363 The reproducer will eventually clean up the buffer in its dtor. */
365 const char *
366 reproducer::get_identifier (recording::context *ctxt)
368 return m_allocator.xstrdup_printf ("ctxt_%p",
369 (void *)ctxt);
372 /* Locate the C identifier for the given memento, which is assumed to
373 have already been created via make_identifier. */
375 const char *
376 reproducer::get_identifier (recording::memento *m)
378 if (!m)
379 return "NULL";
381 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
382 and hence these locations appear in the context's memento list
383 out-of-order: they appear in the context's memento list *after*
384 the memento that refers to them. For this case, it's simplest to
385 pretend that they're NULL when writing out the code to recreate the
386 memento that uses them. */
387 if (recording::location *loc = m->dyn_cast_location ())
388 if (!loc->created_by_user ())
389 return "NULL";
391 const char **slot = m_map_memento_to_identifier.get (m);
392 if (!slot)
394 get_context ().add_error (NULL,
395 "unable to find identifier for %p: %s",
396 (void *)m,
397 m->get_debug_string ());
398 gcc_unreachable ();
400 return *slot;
403 /* Locate the C identifier for the given rvalue, wrapping it within
404 a gcc_*_as_rvalue upcast if necessary. */
406 const char *
407 reproducer::get_identifier_as_rvalue (recording::rvalue *m)
409 return m->access_as_rvalue (*this);
412 /* Locate the C identifier for the given lvalue, wrapping it within
413 a gcc_*_as_lvalue upcast if necessary. */
415 const char *
416 reproducer::get_identifier_as_lvalue (recording::lvalue *m)
418 return m->access_as_lvalue (*this);
421 /* Locate the C identifier for the given type, wrapping it within
422 a gcc_*_as_type upcast if necessary. */
424 const char *
425 reproducer::get_identifier_as_type (recording::type *m)
427 return m->access_as_type (*this);
430 /* Formatted printing, allocating to a buffer (or exiting the process if
431 the allocation fails).
433 The buffer exists until the allocator is cleaned up, and is freed at
434 that point, so the caller doesn't need to track the result.
436 Note that we can't use ggc_printf since we're not within the compiler
437 proper (when within gcc_jit_context_dump_reproducer_to_file). */
439 char *
440 reproducer::xstrdup_printf (const char *fmt, ...)
442 char *result;
443 va_list ap;
444 va_start (ap, fmt);
445 result = m_allocator.xstrdup_printf_va (fmt, ap);
446 va_end (ap);
447 return result;
450 /**********************************************************************
451 Recording.
452 **********************************************************************/
454 /* Get the playback::location for the given recording::location,
455 handling a NULL input with a NULL output. */
457 playback::location *
458 recording::playback_location (replayer *r, recording::location *loc)
460 if (loc)
461 return loc->playback_location (r);
462 else
463 return NULL;
466 /* Get a const char * for the given recording::string
467 handling a NULL input with a NULL output. */
469 const char *
470 recording::playback_string (recording::string *str)
472 if (str)
473 return str->c_str ();
474 else
475 return NULL;
478 /* Get the playback::block for the given recording::block,
479 handling a NULL input with a NULL output. */
481 playback::block *
482 recording::playback_block (recording::block *b)
484 if (b)
485 return b->playback_block ();
486 else
487 return NULL;
490 /* Methods of cc::jit::recording::context. */
492 /* The constructor for gcc::jit::recording::context, used by
493 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
495 recording::context::context (context *parent_ctxt)
496 : log_user (NULL),
497 m_parent_ctxt (parent_ctxt),
498 m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this),
499 m_timer (NULL),
500 m_error_count (0),
501 m_first_error_str (NULL),
502 m_owns_first_error_str (false),
503 m_last_error_str (NULL),
504 m_owns_last_error_str (false),
505 m_mementos (),
506 m_compound_types (),
507 m_globals (),
508 m_functions (),
509 m_FILE_type (NULL),
510 m_builtins_manager(NULL)
512 if (parent_ctxt)
514 /* Inherit options from parent. */
515 for (unsigned i = 0;
516 i < sizeof (m_str_options) / sizeof (m_str_options[0]);
517 i++)
519 const char *parent_opt = parent_ctxt->m_str_options[i];
520 m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
522 memcpy (m_int_options,
523 parent_ctxt->m_int_options,
524 sizeof (m_int_options));
525 memcpy (m_bool_options,
526 parent_ctxt->m_bool_options,
527 sizeof (m_bool_options));
528 memcpy (m_inner_bool_options,
529 parent_ctxt->m_inner_bool_options,
530 sizeof (m_inner_bool_options));
531 set_logger (parent_ctxt->get_logger ());
533 else
535 memset (m_str_options, 0, sizeof (m_str_options));
536 memset (m_int_options, 0, sizeof (m_int_options));
537 memset (m_bool_options, 0, sizeof (m_bool_options));
538 memset (m_inner_bool_options, 0, sizeof (m_inner_bool_options));
541 memset (m_basic_types, 0, sizeof (m_basic_types));
544 /* The destructor for gcc::jit::recording::context, implicitly used by
545 gcc_jit_context_release. */
547 recording::context::~context ()
549 JIT_LOG_SCOPE (get_logger ());
550 int i;
551 memento *m;
552 FOR_EACH_VEC_ELT (m_mementos, i, m)
554 delete m;
557 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
558 free (m_str_options[i]);
560 char *optname;
561 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
562 free (optname);
564 if (m_builtins_manager)
565 delete m_builtins_manager;
567 if (m_owns_first_error_str)
568 free (m_first_error_str);
570 if (m_owns_last_error_str)
571 if (m_last_error_str != m_first_error_str)
572 free (m_last_error_str);
575 /* Add the given mememto to the list of those tracked by this
576 gcc::jit::recording::context, so that e.g. it can be deleted
577 when this context is released. */
579 void
580 recording::context::record (memento *m)
582 gcc_assert (m);
584 m_mementos.safe_push (m);
587 /* Replay this context (and any parents) into the given replayer. */
589 void
590 recording::context::replay_into (replayer *r)
592 JIT_LOG_SCOPE (get_logger ());
593 int i;
594 memento *m;
596 /* If we have a parent context, we must replay it. This will
597 recursively walk backwards up the historical tree, then replay things
598 forwards "in historical order", starting with the ultimate parent
599 context, until we reach the "this" context.
601 Note that we fully replay the parent, then fully replay the child,
602 which means that inter-context references can only exist from child
603 to parent, not the other way around.
605 All of this replaying is suboptimal - it would be better to do the
606 work for the parent context *once*, rather than replaying the parent
607 every time we replay each child. However, fixing this requires deep
608 surgery to lifetime-management: we'd need every context family tree
609 to have its own GC heap, and to initialize the GCC code to use that
610 heap (with a mutex on such a heap). */
611 if (m_parent_ctxt)
612 m_parent_ctxt->replay_into (r);
614 if (r->errors_occurred ())
615 return;
617 /* Replay this context's saved operations into r. */
618 FOR_EACH_VEC_ELT (m_mementos, i, m)
620 /* Disabled low-level debugging, here if we need it: print what
621 we're replaying.
622 Note that the calls to get_debug_string might lead to more
623 mementos being created for the strings.
624 This can also be used to exercise the debug_string
625 machinery. */
626 if (0)
627 printf ("context %p replaying (%p): %s\n",
628 (void *)this, (void *)m, m->get_debug_string ());
630 m->replay_into (r);
632 if (r->errors_occurred ())
633 return;
637 /* During a playback, we associate objects from the recording with
638 their counterparts during this playback.
640 For simplicity, we store this within the recording objects.
642 The following method cleans away these associations, to ensure that
643 we never have out-of-date associations lingering on subsequent
644 playbacks (the objects pointed to are GC-managed, but the
645 recording objects don't own refs to them). */
647 void
648 recording::context::disassociate_from_playback ()
650 JIT_LOG_SCOPE (get_logger ());
651 int i;
652 memento *m;
654 if (m_parent_ctxt)
655 m_parent_ctxt->disassociate_from_playback ();
657 FOR_EACH_VEC_ELT (m_mementos, i, m)
659 m->set_playback_obj (NULL);
663 /* Create a recording::string instance and add it to this context's list
664 of mementos.
666 This creates a fresh copy of the given 0-terminated buffer. */
668 recording::string *
669 recording::context::new_string (const char *text)
671 if (!text)
672 return NULL;
674 recording::string *result = new string (this, text);
675 record (result);
676 return result;
679 /* Create a recording::location instance and add it to this context's
680 list of mementos.
682 Implements the post-error-checking part of
683 gcc_jit_context_new_location. */
685 recording::location *
686 recording::context::new_location (const char *filename,
687 int line,
688 int column,
689 bool created_by_user)
691 recording::location *result =
692 new recording::location (this,
693 new_string (filename),
694 line, column,
695 created_by_user);
696 record (result);
697 return result;
700 /* If we haven't seen this enum value yet, create a recording::type
701 instance and add it to this context's list of mementos.
703 If we have seen it before, reuse our cached value, so that repeated
704 calls on the context give the same object.
706 If we have a parent context, the cache is within the ultimate
707 ancestor context.
709 Implements the post-error-checking part of
710 gcc_jit_context_get_type. */
712 recording::type *
713 recording::context::get_type (enum gcc_jit_types kind)
715 if (!m_basic_types[kind])
717 if (m_parent_ctxt)
718 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
719 else
721 recording::type *result = new memento_of_get_type (this, kind);
722 record (result);
723 m_basic_types[kind] = result;
727 return m_basic_types[kind];
730 /* Get a recording::type instance for the given size and signedness.
731 This is implemented in terms of recording::context::get_type
732 above.
734 Implements the post-error-checking part of
735 gcc_jit_context_get_int_type. */
737 recording::type *
738 recording::context::get_int_type (int num_bytes, int is_signed)
740 /* We can't use a switch here since some of the values are macros affected
741 by options; e.g. i386.h has
742 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
743 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
744 are in bits, rather than bytes.
746 const int num_bits = num_bytes * 8;
747 if (num_bits == INT_TYPE_SIZE)
748 return get_type (is_signed
749 ? GCC_JIT_TYPE_INT
750 : GCC_JIT_TYPE_UNSIGNED_INT);
751 if (num_bits == CHAR_TYPE_SIZE)
752 return get_type (is_signed
753 ? GCC_JIT_TYPE_SIGNED_CHAR
754 : GCC_JIT_TYPE_UNSIGNED_CHAR);
755 if (num_bits == SHORT_TYPE_SIZE)
756 return get_type (is_signed
757 ? GCC_JIT_TYPE_SHORT
758 : GCC_JIT_TYPE_UNSIGNED_SHORT);
759 if (num_bits == LONG_TYPE_SIZE)
760 return get_type (is_signed
761 ? GCC_JIT_TYPE_LONG
762 : GCC_JIT_TYPE_UNSIGNED_LONG);
763 if (num_bits == LONG_LONG_TYPE_SIZE)
764 return get_type (is_signed
765 ? GCC_JIT_TYPE_LONG_LONG
766 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
768 /* Some other size, not corresponding to the C int types. */
769 /* To be written: support arbitrary other sizes, sharing by
770 memoizing at the recording::context level? */
771 gcc_unreachable ();
774 /* Create a recording::type instance and add it to this context's list
775 of mementos.
777 Implements the post-error-checking part of
778 gcc_jit_context_new_array_type. */
780 recording::type *
781 recording::context::new_array_type (recording::location *loc,
782 recording::type *element_type,
783 int num_elements)
785 if (struct_ *s = element_type->dyn_cast_struct ())
786 if (!s->get_fields ())
788 add_error (NULL,
789 "cannot create an array of type %s"
790 " until the fields have been set",
791 s->get_name ()->c_str ());
792 return NULL;
794 recording::type *result =
795 new recording::array_type (this, loc, element_type, num_elements);
796 record (result);
797 return result;
800 /* Create a recording::field instance and add it to this context's list
801 of mementos.
803 Implements the post-error-checking part of
804 gcc_jit_context_new_field. */
806 recording::field *
807 recording::context::new_field (recording::location *loc,
808 recording::type *type,
809 const char *name)
811 recording::field *result =
812 new recording::field (this, loc, type, new_string (name));
813 record (result);
814 return result;
817 /* Create a recording::struct_ instance and add it to this context's
818 list of mementos and list of compound types.
820 Implements the post-error-checking part of
821 gcc_jit_context_new_struct_type. */
823 recording::struct_ *
824 recording::context::new_struct_type (recording::location *loc,
825 const char *name)
827 recording::struct_ *result = new struct_ (this, loc, new_string (name));
828 record (result);
829 m_compound_types.safe_push (result);
830 return result;
833 /* Create a recording::union_ instance and add it to this context's
834 list of mementos and list of compound types.
836 Implements the first post-error-checking part of
837 gcc_jit_context_new_union_type. */
839 recording::union_ *
840 recording::context::new_union_type (recording::location *loc,
841 const char *name)
843 recording::union_ *result = new union_ (this, loc, new_string (name));
844 record (result);
845 m_compound_types.safe_push (result);
846 return result;
849 /* Create a recording::function_type instance and add it to this context's
850 list of mementos.
852 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
854 recording::function_type *
855 recording::context::new_function_type (recording::type *return_type,
856 int num_params,
857 recording::type **param_types,
858 int is_variadic)
860 recording::function_type *fn_type
861 = new function_type (this,
862 return_type,
863 num_params,
864 param_types,
865 is_variadic);
866 record (fn_type);
867 return fn_type;
870 /* Create a recording::type instance and add it to this context's list
871 of mementos.
873 Implements the post-error-checking part of
874 gcc_jit_context_new_function_ptr_type. */
876 recording::type *
877 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
878 recording::type *return_type,
879 int num_params,
880 recording::type **param_types,
881 int is_variadic)
883 recording::function_type *fn_type
884 = new_function_type (return_type,
885 num_params,
886 param_types,
887 is_variadic);
889 /* Return a pointer-type to the function type. */
890 return fn_type->get_pointer ();
893 /* Create a recording::param instance and add it to this context's list
894 of mementos.
896 Implements the post-error-checking part of
897 gcc_jit_context_new_param. */
899 recording::param *
900 recording::context::new_param (recording::location *loc,
901 recording::type *type,
902 const char *name)
904 recording::param *result = new recording::param (this, loc, type, new_string (name));
905 record (result);
906 return result;
909 /* Create a recording::function instance and add it to this context's list
910 of mementos and list of functions.
912 Implements the post-error-checking part of
913 gcc_jit_context_new_function. */
915 recording::function *
916 recording::context::new_function (recording::location *loc,
917 enum gcc_jit_function_kind kind,
918 recording::type *return_type,
919 const char *name,
920 int num_params,
921 recording::param **params,
922 int is_variadic,
923 enum built_in_function builtin_id)
925 recording::function *result =
926 new recording::function (this,
927 loc, kind, return_type,
928 new_string (name),
929 num_params, params, is_variadic,
930 builtin_id);
931 record (result);
932 m_functions.safe_push (result);
934 return result;
937 /* Locate the builtins_manager (if any) for this family of contexts,
938 creating it if it doesn't exist already.
940 All of the recording contexts in a family share one builtins_manager:
941 if we have a child context, follow the parent links to get the
942 ultimate ancestor context, and look for it/store it there. */
944 builtins_manager *
945 recording::context::get_builtins_manager ()
947 if (m_parent_ctxt)
948 return m_parent_ctxt->get_builtins_manager ();
950 if (!m_builtins_manager)
951 m_builtins_manager = new builtins_manager (this);
953 return m_builtins_manager;
956 /* Get a recording::function instance, which is lazily-created and added
957 to the context's lists of mementos.
959 Implements the post-error-checking part of
960 gcc_jit_context_get_builtin_function. */
962 recording::function *
963 recording::context::get_builtin_function (const char *name)
965 builtins_manager *bm = get_builtins_manager ();
966 return bm->get_builtin_function (name);
969 /* Create a recording::global instance and add it to this context's list
970 of mementos.
972 Implements the post-error-checking part of
973 gcc_jit_context_new_global. */
975 recording::lvalue *
976 recording::context::new_global (recording::location *loc,
977 enum gcc_jit_global_kind kind,
978 recording::type *type,
979 const char *name)
981 recording::global *result =
982 new recording::global (this, loc, kind, type, new_string (name));
983 record (result);
984 m_globals.safe_push (result);
986 return result;
989 /* Create a recording::memento_of_new_string_literal instance and add it
990 to this context's list of mementos.
992 Implements the post-error-checking part of
993 gcc_jit_context_new_string_literal. */
995 recording::rvalue *
996 recording::context::new_string_literal (const char *value)
998 recording::rvalue *result =
999 new memento_of_new_string_literal (this, NULL, new_string (value));
1000 record (result);
1001 return result;
1004 /* Create a recording::unary_op instance and add it to this context's
1005 list of mementos.
1007 Implements the post-error-checking part of
1008 gcc_jit_context_new_unary_op. */
1010 recording::rvalue *
1011 recording::context::new_unary_op (recording::location *loc,
1012 enum gcc_jit_unary_op op,
1013 recording::type *result_type,
1014 recording::rvalue *a)
1016 recording::rvalue *result =
1017 new unary_op (this, loc, op, result_type, a);
1018 record (result);
1019 return result;
1022 /* Create a recording::binary_op instance and add it to this context's
1023 list of mementos.
1025 Implements the post-error-checking part of
1026 gcc_jit_context_new_binary_op. */
1028 recording::rvalue *
1029 recording::context::new_binary_op (recording::location *loc,
1030 enum gcc_jit_binary_op op,
1031 recording::type *result_type,
1032 recording::rvalue *a,
1033 recording::rvalue *b)
1035 recording::rvalue *result =
1036 new binary_op (this, loc, op, result_type, a, b);
1037 record (result);
1038 return result;
1041 /* Create a recording::comparison instance and add it to this context's
1042 list of mementos.
1044 Implements the post-error-checking part of
1045 gcc_jit_context_new_comparison. */
1047 recording::rvalue *
1048 recording::context::new_comparison (recording::location *loc,
1049 enum gcc_jit_comparison op,
1050 recording::rvalue *a,
1051 recording::rvalue *b)
1053 recording::rvalue *result = new comparison (this, loc, op, a, b);
1054 record (result);
1055 return result;
1058 /* Create a recording::cast instance and add it to this context's list
1059 of mementos.
1061 Implements the post-error-checking part of
1062 gcc_jit_context_new_cast. */
1064 recording::rvalue *
1065 recording::context::new_cast (recording::location *loc,
1066 recording::rvalue *expr,
1067 recording::type *type_)
1069 recording::rvalue *result = new cast (this, loc, expr, type_);
1070 record (result);
1071 return result;
1074 /* Create a recording::call instance and add it to this context's list
1075 of mementos.
1077 Implements the post-error-checking part of
1078 gcc_jit_context_new_call. */
1080 recording::rvalue *
1081 recording::context::new_call (recording::location *loc,
1082 function *func,
1083 int numargs , recording::rvalue **args)
1085 recording::rvalue *result = new call (this, loc, func, numargs, args);
1086 record (result);
1087 return result;
1090 /* Create a recording::call_through_ptr instance and add it to this
1091 context's list of mementos.
1093 Implements the post-error-checking part of
1094 gcc_jit_context_new_call_through_ptr. */
1096 recording::rvalue *
1097 recording::context::new_call_through_ptr (recording::location *loc,
1098 recording::rvalue *fn_ptr,
1099 int numargs,
1100 recording::rvalue **args)
1102 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
1103 record (result);
1104 return result;
1107 /* Create a recording::array_access instance and add it to this context's list
1108 of mementos.
1110 Implements the post-error-checking part of
1111 gcc_jit_context_new_array_access. */
1113 recording::lvalue *
1114 recording::context::new_array_access (recording::location *loc,
1115 recording::rvalue *ptr,
1116 recording::rvalue *index)
1118 recording::lvalue *result = new array_access (this, loc, ptr, index);
1119 record (result);
1120 return result;
1123 /* Create a recording::case_ instance and add it to this context's list
1124 of mementos.
1126 Implements the post-error-checking part of
1127 gcc_jit_context_new_case. */
1129 recording::case_ *
1130 recording::context::new_case (recording::rvalue *min_value,
1131 recording::rvalue *max_value,
1132 recording::block *block)
1134 recording::case_ *result = new case_ (this, min_value, max_value, block);
1135 record (result);
1136 return result;
1139 /* Set the given string option for this context, or add an error if
1140 it's not recognized.
1142 Implements the post-error-checking part of
1143 gcc_jit_context_set_str_option. */
1145 void
1146 recording::context::set_str_option (enum gcc_jit_str_option opt,
1147 const char *value)
1149 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
1151 add_error (NULL,
1152 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
1153 return;
1155 free (m_str_options[opt]);
1156 m_str_options[opt] = value ? xstrdup (value) : NULL;
1157 log_str_option (opt);
1160 /* Set the given integer option for this context, or add an error if
1161 it's not recognized.
1163 Implements the post-error-checking part of
1164 gcc_jit_context_set_int_option. */
1166 void
1167 recording::context::set_int_option (enum gcc_jit_int_option opt,
1168 int value)
1170 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
1172 add_error (NULL,
1173 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
1174 return;
1176 m_int_options[opt] = value;
1177 log_int_option (opt);
1180 /* Set the given boolean option for this context, or add an error if
1181 it's not recognized.
1183 Implements the post-error-checking part of
1184 gcc_jit_context_set_bool_option. */
1186 void
1187 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
1188 int value)
1190 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
1192 add_error (NULL,
1193 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
1194 return;
1196 m_bool_options[opt] = value ? true : false;
1197 log_bool_option (opt);
1200 void
1201 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt,
1202 int value)
1204 gcc_assert (inner_opt >= 0 && inner_opt < NUM_INNER_BOOL_OPTIONS);
1205 m_inner_bool_options[inner_opt] = value ? true : false;
1206 log_inner_bool_option (inner_opt);
1210 /* Add the given optname to this context's list of extra options.
1212 Implements the post-error-checking part of
1213 gcc_jit_context_add_command_line_option. */
1215 void
1216 recording::context::add_command_line_option (const char *optname)
1218 m_command_line_options.safe_push (xstrdup (optname));
1221 /* Add any user-provided extra options, starting with any from
1222 parent contexts.
1223 Called by playback::context::make_fake_args. */
1225 void
1226 recording::context::append_command_line_options (vec <char *> *argvec)
1228 if (m_parent_ctxt)
1229 m_parent_ctxt->append_command_line_options (argvec);
1231 int i;
1232 char *optname;
1233 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1234 argvec->safe_push (xstrdup (optname));
1237 /* Add the given dumpname/out_ptr pair to this context's list of requested
1238 dumps.
1240 Implements the post-error-checking part of
1241 gcc_jit_context_enable_dump. */
1243 void
1244 recording::context::enable_dump (const char *dumpname,
1245 char **out_ptr)
1247 requested_dump d;
1248 gcc_assert (dumpname);
1249 gcc_assert (out_ptr);
1251 d.m_dumpname = dumpname;
1252 d.m_out_ptr = out_ptr;
1253 *out_ptr = NULL;
1254 m_requested_dumps.safe_push (d);
1257 /* Validate this context, and if it passes, compile it to memory
1258 (within a mutex).
1260 Implements the post-error-checking part of
1261 gcc_jit_context_compile. */
1263 result *
1264 recording::context::compile ()
1266 JIT_LOG_SCOPE (get_logger ());
1268 log_all_options ();
1270 validate ();
1272 if (errors_occurred ())
1273 return NULL;
1275 /* Set up a compile_to_memory playback context. */
1276 ::gcc::jit::playback::compile_to_memory replayer (this);
1278 /* Use it. */
1279 replayer.compile ();
1281 /* Get the jit::result (or NULL) from the
1282 compile_to_memory playback context. */
1283 return replayer.get_result_obj ();
1286 /* Validate this context, and if it passes, compile it to a file
1287 (within a mutex).
1289 Implements the post-error-checking part of
1290 gcc_jit_context_compile_to_file. */
1292 void
1293 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
1294 const char *output_path)
1296 JIT_LOG_SCOPE (get_logger ());
1298 log_all_options ();
1300 validate ();
1302 if (errors_occurred ())
1303 return;
1305 /* Set up a compile_to_file playback context. */
1306 ::gcc::jit::playback::compile_to_file replayer (this,
1307 output_kind,
1308 output_path);
1310 /* Use it. */
1311 replayer.compile ();
1314 /* Format the given error using printf's conventions, print
1315 it to stderr, and add it to the context. */
1317 void
1318 recording::context::add_error (location *loc, const char *fmt, ...)
1320 va_list ap;
1321 va_start (ap, fmt);
1322 add_error_va (loc, fmt, ap);
1323 va_end (ap);
1326 /* Format the given error using printf's conventions, print
1327 it to stderr, and add it to the context. */
1329 void
1330 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
1332 int len;
1333 char *malloced_msg;
1334 const char *errmsg;
1335 bool has_ownership;
1337 JIT_LOG_SCOPE (get_logger ());
1339 len = vasprintf (&malloced_msg, fmt, ap);
1340 if (malloced_msg == NULL || len < 0)
1342 errmsg = "out of memory generating error message";
1343 has_ownership = false;
1345 else
1347 errmsg = malloced_msg;
1348 has_ownership = true;
1350 if (get_logger ())
1351 get_logger ()->log ("error %i: %s", m_error_count, errmsg);
1353 const char *ctxt_progname =
1354 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
1355 if (!ctxt_progname)
1356 ctxt_progname = "libgccjit.so";
1358 if (loc)
1359 fprintf (stderr, "%s: %s: error: %s\n",
1360 ctxt_progname,
1361 loc->get_debug_string (),
1362 errmsg);
1363 else
1364 fprintf (stderr, "%s: error: %s\n",
1365 ctxt_progname,
1366 errmsg);
1368 if (!m_error_count)
1370 m_first_error_str = const_cast <char *> (errmsg);
1371 m_owns_first_error_str = has_ownership;
1374 if (m_owns_last_error_str)
1375 if (m_last_error_str != m_first_error_str)
1376 free (m_last_error_str);
1377 m_last_error_str = const_cast <char *> (errmsg);
1378 m_owns_last_error_str = has_ownership;
1380 m_error_count++;
1383 /* Get the message for the first error that occurred on this context, or
1384 NULL if no errors have occurred on it.
1386 Implements the post-error-checking part of
1387 gcc_jit_context_get_first_error. */
1389 const char *
1390 recording::context::get_first_error () const
1392 return m_first_error_str;
1395 /* Get the message for the last error that occurred on this context, or
1396 NULL if no errors have occurred on it.
1398 Implements the post-error-checking part of
1399 gcc_jit_context_get_last_error. */
1401 const char *
1402 recording::context::get_last_error () const
1404 return m_last_error_str;
1407 /* Lazily generate and record a recording::type representing an opaque
1408 struct named "FILE".
1410 For use if client code tries to dereference the result of
1411 get_type (GCC_JIT_TYPE_FILE_PTR). */
1413 recording::type *
1414 recording::context::get_opaque_FILE_type ()
1416 if (!m_FILE_type)
1417 m_FILE_type = new_struct_type (NULL, "FILE");
1418 return m_FILE_type;
1421 /* Dump a C-like representation of the given context to the given path.
1422 If UPDATE_LOCATIONS is true, update the locations within the
1423 context's mementos to point to the dumpfile.
1425 Implements the post-error-checking part of
1426 gcc_jit_context_dump_to_file. */
1428 void
1429 recording::context::dump_to_file (const char *path, bool update_locations)
1431 int i;
1432 dump d (*this, path, update_locations);
1434 /* Forward declaration of structs and unions. */
1435 compound_type *st;
1436 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1438 d.write ("%s;\n\n", st->get_debug_string ());
1441 /* Content of structs, where set. */
1442 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1443 if (st->get_fields ())
1445 st->get_fields ()->write_to_dump (d);
1446 d.write ("\n");
1449 /* Globals. */
1450 global *g;
1451 FOR_EACH_VEC_ELT (m_globals, i, g)
1453 g->write_to_dump (d);
1455 if (!m_globals.is_empty ())
1456 d.write ("\n");
1458 function *fn;
1459 FOR_EACH_VEC_ELT (m_functions, i, fn)
1461 fn->write_to_dump (d);
1465 static const char * const
1466 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
1467 "GCC_JIT_STR_OPTION_PROGNAME"
1470 static const char * const
1471 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
1472 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1475 static const char * const
1476 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
1477 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1478 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1479 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1480 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1481 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1482 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1483 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1484 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1487 static const char * const
1488 inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = {
1489 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1490 "gcc_jit_context_set_bool_use_external_driver"
1493 /* Write the current value of all options to the log file (if any). */
1495 void
1496 recording::context::log_all_options () const
1498 int opt_idx;
1500 if (!get_logger ())
1501 return;
1503 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1504 log_str_option ((enum gcc_jit_str_option)opt_idx);
1506 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1507 log_int_option ((enum gcc_jit_int_option)opt_idx);
1509 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1510 log_bool_option ((enum gcc_jit_bool_option)opt_idx);
1511 for (opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1512 log_inner_bool_option ((enum inner_bool_option)opt_idx);
1515 /* Write the current value of the given string option to the
1516 log file (if any). */
1518 void
1519 recording::context::log_str_option (enum gcc_jit_str_option opt) const
1521 gcc_assert (opt < GCC_JIT_NUM_STR_OPTIONS);
1522 if (get_logger ())
1524 if (m_str_options[opt])
1525 log ("%s: \"%s\"",
1526 str_option_reproducer_strings[opt],
1527 m_str_options[opt]);
1528 else
1529 log ("%s: NULL",
1530 str_option_reproducer_strings[opt]);
1534 /* Write the current value of the given int option to the
1535 log file (if any). */
1537 void
1538 recording::context::log_int_option (enum gcc_jit_int_option opt) const
1540 gcc_assert (opt < GCC_JIT_NUM_INT_OPTIONS);
1541 if (get_logger ())
1542 log ("%s: %i",
1543 int_option_reproducer_strings[opt],
1544 m_int_options[opt]);
1547 /* Write the current value of the given bool option to the
1548 log file (if any). */
1550 void
1551 recording::context::log_bool_option (enum gcc_jit_bool_option opt) const
1553 gcc_assert (opt < GCC_JIT_NUM_BOOL_OPTIONS);
1554 if (get_logger ())
1555 log ("%s: %s",
1556 bool_option_reproducer_strings[opt],
1557 m_bool_options[opt] ? "true" : "false");
1560 /* Write the current value of the given "inner" bool option to the
1561 log file (if any). */
1563 void
1564 recording::context::log_inner_bool_option (enum inner_bool_option opt) const
1566 gcc_assert (opt < NUM_INNER_BOOL_OPTIONS);
1567 if (get_logger ())
1568 log ("%s: %s",
1569 inner_bool_option_reproducer_strings[opt],
1570 m_inner_bool_options[opt] ? "true" : "false");
1573 /* Write C source code to PATH that attempts to replay the API
1574 calls made to this context (and its parents), for use in
1575 minimizing test cases for libgccjit.
1577 Implements the post-error-checking part of
1578 gcc_jit_context_dump_reproducer_to_file. */
1580 void
1581 recording::context::dump_reproducer_to_file (const char *path)
1583 JIT_LOG_SCOPE (get_logger ());
1584 reproducer r (*this, path);
1586 /* Generate the "ancestry" of this context, as a list. */
1587 auto_vec <context *> ascending_contexts;
1588 for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
1589 ascending_contexts.safe_push (ctxt);
1591 /* Reverse the list, giving a list of contexts from
1592 top-most parent context down through to youngest child context.
1593 We will use this list as the parameters of the functions in
1594 our generated file. */
1595 unsigned num_ctxts = ascending_contexts.length ();
1596 auto_vec <context *> contexts (num_ctxts);
1597 for (unsigned i = 0; i < num_ctxts; i++)
1598 contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
1600 /* contexts[0] should be the top-level context. */
1601 gcc_assert (contexts[0]);
1602 gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
1604 /* The final element in contexts should be "this". */
1605 gcc_assert (contexts[contexts.length () - 1] == this);
1606 gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
1607 == contexts[0]);
1609 r.write ("/* This code was autogenerated by"
1610 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1611 print_version (r.get_file (), " ", false);
1612 r.write ("*/\n");
1613 r.write ("#include <libgccjit.h>\n\n");
1614 r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1615 r.write ("static void\nset_options (");
1616 r.write_params (contexts);
1617 r.write (");\n\n");
1618 r.write ("static void\ncreate_code (");
1619 r.write_params (contexts);
1620 r.write (");\n\n");
1621 r.write ("int\nmain (int argc, const char **argv)\n");
1622 r.write ("{\n");
1623 for (unsigned i = 0; i < num_ctxts; i++)
1624 r.write (" gcc_jit_context *%s;\n",
1625 r.get_identifier (contexts[i]));
1626 r.write (" gcc_jit_result *result;\n"
1627 "\n");
1629 /* Create the contexts.
1630 The top-level context is acquired from a clean slate, the others as
1631 children of the prior context. */
1632 r.write (" %s = gcc_jit_context_acquire ();\n",
1633 r.get_identifier (contexts[0]));
1634 for (unsigned i = 1; i < num_ctxts; i++)
1635 r.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1636 r.get_identifier (contexts[i]),
1637 r.get_identifier (contexts[i - 1]));
1638 r.write (" set_options (");
1639 r.write_args (contexts);
1640 r.write (");\n");
1641 r.write (" create_code (");
1642 r.write_args (contexts);
1643 r.write (");\n");
1645 r.write (" result = gcc_jit_context_compile (%s);\n",
1646 r.get_identifier (this));
1648 for (unsigned i = num_ctxts; i > 0; i--)
1649 r.write (" gcc_jit_context_release (%s);\n",
1650 r.get_identifier (contexts[i - 1]));
1652 r.write (" gcc_jit_result_release (result);\n"
1653 " return 0;\n"
1654 "}\n\n");
1656 /* Define (char *) variables for use in calls to
1657 gcc_jit_context_enable_dump. */
1658 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1660 if (m_requested_dumps.length ())
1662 r.write ("/* Requested dumps for %s. */\n",
1663 r.get_identifier (contexts[ctxt_idx]));
1664 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1665 r.write ("static char *dump_%p;\n",
1666 (void *)&m_requested_dumps[i]);
1667 r.write ("\n");
1671 /* Write out values of options. */
1672 r.write ("static void\nset_options (");
1673 r.write_params (contexts);
1674 r.write (")\n{\n");
1675 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1677 if (ctxt_idx > 0)
1678 r.write ("\n");
1680 r.write (" /* Set options for %s. */\n",
1681 r.get_identifier (contexts[ctxt_idx]));
1683 r.write (" /* String options. */\n");
1684 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1686 r.write (" gcc_jit_context_set_str_option (%s,\n"
1687 " %s,\n",
1688 r.get_identifier (contexts[ctxt_idx]),
1689 str_option_reproducer_strings[opt_idx]);
1690 if (m_str_options[opt_idx])
1691 r.write (" \"%s\");\n",
1692 m_str_options[opt_idx]);
1693 else
1694 r.write (" NULL);\n");
1696 r.write (" /* Int options. */\n");
1697 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1698 r.write (" gcc_jit_context_set_int_option (%s,\n"
1699 " %s,\n"
1700 " %i);\n",
1701 r.get_identifier (contexts[ctxt_idx]),
1702 int_option_reproducer_strings[opt_idx],
1703 m_int_options[opt_idx]);
1704 r.write (" /* Boolean options. */\n");
1705 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1706 r.write (" gcc_jit_context_set_bool_option (%s,\n"
1707 " %s,\n"
1708 " %i);\n",
1709 r.get_identifier (contexts[ctxt_idx]),
1710 bool_option_reproducer_strings[opt_idx],
1711 m_bool_options[opt_idx]);
1712 for (int opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1713 r.write (" %s (%s, %i);\n",
1714 inner_bool_option_reproducer_strings[opt_idx],
1715 r.get_identifier (contexts[ctxt_idx]),
1716 m_inner_bool_options[opt_idx]);
1718 if (!m_command_line_options.is_empty ())
1720 int i;
1721 char *optname;
1722 r.write (" /* User-provided command-line options. */\n");
1723 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1724 r.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1725 r.get_identifier (contexts[ctxt_idx]),
1726 optname);
1729 if (m_requested_dumps.length ())
1731 r.write (" /* Requested dumps. */\n");
1732 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1733 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1735 r.write (" gcc_jit_context_enable_dump (%s,\n"
1736 " \"%s\",\n"
1737 " &dump_%p);\n",
1738 r.get_identifier (contexts[ctxt_idx]),
1739 m_requested_dumps[i].m_dumpname,
1740 (void *)&m_requested_dumps[i]);
1744 r.write ("}\n\n");
1746 r.write ("static void\ncreate_code (");
1747 r.write_params (contexts);
1748 r.write (")\n"
1749 "{\n");
1750 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1752 memento *m;
1753 int i;
1754 if (ctxt_idx > 0)
1755 r.write ("\n\n");
1757 r.write (" /* Replay of API calls for %s. */\n",
1758 r.get_identifier (contexts[ctxt_idx]));
1759 FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
1760 m->write_reproducer (r);
1762 r.write ("}\n");
1765 /* Copy the requested dumps within this context and all ancestors into
1766 OUT. */
1768 void
1769 recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
1771 if (m_parent_ctxt)
1772 m_parent_ctxt->get_all_requested_dumps (out);
1774 out->reserve (m_requested_dumps.length ());
1775 out->splice (m_requested_dumps);
1778 /* This is a pre-compilation check for the context (and any parents).
1780 Detect errors within the context, adding errors if any are found. */
1782 void
1783 recording::context::validate ()
1785 JIT_LOG_SCOPE (get_logger ());
1787 if (m_parent_ctxt)
1788 m_parent_ctxt->validate ();
1790 int i;
1791 function *fn;
1792 FOR_EACH_VEC_ELT (m_functions, i, fn)
1793 fn->validate ();
1796 /* The implementation of class gcc::jit::recording::memento. */
1798 /* Get a (const char *) debug description of the given memento, by
1799 calling the pure-virtual make_debug_string hook, caching the
1800 result.
1802 It is intended that this should only be called in debugging and
1803 error-handling paths, so this doesn't need to be particularly
1804 optimized. */
1806 const char *
1807 recording::memento::get_debug_string ()
1809 if (!m_debug_string)
1810 m_debug_string = make_debug_string ();
1811 return m_debug_string->c_str ();
1814 /* Default implementation of recording::memento::write_to_dump, writing
1815 an indented form of the memento's debug string to the dump. */
1817 void
1818 recording::memento::write_to_dump (dump &d)
1820 d.write(" %s\n", get_debug_string ());
1823 /* The implementation of class gcc::jit::recording::string. */
1825 /* Constructor for gcc::jit::recording::string::string, allocating a
1826 copy of the given text using new char[]. */
1828 recording::string::string (context *ctxt, const char *text)
1829 : memento (ctxt)
1831 m_len = strlen (text);
1832 m_buffer = new char[m_len + 1];
1833 strcpy (m_buffer, text);
1836 /* Destructor for gcc::jit::recording::string::string. */
1838 recording::string::~string ()
1840 delete[] m_buffer;
1843 /* Function for making gcc::jit::recording::string instances on a
1844 context via printf-style formatting.
1846 It is intended that this should only be called in debugging and
1847 error-handling paths, so this doesn't need to be particularly
1848 optimized, hence the double-copy of the string is acceptable. */
1850 recording::string *
1851 recording::string::from_printf (context *ctxt, const char *fmt, ...)
1853 int len;
1854 va_list ap;
1855 char *buf;
1856 recording::string *result;
1858 va_start (ap, fmt);
1859 len = vasprintf (&buf, fmt, ap);
1860 va_end (ap);
1862 if (buf == NULL || len < 0)
1864 ctxt->add_error (NULL, "malloc failure");
1865 return NULL;
1868 result = ctxt->new_string (buf);
1869 free (buf);
1870 return result;
1873 /* Implementation of recording::memento::make_debug_string for strings,
1874 wrapping the given string in quotes and escaping as necessary. */
1876 recording::string *
1877 recording::string::make_debug_string ()
1879 /* Hack to avoid infinite recursion into strings when logging all
1880 mementos: don't re-escape strings: */
1881 if (m_buffer[0] == '"')
1882 return this;
1884 /* Wrap in quotes and do escaping etc */
1886 size_t sz = (1 /* opening quote */
1887 + (m_len * 2) /* each char might get escaped */
1888 + 1 /* closing quote */
1889 + 1); /* nil termintator */
1890 char *tmp = new char[sz];
1891 size_t len = 0;
1893 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1894 APPEND('"'); /* opening quote */
1895 for (size_t i = 0; i < m_len ; i++)
1897 char ch = m_buffer[i];
1898 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
1899 APPEND('\\');
1900 APPEND(ch);
1902 APPEND('"'); /* closing quote */
1903 #undef APPEND
1904 tmp[len] = '\0'; /* nil termintator */
1906 string *result = m_ctxt->new_string (tmp);
1908 delete[] tmp;
1909 return result;
1912 /* Implementation of recording::memento::write_reproducer for strings. */
1914 void
1915 recording::string::write_reproducer (reproducer &)
1917 /* Empty. */
1920 /* The implementation of class gcc::jit::recording::location. */
1922 /* Implementation of recording::memento::replay_into for locations.
1924 Create a new playback::location and store it into the
1925 recording::location's m_playback_obj field. */
1927 void
1928 recording::location::replay_into (replayer *r)
1930 m_playback_obj = r->new_location (this,
1931 m_filename->c_str (),
1932 m_line,
1933 m_column);
1936 /* Implementation of recording::memento::make_debug_string for locations,
1937 turning them into the usual form:
1938 FILENAME:LINE:COLUMN
1939 like we do when emitting diagnostics. */
1941 recording::string *
1942 recording::location::make_debug_string ()
1944 return string::from_printf (m_ctxt,
1945 "%s:%i:%i",
1946 m_filename->c_str (), m_line, m_column);
1949 /* Implementation of recording::memento::write_reproducer for locations. */
1951 void
1952 recording::location::write_reproducer (reproducer &r)
1954 const char *id = r.make_identifier (this, "loc");
1955 r.write (" gcc_jit_location *%s =\n"
1956 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1957 " %s, /* const char *filename */\n"
1958 " %i, /* int line */\n"
1959 " %i);/* int column */\n",
1961 r.get_identifier (get_context ()),
1962 m_filename->get_debug_string (),
1963 m_line, m_column);
1966 /* The implementation of class gcc::jit::recording::type. */
1968 /* Given a type T, get the type T*.
1970 If this doesn't already exist, generate a new memento_of_get_pointer
1971 instance and add it to this type's context's list of mementos.
1973 Otherwise, use the cached type.
1975 Implements the post-error-checking part of
1976 gcc_jit_type_get_pointer. */
1978 recording::type *
1979 recording::type::get_pointer ()
1981 if (!m_pointer_to_this_type)
1983 m_pointer_to_this_type = new memento_of_get_pointer (this);
1984 m_ctxt->record (m_pointer_to_this_type);
1986 return m_pointer_to_this_type;
1989 /* Given a type T, get the type const T.
1991 Implements the post-error-checking part of
1992 gcc_jit_type_get_const. */
1994 recording::type *
1995 recording::type::get_const ()
1997 recording::type *result = new memento_of_get_const (this);
1998 m_ctxt->record (result);
1999 return result;
2002 /* Given a type T, get the type volatile T.
2004 Implements the post-error-checking part of
2005 gcc_jit_type_get_volatile. */
2007 recording::type *
2008 recording::type::get_volatile ()
2010 recording::type *result = new memento_of_get_volatile (this);
2011 m_ctxt->record (result);
2012 return result;
2015 /* Given a type, get an aligned version of the type.
2017 Implements the post-error-checking part of
2018 gcc_jit_type_get_aligned. */
2020 recording::type *
2021 recording::type::get_aligned (size_t alignment_in_bytes)
2023 recording::type *result
2024 = new memento_of_get_aligned (this, alignment_in_bytes);
2025 m_ctxt->record (result);
2026 return result;
2029 /* Given a type, get a vector version of the type.
2031 Implements the post-error-checking part of
2032 gcc_jit_type_get_vector. */
2034 recording::type *
2035 recording::type::get_vector (size_t num_units)
2037 recording::type *result
2038 = new memento_of_get_vector (this, num_units);
2039 m_ctxt->record (result);
2040 return result;
2043 const char *
2044 recording::type::access_as_type (reproducer &r)
2046 return r.get_identifier (this);
2049 /* Implementation of pure virtual hook recording::type::dereference for
2050 recording::memento_of_get_type. */
2052 recording::type *
2053 recording::memento_of_get_type::dereference ()
2055 switch (m_kind)
2057 default: gcc_unreachable ();
2059 case GCC_JIT_TYPE_VOID:
2060 return NULL;
2062 case GCC_JIT_TYPE_VOID_PTR:
2063 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
2065 case GCC_JIT_TYPE_BOOL:
2066 case GCC_JIT_TYPE_CHAR:
2067 case GCC_JIT_TYPE_SIGNED_CHAR:
2068 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2069 case GCC_JIT_TYPE_SHORT:
2070 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2071 case GCC_JIT_TYPE_INT:
2072 case GCC_JIT_TYPE_UNSIGNED_INT:
2073 case GCC_JIT_TYPE_LONG:
2074 case GCC_JIT_TYPE_UNSIGNED_LONG:
2075 case GCC_JIT_TYPE_LONG_LONG:
2076 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2077 case GCC_JIT_TYPE_FLOAT:
2078 case GCC_JIT_TYPE_DOUBLE:
2079 case GCC_JIT_TYPE_LONG_DOUBLE:
2080 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2081 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2082 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2083 /* Not a pointer: */
2084 return NULL;
2086 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2087 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
2089 case GCC_JIT_TYPE_SIZE_T:
2090 /* Not a pointer: */
2091 return NULL;
2093 case GCC_JIT_TYPE_FILE_PTR:
2094 /* Give the client code back an opaque "struct FILE". */
2095 return m_ctxt->get_opaque_FILE_type ();
2099 /* Implementation of pure virtual hook recording::type::is_int for
2100 recording::memento_of_get_type. */
2102 bool
2103 recording::memento_of_get_type::is_int () const
2105 switch (m_kind)
2107 default: gcc_unreachable ();
2109 case GCC_JIT_TYPE_VOID:
2110 return false;
2112 case GCC_JIT_TYPE_VOID_PTR:
2113 return false;
2115 case GCC_JIT_TYPE_BOOL:
2116 return false;
2118 case GCC_JIT_TYPE_CHAR:
2119 case GCC_JIT_TYPE_SIGNED_CHAR:
2120 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2121 case GCC_JIT_TYPE_SHORT:
2122 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2123 case GCC_JIT_TYPE_INT:
2124 case GCC_JIT_TYPE_UNSIGNED_INT:
2125 case GCC_JIT_TYPE_LONG:
2126 case GCC_JIT_TYPE_UNSIGNED_LONG:
2127 case GCC_JIT_TYPE_LONG_LONG:
2128 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2129 return true;
2131 case GCC_JIT_TYPE_FLOAT:
2132 case GCC_JIT_TYPE_DOUBLE:
2133 case GCC_JIT_TYPE_LONG_DOUBLE:
2134 return false;
2136 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2137 return false;
2139 case GCC_JIT_TYPE_SIZE_T:
2140 return true;
2142 case GCC_JIT_TYPE_FILE_PTR:
2143 return false;
2145 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2146 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2147 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2148 return false;
2152 /* Implementation of pure virtual hook recording::type::is_float for
2153 recording::memento_of_get_type. */
2155 bool
2156 recording::memento_of_get_type::is_float () const
2158 switch (m_kind)
2160 default: gcc_unreachable ();
2162 case GCC_JIT_TYPE_VOID:
2163 return false;
2165 case GCC_JIT_TYPE_VOID_PTR:
2166 return false;
2168 case GCC_JIT_TYPE_BOOL:
2169 return false;
2171 case GCC_JIT_TYPE_CHAR:
2172 case GCC_JIT_TYPE_SIGNED_CHAR:
2173 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2174 case GCC_JIT_TYPE_SHORT:
2175 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2176 case GCC_JIT_TYPE_INT:
2177 case GCC_JIT_TYPE_UNSIGNED_INT:
2178 case GCC_JIT_TYPE_LONG:
2179 case GCC_JIT_TYPE_UNSIGNED_LONG:
2180 case GCC_JIT_TYPE_LONG_LONG:
2181 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2182 return false;
2184 case GCC_JIT_TYPE_FLOAT:
2185 case GCC_JIT_TYPE_DOUBLE:
2186 case GCC_JIT_TYPE_LONG_DOUBLE:
2187 return true;
2189 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2190 return false;
2192 case GCC_JIT_TYPE_SIZE_T:
2193 return false;
2195 case GCC_JIT_TYPE_FILE_PTR:
2196 return false;
2198 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2199 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2200 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2201 return true;
2205 /* Implementation of pure virtual hook recording::type::is_bool for
2206 recording::memento_of_get_type. */
2208 bool
2209 recording::memento_of_get_type::is_bool () const
2211 switch (m_kind)
2213 default: gcc_unreachable ();
2215 case GCC_JIT_TYPE_VOID:
2216 return false;
2218 case GCC_JIT_TYPE_VOID_PTR:
2219 return false;
2221 case GCC_JIT_TYPE_BOOL:
2222 return true;
2224 case GCC_JIT_TYPE_CHAR:
2225 case GCC_JIT_TYPE_SIGNED_CHAR:
2226 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2227 case GCC_JIT_TYPE_SHORT:
2228 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2229 case GCC_JIT_TYPE_INT:
2230 case GCC_JIT_TYPE_UNSIGNED_INT:
2231 case GCC_JIT_TYPE_LONG:
2232 case GCC_JIT_TYPE_UNSIGNED_LONG:
2233 case GCC_JIT_TYPE_LONG_LONG:
2234 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2235 return false;
2237 case GCC_JIT_TYPE_FLOAT:
2238 case GCC_JIT_TYPE_DOUBLE:
2239 case GCC_JIT_TYPE_LONG_DOUBLE:
2240 return false;
2242 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2243 return false;
2245 case GCC_JIT_TYPE_SIZE_T:
2246 return false;
2248 case GCC_JIT_TYPE_FILE_PTR:
2249 return false;
2251 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2252 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2253 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2254 return false;
2258 /* Implementation of pure virtual hook recording::memento::replay_into
2259 for recording::memento_of_get_type. */
2261 void
2262 recording::memento_of_get_type::replay_into (replayer *r)
2264 set_playback_obj (r->get_type (m_kind));
2267 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2269 /* Descriptive strings for each of enum gcc_jit_types. */
2271 static const char * const get_type_strings[] = {
2272 "void", /* GCC_JIT_TYPE_VOID */
2273 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2275 "bool", /* GCC_JIT_TYPE_BOOL */
2277 "char", /* GCC_JIT_TYPE_CHAR */
2278 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2279 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2281 "short", /* GCC_JIT_TYPE_SHORT */
2282 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2284 "int", /* GCC_JIT_TYPE_INT */
2285 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2287 "long", /* GCC_JIT_TYPE_LONG */
2288 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2290 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2291 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2293 "float", /* GCC_JIT_TYPE_FLOAT */
2294 "double", /* GCC_JIT_TYPE_DOUBLE */
2295 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2297 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2299 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2301 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2303 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2304 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2305 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2309 /* Implementation of recording::memento::make_debug_string for
2310 results of get_type, using a simple table of type names. */
2312 recording::string *
2313 recording::memento_of_get_type::make_debug_string ()
2315 return m_ctxt->new_string (get_type_strings[m_kind]);
2318 static const char * const get_type_enum_strings[] = {
2319 "GCC_JIT_TYPE_VOID",
2320 "GCC_JIT_TYPE_VOID_PTR",
2321 "GCC_JIT_TYPE_BOOL",
2322 "GCC_JIT_TYPE_CHAR",
2323 "GCC_JIT_TYPE_SIGNED_CHAR",
2324 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2325 "GCC_JIT_TYPE_SHORT",
2326 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2327 "GCC_JIT_TYPE_INT",
2328 "GCC_JIT_TYPE_UNSIGNED_INT",
2329 "GCC_JIT_TYPE_LONG",
2330 "GCC_JIT_TYPE_UNSIGNED_LONG",
2331 "GCC_JIT_TYPE_LONG_LONG",
2332 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2333 "GCC_JIT_TYPE_FLOAT",
2334 "GCC_JIT_TYPE_DOUBLE",
2335 "GCC_JIT_TYPE_LONG_DOUBLE",
2336 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2337 "GCC_JIT_TYPE_SIZE_T",
2338 "GCC_JIT_TYPE_FILE_PTR",
2339 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2340 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2341 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2344 void
2345 recording::memento_of_get_type::write_reproducer (reproducer &r)
2347 const char *id = r.make_identifier (this, "type");
2348 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2350 r.get_identifier (get_context ()),
2351 get_type_enum_strings[m_kind]);
2354 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2356 /* Override of default implementation of
2357 recording::type::accepts_writes_from for get_pointer.
2359 Require a pointer type, and allowing writes to
2360 (const T *) from a (T*), but not the other way around. */
2362 bool
2363 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2365 /* Must be a pointer type: */
2366 type *rtype_points_to = rtype->is_pointer ();
2367 if (!rtype_points_to)
2368 return false;
2370 /* It's OK to assign to a (const T *) from a (T *). */
2371 return m_other_type->unqualified ()
2372 ->accepts_writes_from (rtype_points_to);
2375 /* Implementation of pure virtual hook recording::memento::replay_into
2376 for recording::memento_of_get_pointer. */
2378 void
2379 recording::memento_of_get_pointer::replay_into (replayer *)
2381 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2384 /* Implementation of recording::memento::make_debug_string for
2385 results of get_pointer, adding " *" to the underlying type,
2386 with special-casing to handle function pointer types. */
2388 recording::string *
2389 recording::memento_of_get_pointer::make_debug_string ()
2391 /* Special-case function pointer types, to put the "*" in parens between
2392 the return type and the params (for one level of dereferencing, at
2393 least). */
2394 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2395 return fn_type->make_debug_string_with_ptr ();
2397 return string::from_printf (m_ctxt,
2398 "%s *", m_other_type->get_debug_string ());
2401 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2403 void
2404 recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2406 /* We need to special-case function pointer types; see the notes in
2407 recording::function_type::write_deferred_reproducer. */
2408 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2410 fn_type->write_deferred_reproducer (r, this);
2411 return;
2414 const char *id = r.make_identifier (this, "type");
2415 r.write (" gcc_jit_type *%s =\n"
2416 " gcc_jit_type_get_pointer (%s);\n",
2418 r.get_identifier_as_type (m_other_type));
2421 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2423 /* Implementation of pure virtual hook recording::memento::replay_into
2424 for recording::memento_of_get_const. */
2426 void
2427 recording::memento_of_get_const::replay_into (replayer *)
2429 set_playback_obj (m_other_type->playback_type ()->get_const ());
2432 /* Implementation of recording::memento::make_debug_string for
2433 results of get_const, prepending "const ". */
2435 recording::string *
2436 recording::memento_of_get_const::make_debug_string ()
2438 return string::from_printf (m_ctxt,
2439 "const %s", m_other_type->get_debug_string ());
2442 /* Implementation of recording::memento::write_reproducer for const types. */
2444 void
2445 recording::memento_of_get_const::write_reproducer (reproducer &r)
2447 const char *id = r.make_identifier (this, "type");
2448 r.write (" gcc_jit_type *%s =\n"
2449 " gcc_jit_type_get_const (%s);\n",
2451 r.get_identifier_as_type (m_other_type));
2454 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2456 /* Implementation of pure virtual hook recording::memento::replay_into
2457 for recording::memento_of_get_volatile. */
2459 void
2460 recording::memento_of_get_volatile::replay_into (replayer *)
2462 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2465 /* Implementation of recording::memento::make_debug_string for
2466 results of get_volatile, prepending "volatile ". */
2468 recording::string *
2469 recording::memento_of_get_volatile::make_debug_string ()
2471 return string::from_printf (m_ctxt,
2472 "volatile %s", m_other_type->get_debug_string ());
2475 /* Implementation of recording::memento::write_reproducer for volatile
2476 types. */
2478 void
2479 recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2481 const char *id = r.make_identifier (this, "type");
2482 r.write (" gcc_jit_type *%s =\n"
2483 " gcc_jit_type_get_volatile (%s);\n",
2485 r.get_identifier_as_type (m_other_type));
2488 /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
2490 /* Implementation of pure virtual hook recording::memento::replay_into
2491 for recording::memento_of_get_aligned. */
2493 void
2494 recording::memento_of_get_aligned::replay_into (replayer *)
2496 set_playback_obj
2497 (m_other_type->playback_type ()->get_aligned (m_alignment_in_bytes));
2500 /* Implementation of recording::memento::make_debug_string for
2501 results of get_aligned. */
2503 recording::string *
2504 recording::memento_of_get_aligned::make_debug_string ()
2506 return string::from_printf (m_ctxt,
2507 "%s __attribute__((aligned(%zi)))",
2508 m_other_type->get_debug_string (),
2509 m_alignment_in_bytes);
2512 /* Implementation of recording::memento::write_reproducer for aligned
2513 types. */
2515 void
2516 recording::memento_of_get_aligned::write_reproducer (reproducer &r)
2518 const char *id = r.make_identifier (this, "type");
2519 r.write (" gcc_jit_type *%s =\n"
2520 " gcc_jit_type_get_aligned (%s, %zi);\n",
2522 r.get_identifier_as_type (m_other_type),
2523 m_alignment_in_bytes);
2526 /* The implementation of class gcc::jit::recording::memento_of_get_vector. */
2528 /* Implementation of pure virtual hook recording::memento::replay_into
2529 for recording::memento_of_get_vector. */
2531 void
2532 recording::memento_of_get_vector::replay_into (replayer *)
2534 set_playback_obj
2535 (m_other_type->playback_type ()->get_vector (m_num_units));
2538 /* Implementation of recording::memento::make_debug_string for
2539 results of get_vector. */
2541 recording::string *
2542 recording::memento_of_get_vector::make_debug_string ()
2544 return string::from_printf
2545 (m_ctxt,
2546 "%s __attribute__((vector_size(sizeof (%s) * %zi)))",
2547 m_other_type->get_debug_string (),
2548 m_other_type->get_debug_string (),
2549 m_num_units);
2552 /* Implementation of recording::memento::write_reproducer for volatile
2553 types. */
2555 void
2556 recording::memento_of_get_vector::write_reproducer (reproducer &r)
2558 const char *id = r.make_identifier (this, "type");
2559 r.write (" gcc_jit_type *%s =\n"
2560 " gcc_jit_type_get_vector (%s, %zi);\n",
2562 r.get_identifier_as_type (m_other_type),
2563 m_num_units);
2566 /* The implementation of class gcc::jit::recording::array_type */
2568 /* Implementation of pure virtual hook recording::type::dereference for
2569 recording::array_type. */
2571 recording::type *
2572 recording::array_type::dereference ()
2574 return m_element_type;
2577 /* Implementation of pure virtual hook recording::memento::replay_into
2578 for recording::array_type. */
2580 void
2581 recording::array_type::replay_into (replayer *r)
2583 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
2584 m_element_type->playback_type (),
2585 m_num_elements));
2588 /* Implementation of recording::memento::make_debug_string for
2589 results of new_array_type. */
2591 recording::string *
2592 recording::array_type::make_debug_string ()
2594 return string::from_printf (m_ctxt,
2595 "%s[%d]",
2596 m_element_type->get_debug_string (),
2597 m_num_elements);
2600 /* Implementation of recording::memento::write_reproducer for array
2601 types. */
2603 void
2604 recording::array_type::write_reproducer (reproducer &r)
2606 const char *id = r.make_identifier (this, "array_type");
2607 r.write (" gcc_jit_type *%s =\n"
2608 " gcc_jit_context_new_array_type (%s,\n"
2609 " %s, /* gcc_jit_location *loc */\n"
2610 " %s, /* gcc_jit_type *element_type */\n"
2611 " %i); /* int num_elements */\n",
2613 r.get_identifier (get_context ()),
2614 r.get_identifier (m_loc),
2615 r.get_identifier_as_type (m_element_type),
2616 m_num_elements);
2619 /* The implementation of class gcc::jit::recording::function_type */
2621 /* Constructor for gcc::jit::recording::function_type. */
2623 recording::function_type::function_type (context *ctxt,
2624 type *return_type,
2625 int num_params,
2626 type **param_types,
2627 int is_variadic)
2628 : type (ctxt),
2629 m_return_type (return_type),
2630 m_param_types (),
2631 m_is_variadic (is_variadic)
2633 for (int i = 0; i< num_params; i++)
2634 m_param_types.safe_push (param_types[i]);
2637 /* Implementation of pure virtual hook recording::type::dereference for
2638 recording::function_type. */
2640 recording::type *
2641 recording::function_type::dereference ()
2643 return NULL;
2646 /* Implementation of pure virtual hook recording::memento::replay_into
2647 for recording::function_type. */
2649 void
2650 recording::function_type::replay_into (replayer *r)
2652 /* Convert m_param_types to a vec of playback type. */
2653 auto_vec <playback::type *> param_types;
2654 int i;
2655 recording::type *type;
2656 param_types.create (m_param_types.length ());
2657 FOR_EACH_VEC_ELT (m_param_types, i, type)
2658 param_types.safe_push (type->playback_type ());
2660 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
2661 &param_types,
2662 m_is_variadic));
2665 /* Special-casing for make_debug_string for get_pointer results for
2666 handling (one level) of pointers to functions. */
2668 recording::string *
2669 recording::function_type::make_debug_string_with_ptr ()
2671 return make_debug_string_with ("(*) ");
2674 /* Implementation of recording::memento::make_debug_string for
2675 results of new_function_type. */
2677 recording::string *
2678 recording::function_type::make_debug_string ()
2680 return make_debug_string_with ("");
2683 /* Build a debug string representation of the form:
2685 RESULT_TYPE INSERT (PARAM_TYPES)
2687 for use when handling 0 and 1 level of indirection to this
2688 function type. */
2690 recording::string *
2691 recording::function_type::make_debug_string_with (const char *insert)
2693 /* First, build a buffer for the arguments. */
2694 /* Calculate length of said buffer. */
2695 size_t sz = 1; /* nil terminator */
2696 for (unsigned i = 0; i< m_param_types.length (); i++)
2698 sz += strlen (m_param_types[i]->get_debug_string ());
2699 sz += 2; /* ", " separator */
2701 if (m_is_variadic)
2702 sz += 5; /* ", ..." separator and ellipsis */
2704 /* Now allocate and populate the buffer. */
2705 char *argbuf = new char[sz];
2706 size_t len = 0;
2708 for (unsigned i = 0; i< m_param_types.length (); i++)
2710 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
2711 len += strlen (m_param_types[i]->get_debug_string ());
2712 if (i + 1 < m_param_types.length ())
2714 strcpy (argbuf + len, ", ");
2715 len += 2;
2718 if (m_is_variadic)
2720 if (m_param_types.length ())
2722 strcpy (argbuf + len, ", ");
2723 len += 2;
2725 strcpy (argbuf + len, "...");
2726 len += 3;
2728 argbuf[len] = '\0';
2730 /* ...and use it to get the string for the call as a whole. */
2731 string *result = string::from_printf (m_ctxt,
2732 "%s %s(%s)",
2733 m_return_type->get_debug_string (),
2734 insert,
2735 argbuf);
2737 delete[] argbuf;
2739 return result;
2742 /* Implementation of recording::memento::write_reproducer for function
2743 types. */
2745 void
2746 recording::function_type::write_reproducer (reproducer &)
2748 /* see notes below. */
2751 /* There's a get_pointer within context::new_function_ptr_type:
2752 the type received by client code isn't the memento for the
2753 function_type, but instead the result of get_pointer on it.
2755 Hence we can't directly write a reproducer that gives function_type.
2756 Instead we special-case things within get_pointer, detecting this
2757 case, calling the following function. */
2759 void
2760 recording::function_type::write_deferred_reproducer (reproducer &r,
2761 memento *ptr_type)
2763 gcc_assert (ptr_type);
2764 r.make_identifier (this, "function_type");
2765 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
2766 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
2767 r.write (" gcc_jit_type *%s[%i] = {\n",
2768 param_types_id,
2769 m_param_types.length ());
2770 int i;
2771 type *param_type;
2772 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2773 r.write (" %s,\n", r.get_identifier_as_type (param_type));
2774 r.write (" };\n");
2775 r.write (" gcc_jit_type *%s =\n"
2776 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2777 " %s, /* gcc_jit_location *loc */\n"
2778 " %s, /* gcc_jit_type *return_type */\n"
2779 " %i, /* int num_params */\n"
2780 " %s, /* gcc_jit_type **param_types */\n"
2781 " %i); /* int is_variadic */\n",
2782 ptr_id,
2783 r.get_identifier (get_context ()),
2784 "NULL", /* location is not stored */
2785 r.get_identifier_as_type (m_return_type),
2786 m_param_types.length (),
2787 param_types_id,
2788 m_is_variadic);
2791 /* The implementation of class gcc::jit::recording::field. */
2793 /* Implementation of pure virtual hook recording::memento::replay_into
2794 for recording::field. */
2796 void
2797 recording::field::replay_into (replayer *r)
2799 set_playback_obj (r->new_field (playback_location (r, m_loc),
2800 m_type->playback_type (),
2801 playback_string (m_name)));
2804 /* Override the default implementation of
2805 recording::memento::write_to_dump. Dump each field
2806 by dumping a line of the form:
2807 TYPE NAME;
2808 so that we can build up a struct/union field-byfield. */
2810 void
2811 recording::field::write_to_dump (dump &d)
2813 d.write (" %s %s;\n",
2814 m_type->get_debug_string (),
2815 m_name->c_str ());
2818 /* Implementation of recording::memento::make_debug_string for
2819 results of new_field. */
2821 recording::string *
2822 recording::field::make_debug_string ()
2824 return m_name;
2827 /* Implementation of recording::memento::write_reproducer for fields. */
2829 void
2830 recording::field::write_reproducer (reproducer &r)
2832 const char *id = r.make_identifier (this, "field");
2833 r.write(" gcc_jit_field *%s =\n"
2834 " gcc_jit_context_new_field (%s,\n"
2835 " %s, /* gcc_jit_location *loc */\n"
2836 " %s, /* gcc_jit_type *type, */\n"
2837 " %s); /* const char *name */\n",
2839 r.get_identifier (get_context ()),
2840 r.get_identifier (m_loc),
2841 r.get_identifier_as_type (m_type),
2842 m_name->get_debug_string ());
2845 /* The implementation of class gcc::jit::recording::compound_type */
2847 /* The constructor for gcc::jit::recording::compound_type. */
2849 recording::compound_type::compound_type (context *ctxt,
2850 location *loc,
2851 string *name)
2852 : type (ctxt),
2853 m_loc (loc),
2854 m_name (name),
2855 m_fields (NULL)
2859 /* Set the fields of a compound type.
2861 Implements the post-error-checking part of
2862 gcc_jit_struct_set_fields, and is also used by
2863 gcc_jit_context_new_union_type. */
2865 void
2866 recording::compound_type::set_fields (location *loc,
2867 int num_fields,
2868 field **field_array)
2870 m_loc = loc;
2871 gcc_assert (NULL == m_fields);
2873 m_fields = new fields (this, num_fields, field_array);
2874 m_ctxt->record (m_fields);
2877 /* Implementation of pure virtual hook recording::type::dereference for
2878 recording::compound_type. */
2880 recording::type *
2881 recording::compound_type::dereference ()
2883 return NULL; /* not a pointer */
2886 /* The implementation of class gcc::jit::recording::struct_. */
2888 /* The constructor for gcc::jit::recording::struct_. */
2890 recording::struct_::struct_ (context *ctxt,
2891 location *loc,
2892 string *name)
2893 : compound_type (ctxt, loc, name)
2897 /* Implementation of pure virtual hook recording::memento::replay_into
2898 for recording::struct_. */
2900 void
2901 recording::struct_::replay_into (replayer *r)
2903 set_playback_obj (
2904 r->new_compound_type (playback_location (r, get_loc ()),
2905 get_name ()->c_str (),
2906 true /* is_struct */));
2909 const char *
2910 recording::struct_::access_as_type (reproducer &r)
2912 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2913 r.get_identifier (this));
2916 /* Implementation of recording::memento::make_debug_string for
2917 structs. */
2919 recording::string *
2920 recording::struct_::make_debug_string ()
2922 return string::from_printf (m_ctxt,
2923 "struct %s", get_name ()->c_str ());
2926 void
2927 recording::struct_::write_reproducer (reproducer &r)
2929 const char *id = r.make_identifier (this, "struct");
2930 r.write (" gcc_jit_struct *%s =\n"
2931 " gcc_jit_context_new_opaque_struct (%s,\n"
2932 " %s, /* gcc_jit_location *loc */\n"
2933 " %s); /* const char *name */\n",
2935 r.get_identifier (get_context ()),
2936 r.get_identifier (get_loc ()),
2937 get_name ()->get_debug_string ());
2940 /* The implementation of class gcc::jit::recording::union_. */
2942 /* The constructor for gcc::jit::recording::union_. */
2944 recording::union_::union_ (context *ctxt,
2945 location *loc,
2946 string *name)
2947 : compound_type (ctxt, loc, name)
2951 /* Implementation of pure virtual hook recording::memento::replay_into
2952 for recording::union_. */
2954 void
2955 recording::union_::replay_into (replayer *r)
2957 set_playback_obj (
2958 r->new_compound_type (playback_location (r, get_loc ()),
2959 get_name ()->c_str (),
2960 false /* is_struct */));
2963 /* Implementation of recording::memento::make_debug_string for
2964 unions. */
2966 recording::string *
2967 recording::union_::make_debug_string ()
2969 return string::from_printf (m_ctxt,
2970 "union %s", get_name ()->c_str ());
2973 /* Implementation of recording::memento::write_reproducer for unions. */
2975 void
2976 recording::union_::write_reproducer (reproducer &r)
2978 const char *id = r.make_identifier (this, "union");
2980 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
2981 r.write (" gcc_jit_field *%s[%i] = {\n",
2982 fields_id,
2983 get_fields ()->length ());
2984 for (int i = 0; i < get_fields ()->length (); i++)
2985 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
2986 r.write (" };\n");
2988 r.write (" gcc_jit_type *%s =\n"
2989 " gcc_jit_context_new_union_type (%s,\n"
2990 " %s, /* gcc_jit_location *loc */\n"
2991 " %s, /* const char *name */\n"
2992 " %i, /* int num_fields */\n"
2993 " %s); /* gcc_jit_field **fields */\n",
2995 r.get_identifier (get_context ()),
2996 r.get_identifier (get_loc ()),
2997 get_name ()->get_debug_string (),
2998 get_fields ()->length (),
2999 fields_id);
3002 /* The implementation of class gcc::jit::recording::fields. */
3004 /* The constructor for gcc::jit::recording::fields. */
3006 recording::fields::fields (compound_type *struct_or_union,
3007 int num_fields,
3008 field **fields)
3009 : memento (struct_or_union->m_ctxt),
3010 m_struct_or_union (struct_or_union),
3011 m_fields ()
3013 for (int i = 0; i < num_fields; i++)
3015 gcc_assert (fields[i]->get_container () == NULL);
3016 fields[i]->set_container (m_struct_or_union);
3017 m_fields.safe_push (fields[i]);
3021 /* Implementation of pure virtual hook recording::memento::replay_into
3022 for recording::fields. */
3024 void
3025 recording::fields::replay_into (replayer *)
3027 auto_vec<playback::field *> playback_fields;
3028 playback_fields.create (m_fields.length ());
3029 for (unsigned i = 0; i < m_fields.length (); i++)
3030 playback_fields.safe_push (m_fields[i]->playback_field ());
3031 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
3034 /* Override the default implementation of
3035 recording::memento::write_to_dump by writing a union/struct
3036 declaration of this form:
3038 struct/union NAME {
3039 TYPE_1 NAME_1;
3040 TYPE_2 NAME_2;
3041 ....
3042 TYPE_N NAME_N;
3045 to the dump. */
3047 void
3048 recording::fields::write_to_dump (dump &d)
3050 int i;
3051 field *f;
3053 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
3054 FOR_EACH_VEC_ELT (m_fields, i, f)
3055 f->write_to_dump (d);
3056 d.write ("};\n");
3059 /* Implementation of recording::memento::write_reproducer for the fields
3060 subclass. */
3062 void
3063 recording::fields::write_reproducer (reproducer &r)
3065 if (m_struct_or_union)
3066 if (NULL == m_struct_or_union->dyn_cast_struct ())
3067 /* We have a union; the fields have already been written by
3068 union::write_reproducer. */
3069 return;
3071 const char *fields_id = r.make_identifier (this, "fields");
3072 r.write (" gcc_jit_field *%s[%i] = {\n",
3073 fields_id,
3074 m_fields.length ());
3075 int i;
3076 field *field;
3077 FOR_EACH_VEC_ELT (m_fields, i, field)
3078 r.write (" %s,\n", r.get_identifier (field));
3079 r.write (" };\n");
3081 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
3082 " %s, /* gcc_jit_location *loc */\n"
3083 " %i, /* int num_fields */\n"
3084 " %s); /* gcc_jit_field **fields */\n",
3085 r.get_identifier (m_struct_or_union),
3086 r.get_identifier ((memento *)NULL),
3087 m_fields.length (),
3088 fields_id);
3091 /* Implementation of recording::memento::make_debug_string for
3092 field tables. */
3094 recording::string *
3095 recording::fields::make_debug_string ()
3097 return string::from_printf (m_ctxt,
3098 "fields");
3101 /* The implementation of class gcc::jit::recording::rvalue. */
3103 /* Create a recording::access_field_rvalue instance and add it to
3104 the rvalue's context's list of mementos.
3106 Implements the post-error-checking part of
3107 gcc_jit_rvalue_access_field. */
3109 recording::rvalue *
3110 recording::rvalue::access_field (recording::location *loc,
3111 field *field)
3113 recording::rvalue *result =
3114 new access_field_rvalue (m_ctxt, loc, this, field);
3115 m_ctxt->record (result);
3116 return result;
3119 /* Create a recording::dereference_field_rvalue instance and add it to
3120 the rvalue's context's list of mementos.
3122 Implements the post-error-checking part of
3123 gcc_jit_rvalue_dereference_field. */
3125 recording::lvalue *
3126 recording::rvalue::dereference_field (recording::location *loc,
3127 field *field)
3129 recording::lvalue *result =
3130 new dereference_field_rvalue (m_ctxt, loc, this, field);
3131 m_ctxt->record (result);
3132 return result;
3135 /* Create a recording::dereference_rvalue instance and add it to the
3136 rvalue's context's list of mementos.
3138 Implements the post-error-checking part of
3139 gcc_jit_rvalue_dereference. */
3141 recording::lvalue *
3142 recording::rvalue::dereference (recording::location *loc)
3144 recording::lvalue *result =
3145 new dereference_rvalue (m_ctxt, loc, this);
3146 m_ctxt->record (result);
3147 return result;
3150 /* An rvalue visitor, for validating that every rvalue within an expression
3151 trees within "STMT" has the correct scope (e.g. no access to locals
3152 of a different function). */
3154 class rvalue_usage_validator : public recording::rvalue_visitor
3156 public:
3157 rvalue_usage_validator (const char *api_funcname,
3158 recording::context *ctxt,
3159 recording::statement *stmt);
3161 void
3162 visit (recording::rvalue *rvalue) FINAL OVERRIDE;
3164 private:
3165 const char *m_api_funcname;
3166 recording::context *m_ctxt;
3167 recording::statement *m_stmt;
3170 /* The trivial constructor for rvalue_usage_validator. */
3172 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
3173 recording::context *ctxt,
3174 recording::statement *stmt)
3175 : m_api_funcname (api_funcname),
3176 m_ctxt (ctxt),
3177 m_stmt (stmt)
3181 /* Verify that the given rvalue is in the correct scope. */
3183 void
3184 rvalue_usage_validator::visit (recording::rvalue *rvalue)
3186 gcc_assert (m_stmt->get_block ());
3187 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
3189 /* Most rvalues don't have a scope (only locals and params). */
3190 if (rvalue->get_scope ())
3192 if (rvalue->get_scope () != stmt_scope)
3193 m_ctxt->add_error
3194 (rvalue->get_loc (),
3195 "%s:"
3196 " rvalue %s (type: %s)"
3197 " has scope limited to function %s"
3198 " but was used within function %s"
3199 " (in statement: %s)",
3200 m_api_funcname,
3201 rvalue->get_debug_string (),
3202 rvalue->get_type ()->get_debug_string (),
3203 rvalue->get_scope ()->get_debug_string (),
3204 stmt_scope->get_debug_string (),
3205 m_stmt->get_debug_string ());
3207 else
3209 if (rvalue->dyn_cast_param ())
3210 m_ctxt->add_error
3211 (rvalue->get_loc (),
3212 "%s:"
3213 " param %s (type: %s)"
3214 " was used within function %s"
3215 " (in statement: %s)"
3216 " but is not associated with any function",
3217 m_api_funcname,
3218 rvalue->get_debug_string (),
3219 rvalue->get_type ()->get_debug_string (),
3220 stmt_scope->get_debug_string (),
3221 m_stmt->get_debug_string ());
3225 /* Verify that it's valid to use this rvalue (and all expressions
3226 in the tree below it) within the given statement.
3228 For example, we must reject attempts to use a local from one
3229 function within a different function here, or we'll get
3230 an ICE deep inside toplev::main. */
3232 void
3233 recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
3235 rvalue_usage_validator v (api_funcname,
3236 s->get_context (),
3239 /* Verify that it's OK to use this rvalue within s. */
3240 v.visit (this);
3242 /* Traverse the expression tree below "this", verifying all rvalues
3243 within it. */
3244 visit_children (&v);
3247 /* Set the scope of this rvalue to be the given function. This can only
3248 be done once on a given rvalue. */
3250 void
3251 recording::rvalue::set_scope (function *scope)
3253 gcc_assert (scope);
3254 gcc_assert (NULL == m_scope);
3255 m_scope = scope;
3259 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3260 themselves.
3261 Instances of rvalue don't need an upcast call. */
3263 const char *
3264 recording::rvalue::access_as_rvalue (reproducer &r)
3266 return r.get_identifier (this);
3269 /* Return a debug string for the given rvalue, wrapping it in parentheses
3270 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3271 stronger precedence that this rvalue's precedence.
3273 For example, given:
3275 MULT
3277 PLUS MINUS
3278 / \ / \
3279 A B C D
3281 we want to emit:
3283 (A + B) * (C - D)
3285 since MULT has strong precedence than PLUS and MINUS, whereas for:
3287 PLUS
3289 MULT DIVIDE
3290 / \ / \
3291 A B C D
3293 we can simply emit:
3295 A * B + C / D
3297 since PLUS has weaker precedence than MULT and DIVIDE. */
3299 const char *
3300 recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
3302 enum precedence this_prec = get_precedence ();
3304 /* If this_prec has stronger precedence than outer_prec, we don't
3305 need to wrap this in parens within the outer debug string.
3306 Stronger precedences occur earlier than weaker within the enum,
3307 so this is a less than test. Equal precedences don't need
3308 parentheses. */
3309 if (this_prec <= outer_prec)
3310 return get_debug_string();
3312 /* Otherwise, we need parentheses. */
3314 /* Lazily-build and cache m_parenthesized_string. */
3315 if (!m_parenthesized_string)
3317 const char *debug_string = get_debug_string ();
3318 m_parenthesized_string = string::from_printf (get_context (),
3319 "(%s)",
3320 debug_string);
3322 gcc_assert (m_parenthesized_string);
3323 return m_parenthesized_string->c_str ();
3327 /* The implementation of class gcc::jit::recording::lvalue. */
3329 /* Create a recording::new_access_field_of_lvalue instance and add it to
3330 the lvalue's context's list of mementos.
3332 Implements the post-error-checking part of
3333 gcc_jit_lvalue_access_field. */
3335 recording::lvalue *
3336 recording::lvalue::access_field (recording::location *loc,
3337 field *field)
3339 recording::lvalue *result =
3340 new access_field_of_lvalue (m_ctxt, loc, this, field);
3341 m_ctxt->record (result);
3342 return result;
3345 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3346 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3347 upcast call. */
3349 const char *
3350 recording::lvalue::access_as_rvalue (reproducer &r)
3352 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3353 r.get_identifier (this));
3356 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3357 Instances of lvalue don't need to be upcast. */
3359 const char *
3360 recording::lvalue::access_as_lvalue (reproducer &r)
3362 return r.get_identifier (this);
3365 /* Create a recording::get_address_of_lvalue instance and add it to
3366 the lvalue's context's list of mementos.
3368 Implements the post-error-checking part of
3369 gcc_jit_lvalue_get_address. */
3371 recording::rvalue *
3372 recording::lvalue::get_address (recording::location *loc)
3374 recording::rvalue *result =
3375 new get_address_of_lvalue (m_ctxt, loc, this);
3376 m_ctxt->record (result);
3377 return result;
3380 /* The implementation of class gcc::jit::recording::param. */
3382 /* Implementation of pure virtual hook recording::memento::replay_into
3383 for recording::param. */
3385 void
3386 recording::param::replay_into (replayer *r)
3388 set_playback_obj (r->new_param (playback_location (r, m_loc),
3389 m_type->playback_type (),
3390 m_name->c_str ()));
3393 /* Implementation of recording::rvalue::access_as_rvalue for params.
3394 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3395 upcast call. */
3397 const char *
3398 recording::param::access_as_rvalue (reproducer &r)
3400 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3401 r.get_identifier (this));
3404 /* Implementation of recording::lvalue::access_as_lvalue for params.
3405 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3406 upcast call. */
3408 const char *
3409 recording::param::access_as_lvalue (reproducer &r)
3411 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3412 r.get_identifier (this));
3415 /* Implementation of recording::memento::write_reproducer for params. */
3417 void
3418 recording::param::write_reproducer (reproducer &r)
3420 const char *id = r.make_identifier (this, "param");
3421 r.write (" gcc_jit_param *%s =\n"
3422 " gcc_jit_context_new_param (%s,\n"
3423 " %s, /* gcc_jit_location *loc */\n"
3424 " %s, /*gcc_jit_type *type */\n"
3425 " %s); /* const char *name */\n",
3427 r.get_identifier (get_context ()),
3428 r.get_identifier (m_loc),
3429 r.get_identifier_as_type (m_type),
3430 m_name->get_debug_string ());
3433 /* The implementation of class gcc::jit::recording::function. */
3435 /* gcc::jit::recording::function's constructor. */
3437 recording::function::function (context *ctxt,
3438 recording::location *loc,
3439 enum gcc_jit_function_kind kind,
3440 type *return_type,
3441 recording::string *name,
3442 int num_params,
3443 recording::param **params,
3444 int is_variadic,
3445 enum built_in_function builtin_id)
3446 : memento (ctxt),
3447 m_loc (loc),
3448 m_kind (kind),
3449 m_return_type (return_type),
3450 m_name (name),
3451 m_params (),
3452 m_is_variadic (is_variadic),
3453 m_builtin_id (builtin_id),
3454 m_locals (),
3455 m_blocks ()
3457 for (int i = 0; i< num_params; i++)
3459 param *param = params[i];
3460 gcc_assert (param);
3462 /* Associate each param with this function.
3464 Verify that the param doesn't already have a function. */
3465 if (param->get_scope ())
3467 /* We've already rejected attempts to reuse a param between
3468 different functions (within gcc_jit_context_new_function), so
3469 if the param *does* already have a function, it must be being
3470 reused within the params array for this function. We must
3471 produce an error for this reuse (blocking the compile), since
3472 otherwise we'd have an ICE later on. */
3473 gcc_assert (this == param->get_scope ());
3474 ctxt->add_error
3475 (loc,
3476 "gcc_jit_context_new_function:"
3477 " parameter %s (type: %s)"
3478 " is used more than once when creating function %s",
3479 param->get_debug_string (),
3480 param->get_type ()->get_debug_string (),
3481 name->c_str ());
3483 else
3485 /* The normal, non-error case: associate this function with the
3486 param. */
3487 param->set_scope (this);
3490 m_params.safe_push (param);
3494 /* Implementation of pure virtual hook recording::memento::replay_into
3495 for recording::function. */
3497 void
3498 recording::function::replay_into (replayer *r)
3500 /* Convert m_params to a vec of playback param. */
3501 auto_vec <playback::param *> params;
3502 int i;
3503 recording::param *param;
3504 params.create (m_params.length ());
3505 FOR_EACH_VEC_ELT (m_params, i, param)
3506 params.safe_push (param->playback_param ());
3508 set_playback_obj (r->new_function (playback_location (r, m_loc),
3509 m_kind,
3510 m_return_type->playback_type (),
3511 m_name->c_str (),
3512 &params,
3513 m_is_variadic,
3514 m_builtin_id));
3517 /* Create a recording::local instance and add it to
3518 the functions's context's list of mementos, and to the function's
3519 list of locals.
3521 Implements the post-error-checking part of
3522 gcc_jit_function_new_local. */
3524 recording::lvalue *
3525 recording::function::new_local (recording::location *loc,
3526 type *type,
3527 const char *name)
3529 local *result = new local (this, loc, type, new_string (name));
3530 m_ctxt->record (result);
3531 m_locals.safe_push (result);
3532 return result;
3535 /* Create a recording::block instance and add it to
3536 the functions's context's list of mementos, and to the function's
3537 list of blocks.
3539 Implements the post-error-checking part of
3540 gcc_jit_function_new_block. */
3542 recording::block*
3543 recording::function::new_block (const char *name)
3545 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
3547 recording::block *result =
3548 new recording::block (this, m_blocks.length (), new_string (name));
3549 m_ctxt->record (result);
3550 m_blocks.safe_push (result);
3551 return result;
3554 /* Override the default implementation of
3555 recording::memento::write_to_dump by dumping a C-like
3556 representation of the function; either like a prototype
3557 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3558 all other kinds of function. */
3560 void
3561 recording::function::write_to_dump (dump &d)
3563 switch (m_kind)
3565 default: gcc_unreachable ();
3566 case GCC_JIT_FUNCTION_EXPORTED:
3567 case GCC_JIT_FUNCTION_IMPORTED:
3568 d.write ("extern ");
3569 break;
3570 case GCC_JIT_FUNCTION_INTERNAL:
3571 d.write ("static ");
3572 break;
3573 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
3574 d.write ("static inline ");
3575 break;
3577 d.write ("%s\n", m_return_type->get_debug_string ());
3579 if (d.update_locations ())
3580 m_loc = d.make_location ();
3582 d.write ("%s (", get_debug_string ());
3584 int i;
3585 recording::param *param;
3586 FOR_EACH_VEC_ELT (m_params, i, param)
3588 if (i > 0)
3589 d.write (", ");
3590 d.write ("%s %s",
3591 param->get_type ()->get_debug_string (),
3592 param->get_debug_string ());
3594 d.write (")");
3595 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
3597 d.write ("; /* (imported) */\n\n");
3599 else
3601 int i;
3602 local *var = NULL;
3603 block *b;
3604 d.write ("\n{\n");
3606 /* Write locals: */
3607 FOR_EACH_VEC_ELT (m_locals, i, var)
3608 var->write_to_dump (d);
3609 if (m_locals.length ())
3610 d.write ("\n");
3612 /* Write each block: */
3613 FOR_EACH_VEC_ELT (m_blocks, i, b)
3615 if (i > 0)
3616 d.write ("\n");
3617 b->write_to_dump (d);
3620 d.write ("}\n\n");
3624 /* Pre-compilation validation of a function, for those things we can't
3625 check until the context is (supposedly) fully-populated. */
3627 void
3628 recording::function::validate ()
3630 /* Complain about empty functions with non-void return type. */
3631 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
3632 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
3633 if (0 == m_blocks.length ())
3634 m_ctxt->add_error (m_loc,
3635 "function %s returns non-void (type: %s)"
3636 " but has no blocks",
3637 get_debug_string (),
3638 m_return_type->get_debug_string ());
3640 /* Check that all blocks are terminated. */
3641 int num_invalid_blocks = 0;
3643 int i;
3644 block *b;
3646 FOR_EACH_VEC_ELT (m_blocks, i, b)
3647 if (!b->validate ())
3648 num_invalid_blocks++;
3651 /* Check that all blocks are reachable. */
3652 if (!m_ctxt->get_inner_bool_option
3653 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
3654 && m_blocks.length () > 0 && 0 == num_invalid_blocks)
3656 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3657 flag, starting at the initial block. */
3658 auto_vec<block *> worklist (m_blocks.length ());
3659 worklist.safe_push (m_blocks[0]);
3660 while (worklist.length () > 0)
3662 block *b = worklist.pop ();
3663 b->m_is_reachable = true;
3665 /* Add successor blocks that aren't yet marked to the worklist. */
3666 /* We checked that each block has a terminating statement above . */
3667 vec <block *> successors = b->get_successor_blocks ();
3668 int i;
3669 block *succ;
3670 FOR_EACH_VEC_ELT (successors, i, succ)
3671 if (!succ->m_is_reachable)
3672 worklist.safe_push (succ);
3673 successors.release ();
3676 /* Now complain about any blocks that haven't been marked. */
3678 int i;
3679 block *b;
3680 FOR_EACH_VEC_ELT (m_blocks, i, b)
3681 if (!b->m_is_reachable)
3682 m_ctxt->add_error (b->get_loc (),
3683 "unreachable block: %s",
3684 b->get_debug_string ());
3689 /* Implements the post-error-checking part of
3690 gcc_jit_function_dump_to_dot. */
3692 void
3693 recording::function::dump_to_dot (const char *path)
3695 FILE *fp = fopen (path, "w");
3696 if (!fp)
3697 return;
3699 pretty_printer the_pp;
3700 the_pp.buffer->stream = fp;
3702 pretty_printer *pp = &the_pp;
3704 pp_printf (pp,
3705 "digraph %s {\n", get_debug_string ());
3707 /* Blocks: */
3709 int i;
3710 block *b;
3711 FOR_EACH_VEC_ELT (m_blocks, i, b)
3712 b->dump_to_dot (pp);
3715 /* Edges: */
3717 int i;
3718 block *b;
3719 FOR_EACH_VEC_ELT (m_blocks, i, b)
3720 b->dump_edges_to_dot (pp);
3723 pp_printf (pp, "}\n");
3724 pp_flush (pp);
3725 fclose (fp);
3728 /* Implementation of recording::memento::make_debug_string for
3729 functions. */
3731 recording::string *
3732 recording::function::make_debug_string ()
3734 return m_name;
3737 /* A table of enum gcc_jit_function_kind values expressed in string
3738 form. */
3740 static const char * const names_of_function_kinds[] = {
3741 "GCC_JIT_FUNCTION_EXPORTED",
3742 "GCC_JIT_FUNCTION_INTERNAL",
3743 "GCC_JIT_FUNCTION_IMPORTED",
3744 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3747 /* Implementation of recording::memento::write_reproducer for functions. */
3749 void
3750 recording::function::write_reproducer (reproducer &r)
3752 const char *id = r.make_identifier (this, "func");
3754 if (m_builtin_id)
3756 r.write (" gcc_jit_function *%s =\n"
3757 " gcc_jit_context_get_builtin_function (%s,\n"
3758 " %s);\n",
3760 r.get_identifier (get_context ()),
3761 m_name->get_debug_string ());
3762 return;
3764 const char *params_id = r.make_tmp_identifier ("params_for", this);
3765 r.write (" gcc_jit_param *%s[%i] = {\n",
3766 params_id,
3767 m_params.length ());
3768 int i;
3769 param *param;
3770 FOR_EACH_VEC_ELT (m_params, i, param)
3771 r.write (" %s,\n", r.get_identifier (param));
3772 r.write (" };\n");
3773 r.write (" gcc_jit_function *%s =\n"
3774 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3775 " %s, /* gcc_jit_location *loc */\n"
3776 " %s, /* enum gcc_jit_function_kind kind */\n"
3777 " %s, /* gcc_jit_type *return_type */\n"
3778 " %s, /* const char *name */\n"
3779 " %i, /* int num_params */\n"
3780 " %s, /* gcc_jit_param **params */\n"
3781 " %i); /* int is_variadic */\n",
3783 r.get_identifier (get_context ()),
3784 r.get_identifier (m_loc),
3785 names_of_function_kinds[m_kind],
3786 r.get_identifier_as_type (m_return_type),
3787 m_name->get_debug_string (),
3788 m_params.length (),
3789 params_id,
3790 m_is_variadic);
3794 /* The implementation of class gcc::jit::recording::block. */
3796 /* Create a recording::eval instance and add it to
3797 the block's context's list of mementos, and to the block's
3798 list of statements.
3800 Implements the heart of gcc_jit_block_add_eval. */
3802 recording::statement *
3803 recording::block::add_eval (recording::location *loc,
3804 recording::rvalue *rvalue)
3806 statement *result = new eval (this, loc, rvalue);
3807 m_ctxt->record (result);
3808 m_statements.safe_push (result);
3809 return result;
3812 /* Create a recording::assignment instance and add it to
3813 the block's context's list of mementos, and to the block's
3814 list of statements.
3816 Implements the heart of gcc_jit_block_add_assignment. */
3818 recording::statement *
3819 recording::block::add_assignment (recording::location *loc,
3820 recording::lvalue *lvalue,
3821 recording::rvalue *rvalue)
3823 statement *result = new assignment (this, loc, lvalue, rvalue);
3824 m_ctxt->record (result);
3825 m_statements.safe_push (result);
3826 return result;
3829 /* Create a recording::assignment_op instance and add it to
3830 the block's context's list of mementos, and to the block's
3831 list of statements.
3833 Implements the heart of gcc_jit_block_add_assignment_op. */
3835 recording::statement *
3836 recording::block::add_assignment_op (recording::location *loc,
3837 recording::lvalue *lvalue,
3838 enum gcc_jit_binary_op op,
3839 recording::rvalue *rvalue)
3841 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
3842 m_ctxt->record (result);
3843 m_statements.safe_push (result);
3844 return result;
3847 /* Create a recording::comment instance and add it to
3848 the block's context's list of mementos, and to the block's
3849 list of statements.
3851 Implements the heart of gcc_jit_block_add_comment. */
3853 recording::statement *
3854 recording::block::add_comment (recording::location *loc,
3855 const char *text)
3857 statement *result = new comment (this, loc, new_string (text));
3858 m_ctxt->record (result);
3859 m_statements.safe_push (result);
3860 return result;
3863 /* Create a recording::end_with_conditional instance and add it to
3864 the block's context's list of mementos, and to the block's
3865 list of statements.
3867 Implements the heart of gcc_jit_block_end_with_conditional. */
3869 recording::statement *
3870 recording::block::end_with_conditional (recording::location *loc,
3871 recording::rvalue *boolval,
3872 recording::block *on_true,
3873 recording::block *on_false)
3875 statement *result = new conditional (this, loc, boolval, on_true, on_false);
3876 m_ctxt->record (result);
3877 m_statements.safe_push (result);
3878 m_has_been_terminated = true;
3879 return result;
3882 /* Create a recording::end_with_jump instance and add it to
3883 the block's context's list of mementos, and to the block's
3884 list of statements.
3886 Implements the heart of gcc_jit_block_end_with_jump. */
3888 recording::statement *
3889 recording::block::end_with_jump (recording::location *loc,
3890 recording::block *target)
3892 statement *result = new jump (this, loc, target);
3893 m_ctxt->record (result);
3894 m_statements.safe_push (result);
3895 m_has_been_terminated = true;
3896 return result;
3899 /* Create a recording::end_with_return instance and add it to
3900 the block's context's list of mementos, and to the block's
3901 list of statements.
3903 Implements the post-error-checking parts of
3904 gcc_jit_block_end_with_return and
3905 gcc_jit_block_end_with_void_return. */
3907 recording::statement *
3908 recording::block::end_with_return (recording::location *loc,
3909 recording::rvalue *rvalue)
3911 /* This is used by both gcc_jit_function_add_return and
3912 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3913 the former and NULL for the latter. */
3914 statement *result = new return_ (this, loc, rvalue);
3915 m_ctxt->record (result);
3916 m_statements.safe_push (result);
3917 m_has_been_terminated = true;
3918 return result;
3921 /* Create a recording::switch_ instance and add it to
3922 the block's context's list of mementos, and to the block's
3923 list of statements.
3925 Implements the heart of gcc_jit_block_end_with_switch. */
3927 recording::statement *
3928 recording::block::end_with_switch (recording::location *loc,
3929 recording::rvalue *expr,
3930 recording::block *default_block,
3931 int num_cases,
3932 recording::case_ **cases)
3934 statement *result = new switch_ (this, loc,
3935 expr,
3936 default_block,
3937 num_cases,
3938 cases);
3939 m_ctxt->record (result);
3940 m_statements.safe_push (result);
3941 m_has_been_terminated = true;
3942 return result;
3945 /* Override the default implementation of
3946 recording::memento::write_to_dump for blocks by writing
3947 an unindented block name as a label, followed by the indented
3948 statements:
3950 BLOCK_NAME:
3951 STATEMENT_1;
3952 STATEMENT_2;
3954 STATEMENT_N; */
3956 void
3957 recording::block::write_to_dump (dump &d)
3959 d.write ("%s:\n", get_debug_string ());
3961 int i;
3962 statement *s;
3963 FOR_EACH_VEC_ELT (m_statements, i, s)
3964 s->write_to_dump (d);
3967 /* Validate a block by ensuring that it has been terminated. */
3969 bool
3970 recording::block::validate ()
3972 /* Check for termination. */
3973 if (!has_been_terminated ())
3975 statement *stmt = get_last_statement ();
3976 location *loc = stmt ? stmt->get_loc () : NULL;
3977 m_func->get_context ()->add_error (loc,
3978 "unterminated block in %s: %s",
3979 m_func->get_debug_string (),
3980 get_debug_string ());
3981 return false;
3984 return true;
3987 /* Get the source-location of a block by using that of the first
3988 statement within it, if any. */
3990 recording::location *
3991 recording::block::get_loc () const
3993 recording::statement *stmt = get_first_statement ();
3994 if (stmt)
3995 return stmt->get_loc ();
3996 else
3997 return NULL;
4000 /* Get the first statement within a block, if any. */
4002 recording::statement *
4003 recording::block::get_first_statement () const
4005 if (m_statements.length ())
4006 return m_statements[0];
4007 else
4008 return NULL;
4011 /* Get the last statement within a block, if any. */
4013 recording::statement *
4014 recording::block::get_last_statement () const
4016 if (m_statements.length ())
4017 return m_statements[m_statements.length () - 1];
4018 else
4019 return NULL;
4022 /* Assuming that this block has been terminated, get the successor blocks
4023 as a vector. Ownership of the vector transfers to the caller, which
4024 must call its release () method.
4026 Used when validating functions, and when dumping dot representations
4027 of them. */
4029 vec <recording::block *>
4030 recording::block::get_successor_blocks () const
4032 gcc_assert (m_has_been_terminated);
4033 statement *last_statement = get_last_statement ();
4034 gcc_assert (last_statement);
4035 return last_statement->get_successor_blocks ();
4038 /* Implementation of pure virtual hook recording::memento::replay_into
4039 for recording::block. */
4041 void
4042 recording::block::replay_into (replayer *)
4044 set_playback_obj (m_func->playback_function ()
4045 ->new_block (playback_string (m_name)));
4048 /* Implementation of recording::memento::make_debug_string for
4049 blocks. */
4051 recording::string *
4052 recording::block::make_debug_string ()
4054 if (m_name)
4055 return m_name;
4056 else
4057 return string::from_printf (m_ctxt,
4058 "<UNNAMED BLOCK %p>",
4059 (void *)this);
4062 /* Implementation of recording::memento::write_reproducer for blocks. */
4064 void
4065 recording::block::write_reproducer (reproducer &r)
4067 const char *id = r.make_identifier (this, "block");
4068 r.write (" gcc_jit_block *%s =\n"
4069 " gcc_jit_function_new_block (%s, %s);\n",
4071 r.get_identifier (m_func),
4072 m_name ? m_name->get_debug_string () : "NULL");
4075 /* Dump a block in graphviz form into PP, capturing the block name (if
4076 any) and the statements. */
4078 void
4079 recording::block::dump_to_dot (pretty_printer *pp)
4081 pp_printf (pp,
4082 ("\tblock_%d "
4083 "[shape=record,style=filled,fillcolor=white,label=\"{"),
4084 m_index);
4085 pp_write_text_to_stream (pp);
4086 if (m_name)
4088 pp_string (pp, m_name->c_str ());
4089 pp_string (pp, ":");
4090 pp_newline (pp);
4091 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4094 int i;
4095 statement *s;
4096 FOR_EACH_VEC_ELT (m_statements, i, s)
4098 pp_string (pp, s->get_debug_string ());
4099 pp_newline (pp);
4100 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4103 pp_printf (pp,
4104 "}\"];\n\n");
4105 pp_flush (pp);
4108 /* Dump the out-edges of the block in graphviz form into PP. */
4110 void
4111 recording::block::dump_edges_to_dot (pretty_printer *pp)
4113 vec <block *> successors = get_successor_blocks ();
4114 int i;
4115 block *succ;
4116 FOR_EACH_VEC_ELT (successors, i, succ)
4117 pp_printf (pp,
4118 "\tblock_%d:s -> block_%d:n;\n",
4119 m_index, succ->m_index);
4120 successors.release ();
4123 /* The implementation of class gcc::jit::recording::global. */
4125 /* Implementation of pure virtual hook recording::memento::replay_into
4126 for recording::global. */
4128 void
4129 recording::global::replay_into (replayer *r)
4131 set_playback_obj (r->new_global (playback_location (r, m_loc),
4132 m_kind,
4133 m_type->playback_type (),
4134 playback_string (m_name)));
4137 /* Override the default implementation of
4138 recording::memento::write_to_dump for globals.
4139 This will be of the form:
4141 GCC_JIT_GLOBAL_EXPORTED:
4142 "TYPE NAME;"
4143 e.g. "int foo;"
4145 GCC_JIT_GLOBAL_INTERNAL:
4146 "static TYPE NAME;"
4147 e.g. "static int foo;"
4149 GCC_JIT_GLOBAL_IMPORTED:
4150 "extern TYPE NAME;"
4151 e.g. "extern int foo;"
4153 These are written to the top of the dump by
4154 recording::context::dump_to_file. */
4156 void
4157 recording::global::write_to_dump (dump &d)
4159 if (d.update_locations ())
4160 m_loc = d.make_location ();
4162 switch (m_kind)
4164 default:
4165 gcc_unreachable ();
4167 case GCC_JIT_GLOBAL_EXPORTED:
4168 break;
4170 case GCC_JIT_GLOBAL_INTERNAL:
4171 d.write ("static ");
4172 break;
4174 case GCC_JIT_GLOBAL_IMPORTED:
4175 d.write ("extern ");
4176 break;
4178 d.write ("%s %s;\n",
4179 m_type->get_debug_string (),
4180 get_debug_string ());
4183 /* A table of enum gcc_jit_global_kind values expressed in string
4184 form. */
4186 static const char * const global_kind_reproducer_strings[] = {
4187 "GCC_JIT_GLOBAL_EXPORTED",
4188 "GCC_JIT_GLOBAL_INTERNAL",
4189 "GCC_JIT_GLOBAL_IMPORTED"
4192 /* Implementation of recording::memento::write_reproducer for globals. */
4194 void
4195 recording::global::write_reproducer (reproducer &r)
4197 const char *id = r.make_identifier (this, "block");
4198 r.write (" gcc_jit_lvalue *%s =\n"
4199 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4200 " %s, /* gcc_jit_location *loc */\n"
4201 " %s, /* enum gcc_jit_global_kind kind */\n"
4202 " %s, /* gcc_jit_type *type */\n"
4203 " %s); /* const char *name */\n",
4205 r.get_identifier (get_context ()),
4206 r.get_identifier (m_loc),
4207 global_kind_reproducer_strings[m_kind],
4208 r.get_identifier_as_type (get_type ()),
4209 m_name->get_debug_string ());
4212 /* The implementation of the various const-handling classes:
4213 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4215 /* Explicit specialization of the various mementos we're interested in. */
4216 template class recording::memento_of_new_rvalue_from_const <int>;
4217 template class recording::memento_of_new_rvalue_from_const <long>;
4218 template class recording::memento_of_new_rvalue_from_const <double>;
4219 template class recording::memento_of_new_rvalue_from_const <void *>;
4221 /* Implementation of the pure virtual hook recording::memento::replay_into
4222 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4224 template <typename HOST_TYPE>
4225 void
4226 recording::
4227 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
4229 set_playback_obj
4230 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
4231 m_value));
4234 /* The make_debug_string and write_reproducer methods vary between the
4235 various
4236 memento_of_new_rvalue_from_const <HOST_TYPE>
4237 classes, so we explicitly write specializations of them.
4239 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4240 namespaces are written out explicitly, which is why most of this file
4241 doesn't abbreviate things by entering the "recording" namespace.
4243 However, these specializations are required to be in the same namespace
4244 as the template, hence we now have to enter the gcc::jit::recording
4245 namespace. */
4247 namespace recording
4250 /* The make_debug_string specialization for <int>, which renders it as
4251 (TARGET_TYPE)LITERAL
4252 e.g.
4253 "(int)42". */
4255 template <>
4256 string *
4257 memento_of_new_rvalue_from_const <int>::make_debug_string ()
4259 return string::from_printf (m_ctxt,
4260 "(%s)%i",
4261 m_type->get_debug_string (),
4262 m_value);
4265 /* The get_wide_int specialization for <int>. */
4267 template <>
4268 bool
4269 memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const
4271 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4272 return true;
4275 /* The write_reproducer specialization for <int>. */
4277 template <>
4278 void
4279 memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
4281 const char *id = r.make_identifier (this, "rvalue");
4282 r.write (" gcc_jit_rvalue *%s =\n"
4283 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4284 " %s, /* gcc_jit_type *numeric_type */\n"
4285 " %i); /* int value */\n",
4287 r.get_identifier (get_context ()),
4288 r.get_identifier_as_type (m_type),
4289 m_value);
4292 /* The make_debug_string specialization for <long>, rendering it as
4293 (TARGET_TYPE)LITERAL
4294 e.g.
4295 "(long)42". */
4297 template <>
4298 string *
4299 memento_of_new_rvalue_from_const <long>::make_debug_string ()
4301 return string::from_printf (m_ctxt,
4302 "(%s)%li",
4303 m_type->get_debug_string (),
4304 m_value);
4307 /* The get_wide_int specialization for <long>. */
4309 template <>
4310 bool
4311 memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const
4313 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4314 return true;
4317 /* The write_reproducer specialization for <long>. */
4319 template <>
4320 void
4321 recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
4323 const char *id = r.make_identifier (this, "rvalue");
4325 /* We have to special-case LONG_MIN, since e.g.
4326 -9223372036854775808L
4327 is parsed as
4328 -(9223372036854775808L)
4329 and hence we'd get:
4330 error: integer constant is so large that it is unsigned [-Werror]
4331 Workaround this by writing (LONG_MIN + 1) - 1. */
4332 if (m_value == LONG_MIN)
4334 r.write (" gcc_jit_rvalue *%s =\n"
4335 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4336 " %s, /* gcc_jit_type *numeric_type */\n"
4337 " %ldL - 1); /* long value */\n",
4339 r.get_identifier (get_context ()),
4340 r.get_identifier_as_type (m_type),
4341 m_value + 1);;
4342 return;
4345 r.write (" gcc_jit_rvalue *%s =\n"
4346 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4347 " %s, /* gcc_jit_type *numeric_type */\n"
4348 " %ldL); /* long value */\n",
4350 r.get_identifier (get_context ()),
4351 r.get_identifier_as_type (m_type),
4352 m_value);
4355 /* The make_debug_string specialization for <double>, rendering it as
4356 (TARGET_TYPE)LITERAL
4357 e.g.
4358 "(float)42.0". */
4360 template <>
4361 string *
4362 memento_of_new_rvalue_from_const <double>::make_debug_string ()
4364 return string::from_printf (m_ctxt,
4365 "(%s)%f",
4366 m_type->get_debug_string (),
4367 m_value);
4370 /* The get_wide_int specialization for <double>. */
4372 template <>
4373 bool
4374 memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
4376 return false;
4379 /* The write_reproducer specialization for <double>. */
4381 template <>
4382 void
4383 recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
4385 const char *id = r.make_identifier (this, "rvalue");
4386 r.write (" gcc_jit_rvalue *%s =\n"
4387 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4388 " %s, /* gcc_jit_type *numeric_type */\n"
4389 " %f); /* double value */\n",
4391 r.get_identifier (get_context ()),
4392 r.get_identifier_as_type (m_type),
4393 m_value);
4396 /* The make_debug_string specialization for <void *>, rendering it as
4397 (TARGET_TYPE)HEX
4398 e.g.
4399 "(int *)0xdeadbeef"
4401 Zero is rendered as NULL e.g.
4402 "(int *)NULL". */
4404 template <>
4405 string *
4406 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
4408 if (m_value != NULL)
4409 return string::from_printf (m_ctxt,
4410 "(%s)%p",
4411 m_type->get_debug_string (), m_value);
4412 else
4413 return string::from_printf (m_ctxt,
4414 "(%s)NULL",
4415 m_type->get_debug_string ());
4418 /* The get_wide_int specialization for <void *>. */
4420 template <>
4421 bool
4422 memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const
4424 return false;
4427 /* Implementation of recording::memento::write_reproducer for <void *>
4428 values. */
4430 template <>
4431 void
4432 memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
4434 const char *id = r.make_identifier (this, "rvalue");
4435 if (m_value)
4436 r.write (" gcc_jit_rvalue *%s =\n"
4437 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4438 " %s, /* gcc_jit_type *pointer_type */\n"
4439 " (void *)%p); /* void *value */\n",
4441 r.get_identifier (get_context ()),
4442 r.get_identifier_as_type (m_type),
4443 m_value);
4444 else
4445 r.write (" gcc_jit_rvalue *%s =\n"
4446 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4447 " %s); /* gcc_jit_type *pointer_type */\n",
4449 r.get_identifier (get_context ()),
4450 r.get_identifier_as_type (m_type));
4453 /* We're done specializing make_debug_string and write_reproducer, so we
4454 can exit the gcc::jit::recording namespace. */
4456 } // namespace recording
4458 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4460 /* Implementation of pure virtual hook recording::memento::replay_into
4461 for recording::memento_of_new_string_literal. */
4463 void
4464 recording::memento_of_new_string_literal::replay_into (replayer *r)
4466 set_playback_obj (r->new_string_literal (m_value->c_str ()));
4469 /* Implementation of recording::memento::make_debug_string for
4470 string literals. */
4472 recording::string *
4473 recording::memento_of_new_string_literal::make_debug_string ()
4475 return string::from_printf (m_ctxt,
4476 "%s",
4477 m_value->get_debug_string ());
4480 /* Implementation of recording::memento::write_reproducer for string literal
4481 values. */
4483 void
4484 recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
4486 const char *id = r.make_identifier (this, "rvalue");
4487 r.write (" gcc_jit_rvalue *%s =\n"
4488 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4489 " %s); /* const char *value */\n",
4491 r.get_identifier (get_context ()),
4492 m_value->get_debug_string ());
4495 /* The implementation of class gcc::jit::recording::unary_op. */
4497 /* Implementation of pure virtual hook recording::memento::replay_into
4498 for recording::unary_op. */
4500 void
4501 recording::unary_op::replay_into (replayer *r)
4503 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
4504 m_op,
4505 get_type ()->playback_type (),
4506 m_a->playback_rvalue ()));
4509 /* Implementation of pure virtual hook recording::rvalue::visit_children
4510 for recording::unary_op. */
4511 void
4512 recording::unary_op::visit_children (rvalue_visitor *v)
4514 v->visit (m_a);
4517 /* Implementation of recording::memento::make_debug_string for
4518 unary ops. */
4520 static const char * const unary_op_strings[] = {
4521 "-", /* GCC_JIT_UNARY_OP_MINUS */
4522 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4523 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4524 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4527 recording::string *
4528 recording::unary_op::make_debug_string ()
4530 return string::from_printf (m_ctxt,
4531 "%s(%s)",
4532 unary_op_strings[m_op],
4533 m_a->get_debug_string ());
4536 static const char * const unary_op_reproducer_strings[] = {
4537 "GCC_JIT_UNARY_OP_MINUS",
4538 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4539 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4540 "GCC_JIT_UNARY_OP_ABS"
4543 /* Implementation of recording::memento::write_reproducer for unary ops. */
4545 void
4546 recording::unary_op::write_reproducer (reproducer &r)
4548 const char *id = r.make_identifier (this, "rvalue");
4549 r.write (" gcc_jit_rvalue *%s =\n"
4550 " gcc_jit_context_new_unary_op (%s,\n"
4551 " %s, /* gcc_jit_location *loc */\n"
4552 " %s, /* enum gcc_jit_unary_op op */\n"
4553 " %s, /* gcc_jit_type *result_type */\n"
4554 " %s); /* gcc_jit_rvalue *a */\n",
4556 r.get_identifier (get_context ()),
4557 r.get_identifier (m_loc),
4558 unary_op_reproducer_strings[m_op],
4559 r.get_identifier_as_type (get_type ()),
4560 r.get_identifier_as_rvalue (m_a));
4563 /* The implementation of class gcc::jit::recording::binary_op. */
4565 /* Implementation of pure virtual hook recording::memento::replay_into
4566 for recording::binary_op. */
4568 void
4569 recording::binary_op::replay_into (replayer *r)
4571 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
4572 m_op,
4573 get_type ()->playback_type (),
4574 m_a->playback_rvalue (),
4575 m_b->playback_rvalue ()));
4578 /* Implementation of pure virtual hook recording::rvalue::visit_children
4579 for recording::binary_op. */
4580 void
4581 recording::binary_op::visit_children (rvalue_visitor *v)
4583 v->visit (m_a);
4584 v->visit (m_b);
4587 /* Implementation of recording::memento::make_debug_string for
4588 binary ops. */
4590 static const char * const binary_op_strings[] = {
4591 "+", /* GCC_JIT_BINARY_OP_PLUS */
4592 "-", /* GCC_JIT_BINARY_OP_MINUS */
4593 "*", /* GCC_JIT_BINARY_OP_MULT */
4594 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4595 "%", /* GCC_JIT_BINARY_OP_MODULO */
4596 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4597 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4598 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4599 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4600 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4601 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4602 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4605 recording::string *
4606 recording::binary_op::make_debug_string ()
4608 enum precedence prec = get_precedence ();
4609 return string::from_printf (m_ctxt,
4610 "%s %s %s",
4611 m_a->get_debug_string_parens (prec),
4612 binary_op_strings[m_op],
4613 m_b->get_debug_string_parens (prec));
4616 static const char * const binary_op_reproducer_strings[] = {
4617 "GCC_JIT_BINARY_OP_PLUS",
4618 "GCC_JIT_BINARY_OP_MINUS",
4619 "GCC_JIT_BINARY_OP_MULT",
4620 "GCC_JIT_BINARY_OP_DIVIDE",
4621 "GCC_JIT_BINARY_OP_MODULO",
4622 "GCC_JIT_BINARY_OP_BITWISE_AND",
4623 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4624 "GCC_JIT_BINARY_OP_BITWISE_OR",
4625 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4626 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4627 "GCC_JIT_BINARY_OP_LSHIFT",
4628 "GCC_JIT_BINARY_OP_RSHIFT"
4631 /* Implementation of recording::memento::write_reproducer for binary ops. */
4633 void
4634 recording::binary_op::write_reproducer (reproducer &r)
4636 const char *id = r.make_identifier (this, "rvalue");
4637 r.write (" gcc_jit_rvalue *%s =\n"
4638 " gcc_jit_context_new_binary_op (%s,\n"
4639 " %s, /* gcc_jit_location *loc */\n"
4640 " %s, /* enum gcc_jit_binary_op op */\n"
4641 " %s, /* gcc_jit_type *result_type */\n"
4642 " %s, /* gcc_jit_rvalue *a */\n"
4643 " %s); /* gcc_jit_rvalue *b */\n",
4645 r.get_identifier (get_context ()),
4646 r.get_identifier (m_loc),
4647 binary_op_reproducer_strings[m_op],
4648 r.get_identifier_as_type (get_type ()),
4649 r.get_identifier_as_rvalue (m_a),
4650 r.get_identifier_as_rvalue (m_b));
4653 namespace recording {
4654 static const enum precedence binary_op_precedence[] = {
4655 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
4656 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
4658 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
4659 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
4660 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
4662 PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4663 PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4664 PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4665 PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4666 PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4667 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
4668 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
4670 } /* namespace recording */
4672 enum recording::precedence
4673 recording::binary_op::get_precedence () const
4675 return binary_op_precedence[m_op];
4678 /* The implementation of class gcc::jit::recording::comparison. */
4680 /* Implementation of recording::memento::make_debug_string for
4681 comparisons. */
4683 static const char * const comparison_strings[] =
4685 "==", /* GCC_JIT_COMPARISON_EQ */
4686 "!=", /* GCC_JIT_COMPARISON_NE */
4687 "<", /* GCC_JIT_COMPARISON_LT */
4688 "<=", /* GCC_JIT_COMPARISON_LE */
4689 ">", /* GCC_JIT_COMPARISON_GT */
4690 ">=", /* GCC_JIT_COMPARISON_GE */
4693 recording::string *
4694 recording::comparison::make_debug_string ()
4696 enum precedence prec = get_precedence ();
4697 return string::from_printf (m_ctxt,
4698 "%s %s %s",
4699 m_a->get_debug_string_parens (prec),
4700 comparison_strings[m_op],
4701 m_b->get_debug_string_parens (prec));
4704 /* A table of enum gcc_jit_comparison values expressed in string
4705 form. */
4707 static const char * const comparison_reproducer_strings[] =
4709 "GCC_JIT_COMPARISON_EQ",
4710 "GCC_JIT_COMPARISON_NE",
4711 "GCC_JIT_COMPARISON_LT",
4712 "GCC_JIT_COMPARISON_LE",
4713 "GCC_JIT_COMPARISON_GT",
4714 "GCC_JIT_COMPARISON_GE"
4717 /* Implementation of recording::memento::write_reproducer for comparisons. */
4719 void
4720 recording::comparison::write_reproducer (reproducer &r)
4722 const char *id = r.make_identifier (this, "rvalue");
4723 r.write (" gcc_jit_rvalue *%s =\n"
4724 " gcc_jit_context_new_comparison (%s,\n"
4725 " %s, /* gcc_jit_location *loc */\n"
4726 " %s, /* enum gcc_jit_comparison op */\n"
4727 " %s, /* gcc_jit_rvalue *a */\n"
4728 " %s); /* gcc_jit_rvalue *b */\n",
4730 r.get_identifier (get_context ()),
4731 r.get_identifier (m_loc),
4732 comparison_reproducer_strings[m_op],
4733 r.get_identifier_as_rvalue (m_a),
4734 r.get_identifier_as_rvalue (m_b));
4737 /* Implementation of pure virtual hook recording::memento::replay_into
4738 for recording::comparison. */
4740 void
4741 recording::comparison::replay_into (replayer *r)
4743 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
4744 m_op,
4745 m_a->playback_rvalue (),
4746 m_b->playback_rvalue ()));
4749 /* Implementation of pure virtual hook recording::rvalue::visit_children
4750 for recording::comparison. */
4752 void
4753 recording::comparison::visit_children (rvalue_visitor *v)
4755 v->visit (m_a);
4756 v->visit (m_b);
4759 namespace recording {
4760 static const enum precedence comparison_precedence[] =
4762 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
4763 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
4765 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LT */
4766 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
4767 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GT */
4768 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
4770 } /* namespace recording */
4772 enum recording::precedence
4773 recording::comparison::get_precedence () const
4775 return comparison_precedence[m_op];
4778 /* Implementation of pure virtual hook recording::memento::replay_into
4779 for recording::cast. */
4781 void
4782 recording::cast::replay_into (replayer *r)
4784 set_playback_obj (r->new_cast (playback_location (r, m_loc),
4785 m_rvalue->playback_rvalue (),
4786 get_type ()->playback_type ()));
4789 /* Implementation of pure virtual hook recording::rvalue::visit_children
4790 for recording::cast. */
4791 void
4792 recording::cast::visit_children (rvalue_visitor *v)
4794 v->visit (m_rvalue);
4797 /* Implementation of recording::memento::make_debug_string for
4798 casts. */
4800 recording::string *
4801 recording::cast::make_debug_string ()
4803 enum precedence prec = get_precedence ();
4804 return string::from_printf (m_ctxt,
4805 "(%s)%s",
4806 get_type ()->get_debug_string (),
4807 m_rvalue->get_debug_string_parens (prec));
4810 /* Implementation of recording::memento::write_reproducer for casts. */
4812 void
4813 recording::cast::write_reproducer (reproducer &r)
4815 const char *id = r.make_identifier (this, "rvalue");
4816 r.write (" gcc_jit_rvalue *%s =\n"
4817 " gcc_jit_context_new_cast (%s,\n"
4818 " %s, /* gcc_jit_location *loc */\n"
4819 " %s, /* gcc_jit_rvalue *rvalue */\n"
4820 " %s); /* gcc_jit_type *type */\n",
4822 r.get_identifier (get_context ()),
4823 r.get_identifier (m_loc),
4824 r.get_identifier_as_rvalue (m_rvalue),
4825 r.get_identifier_as_type (get_type ()));
4828 /* The implementation of class gcc::jit::recording::base_call. */
4830 /* The constructor for gcc::jit::recording::base_call. */
4832 recording::base_call::base_call (context *ctxt,
4833 location *loc,
4834 type *type_,
4835 int numargs,
4836 rvalue **args)
4837 : rvalue (ctxt, loc, type_),
4838 m_args (),
4839 m_require_tail_call (0)
4841 for (int i = 0; i< numargs; i++)
4842 m_args.safe_push (args[i]);
4845 /* Subroutine for use by call and call_though_ptr's write_reproducer
4846 methods. */
4848 void
4849 recording::base_call::write_reproducer_tail_call (reproducer &r,
4850 const char *id)
4852 if (m_require_tail_call)
4854 r.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
4855 " %i); /* int require_tail_call*/\n",
4861 /* The implementation of class gcc::jit::recording::call. */
4863 /* The constructor for gcc::jit::recording::call. */
4865 recording::call::call (recording::context *ctxt,
4866 recording::location *loc,
4867 recording::function *func,
4868 int numargs,
4869 rvalue **args)
4870 : base_call (ctxt, loc, func->get_return_type (), numargs, args),
4871 m_func (func)
4875 /* Implementation of pure virtual hook recording::memento::replay_into
4876 for recording::call. */
4878 void
4879 recording::call::replay_into (replayer *r)
4881 auto_vec<playback::rvalue *> playback_args;
4882 playback_args.create (m_args.length ());
4883 for (unsigned i = 0; i< m_args.length (); i++)
4884 playback_args.safe_push (m_args[i]->playback_rvalue ());
4886 set_playback_obj (r->new_call (playback_location (r, m_loc),
4887 m_func->playback_function (),
4888 &playback_args,
4889 m_require_tail_call));
4892 /* Implementation of pure virtual hook recording::rvalue::visit_children
4893 for recording::call. */
4895 void
4896 recording::call::visit_children (rvalue_visitor *v)
4898 for (unsigned i = 0; i< m_args.length (); i++)
4899 v->visit (m_args[i]);
4902 /* Implementation of recording::memento::make_debug_string for
4903 function calls. */
4905 recording::string *
4906 recording::call::make_debug_string ()
4908 enum precedence prec = get_precedence ();
4909 /* First, build a buffer for the arguments. */
4910 /* Calculate length of said buffer. */
4911 size_t sz = 1; /* nil terminator */
4912 for (unsigned i = 0; i< m_args.length (); i++)
4914 sz += strlen (m_args[i]->get_debug_string_parens (prec));
4915 sz += 2; /* ", " separator */
4918 /* Now allocate and populate the buffer. */
4919 char *argbuf = new char[sz];
4920 size_t len = 0;
4922 for (unsigned i = 0; i< m_args.length (); i++)
4924 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4925 len += strlen (m_args[i]->get_debug_string_parens (prec));
4926 if (i + 1 < m_args.length ())
4928 strcpy (argbuf + len, ", ");
4929 len += 2;
4932 argbuf[len] = '\0';
4934 /* ...and use it to get the string for the call as a whole. */
4935 string *result = string::from_printf (m_ctxt,
4936 "%s (%s)",
4937 m_func->get_debug_string (),
4938 argbuf);
4940 delete[] argbuf;
4942 return result;
4945 void
4946 recording::call::write_reproducer (reproducer &r)
4948 const char *id = r.make_identifier (this, "call");
4949 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4950 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4951 args_id,
4952 m_args.length ());
4953 for (unsigned i = 0; i< m_args.length (); i++)
4954 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4955 r.write (" };\n");
4956 r.write (" gcc_jit_rvalue *%s =\n"
4957 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4958 " %s, /* gcc_jit_location *loc */\n"
4959 " %s, /* gcc_jit_function *func */\n"
4960 " %i, /* int numargs */ \n"
4961 " %s); /* gcc_jit_rvalue **args*/\n",
4963 r.get_identifier (get_context ()),
4964 r.get_identifier (m_loc),
4965 r.get_identifier (m_func),
4966 m_args.length (),
4967 args_id);
4968 write_reproducer_tail_call (r, id);
4971 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4973 /* The constructor for recording::call_through_ptr. */
4975 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
4976 recording::location *loc,
4977 recording::rvalue *fn_ptr,
4978 int numargs,
4979 rvalue **args)
4980 : base_call (ctxt, loc,
4981 fn_ptr->get_type ()->dereference ()
4982 ->as_a_function_type ()->get_return_type (),
4983 numargs, args),
4984 m_fn_ptr (fn_ptr)
4988 /* Implementation of pure virtual hook recording::memento::replay_into
4989 for recording::call_through_ptr. */
4991 void
4992 recording::call_through_ptr::replay_into (replayer *r)
4994 auto_vec<playback::rvalue *> playback_args;
4995 playback_args.create (m_args.length ());
4996 for (unsigned i = 0; i< m_args.length (); i++)
4997 playback_args.safe_push (m_args[i]->playback_rvalue ());
4999 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
5000 m_fn_ptr->playback_rvalue (),
5001 &playback_args,
5002 m_require_tail_call));
5005 /* Implementation of pure virtual hook recording::rvalue::visit_children
5006 for recording::call_through_ptr. */
5008 void
5009 recording::call_through_ptr::visit_children (rvalue_visitor *v)
5011 v->visit (m_fn_ptr);
5012 for (unsigned i = 0; i< m_args.length (); i++)
5013 v->visit (m_args[i]);
5016 /* Implementation of recording::memento::make_debug_string for
5017 calls through function ptrs. */
5019 recording::string *
5020 recording::call_through_ptr::make_debug_string ()
5022 enum precedence prec = get_precedence ();
5023 /* First, build a buffer for the arguments. */
5024 /* Calculate length of said buffer. */
5025 size_t sz = 1; /* nil terminator */
5026 for (unsigned i = 0; i< m_args.length (); i++)
5028 sz += strlen (m_args[i]->get_debug_string_parens (prec));
5029 sz += 2; /* ", " separator */
5032 /* Now allocate and populate the buffer. */
5033 char *argbuf = new char[sz];
5034 size_t len = 0;
5036 for (unsigned i = 0; i< m_args.length (); i++)
5038 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
5039 len += strlen (m_args[i]->get_debug_string_parens (prec));
5040 if (i + 1 < m_args.length ())
5042 strcpy (argbuf + len, ", ");
5043 len += 2;
5046 argbuf[len] = '\0';
5048 /* ...and use it to get the string for the call as a whole. */
5049 string *result = string::from_printf (m_ctxt,
5050 "%s (%s)",
5051 m_fn_ptr->get_debug_string_parens (prec),
5052 argbuf);
5054 delete[] argbuf;
5056 return result;
5059 /* Implementation of recording::memento::write_reproducer for
5060 call_through_ptr. */
5062 void
5063 recording::call_through_ptr::write_reproducer (reproducer &r)
5065 const char *id = r.make_identifier (this, "call");
5066 const char *args_id = r.make_tmp_identifier ("args_for_", this);
5067 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
5068 args_id,
5069 m_args.length ());
5070 for (unsigned i = 0; i< m_args.length (); i++)
5071 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
5072 r.write (" };\n");
5073 r.write (" gcc_jit_rvalue *%s =\n"
5074 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
5075 " %s, /* gcc_jit_location *loc */\n"
5076 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
5077 " %i, /* int numargs */ \n"
5078 " %s); /* gcc_jit_rvalue **args*/\n",
5080 r.get_identifier (get_context ()),
5081 r.get_identifier (m_loc),
5082 r.get_identifier_as_rvalue (m_fn_ptr),
5083 m_args.length (),
5084 args_id);
5085 write_reproducer_tail_call (r, id);
5088 /* The implementation of class gcc::jit::recording::array_access. */
5090 /* Implementation of pure virtual hook recording::memento::replay_into
5091 for recording::array_access. */
5093 void
5094 recording::array_access::replay_into (replayer *r)
5096 set_playback_obj (
5097 r->new_array_access (playback_location (r, m_loc),
5098 m_ptr->playback_rvalue (),
5099 m_index->playback_rvalue ()));
5102 /* Implementation of pure virtual hook recording::rvalue::visit_children
5103 for recording::array_access. */
5105 void
5106 recording::array_access::visit_children (rvalue_visitor *v)
5108 v->visit (m_ptr);
5109 v->visit (m_index);
5112 /* Implementation of recording::memento::make_debug_string for
5113 array accesses. */
5115 recording::string *
5116 recording::array_access::make_debug_string ()
5118 enum precedence prec = get_precedence ();
5119 return string::from_printf (m_ctxt,
5120 "%s[%s]",
5121 m_ptr->get_debug_string_parens (prec),
5122 m_index->get_debug_string_parens (prec));
5125 /* Implementation of recording::memento::write_reproducer for
5126 array_access. */
5128 void
5129 recording::array_access::write_reproducer (reproducer &r)
5131 const char *id = r.make_identifier (this, "lvalue");
5132 r.write (" gcc_jit_lvalue *%s = \n"
5133 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
5134 " %s, /*gcc_jit_location *loc */\n"
5135 " %s, /* gcc_jit_rvalue *ptr */\n"
5136 " %s); /* gcc_jit_rvalue *index */\n",
5138 r.get_identifier (get_context ()),
5139 r.get_identifier (m_loc),
5140 r.get_identifier_as_rvalue (m_ptr),
5141 r.get_identifier_as_rvalue (m_index));
5144 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
5146 /* Implementation of pure virtual hook recording::memento::replay_into
5147 for recording::access_field_of_lvalue. */
5149 void
5150 recording::access_field_of_lvalue::replay_into (replayer *r)
5152 set_playback_obj (
5153 m_lvalue->playback_lvalue ()
5154 ->access_field (playback_location (r, m_loc),
5155 m_field->playback_field ()));
5159 /* Implementation of pure virtual hook recording::rvalue::visit_children
5160 for recording::access_field_of_lvalue. */
5162 void
5163 recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
5165 v->visit (m_lvalue);
5168 /* Implementation of recording::memento::make_debug_string for
5169 accessing a field of an lvalue. */
5171 recording::string *
5172 recording::access_field_of_lvalue::make_debug_string ()
5174 enum precedence prec = get_precedence ();
5175 return string::from_printf (m_ctxt,
5176 "%s.%s",
5177 m_lvalue->get_debug_string_parens (prec),
5178 m_field->get_debug_string ());
5181 /* Implementation of recording::memento::write_reproducer for
5182 access_field_of_lvalue. */
5184 void
5185 recording::access_field_of_lvalue::write_reproducer (reproducer &r)
5187 const char *id = r.make_identifier (this, "lvalue");
5188 r.write (" gcc_jit_lvalue *%s = \n"
5189 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5190 " %s, /*gcc_jit_location *loc */\n"
5191 " %s);\n",
5193 r.get_identifier_as_lvalue (m_lvalue),
5194 r.get_identifier (m_loc),
5195 r.get_identifier (m_field));
5198 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
5200 /* Implementation of pure virtual hook recording::memento::replay_into
5201 for recording::access_field_rvalue. */
5203 void
5204 recording::access_field_rvalue::replay_into (replayer *r)
5206 set_playback_obj (
5207 m_rvalue->playback_rvalue ()
5208 ->access_field (playback_location (r, m_loc),
5209 m_field->playback_field ()));
5212 /* Implementation of pure virtual hook recording::rvalue::visit_children
5213 for recording::access_field_rvalue. */
5215 void
5216 recording::access_field_rvalue::visit_children (rvalue_visitor *v)
5218 v->visit (m_rvalue);
5221 /* Implementation of recording::memento::make_debug_string for
5222 accessing a field of an rvalue. */
5224 recording::string *
5225 recording::access_field_rvalue::make_debug_string ()
5227 enum precedence prec = get_precedence ();
5228 return string::from_printf (m_ctxt,
5229 "%s.%s",
5230 m_rvalue->get_debug_string_parens (prec),
5231 m_field->get_debug_string ());
5234 /* Implementation of recording::memento::write_reproducer for
5235 access_field_rvalue. */
5237 void
5238 recording::access_field_rvalue::write_reproducer (reproducer &r)
5240 const char *id = r.make_identifier (this, "rvalue");
5241 r.write (" gcc_jit_rvalue *%s = \n"
5242 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5243 " %s, /*gcc_jit_location *loc */\n"
5244 " %s);\n",
5246 r.get_identifier_as_rvalue (m_rvalue),
5247 r.get_identifier (m_loc),
5248 r.get_identifier (m_field));
5251 /* The implementation of class
5252 gcc::jit::recording::dereference_field_rvalue. */
5254 /* Implementation of pure virtual hook recording::memento::replay_into
5255 for recording::dereference_field_rvalue. */
5257 void
5258 recording::dereference_field_rvalue::replay_into (replayer *r)
5260 set_playback_obj (
5261 m_rvalue->playback_rvalue ()->
5262 dereference_field (playback_location (r, m_loc),
5263 m_field->playback_field ()));
5266 /* Implementation of pure virtual hook recording::rvalue::visit_children
5267 for recording::dereference_field_rvalue. */
5269 void
5270 recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
5272 v->visit (m_rvalue);
5275 /* Implementation of recording::memento::make_debug_string for
5276 dereferencing a field of an rvalue. */
5278 recording::string *
5279 recording::dereference_field_rvalue::make_debug_string ()
5281 enum precedence prec = get_precedence ();
5282 return string::from_printf (m_ctxt,
5283 "%s->%s",
5284 m_rvalue->get_debug_string_parens (prec),
5285 m_field->get_debug_string ());
5288 /* Implementation of recording::memento::write_reproducer for
5289 dereference_field_rvalue. */
5291 void
5292 recording::dereference_field_rvalue::write_reproducer (reproducer &r)
5294 const char *id = r.make_identifier (this, "lvalue");
5295 r.write (" gcc_jit_lvalue *%s=\n"
5296 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5297 " %s, /* gcc_jit_location *loc */\n"
5298 " %s); /* gcc_jit_field *field */\n",
5300 r.get_identifier_as_rvalue (m_rvalue),
5301 r.get_identifier (m_loc),
5302 r.get_identifier (m_field));
5305 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5307 /* Implementation of pure virtual hook recording::memento::replay_into
5308 for recording::dereference_rvalue. */
5310 void
5311 recording::dereference_rvalue::replay_into (replayer *r)
5313 set_playback_obj (
5314 m_rvalue->playback_rvalue ()->
5315 dereference (playback_location (r, m_loc)));
5318 /* Implementation of pure virtual hook recording::rvalue::visit_children
5319 for recording::dereference_rvalue. */
5321 void
5322 recording::dereference_rvalue::visit_children (rvalue_visitor *v)
5324 v->visit (m_rvalue);
5327 /* Implementation of recording::memento::make_debug_string for
5328 dereferencing an rvalue. */
5330 recording::string *
5331 recording::dereference_rvalue::make_debug_string ()
5333 enum precedence prec = get_precedence ();
5334 return string::from_printf (m_ctxt,
5335 "*%s",
5336 m_rvalue->get_debug_string_parens (prec));
5339 /* Implementation of recording::memento::write_reproducer for
5340 dereference_rvalue. */
5342 void
5343 recording::dereference_rvalue::write_reproducer (reproducer &r)
5345 const char *id = r.make_identifier (this, "dereference");
5346 r.write (" gcc_jit_lvalue *%s =\n"
5347 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5348 " %s); /* gcc_jit_location *loc */\n",
5350 r.get_identifier_as_rvalue (m_rvalue),
5351 r.get_identifier (m_loc));
5354 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5356 /* Implementation of pure virtual hook recording::memento::replay_into
5357 for recording::get_address_of_lvalue. */
5359 void
5360 recording::get_address_of_lvalue::replay_into (replayer *r)
5362 set_playback_obj (
5363 m_lvalue->playback_lvalue ()->
5364 get_address (playback_location (r, m_loc)));
5367 /* Implementation of pure virtual hook recording::rvalue::visit_children
5368 for recording::get_address_of_lvalue. */
5370 void
5371 recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
5373 v->visit (m_lvalue);
5376 /* Implementation of recording::memento::make_debug_string for
5377 getting the address of an lvalue. */
5379 recording::string *
5380 recording::get_address_of_lvalue::make_debug_string ()
5382 enum precedence prec = get_precedence ();
5383 return string::from_printf (m_ctxt,
5384 "&%s",
5385 m_lvalue->get_debug_string_parens (prec));
5388 /* Implementation of recording::memento::write_reproducer for
5389 get_address_of_lvalue. */
5391 void
5392 recording::get_address_of_lvalue::write_reproducer (reproducer &r)
5394 const char *id = r.make_identifier (this, "address_of");
5395 r.write (" gcc_jit_rvalue *%s =\n"
5396 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5397 " %s); /* gcc_jit_location *loc */\n",
5399 r.get_identifier_as_lvalue (m_lvalue),
5400 r.get_identifier (m_loc));
5403 /* The implementation of class gcc::jit::recording::local. */
5405 /* Implementation of pure virtual hook recording::memento::replay_into
5406 for recording::local. */
5408 void
5409 recording::local::replay_into (replayer *r)
5411 set_playback_obj (
5412 m_func->playback_function ()
5413 ->new_local (playback_location (r, m_loc),
5414 m_type->playback_type (),
5415 playback_string (m_name)));
5418 /* Override the default implementation of
5419 recording::memento::write_to_dump for locals by writing
5420 TYPE NAME;
5421 for use at the top of the function body as if it were a
5422 declaration. */
5424 void
5425 recording::local::write_to_dump (dump &d)
5427 if (d.update_locations ())
5428 m_loc = d.make_location ();
5429 d.write(" %s %s;\n",
5430 m_type->get_debug_string (),
5431 get_debug_string ());
5434 void
5435 recording::local::write_reproducer (reproducer &r)
5437 const char *id = r.make_identifier (this, "local");
5438 r.write (" gcc_jit_lvalue *%s =\n"
5439 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5440 " %s, /* gcc_jit_location *loc */\n"
5441 " %s, /* gcc_jit_type *type */\n"
5442 " %s); /* const char *name */\n",
5444 r.get_identifier (m_func),
5445 r.get_identifier (m_loc),
5446 r.get_identifier_as_type (m_type),
5447 m_name->get_debug_string ());
5450 /* The implementation of class gcc::jit::recording::statement. */
5452 /* We poison the default implementation of
5453 gcc::jit::recording::statement::get_successor_blocks
5454 since this vfunc must only ever be called on terminator
5455 statements. */
5457 vec <recording::block *>
5458 recording::statement::get_successor_blocks () const
5460 /* The base class implementation is for non-terminating statements,
5461 and thus should never be called. */
5462 gcc_unreachable ();
5463 vec <block *> result;
5464 result.create (0);
5465 return result;
5468 /* Extend the default implementation of
5469 recording::memento::write_to_dump for statements by (if requested)
5470 updating the location of the statement to the current location in
5471 the dumpfile. */
5473 void
5474 recording::statement::write_to_dump (dump &d)
5476 memento::write_to_dump (d);
5477 if (d.update_locations ())
5478 m_loc = d.make_location ();
5481 /* The implementation of class gcc::jit::recording::eval. */
5483 /* Implementation of pure virtual hook recording::memento::replay_into
5484 for recording::eval. */
5486 void
5487 recording::eval::replay_into (replayer *r)
5489 playback_block (get_block ())
5490 ->add_eval (playback_location (r),
5491 m_rvalue->playback_rvalue ());
5494 /* Implementation of recording::memento::make_debug_string for
5495 an eval statement. */
5497 recording::string *
5498 recording::eval::make_debug_string ()
5500 return string::from_printf (m_ctxt,
5501 "(void)%s;",
5502 m_rvalue->get_debug_string ());
5505 /* Implementation of recording::memento::write_reproducer for
5506 eval statements. */
5508 void
5509 recording::eval::write_reproducer (reproducer &r)
5511 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5512 " %s, /* gcc_jit_location *loc */\n"
5513 " %s); /* gcc_jit_rvalue *rvalue */\n",
5514 r.get_identifier (get_block ()),
5515 r.get_identifier (get_loc ()),
5516 r.get_identifier_as_rvalue (m_rvalue));
5519 /* The implementation of class gcc::jit::recording::assignment. */
5521 /* Implementation of pure virtual hook recording::memento::replay_into
5522 for recording::assignment. */
5524 void
5525 recording::assignment::replay_into (replayer *r)
5527 playback_block (get_block ())
5528 ->add_assignment (playback_location (r),
5529 m_lvalue->playback_lvalue (),
5530 m_rvalue->playback_rvalue ());
5533 /* Implementation of recording::memento::make_debug_string for
5534 an assignment statement. */
5536 recording::string *
5537 recording::assignment::make_debug_string ()
5539 return string::from_printf (m_ctxt,
5540 "%s = %s;",
5541 m_lvalue->get_debug_string (),
5542 m_rvalue->get_debug_string ());
5545 /* Implementation of recording::memento::write_reproducer for
5546 assignment statements. */
5548 void
5549 recording::assignment::write_reproducer (reproducer &r)
5551 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5552 " %s, /* gcc_jit_location *loc */\n"
5553 " %s, /* gcc_jit_lvalue *lvalue */\n"
5554 " %s); /* gcc_jit_rvalue *rvalue */\n",
5555 r.get_identifier (get_block ()),
5556 r.get_identifier (get_loc ()),
5557 r.get_identifier_as_lvalue (m_lvalue),
5558 r.get_identifier_as_rvalue (m_rvalue));
5561 /* The implementation of class gcc::jit::recording::assignment_op. */
5563 /* Implementation of pure virtual hook recording::memento::replay_into
5564 for recording::assignment_op. */
5566 void
5567 recording::assignment_op::replay_into (replayer *r)
5569 playback::type *result_type =
5570 m_lvalue->playback_lvalue ()->get_type ();
5572 playback::rvalue *binary_op =
5573 r->new_binary_op (playback_location (r),
5574 m_op,
5575 result_type,
5576 m_lvalue->playback_rvalue (),
5577 m_rvalue->playback_rvalue ());
5579 playback_block (get_block ())
5580 ->add_assignment (playback_location (r),
5581 m_lvalue->playback_lvalue (),
5582 binary_op);
5585 /* Implementation of recording::memento::make_debug_string for
5586 an assignment_op statement. */
5588 recording::string *
5589 recording::assignment_op::make_debug_string ()
5591 return string::from_printf (m_ctxt,
5592 "%s %s= %s;",
5593 m_lvalue->get_debug_string (),
5594 binary_op_strings[m_op],
5595 m_rvalue->get_debug_string ());
5598 /* Implementation of recording::memento::write_reproducer for
5599 assignment_op statements. */
5601 void
5602 recording::assignment_op::write_reproducer (reproducer &r)
5604 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5605 " %s, /* gcc_jit_location *loc */\n"
5606 " %s, /* gcc_jit_lvalue *lvalue */\n"
5607 " %s, /* enum gcc_jit_binary_op op */\n"
5608 " %s); /* gcc_jit_rvalue *rvalue */\n",
5609 r.get_identifier (get_block ()),
5610 r.get_identifier (get_loc ()),
5611 r.get_identifier_as_lvalue (m_lvalue),
5612 binary_op_reproducer_strings[m_op],
5613 r.get_identifier_as_rvalue (m_rvalue));
5616 /* The implementation of class gcc::jit::recording::comment. */
5618 /* Implementation of pure virtual hook recording::memento::replay_into
5619 for recording::comment. */
5621 void
5622 recording::comment::replay_into (replayer *r)
5624 playback_block (get_block ())
5625 ->add_comment (playback_location (r),
5626 m_text->c_str ());
5629 /* Implementation of recording::memento::make_debug_string for
5630 a comment "statement". */
5632 recording::string *
5633 recording::comment::make_debug_string ()
5635 return string::from_printf (m_ctxt,
5636 "/* %s */",
5637 m_text->c_str ());
5640 /* Implementation of recording::memento::write_reproducer for
5641 comments. */
5643 void
5644 recording::comment::write_reproducer (reproducer &r)
5646 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5647 " %s, /* gcc_jit_location *loc */\n"
5648 " %s); /* const char *text */\n",
5649 r.get_identifier (get_block ()),
5650 r.get_identifier (get_loc ()),
5651 m_text->get_debug_string ());
5654 /* The implementation of class gcc::jit::recording::conditional. */
5656 /* Implementation of pure virtual hook recording::memento::replay_into
5657 for recording::conditional. */
5659 void
5660 recording::conditional::replay_into (replayer *r)
5662 playback_block (get_block ())
5663 ->add_conditional (playback_location (r),
5664 m_boolval->playback_rvalue (),
5665 playback_block (m_on_true),
5666 playback_block (m_on_false));
5669 /* Override the poisoned default implementation of
5670 gcc::jit::recording::statement::get_successor_blocks
5672 A conditional jump has 2 successor blocks. */
5674 vec <recording::block *>
5675 recording::conditional::get_successor_blocks () const
5677 vec <block *> result;
5678 result.create (2);
5679 result.quick_push (m_on_true);
5680 result.quick_push (m_on_false);
5681 return result;
5684 /* Implementation of recording::memento::make_debug_string for
5685 a conditional jump statement. */
5687 recording::string *
5688 recording::conditional::make_debug_string ()
5690 if (m_on_false)
5691 return string::from_printf (m_ctxt,
5692 "if (%s) goto %s; else goto %s;",
5693 m_boolval->get_debug_string (),
5694 m_on_true->get_debug_string (),
5695 m_on_false->get_debug_string ());
5696 else
5697 return string::from_printf (m_ctxt,
5698 "if (%s) goto %s;",
5699 m_boolval->get_debug_string (),
5700 m_on_true->get_debug_string ());
5703 /* Implementation of recording::memento::write_reproducer for
5704 conditional statements. */
5706 void
5707 recording::conditional::write_reproducer (reproducer &r)
5709 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5710 " %s, /* gcc_jit_location *loc */\n"
5711 " %s, /* gcc_jit_rvalue *boolval */\n"
5712 " %s, /* gcc_jit_block *on_true */\n"
5713 " %s); /* gcc_jit_block *on_false */\n",
5714 r.get_identifier (get_block ()),
5715 r.get_identifier (get_loc ()),
5716 r.get_identifier_as_rvalue (m_boolval),
5717 r.get_identifier (m_on_true),
5718 r.get_identifier (m_on_false));
5721 /* The implementation of class gcc::jit::recording::jump. */
5723 /* Implementation of pure virtual hook recording::memento::replay_into
5724 for recording::jump. */
5726 void
5727 recording::jump::replay_into (replayer *r)
5729 playback_block (get_block ())
5730 ->add_jump (playback_location (r),
5731 m_target->playback_block ());
5734 /* Override the poisoned default implementation of
5735 gcc::jit::recording::statement::get_successor_blocks
5737 An unconditional jump has 1 successor block. */
5739 vec <recording::block *>
5740 recording::jump::get_successor_blocks () const
5742 vec <block *> result;
5743 result.create (1);
5744 result.quick_push (m_target);
5745 return result;
5748 /* Implementation of recording::memento::make_debug_string for
5749 a unconditional jump statement. */
5751 recording::string *
5752 recording::jump::make_debug_string ()
5754 return string::from_printf (m_ctxt,
5755 "goto %s;",
5756 m_target->get_debug_string ());
5759 /* Implementation of recording::memento::write_reproducer for
5760 jump statements. */
5762 void
5763 recording::jump::write_reproducer (reproducer &r)
5765 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5766 " %s, /* gcc_jit_location *loc */\n"
5767 " %s); /* gcc_jit_block *target */\n",
5768 r.get_identifier (get_block ()),
5769 r.get_identifier (get_loc ()),
5770 r.get_identifier (m_target));
5773 /* The implementation of class gcc::jit::recording::return_. */
5775 /* Implementation of pure virtual hook recording::memento::replay_into
5776 for recording::return_. */
5778 void
5779 recording::return_::replay_into (replayer *r)
5781 playback_block (get_block ())
5782 ->add_return (playback_location (r),
5783 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
5786 /* Override the poisoned default implementation of
5787 gcc::jit::recording::statement::get_successor_blocks
5789 A return statement has no successor block. */
5791 vec <recording::block *>
5792 recording::return_::get_successor_blocks () const
5794 vec <block *> result;
5795 result.create (0);
5796 return result;
5799 /* Implementation of recording::memento::make_debug_string for
5800 a return statement (covers both those with and without rvalues). */
5802 recording::string *
5803 recording::return_::make_debug_string ()
5805 if (m_rvalue)
5806 return string::from_printf (m_ctxt,
5807 "return %s;",
5808 m_rvalue->get_debug_string ());
5809 else
5810 return string::from_printf (m_ctxt,
5811 "return;");
5814 /* Implementation of recording::memento::write_reproducer for
5815 return statements. */
5817 void
5818 recording::return_::write_reproducer (reproducer &r)
5820 if (m_rvalue)
5821 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5822 " %s, /* gcc_jit_location *loc */\n"
5823 " %s); /* gcc_jit_rvalue *rvalue */\n",
5824 r.get_identifier (get_block ()),
5825 r.get_identifier (get_loc ()),
5826 r.get_identifier_as_rvalue (m_rvalue));
5827 else
5828 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5829 " %s); /* gcc_jit_location *loc */\n",
5830 r.get_identifier (get_block ()),
5831 r.get_identifier (get_loc ()));
5834 /* The implementation of class gcc::jit::recording::case_. */
5836 void
5837 recording::case_::write_reproducer (reproducer &r)
5839 const char *id = r.make_identifier (this, "case");
5840 const char *fmt =
5841 " gcc_jit_case *%s = \n"
5842 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
5843 " %s, /* gcc_jit_rvalue *min_value */\n"
5844 " %s, /* gcc_jit_rvalue *max_value */\n"
5845 " %s); /* gcc_jit_block *dest_block */\n";
5846 r.write (fmt,
5848 r.get_identifier (get_context ()),
5849 r.get_identifier_as_rvalue (m_min_value),
5850 r.get_identifier_as_rvalue (m_max_value),
5851 r.get_identifier (m_dest_block));
5854 recording::string *
5855 recording::case_::make_debug_string ()
5857 return string::from_printf (get_context (),
5858 "case %s ... %s: goto %s;",
5859 m_min_value->get_debug_string (),
5860 m_max_value->get_debug_string (),
5861 m_dest_block->get_debug_string ());
5864 /* The implementation of class gcc::jit::recording::switch_. */
5866 /* gcc::jit::recording::switch_'s constructor. */
5868 recording::switch_::switch_ (block *b,
5869 location *loc,
5870 rvalue *expr,
5871 block *default_block,
5872 int num_cases,
5873 case_ **cases)
5874 : statement (b, loc),
5875 m_expr (expr),
5876 m_default_block (default_block)
5878 m_cases.reserve_exact (num_cases);
5879 for (int i = 0; i< num_cases; i++)
5880 m_cases.quick_push (cases[i]);
5883 /* Implementation of pure virtual hook recording::memento::replay_into
5884 for recording::switch_. */
5886 void
5887 recording::switch_::replay_into (replayer *r)
5889 auto_vec <playback::case_> pcases;
5890 int i;
5891 recording::case_ *rcase;
5892 pcases.reserve_exact (m_cases.length ());
5893 FOR_EACH_VEC_ELT (m_cases, i, rcase)
5895 playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (),
5896 rcase->get_max_value ()->playback_rvalue (),
5897 rcase->get_dest_block ()->playback_block ());
5898 pcases.safe_push (pcase);
5900 playback_block (get_block ())
5901 ->add_switch (playback_location (r),
5902 m_expr->playback_rvalue (),
5903 m_default_block->playback_block (),
5904 &pcases);
5907 /* Override the poisoned default implementation of
5908 gcc::jit::recording::statement::get_successor_blocks
5910 A switch statement has (NUM_CASES + 1) successor blocks. */
5912 vec <recording::block *>
5913 recording::switch_::get_successor_blocks () const
5915 vec <block *> result;
5916 result.create (m_cases.length () + 1);
5917 result.quick_push (m_default_block);
5918 int i;
5919 case_ *c;
5920 FOR_EACH_VEC_ELT (m_cases, i, c)
5921 result.quick_push (c->get_dest_block ());
5922 return result;
5925 /* Implementation of recording::memento::make_debug_string for
5926 a switch statement. */
5928 recording::string *
5929 recording::switch_::make_debug_string ()
5931 auto_vec <char> cases_str;
5932 int i;
5933 case_ *c;
5934 FOR_EACH_VEC_ELT (m_cases, i, c)
5936 size_t len = strlen (c->get_debug_string ());
5937 unsigned idx = cases_str.length ();
5938 cases_str.safe_grow (idx + 1 + len);
5939 cases_str[idx] = ' ';
5940 memcpy (&(cases_str[idx + 1]),
5941 c->get_debug_string (),
5942 len);
5944 cases_str.safe_push ('\0');
5946 return string::from_printf (m_ctxt,
5947 "switch (%s) {default: goto %s;%s}",
5948 m_expr->get_debug_string (),
5949 m_default_block->get_debug_string (),
5950 &cases_str[0]);
5953 /* Implementation of recording::memento::write_reproducer for
5954 switch statements. */
5956 void
5957 recording::switch_::write_reproducer (reproducer &r)
5959 r.make_identifier (this, "switch");
5960 int i;
5961 case_ *c;
5962 const char *cases_id =
5963 r.make_tmp_identifier ("cases_for", this);
5964 r.write (" gcc_jit_case *%s[%i] = {\n",
5965 cases_id,
5966 m_cases.length ());
5967 FOR_EACH_VEC_ELT (m_cases, i, c)
5968 r.write (" %s,\n", r.get_identifier (c));
5969 r.write (" };\n");
5970 const char *fmt =
5971 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
5972 " %s, /* gcc_jit_location *loc */\n"
5973 " %s, /* gcc_jit_rvalue *expr */\n"
5974 " %s, /* gcc_jit_block *default_block */\n"
5975 " %i, /* int num_cases */\n"
5976 " %s); /* gcc_jit_case **cases */\n";
5977 r.write (fmt,
5978 r.get_identifier (get_block ()),
5979 r.get_identifier (get_loc ()),
5980 r.get_identifier_as_rvalue (m_expr),
5981 r.get_identifier (m_default_block),
5982 m_cases.length (),
5983 cases_id);
5986 } // namespace gcc::jit
5988 } // namespace gcc