Improve costs for DImode shifts of interger constants.
[official-gcc.git] / gcc / jit / jit-recording.c
blob3cbeba0f3714b97d2c50559c508b526bfcfeca12
1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2020 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 *, false, 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 /* A helper class for implementing make_debug_string, for building
451 a temporary string from a vec of rvalues. */
453 class comma_separated_string
455 public:
456 comma_separated_string (const auto_vec<recording::rvalue *> &rvalues,
457 enum recording::precedence prec);
458 ~comma_separated_string ();
460 const char *as_char_ptr () const { return m_buf; }
462 private:
463 char *m_buf;
466 /* comma_separated_string's ctor
467 Build m_buf. */
469 comma_separated_string::comma_separated_string
470 (const auto_vec<recording::rvalue *> &rvalues,
471 enum recording::precedence prec)
472 : m_buf (NULL)
474 /* Calculate length of said buffer. */
475 size_t sz = 1; /* nil terminator */
476 for (unsigned i = 0; i< rvalues.length (); i++)
478 sz += strlen (rvalues[i]->get_debug_string_parens (prec));
479 sz += 2; /* ", " separator */
482 /* Now allocate and populate the buffer. */
483 m_buf = new char[sz];
484 size_t len = 0;
486 for (unsigned i = 0; i< rvalues.length (); i++)
488 strcpy (m_buf + len, rvalues[i]->get_debug_string_parens (prec));
489 len += strlen (rvalues[i]->get_debug_string_parens (prec));
490 if (i + 1 < rvalues.length ())
492 strcpy (m_buf + len, ", ");
493 len += 2;
496 m_buf[len] = '\0';
499 /* comma_separated_string's dtor. */
501 comma_separated_string::~comma_separated_string ()
503 delete[] m_buf;
506 /**********************************************************************
507 Recording.
508 **********************************************************************/
510 /* Get the playback::location for the given recording::location,
511 handling a NULL input with a NULL output. */
513 playback::location *
514 recording::playback_location (replayer *r, recording::location *loc)
516 if (loc)
517 return loc->playback_location (r);
518 else
519 return NULL;
522 /* Get a const char * for the given recording::string
523 handling a NULL input with a NULL output. */
525 const char *
526 recording::playback_string (recording::string *str)
528 if (str)
529 return str->c_str ();
530 else
531 return NULL;
534 /* Get the playback::block for the given recording::block,
535 handling a NULL input with a NULL output. */
537 playback::block *
538 recording::playback_block (recording::block *b)
540 if (b)
541 return b->playback_block ();
542 else
543 return NULL;
546 /* Methods of cc::jit::recording::context. */
548 /* The constructor for gcc::jit::recording::context, used by
549 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
551 recording::context::context (context *parent_ctxt)
552 : log_user (NULL),
553 m_parent_ctxt (parent_ctxt),
554 m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this),
555 m_timer (NULL),
556 m_error_count (0),
557 m_first_error_str (NULL),
558 m_owns_first_error_str (false),
559 m_last_error_str (NULL),
560 m_owns_last_error_str (false),
561 m_mementos (),
562 m_compound_types (),
563 m_globals (),
564 m_functions (),
565 m_FILE_type (NULL),
566 m_builtins_manager(NULL)
568 if (parent_ctxt)
570 /* Inherit options from parent. */
571 for (unsigned i = 0;
572 i < sizeof (m_str_options) / sizeof (m_str_options[0]);
573 i++)
575 const char *parent_opt = parent_ctxt->m_str_options[i];
576 m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
578 memcpy (m_int_options,
579 parent_ctxt->m_int_options,
580 sizeof (m_int_options));
581 memcpy (m_bool_options,
582 parent_ctxt->m_bool_options,
583 sizeof (m_bool_options));
584 memcpy (m_inner_bool_options,
585 parent_ctxt->m_inner_bool_options,
586 sizeof (m_inner_bool_options));
587 set_logger (parent_ctxt->get_logger ());
589 else
591 memset (m_str_options, 0, sizeof (m_str_options));
592 memset (m_int_options, 0, sizeof (m_int_options));
593 memset (m_bool_options, 0, sizeof (m_bool_options));
594 memset (m_inner_bool_options, 0, sizeof (m_inner_bool_options));
597 memset (m_basic_types, 0, sizeof (m_basic_types));
600 /* The destructor for gcc::jit::recording::context, implicitly used by
601 gcc_jit_context_release. */
603 recording::context::~context ()
605 JIT_LOG_SCOPE (get_logger ());
606 int i;
607 memento *m;
608 FOR_EACH_VEC_ELT (m_mementos, i, m)
610 delete m;
613 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
614 free (m_str_options[i]);
616 char *optname;
617 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
618 free (optname);
619 FOR_EACH_VEC_ELT (m_driver_options, i, optname)
620 free (optname);
622 if (m_builtins_manager)
623 delete m_builtins_manager;
625 if (m_owns_first_error_str)
626 free (m_first_error_str);
628 if (m_owns_last_error_str)
629 if (m_last_error_str != m_first_error_str)
630 free (m_last_error_str);
633 /* Add the given mememto to the list of those tracked by this
634 gcc::jit::recording::context, so that e.g. it can be deleted
635 when this context is released. */
637 void
638 recording::context::record (memento *m)
640 gcc_assert (m);
642 m_mementos.safe_push (m);
645 /* Replay this context (and any parents) into the given replayer. */
647 void
648 recording::context::replay_into (replayer *r)
650 JIT_LOG_SCOPE (get_logger ());
651 int i;
652 memento *m;
654 /* If we have a parent context, we must replay it. This will
655 recursively walk backwards up the historical tree, then replay things
656 forwards "in historical order", starting with the ultimate parent
657 context, until we reach the "this" context.
659 Note that we fully replay the parent, then fully replay the child,
660 which means that inter-context references can only exist from child
661 to parent, not the other way around.
663 All of this replaying is suboptimal - it would be better to do the
664 work for the parent context *once*, rather than replaying the parent
665 every time we replay each child. However, fixing this requires deep
666 surgery to lifetime-management: we'd need every context family tree
667 to have its own GC heap, and to initialize the GCC code to use that
668 heap (with a mutex on such a heap). */
669 if (m_parent_ctxt)
670 m_parent_ctxt->replay_into (r);
672 if (r->errors_occurred ())
673 return;
675 /* Replay this context's saved operations into r. */
676 FOR_EACH_VEC_ELT (m_mementos, i, m)
678 /* Disabled low-level debugging, here if we need it: print what
679 we're replaying.
680 Note that the calls to get_debug_string might lead to more
681 mementos being created for the strings.
682 This can also be used to exercise the debug_string
683 machinery. */
684 if (0)
685 printf ("context %p replaying (%p): %s\n",
686 (void *)this, (void *)m, m->get_debug_string ());
688 m->replay_into (r);
690 if (r->errors_occurred ())
691 return;
695 /* During a playback, we associate objects from the recording with
696 their counterparts during this playback.
698 For simplicity, we store this within the recording objects.
700 The following method cleans away these associations, to ensure that
701 we never have out-of-date associations lingering on subsequent
702 playbacks (the objects pointed to are GC-managed, but the
703 recording objects don't own refs to them). */
705 void
706 recording::context::disassociate_from_playback ()
708 JIT_LOG_SCOPE (get_logger ());
709 int i;
710 memento *m;
712 if (m_parent_ctxt)
713 m_parent_ctxt->disassociate_from_playback ();
715 FOR_EACH_VEC_ELT (m_mementos, i, m)
717 m->set_playback_obj (NULL);
721 /* Create a recording::string instance and add it to this context's list
722 of mementos.
724 This creates a fresh copy of the given 0-terminated buffer. */
726 recording::string *
727 recording::context::new_string (const char *text)
729 if (!text)
730 return NULL;
732 recording::string *result = new string (this, text);
733 record (result);
734 return result;
737 /* Create a recording::location instance and add it to this context's
738 list of mementos.
740 Implements the post-error-checking part of
741 gcc_jit_context_new_location. */
743 recording::location *
744 recording::context::new_location (const char *filename,
745 int line,
746 int column,
747 bool created_by_user)
749 recording::location *result =
750 new recording::location (this,
751 new_string (filename),
752 line, column,
753 created_by_user);
754 record (result);
755 return result;
758 /* If we haven't seen this enum value yet, create a recording::type
759 instance and add it to this context's list of mementos.
761 If we have seen it before, reuse our cached value, so that repeated
762 calls on the context give the same object.
764 If we have a parent context, the cache is within the ultimate
765 ancestor context.
767 Implements the post-error-checking part of
768 gcc_jit_context_get_type. */
770 recording::type *
771 recording::context::get_type (enum gcc_jit_types kind)
773 if (!m_basic_types[kind])
775 if (m_parent_ctxt)
776 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
777 else
779 recording::type *result = new memento_of_get_type (this, kind);
780 record (result);
781 m_basic_types[kind] = result;
785 return m_basic_types[kind];
788 /* Get a recording::type instance for the given size and signedness.
789 This is implemented in terms of recording::context::get_type
790 above.
792 Implements the post-error-checking part of
793 gcc_jit_context_get_int_type. */
795 recording::type *
796 recording::context::get_int_type (int num_bytes, int is_signed)
798 /* We can't use a switch here since some of the values are macros affected
799 by options; e.g. i386.h has
800 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
801 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
802 are in bits, rather than bytes.
804 const int num_bits = num_bytes * 8;
805 if (num_bits == INT_TYPE_SIZE)
806 return get_type (is_signed
807 ? GCC_JIT_TYPE_INT
808 : GCC_JIT_TYPE_UNSIGNED_INT);
809 if (num_bits == CHAR_TYPE_SIZE)
810 return get_type (is_signed
811 ? GCC_JIT_TYPE_SIGNED_CHAR
812 : GCC_JIT_TYPE_UNSIGNED_CHAR);
813 if (num_bits == SHORT_TYPE_SIZE)
814 return get_type (is_signed
815 ? GCC_JIT_TYPE_SHORT
816 : GCC_JIT_TYPE_UNSIGNED_SHORT);
817 if (num_bits == LONG_TYPE_SIZE)
818 return get_type (is_signed
819 ? GCC_JIT_TYPE_LONG
820 : GCC_JIT_TYPE_UNSIGNED_LONG);
821 if (num_bits == LONG_LONG_TYPE_SIZE)
822 return get_type (is_signed
823 ? GCC_JIT_TYPE_LONG_LONG
824 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
826 /* Some other size, not corresponding to the C int types. */
827 /* To be written: support arbitrary other sizes, sharing by
828 memoizing at the recording::context level? */
829 gcc_unreachable ();
832 /* Create a recording::type instance and add it to this context's list
833 of mementos.
835 Implements the post-error-checking part of
836 gcc_jit_context_new_array_type. */
838 recording::type *
839 recording::context::new_array_type (recording::location *loc,
840 recording::type *element_type,
841 int num_elements)
843 if (struct_ *s = element_type->dyn_cast_struct ())
844 if (!s->get_fields ())
846 add_error (NULL,
847 "cannot create an array of type %s"
848 " until the fields have been set",
849 s->get_name ()->c_str ());
850 return NULL;
852 recording::type *result =
853 new recording::array_type (this, loc, element_type, num_elements);
854 record (result);
855 return result;
858 /* Create a recording::field instance and add it to this context's list
859 of mementos.
861 Implements the post-error-checking part of
862 gcc_jit_context_new_field. */
864 recording::field *
865 recording::context::new_field (recording::location *loc,
866 recording::type *type,
867 const char *name)
869 recording::field *result =
870 new recording::field (this, loc, type, new_string (name));
871 record (result);
872 return result;
875 /* Create a recording::bitfield instance and add it to this context's list
876 of mementos.
878 Implements the post-error-checking part of
879 gcc_jit_context_new_bitfield. */
881 recording::field *
882 recording::context::new_bitfield (recording::location *loc,
883 recording::type *type,
884 int width,
885 const char *name)
887 recording::field *result =
888 new recording::bitfield (this, loc, type, width, new_string (name));
889 record (result);
890 return result;
893 /* Create a recording::struct_ instance and add it to this context's
894 list of mementos and list of compound types.
896 Implements the post-error-checking part of
897 gcc_jit_context_new_struct_type. */
899 recording::struct_ *
900 recording::context::new_struct_type (recording::location *loc,
901 const char *name)
903 recording::struct_ *result = new struct_ (this, loc, new_string (name));
904 record (result);
905 m_compound_types.safe_push (result);
906 return result;
909 /* Create a recording::union_ instance and add it to this context's
910 list of mementos and list of compound types.
912 Implements the first post-error-checking part of
913 gcc_jit_context_new_union_type. */
915 recording::union_ *
916 recording::context::new_union_type (recording::location *loc,
917 const char *name)
919 recording::union_ *result = new union_ (this, loc, new_string (name));
920 record (result);
921 m_compound_types.safe_push (result);
922 return result;
925 /* Create a recording::function_type instance and add it to this context's
926 list of mementos.
928 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
930 recording::function_type *
931 recording::context::new_function_type (recording::type *return_type,
932 int num_params,
933 recording::type **param_types,
934 int is_variadic)
936 recording::function_type *fn_type
937 = new function_type (this,
938 return_type,
939 num_params,
940 param_types,
941 is_variadic);
942 record (fn_type);
943 return fn_type;
946 /* Create a recording::type instance and add it to this context's list
947 of mementos.
949 Implements the post-error-checking part of
950 gcc_jit_context_new_function_ptr_type. */
952 recording::type *
953 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
954 recording::type *return_type,
955 int num_params,
956 recording::type **param_types,
957 int is_variadic)
959 recording::function_type *fn_type
960 = new_function_type (return_type,
961 num_params,
962 param_types,
963 is_variadic);
965 /* Return a pointer-type to the function type. */
966 return fn_type->get_pointer ();
969 /* Create a recording::param 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_param. */
975 recording::param *
976 recording::context::new_param (recording::location *loc,
977 recording::type *type,
978 const char *name)
980 recording::param *result = new recording::param (this, loc, type, new_string (name));
981 record (result);
982 return result;
985 /* Create a recording::function instance and add it to this context's list
986 of mementos and list of functions.
988 Implements the post-error-checking part of
989 gcc_jit_context_new_function. */
991 recording::function *
992 recording::context::new_function (recording::location *loc,
993 enum gcc_jit_function_kind kind,
994 recording::type *return_type,
995 const char *name,
996 int num_params,
997 recording::param **params,
998 int is_variadic,
999 enum built_in_function builtin_id)
1001 recording::function *result =
1002 new recording::function (this,
1003 loc, kind, return_type,
1004 new_string (name),
1005 num_params, params, is_variadic,
1006 builtin_id);
1007 record (result);
1008 m_functions.safe_push (result);
1010 return result;
1013 /* Locate the builtins_manager (if any) for this family of contexts,
1014 creating it if it doesn't exist already.
1016 All of the recording contexts in a family share one builtins_manager:
1017 if we have a child context, follow the parent links to get the
1018 ultimate ancestor context, and look for it/store it there. */
1020 builtins_manager *
1021 recording::context::get_builtins_manager ()
1023 if (m_parent_ctxt)
1024 return m_parent_ctxt->get_builtins_manager ();
1026 if (!m_builtins_manager)
1027 m_builtins_manager = new builtins_manager (this);
1029 return m_builtins_manager;
1032 /* Get a recording::function instance, which is lazily-created and added
1033 to the context's lists of mementos.
1035 Implements the post-error-checking part of
1036 gcc_jit_context_get_builtin_function. */
1038 recording::function *
1039 recording::context::get_builtin_function (const char *name)
1041 builtins_manager *bm = get_builtins_manager ();
1042 return bm->get_builtin_function (name);
1045 /* Create a recording::global instance and add it to this context's list
1046 of mementos.
1048 Implements the post-error-checking part of
1049 gcc_jit_context_new_global. */
1051 recording::lvalue *
1052 recording::context::new_global (recording::location *loc,
1053 enum gcc_jit_global_kind kind,
1054 recording::type *type,
1055 const char *name)
1057 recording::global *result =
1058 new recording::global (this, loc, kind, type, new_string (name));
1059 record (result);
1060 m_globals.safe_push (result);
1062 return result;
1065 /* Create a recording::memento_of_new_string_literal instance and add it
1066 to this context's list of mementos.
1068 Implements the post-error-checking part of
1069 gcc_jit_context_new_string_literal. */
1071 recording::rvalue *
1072 recording::context::new_string_literal (const char *value)
1074 recording::rvalue *result =
1075 new memento_of_new_string_literal (this, NULL, new_string (value));
1076 record (result);
1077 return result;
1080 /* Create a recording::memento_of_new_rvalue_from_vector instance and add it
1081 to this context's list of mementos.
1083 Implements the post-error-checking part of
1084 gcc_jit_context_new_rvalue_from_vector. */
1086 recording::rvalue *
1087 recording::context::new_rvalue_from_vector (location *loc,
1088 vector_type *type,
1089 rvalue **elements)
1091 recording::rvalue *result
1092 = new memento_of_new_rvalue_from_vector (this, loc, type, elements);
1093 record (result);
1094 return result;
1097 /* Create a recording::unary_op instance and add it to this context's
1098 list of mementos.
1100 Implements the post-error-checking part of
1101 gcc_jit_context_new_unary_op. */
1103 recording::rvalue *
1104 recording::context::new_unary_op (recording::location *loc,
1105 enum gcc_jit_unary_op op,
1106 recording::type *result_type,
1107 recording::rvalue *a)
1109 recording::rvalue *result =
1110 new unary_op (this, loc, op, result_type, a);
1111 record (result);
1112 return result;
1115 /* Create a recording::binary_op instance and add it to this context's
1116 list of mementos.
1118 Implements the post-error-checking part of
1119 gcc_jit_context_new_binary_op. */
1121 recording::rvalue *
1122 recording::context::new_binary_op (recording::location *loc,
1123 enum gcc_jit_binary_op op,
1124 recording::type *result_type,
1125 recording::rvalue *a,
1126 recording::rvalue *b)
1128 recording::rvalue *result =
1129 new binary_op (this, loc, op, result_type, a, b);
1130 record (result);
1131 return result;
1134 /* Create a recording::comparison instance and add it to this context's
1135 list of mementos.
1137 Implements the post-error-checking part of
1138 gcc_jit_context_new_comparison. */
1140 recording::rvalue *
1141 recording::context::new_comparison (recording::location *loc,
1142 enum gcc_jit_comparison op,
1143 recording::rvalue *a,
1144 recording::rvalue *b)
1146 recording::rvalue *result = new comparison (this, loc, op, a, b);
1147 record (result);
1148 return result;
1151 /* Create a recording::cast instance and add it to this context's list
1152 of mementos.
1154 Implements the post-error-checking part of
1155 gcc_jit_context_new_cast. */
1157 recording::rvalue *
1158 recording::context::new_cast (recording::location *loc,
1159 recording::rvalue *expr,
1160 recording::type *type_)
1162 recording::rvalue *result = new cast (this, loc, expr, type_);
1163 record (result);
1164 return result;
1167 /* Create a recording::call instance and add it to this context's list
1168 of mementos.
1170 Implements the post-error-checking part of
1171 gcc_jit_context_new_call. */
1173 recording::rvalue *
1174 recording::context::new_call (recording::location *loc,
1175 function *func,
1176 int numargs , recording::rvalue **args)
1178 recording::rvalue *result = new call (this, loc, func, numargs, args);
1179 record (result);
1180 return result;
1183 /* Create a recording::call_through_ptr instance and add it to this
1184 context's list of mementos.
1186 Implements the post-error-checking part of
1187 gcc_jit_context_new_call_through_ptr. */
1189 recording::rvalue *
1190 recording::context::new_call_through_ptr (recording::location *loc,
1191 recording::rvalue *fn_ptr,
1192 int numargs,
1193 recording::rvalue **args)
1195 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
1196 record (result);
1197 return result;
1200 /* Create a recording::array_access instance and add it to this context's list
1201 of mementos.
1203 Implements the post-error-checking part of
1204 gcc_jit_context_new_array_access. */
1206 recording::lvalue *
1207 recording::context::new_array_access (recording::location *loc,
1208 recording::rvalue *ptr,
1209 recording::rvalue *index)
1211 recording::lvalue *result = new array_access (this, loc, ptr, index);
1212 record (result);
1213 return result;
1216 /* Create a recording::case_ instance and add it to this context's list
1217 of mementos.
1219 Implements the post-error-checking part of
1220 gcc_jit_context_new_case. */
1222 recording::case_ *
1223 recording::context::new_case (recording::rvalue *min_value,
1224 recording::rvalue *max_value,
1225 recording::block *block)
1227 recording::case_ *result = new case_ (this, min_value, max_value, block);
1228 record (result);
1229 return result;
1232 /* Set the given string option for this context, or add an error if
1233 it's not recognized.
1235 Implements the post-error-checking part of
1236 gcc_jit_context_set_str_option. */
1238 void
1239 recording::context::set_str_option (enum gcc_jit_str_option opt,
1240 const char *value)
1242 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
1244 add_error (NULL,
1245 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
1246 return;
1248 free (m_str_options[opt]);
1249 m_str_options[opt] = value ? xstrdup (value) : NULL;
1250 log_str_option (opt);
1253 /* Set the given integer option for this context, or add an error if
1254 it's not recognized.
1256 Implements the post-error-checking part of
1257 gcc_jit_context_set_int_option. */
1259 void
1260 recording::context::set_int_option (enum gcc_jit_int_option opt,
1261 int value)
1263 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
1265 add_error (NULL,
1266 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
1267 return;
1269 m_int_options[opt] = value;
1270 log_int_option (opt);
1273 /* Set the given boolean option for this context, or add an error if
1274 it's not recognized.
1276 Implements the post-error-checking part of
1277 gcc_jit_context_set_bool_option. */
1279 void
1280 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
1281 int value)
1283 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
1285 add_error (NULL,
1286 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
1287 return;
1289 m_bool_options[opt] = value ? true : false;
1290 log_bool_option (opt);
1293 void
1294 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt,
1295 int value)
1297 gcc_assert (inner_opt >= 0 && inner_opt < NUM_INNER_BOOL_OPTIONS);
1298 m_inner_bool_options[inner_opt] = value ? true : false;
1299 log_inner_bool_option (inner_opt);
1303 /* Add the given optname to this context's list of extra options.
1305 Implements the post-error-checking part of
1306 gcc_jit_context_add_command_line_option. */
1308 void
1309 recording::context::add_command_line_option (const char *optname)
1311 m_command_line_options.safe_push (xstrdup (optname));
1314 /* Add any user-provided extra options, starting with any from
1315 parent contexts.
1316 Called by playback::context::make_fake_args. */
1318 void
1319 recording::context::append_command_line_options (vec <char *> *argvec)
1321 if (m_parent_ctxt)
1322 m_parent_ctxt->append_command_line_options (argvec);
1324 int i;
1325 char *optname;
1326 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1327 argvec->safe_push (xstrdup (optname));
1330 /* Add the given optname to this context's list of extra driver options. */
1332 void
1333 recording::context::add_driver_option (const char *optname)
1335 m_driver_options.safe_push (xstrdup (optname));
1338 /* Add any user-provided driver options, starting with any from
1339 parent contexts.
1340 Called by playback::context::invoke_driver. */
1342 void
1343 recording::context::append_driver_options (auto_string_vec *argvec)
1345 if (m_parent_ctxt)
1346 m_parent_ctxt->append_driver_options (argvec);
1348 int i;
1349 char *optname;
1351 FOR_EACH_VEC_ELT (m_driver_options, i, optname)
1352 argvec->safe_push (xstrdup (optname));
1355 /* Add the given dumpname/out_ptr pair to this context's list of requested
1356 dumps.
1358 Implements the post-error-checking part of
1359 gcc_jit_context_enable_dump. */
1361 void
1362 recording::context::enable_dump (const char *dumpname,
1363 char **out_ptr)
1365 requested_dump d;
1366 gcc_assert (dumpname);
1367 gcc_assert (out_ptr);
1369 d.m_dumpname = dumpname;
1370 d.m_out_ptr = out_ptr;
1371 *out_ptr = NULL;
1372 m_requested_dumps.safe_push (d);
1375 /* Validate this context, and if it passes, compile it to memory
1376 (within a mutex).
1378 Implements the post-error-checking part of
1379 gcc_jit_context_compile. */
1381 result *
1382 recording::context::compile ()
1384 JIT_LOG_SCOPE (get_logger ());
1386 log_all_options ();
1388 validate ();
1390 if (errors_occurred ())
1391 return NULL;
1393 /* Set up a compile_to_memory playback context. */
1394 ::gcc::jit::playback::compile_to_memory replayer (this);
1396 /* Use it. */
1397 replayer.compile ();
1399 /* Get the jit::result (or NULL) from the
1400 compile_to_memory playback context. */
1401 return replayer.get_result_obj ();
1404 /* Validate this context, and if it passes, compile it to a file
1405 (within a mutex).
1407 Implements the post-error-checking part of
1408 gcc_jit_context_compile_to_file. */
1410 void
1411 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
1412 const char *output_path)
1414 JIT_LOG_SCOPE (get_logger ());
1416 log_all_options ();
1418 validate ();
1420 if (errors_occurred ())
1421 return;
1423 /* Set up a compile_to_file playback context. */
1424 ::gcc::jit::playback::compile_to_file replayer (this,
1425 output_kind,
1426 output_path);
1428 /* Use it. */
1429 replayer.compile ();
1432 /* Format the given error using printf's conventions, print
1433 it to stderr, and add it to the context. */
1435 void
1436 recording::context::add_error (location *loc, const char *fmt, ...)
1438 va_list ap;
1439 va_start (ap, fmt);
1440 add_error_va (loc, fmt, ap);
1441 va_end (ap);
1444 /* Format the given error using printf's conventions, print
1445 it to stderr, and add it to the context. */
1447 void
1448 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
1450 int len;
1451 char *malloced_msg;
1452 const char *errmsg;
1453 bool has_ownership;
1455 JIT_LOG_SCOPE (get_logger ());
1457 len = vasprintf (&malloced_msg, fmt, ap);
1458 if (malloced_msg == NULL || len < 0)
1460 errmsg = "out of memory generating error message";
1461 has_ownership = false;
1463 else
1465 errmsg = malloced_msg;
1466 has_ownership = true;
1468 if (get_logger ())
1469 get_logger ()->log ("error %i: %s", m_error_count, errmsg);
1471 const char *ctxt_progname =
1472 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
1473 if (!ctxt_progname)
1474 ctxt_progname = "libgccjit.so";
1476 if (loc)
1477 fprintf (stderr, "%s: %s: error: %s\n",
1478 ctxt_progname,
1479 loc->get_debug_string (),
1480 errmsg);
1481 else
1482 fprintf (stderr, "%s: error: %s\n",
1483 ctxt_progname,
1484 errmsg);
1486 if (!m_error_count)
1488 m_first_error_str = const_cast <char *> (errmsg);
1489 m_owns_first_error_str = has_ownership;
1492 if (m_owns_last_error_str)
1493 if (m_last_error_str != m_first_error_str)
1494 free (m_last_error_str);
1495 m_last_error_str = const_cast <char *> (errmsg);
1496 m_owns_last_error_str = has_ownership;
1498 m_error_count++;
1501 /* Get the message for the first error that occurred on this context, or
1502 NULL if no errors have occurred on it.
1504 Implements the post-error-checking part of
1505 gcc_jit_context_get_first_error. */
1507 const char *
1508 recording::context::get_first_error () const
1510 return m_first_error_str;
1513 /* Get the message for the last error that occurred on this context, or
1514 NULL if no errors have occurred on it.
1516 Implements the post-error-checking part of
1517 gcc_jit_context_get_last_error. */
1519 const char *
1520 recording::context::get_last_error () const
1522 return m_last_error_str;
1525 /* Lazily generate and record a recording::type representing an opaque
1526 struct named "FILE".
1528 For use if client code tries to dereference the result of
1529 get_type (GCC_JIT_TYPE_FILE_PTR). */
1531 recording::type *
1532 recording::context::get_opaque_FILE_type ()
1534 if (!m_FILE_type)
1535 m_FILE_type = new_struct_type (NULL, "FILE");
1536 return m_FILE_type;
1539 /* Dump a C-like representation of the given context to the given path.
1540 If UPDATE_LOCATIONS is true, update the locations within the
1541 context's mementos to point to the dumpfile.
1543 Implements the post-error-checking part of
1544 gcc_jit_context_dump_to_file. */
1546 void
1547 recording::context::dump_to_file (const char *path, bool update_locations)
1549 int i;
1550 dump d (*this, path, update_locations);
1552 /* Forward declaration of structs and unions. */
1553 compound_type *st;
1554 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1556 d.write ("%s;\n\n", st->get_debug_string ());
1559 /* Content of structs, where set. */
1560 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1561 if (st->get_fields ())
1563 st->get_fields ()->write_to_dump (d);
1564 d.write ("\n");
1567 /* Globals. */
1568 global *g;
1569 FOR_EACH_VEC_ELT (m_globals, i, g)
1571 g->write_to_dump (d);
1573 if (!m_globals.is_empty ())
1574 d.write ("\n");
1576 function *fn;
1577 FOR_EACH_VEC_ELT (m_functions, i, fn)
1579 fn->write_to_dump (d);
1583 static const char * const
1584 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
1585 "GCC_JIT_STR_OPTION_PROGNAME"
1588 static const char * const
1589 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
1590 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1593 static const char * const
1594 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
1595 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1596 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1597 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1598 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1599 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1600 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1601 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1602 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1605 static const char * const
1606 inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = {
1607 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1608 "gcc_jit_context_set_bool_use_external_driver"
1611 /* Write the current value of all options to the log file (if any). */
1613 void
1614 recording::context::log_all_options () const
1616 int opt_idx;
1618 if (!get_logger ())
1619 return;
1621 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1622 log_str_option ((enum gcc_jit_str_option)opt_idx);
1624 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1625 log_int_option ((enum gcc_jit_int_option)opt_idx);
1627 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1628 log_bool_option ((enum gcc_jit_bool_option)opt_idx);
1629 for (opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1630 log_inner_bool_option ((enum inner_bool_option)opt_idx);
1633 /* Write the current value of the given string option to the
1634 log file (if any). */
1636 void
1637 recording::context::log_str_option (enum gcc_jit_str_option opt) const
1639 gcc_assert (opt < GCC_JIT_NUM_STR_OPTIONS);
1640 if (get_logger ())
1642 if (m_str_options[opt])
1643 log ("%s: \"%s\"",
1644 str_option_reproducer_strings[opt],
1645 m_str_options[opt]);
1646 else
1647 log ("%s: NULL",
1648 str_option_reproducer_strings[opt]);
1652 /* Write the current value of the given int option to the
1653 log file (if any). */
1655 void
1656 recording::context::log_int_option (enum gcc_jit_int_option opt) const
1658 gcc_assert (opt < GCC_JIT_NUM_INT_OPTIONS);
1659 if (get_logger ())
1660 log ("%s: %i",
1661 int_option_reproducer_strings[opt],
1662 m_int_options[opt]);
1665 /* Write the current value of the given bool option to the
1666 log file (if any). */
1668 void
1669 recording::context::log_bool_option (enum gcc_jit_bool_option opt) const
1671 gcc_assert (opt < GCC_JIT_NUM_BOOL_OPTIONS);
1672 if (get_logger ())
1673 log ("%s: %s",
1674 bool_option_reproducer_strings[opt],
1675 m_bool_options[opt] ? "true" : "false");
1678 /* Write the current value of the given "inner" bool option to the
1679 log file (if any). */
1681 void
1682 recording::context::log_inner_bool_option (enum inner_bool_option opt) const
1684 gcc_assert (opt < NUM_INNER_BOOL_OPTIONS);
1685 if (get_logger ())
1686 log ("%s: %s",
1687 inner_bool_option_reproducer_strings[opt],
1688 m_inner_bool_options[opt] ? "true" : "false");
1691 /* Write C source code to PATH that attempts to replay the API
1692 calls made to this context (and its parents), for use in
1693 minimizing test cases for libgccjit.
1695 Implements the post-error-checking part of
1696 gcc_jit_context_dump_reproducer_to_file. */
1698 void
1699 recording::context::dump_reproducer_to_file (const char *path)
1701 JIT_LOG_SCOPE (get_logger ());
1702 reproducer r (*this, path);
1704 /* Generate the "ancestry" of this context, as a list. */
1705 auto_vec <context *> ascending_contexts;
1706 for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
1707 ascending_contexts.safe_push (ctxt);
1709 /* Reverse the list, giving a list of contexts from
1710 top-most parent context down through to youngest child context.
1711 We will use this list as the parameters of the functions in
1712 our generated file. */
1713 unsigned num_ctxts = ascending_contexts.length ();
1714 auto_vec <context *> contexts (num_ctxts);
1715 for (unsigned i = 0; i < num_ctxts; i++)
1716 contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
1718 /* contexts[0] should be the top-level context. */
1719 gcc_assert (contexts[0]);
1720 gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
1722 /* The final element in contexts should be "this". */
1723 gcc_assert (contexts[contexts.length () - 1] == this);
1724 gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
1725 == contexts[0]);
1727 r.write ("/* This code was autogenerated by"
1728 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1729 print_version (r.get_file (), " ", false);
1730 r.write ("*/\n");
1731 r.write ("#include <libgccjit.h>\n\n");
1732 r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1733 r.write ("static void\nset_options (");
1734 r.write_params (contexts);
1735 r.write (");\n\n");
1736 r.write ("static void\ncreate_code (");
1737 r.write_params (contexts);
1738 r.write (");\n\n");
1739 r.write ("int\nmain (int argc, const char **argv)\n");
1740 r.write ("{\n");
1741 for (unsigned i = 0; i < num_ctxts; i++)
1742 r.write (" gcc_jit_context *%s;\n",
1743 r.get_identifier (contexts[i]));
1744 r.write (" gcc_jit_result *result;\n"
1745 "\n");
1747 /* Create the contexts.
1748 The top-level context is acquired from a clean slate, the others as
1749 children of the prior context. */
1750 r.write (" %s = gcc_jit_context_acquire ();\n",
1751 r.get_identifier (contexts[0]));
1752 for (unsigned i = 1; i < num_ctxts; i++)
1753 r.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1754 r.get_identifier (contexts[i]),
1755 r.get_identifier (contexts[i - 1]));
1756 r.write (" set_options (");
1757 r.write_args (contexts);
1758 r.write (");\n");
1759 r.write (" create_code (");
1760 r.write_args (contexts);
1761 r.write (");\n");
1763 r.write (" result = gcc_jit_context_compile (%s);\n",
1764 r.get_identifier (this));
1766 for (unsigned i = num_ctxts; i > 0; i--)
1767 r.write (" gcc_jit_context_release (%s);\n",
1768 r.get_identifier (contexts[i - 1]));
1770 r.write (" gcc_jit_result_release (result);\n"
1771 " return 0;\n"
1772 "}\n\n");
1774 /* Define (char *) variables for use in calls to
1775 gcc_jit_context_enable_dump. */
1776 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1778 if (m_requested_dumps.length ())
1780 r.write ("/* Requested dumps for %s. */\n",
1781 r.get_identifier (contexts[ctxt_idx]));
1782 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1783 r.write ("static char *dump_%p;\n",
1784 (void *)&m_requested_dumps[i]);
1785 r.write ("\n");
1789 /* Write out values of options. */
1790 r.write ("static void\nset_options (");
1791 r.write_params (contexts);
1792 r.write (")\n{\n");
1793 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1795 if (ctxt_idx > 0)
1796 r.write ("\n");
1798 r.write (" /* Set options for %s. */\n",
1799 r.get_identifier (contexts[ctxt_idx]));
1801 r.write (" /* String options. */\n");
1802 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1804 r.write (" gcc_jit_context_set_str_option (%s,\n"
1805 " %s,\n",
1806 r.get_identifier (contexts[ctxt_idx]),
1807 str_option_reproducer_strings[opt_idx]);
1808 if (m_str_options[opt_idx])
1809 r.write (" \"%s\");\n",
1810 m_str_options[opt_idx]);
1811 else
1812 r.write (" NULL);\n");
1814 r.write (" /* Int options. */\n");
1815 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1816 r.write (" gcc_jit_context_set_int_option (%s,\n"
1817 " %s,\n"
1818 " %i);\n",
1819 r.get_identifier (contexts[ctxt_idx]),
1820 int_option_reproducer_strings[opt_idx],
1821 m_int_options[opt_idx]);
1822 r.write (" /* Boolean options. */\n");
1823 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1824 r.write (" gcc_jit_context_set_bool_option (%s,\n"
1825 " %s,\n"
1826 " %i);\n",
1827 r.get_identifier (contexts[ctxt_idx]),
1828 bool_option_reproducer_strings[opt_idx],
1829 m_bool_options[opt_idx]);
1830 for (int opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1831 r.write (" %s (%s, %i);\n",
1832 inner_bool_option_reproducer_strings[opt_idx],
1833 r.get_identifier (contexts[ctxt_idx]),
1834 m_inner_bool_options[opt_idx]);
1836 if (!m_command_line_options.is_empty ())
1838 int i;
1839 char *optname;
1840 r.write (" /* User-provided command-line options. */\n");
1841 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1842 r.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1843 r.get_identifier (contexts[ctxt_idx]),
1844 optname);
1847 if (!m_driver_options.is_empty ())
1849 int i;
1850 char *optname;
1851 r.write (" /* User-provided driver options. */\n");
1852 FOR_EACH_VEC_ELT (m_driver_options, i, optname)
1853 r.write (" gcc_jit_context_add_driver_option (%s, \"%s\");\n",
1854 r.get_identifier (contexts[ctxt_idx]),
1855 optname);
1858 if (m_requested_dumps.length ())
1860 r.write (" /* Requested dumps. */\n");
1861 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1862 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1864 r.write (" gcc_jit_context_enable_dump (%s,\n"
1865 " \"%s\",\n"
1866 " &dump_%p);\n",
1867 r.get_identifier (contexts[ctxt_idx]),
1868 m_requested_dumps[i].m_dumpname,
1869 (void *)&m_requested_dumps[i]);
1873 r.write ("}\n\n");
1875 r.write ("static void\ncreate_code (");
1876 r.write_params (contexts);
1877 r.write (")\n"
1878 "{\n");
1879 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1881 memento *m;
1882 int i;
1883 if (ctxt_idx > 0)
1884 r.write ("\n\n");
1886 r.write (" /* Replay of API calls for %s. */\n",
1887 r.get_identifier (contexts[ctxt_idx]));
1888 FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
1889 m->write_reproducer (r);
1891 r.write ("}\n");
1894 /* Copy the requested dumps within this context and all ancestors into
1895 OUT. */
1897 void
1898 recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
1900 if (m_parent_ctxt)
1901 m_parent_ctxt->get_all_requested_dumps (out);
1903 out->reserve (m_requested_dumps.length ());
1904 out->splice (m_requested_dumps);
1907 /* This is a pre-compilation check for the context (and any parents).
1909 Detect errors within the context, adding errors if any are found. */
1911 void
1912 recording::context::validate ()
1914 JIT_LOG_SCOPE (get_logger ());
1916 if (m_parent_ctxt)
1917 m_parent_ctxt->validate ();
1919 int i;
1920 function *fn;
1921 FOR_EACH_VEC_ELT (m_functions, i, fn)
1922 fn->validate ();
1925 /* The implementation of class gcc::jit::recording::memento. */
1927 /* Get a (const char *) debug description of the given memento, by
1928 calling the pure-virtual make_debug_string hook, caching the
1929 result.
1931 It is intended that this should only be called in debugging and
1932 error-handling paths, so this doesn't need to be particularly
1933 optimized. */
1935 const char *
1936 recording::memento::get_debug_string ()
1938 if (!m_debug_string)
1939 m_debug_string = make_debug_string ();
1940 return m_debug_string->c_str ();
1943 /* Default implementation of recording::memento::write_to_dump, writing
1944 an indented form of the memento's debug string to the dump. */
1946 void
1947 recording::memento::write_to_dump (dump &d)
1949 d.write(" %s\n", get_debug_string ());
1952 /* The implementation of class gcc::jit::recording::string. */
1954 /* Constructor for gcc::jit::recording::string::string, allocating a
1955 copy of the given text using new char[]. */
1957 recording::string::string (context *ctxt, const char *text)
1958 : memento (ctxt)
1960 m_len = strlen (text);
1961 m_buffer = new char[m_len + 1];
1962 strcpy (m_buffer, text);
1965 /* Destructor for gcc::jit::recording::string::string. */
1967 recording::string::~string ()
1969 delete[] m_buffer;
1972 /* Function for making gcc::jit::recording::string instances on a
1973 context via printf-style formatting.
1975 It is intended that this should only be called in debugging and
1976 error-handling paths, so this doesn't need to be particularly
1977 optimized, hence the double-copy of the string is acceptable. */
1979 recording::string *
1980 recording::string::from_printf (context *ctxt, const char *fmt, ...)
1982 int len;
1983 va_list ap;
1984 char *buf;
1985 recording::string *result;
1987 va_start (ap, fmt);
1988 len = vasprintf (&buf, fmt, ap);
1989 va_end (ap);
1991 if (buf == NULL || len < 0)
1993 ctxt->add_error (NULL, "malloc failure");
1994 return NULL;
1997 result = ctxt->new_string (buf);
1998 free (buf);
1999 return result;
2002 /* Implementation of recording::memento::make_debug_string for strings,
2003 wrapping the given string in quotes and escaping as necessary. */
2005 recording::string *
2006 recording::string::make_debug_string ()
2008 /* Hack to avoid infinite recursion into strings when logging all
2009 mementos: don't re-escape strings: */
2010 if (m_buffer[0] == '"')
2011 return this;
2013 /* Wrap in quotes and do escaping etc */
2015 size_t sz = (1 /* opening quote */
2016 + (m_len * 2) /* each char might get escaped */
2017 + 1 /* closing quote */
2018 + 1); /* nil termintator */
2019 char *tmp = new char[sz];
2020 size_t len = 0;
2022 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
2023 APPEND('"'); /* opening quote */
2024 for (size_t i = 0; i < m_len ; i++)
2026 char ch = m_buffer[i];
2027 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
2028 APPEND('\\');
2029 APPEND(ch);
2031 APPEND('"'); /* closing quote */
2032 #undef APPEND
2033 tmp[len] = '\0'; /* nil termintator */
2035 string *result = m_ctxt->new_string (tmp);
2037 delete[] tmp;
2038 return result;
2041 /* Implementation of recording::memento::write_reproducer for strings. */
2043 void
2044 recording::string::write_reproducer (reproducer &)
2046 /* Empty. */
2049 /* The implementation of class gcc::jit::recording::location. */
2051 /* Implementation of recording::memento::replay_into for locations.
2053 Create a new playback::location and store it into the
2054 recording::location's m_playback_obj field. */
2056 void
2057 recording::location::replay_into (replayer *r)
2059 m_playback_obj = r->new_location (this,
2060 m_filename->c_str (),
2061 m_line,
2062 m_column);
2065 /* Implementation of recording::memento::make_debug_string for locations,
2066 turning them into the usual form:
2067 FILENAME:LINE:COLUMN
2068 like we do when emitting diagnostics. */
2070 recording::string *
2071 recording::location::make_debug_string ()
2073 return string::from_printf (m_ctxt,
2074 "%s:%i:%i",
2075 m_filename->c_str (), m_line, m_column);
2078 /* Implementation of recording::memento::write_reproducer for locations. */
2080 void
2081 recording::location::write_reproducer (reproducer &r)
2083 const char *id = r.make_identifier (this, "loc");
2084 r.write (" gcc_jit_location *%s =\n"
2085 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
2086 " %s, /* const char *filename */\n"
2087 " %i, /* int line */\n"
2088 " %i);/* int column */\n",
2090 r.get_identifier (get_context ()),
2091 m_filename->get_debug_string (),
2092 m_line, m_column);
2095 /* The implementation of class gcc::jit::recording::type. */
2097 /* Given a type T, get the type T*.
2099 If this doesn't already exist, generate a new memento_of_get_pointer
2100 instance and add it to this type's context's list of mementos.
2102 Otherwise, use the cached type.
2104 Implements the post-error-checking part of
2105 gcc_jit_type_get_pointer. */
2107 recording::type *
2108 recording::type::get_pointer ()
2110 if (!m_pointer_to_this_type)
2112 m_pointer_to_this_type = new memento_of_get_pointer (this);
2113 m_ctxt->record (m_pointer_to_this_type);
2115 return m_pointer_to_this_type;
2118 /* Given a type T, get the type const T.
2120 Implements the post-error-checking part of
2121 gcc_jit_type_get_const. */
2123 recording::type *
2124 recording::type::get_const ()
2126 recording::type *result = new memento_of_get_const (this);
2127 m_ctxt->record (result);
2128 return result;
2131 /* Given a type T, get the type volatile T.
2133 Implements the post-error-checking part of
2134 gcc_jit_type_get_volatile. */
2136 recording::type *
2137 recording::type::get_volatile ()
2139 recording::type *result = new memento_of_get_volatile (this);
2140 m_ctxt->record (result);
2141 return result;
2144 /* Given a type, get an aligned version of the type.
2146 Implements the post-error-checking part of
2147 gcc_jit_type_get_aligned. */
2149 recording::type *
2150 recording::type::get_aligned (size_t alignment_in_bytes)
2152 recording::type *result
2153 = new memento_of_get_aligned (this, alignment_in_bytes);
2154 m_ctxt->record (result);
2155 return result;
2158 /* Given a type, get a vector version of the type.
2160 Implements the post-error-checking part of
2161 gcc_jit_type_get_vector. */
2163 recording::type *
2164 recording::type::get_vector (size_t num_units)
2166 recording::type *result
2167 = new vector_type (this, num_units);
2168 m_ctxt->record (result);
2169 return result;
2172 const char *
2173 recording::type::access_as_type (reproducer &r)
2175 return r.get_identifier (this);
2178 /* Override of default implementation of
2179 recording::type::get_size.
2181 Return the size in bytes. This is in use for global
2182 initialization. */
2184 size_t
2185 recording::memento_of_get_type::get_size ()
2187 int size;
2188 switch (m_kind)
2190 case GCC_JIT_TYPE_VOID:
2191 return 0;
2192 case GCC_JIT_TYPE_BOOL:
2193 case GCC_JIT_TYPE_CHAR:
2194 case GCC_JIT_TYPE_SIGNED_CHAR:
2195 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2196 return 1;
2197 case GCC_JIT_TYPE_SHORT:
2198 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2199 size = SHORT_TYPE_SIZE;
2200 break;
2201 case GCC_JIT_TYPE_INT:
2202 case GCC_JIT_TYPE_UNSIGNED_INT:
2203 size = INT_TYPE_SIZE;
2204 break;
2205 case GCC_JIT_TYPE_LONG:
2206 case GCC_JIT_TYPE_UNSIGNED_LONG:
2207 size = LONG_TYPE_SIZE;
2208 break;
2209 case GCC_JIT_TYPE_LONG_LONG:
2210 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2211 size = LONG_LONG_TYPE_SIZE;
2212 break;
2213 case GCC_JIT_TYPE_FLOAT:
2214 size = FLOAT_TYPE_SIZE;
2215 break;
2216 case GCC_JIT_TYPE_DOUBLE:
2217 size = DOUBLE_TYPE_SIZE;
2218 break;
2219 case GCC_JIT_TYPE_LONG_DOUBLE:
2220 size = LONG_DOUBLE_TYPE_SIZE;
2221 break;
2222 default:
2223 /* As this function is called by
2224 'gcc_jit_global_set_initializer' and
2225 'recording::global::write_reproducer' possible types are only
2226 integrals and are covered by the previous cases. */
2227 gcc_unreachable ();
2230 return size / BITS_PER_UNIT;
2233 /* Implementation of pure virtual hook recording::type::dereference for
2234 recording::memento_of_get_type. */
2236 recording::type *
2237 recording::memento_of_get_type::dereference ()
2239 switch (m_kind)
2241 default: gcc_unreachable ();
2243 case GCC_JIT_TYPE_VOID:
2244 return NULL;
2246 case GCC_JIT_TYPE_VOID_PTR:
2247 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
2249 case GCC_JIT_TYPE_BOOL:
2250 case GCC_JIT_TYPE_CHAR:
2251 case GCC_JIT_TYPE_SIGNED_CHAR:
2252 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2253 case GCC_JIT_TYPE_SHORT:
2254 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2255 case GCC_JIT_TYPE_INT:
2256 case GCC_JIT_TYPE_UNSIGNED_INT:
2257 case GCC_JIT_TYPE_LONG:
2258 case GCC_JIT_TYPE_UNSIGNED_LONG:
2259 case GCC_JIT_TYPE_LONG_LONG:
2260 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2261 case GCC_JIT_TYPE_FLOAT:
2262 case GCC_JIT_TYPE_DOUBLE:
2263 case GCC_JIT_TYPE_LONG_DOUBLE:
2264 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2265 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2266 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2267 /* Not a pointer: */
2268 return NULL;
2270 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2271 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
2273 case GCC_JIT_TYPE_SIZE_T:
2274 /* Not a pointer: */
2275 return NULL;
2277 case GCC_JIT_TYPE_FILE_PTR:
2278 /* Give the client code back an opaque "struct FILE". */
2279 return m_ctxt->get_opaque_FILE_type ();
2283 /* Implementation of pure virtual hook recording::type::is_int for
2284 recording::memento_of_get_type. */
2286 bool
2287 recording::memento_of_get_type::is_int () const
2289 switch (m_kind)
2291 default: gcc_unreachable ();
2293 case GCC_JIT_TYPE_VOID:
2294 return false;
2296 case GCC_JIT_TYPE_VOID_PTR:
2297 return false;
2299 case GCC_JIT_TYPE_BOOL:
2300 return false;
2302 case GCC_JIT_TYPE_CHAR:
2303 case GCC_JIT_TYPE_SIGNED_CHAR:
2304 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2305 case GCC_JIT_TYPE_SHORT:
2306 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2307 case GCC_JIT_TYPE_INT:
2308 case GCC_JIT_TYPE_UNSIGNED_INT:
2309 case GCC_JIT_TYPE_LONG:
2310 case GCC_JIT_TYPE_UNSIGNED_LONG:
2311 case GCC_JIT_TYPE_LONG_LONG:
2312 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2313 return true;
2315 case GCC_JIT_TYPE_FLOAT:
2316 case GCC_JIT_TYPE_DOUBLE:
2317 case GCC_JIT_TYPE_LONG_DOUBLE:
2318 return false;
2320 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2321 return false;
2323 case GCC_JIT_TYPE_SIZE_T:
2324 return true;
2326 case GCC_JIT_TYPE_FILE_PTR:
2327 return false;
2329 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2330 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2331 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2332 return false;
2336 /* Implementation of pure virtual hook recording::type::is_float for
2337 recording::memento_of_get_type. */
2339 bool
2340 recording::memento_of_get_type::is_float () const
2342 switch (m_kind)
2344 default: gcc_unreachable ();
2346 case GCC_JIT_TYPE_VOID:
2347 return false;
2349 case GCC_JIT_TYPE_VOID_PTR:
2350 return false;
2352 case GCC_JIT_TYPE_BOOL:
2353 return false;
2355 case GCC_JIT_TYPE_CHAR:
2356 case GCC_JIT_TYPE_SIGNED_CHAR:
2357 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2358 case GCC_JIT_TYPE_SHORT:
2359 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2360 case GCC_JIT_TYPE_INT:
2361 case GCC_JIT_TYPE_UNSIGNED_INT:
2362 case GCC_JIT_TYPE_LONG:
2363 case GCC_JIT_TYPE_UNSIGNED_LONG:
2364 case GCC_JIT_TYPE_LONG_LONG:
2365 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2366 return false;
2368 case GCC_JIT_TYPE_FLOAT:
2369 case GCC_JIT_TYPE_DOUBLE:
2370 case GCC_JIT_TYPE_LONG_DOUBLE:
2371 return true;
2373 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2374 return false;
2376 case GCC_JIT_TYPE_SIZE_T:
2377 return false;
2379 case GCC_JIT_TYPE_FILE_PTR:
2380 return false;
2382 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2383 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2384 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2385 return true;
2389 /* Implementation of pure virtual hook recording::type::is_bool for
2390 recording::memento_of_get_type. */
2392 bool
2393 recording::memento_of_get_type::is_bool () const
2395 switch (m_kind)
2397 default: gcc_unreachable ();
2399 case GCC_JIT_TYPE_VOID:
2400 return false;
2402 case GCC_JIT_TYPE_VOID_PTR:
2403 return false;
2405 case GCC_JIT_TYPE_BOOL:
2406 return true;
2408 case GCC_JIT_TYPE_CHAR:
2409 case GCC_JIT_TYPE_SIGNED_CHAR:
2410 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2411 case GCC_JIT_TYPE_SHORT:
2412 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2413 case GCC_JIT_TYPE_INT:
2414 case GCC_JIT_TYPE_UNSIGNED_INT:
2415 case GCC_JIT_TYPE_LONG:
2416 case GCC_JIT_TYPE_UNSIGNED_LONG:
2417 case GCC_JIT_TYPE_LONG_LONG:
2418 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2419 return false;
2421 case GCC_JIT_TYPE_FLOAT:
2422 case GCC_JIT_TYPE_DOUBLE:
2423 case GCC_JIT_TYPE_LONG_DOUBLE:
2424 return false;
2426 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2427 return false;
2429 case GCC_JIT_TYPE_SIZE_T:
2430 return false;
2432 case GCC_JIT_TYPE_FILE_PTR:
2433 return false;
2435 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2436 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2437 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2438 return false;
2442 /* Implementation of pure virtual hook recording::memento::replay_into
2443 for recording::memento_of_get_type. */
2445 void
2446 recording::memento_of_get_type::replay_into (replayer *r)
2448 set_playback_obj (r->get_type (m_kind));
2451 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2453 /* Descriptive strings for each of enum gcc_jit_types. */
2455 static const char * const get_type_strings[] = {
2456 "void", /* GCC_JIT_TYPE_VOID */
2457 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2459 "bool", /* GCC_JIT_TYPE_BOOL */
2461 "char", /* GCC_JIT_TYPE_CHAR */
2462 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2463 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2465 "short", /* GCC_JIT_TYPE_SHORT */
2466 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2468 "int", /* GCC_JIT_TYPE_INT */
2469 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2471 "long", /* GCC_JIT_TYPE_LONG */
2472 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2474 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2475 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2477 "float", /* GCC_JIT_TYPE_FLOAT */
2478 "double", /* GCC_JIT_TYPE_DOUBLE */
2479 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2481 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2483 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2485 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2487 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2488 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2489 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2493 /* Implementation of recording::memento::make_debug_string for
2494 results of get_type, using a simple table of type names. */
2496 recording::string *
2497 recording::memento_of_get_type::make_debug_string ()
2499 return m_ctxt->new_string (get_type_strings[m_kind]);
2502 static const char * const get_type_enum_strings[] = {
2503 "GCC_JIT_TYPE_VOID",
2504 "GCC_JIT_TYPE_VOID_PTR",
2505 "GCC_JIT_TYPE_BOOL",
2506 "GCC_JIT_TYPE_CHAR",
2507 "GCC_JIT_TYPE_SIGNED_CHAR",
2508 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2509 "GCC_JIT_TYPE_SHORT",
2510 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2511 "GCC_JIT_TYPE_INT",
2512 "GCC_JIT_TYPE_UNSIGNED_INT",
2513 "GCC_JIT_TYPE_LONG",
2514 "GCC_JIT_TYPE_UNSIGNED_LONG",
2515 "GCC_JIT_TYPE_LONG_LONG",
2516 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2517 "GCC_JIT_TYPE_FLOAT",
2518 "GCC_JIT_TYPE_DOUBLE",
2519 "GCC_JIT_TYPE_LONG_DOUBLE",
2520 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2521 "GCC_JIT_TYPE_SIZE_T",
2522 "GCC_JIT_TYPE_FILE_PTR",
2523 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2524 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2525 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2528 void
2529 recording::memento_of_get_type::write_reproducer (reproducer &r)
2531 const char *id = r.make_identifier (this, "type");
2532 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2534 r.get_identifier (get_context ()),
2535 get_type_enum_strings[m_kind]);
2538 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2540 /* Override of default implementation of
2541 recording::type::get_size for get_pointer. */
2543 size_t
2544 recording::memento_of_get_pointer::get_size ()
2546 return POINTER_SIZE / BITS_PER_UNIT;
2549 /* Override of default implementation of
2550 recording::type::accepts_writes_from for get_pointer.
2552 Require a pointer type, and allowing writes to
2553 (const T *) from a (T*), but not the other way around. */
2555 bool
2556 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2558 /* Must be a pointer type: */
2559 type *rtype_points_to = rtype->is_pointer ();
2560 if (!rtype_points_to)
2561 return false;
2563 /* It's OK to assign to a (const T *) from a (T *). */
2564 return m_other_type->unqualified ()
2565 ->accepts_writes_from (rtype_points_to);
2568 /* Implementation of pure virtual hook recording::memento::replay_into
2569 for recording::memento_of_get_pointer. */
2571 void
2572 recording::memento_of_get_pointer::replay_into (replayer *)
2574 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2577 /* Implementation of recording::memento::make_debug_string for
2578 results of get_pointer, adding " *" to the underlying type,
2579 with special-casing to handle function pointer types. */
2581 recording::string *
2582 recording::memento_of_get_pointer::make_debug_string ()
2584 /* Special-case function pointer types, to put the "*" in parens between
2585 the return type and the params (for one level of dereferencing, at
2586 least). */
2587 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2588 return fn_type->make_debug_string_with_ptr ();
2590 return string::from_printf (m_ctxt,
2591 "%s *", m_other_type->get_debug_string ());
2594 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2596 void
2597 recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2599 /* We need to special-case function pointer types; see the notes in
2600 recording::function_type::write_deferred_reproducer. */
2601 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2603 fn_type->write_deferred_reproducer (r, this);
2604 return;
2607 const char *id = r.make_identifier (this, "type");
2608 r.write (" gcc_jit_type *%s =\n"
2609 " gcc_jit_type_get_pointer (%s);\n",
2611 r.get_identifier_as_type (m_other_type));
2614 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2616 /* Implementation of pure virtual hook recording::memento::replay_into
2617 for recording::memento_of_get_const. */
2619 void
2620 recording::memento_of_get_const::replay_into (replayer *)
2622 set_playback_obj (m_other_type->playback_type ()->get_const ());
2625 /* Implementation of recording::memento::make_debug_string for
2626 results of get_const, prepending "const ". */
2628 recording::string *
2629 recording::memento_of_get_const::make_debug_string ()
2631 return string::from_printf (m_ctxt,
2632 "const %s", m_other_type->get_debug_string ());
2635 /* Implementation of recording::memento::write_reproducer for const types. */
2637 void
2638 recording::memento_of_get_const::write_reproducer (reproducer &r)
2640 const char *id = r.make_identifier (this, "type");
2641 r.write (" gcc_jit_type *%s =\n"
2642 " gcc_jit_type_get_const (%s);\n",
2644 r.get_identifier_as_type (m_other_type));
2647 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2649 /* Implementation of pure virtual hook recording::memento::replay_into
2650 for recording::memento_of_get_volatile. */
2652 void
2653 recording::memento_of_get_volatile::replay_into (replayer *)
2655 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2658 /* Implementation of recording::memento::make_debug_string for
2659 results of get_volatile, prepending "volatile ". */
2661 recording::string *
2662 recording::memento_of_get_volatile::make_debug_string ()
2664 return string::from_printf (m_ctxt,
2665 "volatile %s", m_other_type->get_debug_string ());
2668 /* Implementation of recording::memento::write_reproducer for volatile
2669 types. */
2671 void
2672 recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2674 const char *id = r.make_identifier (this, "type");
2675 r.write (" gcc_jit_type *%s =\n"
2676 " gcc_jit_type_get_volatile (%s);\n",
2678 r.get_identifier_as_type (m_other_type));
2681 /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
2683 /* Implementation of pure virtual hook recording::memento::replay_into
2684 for recording::memento_of_get_aligned. */
2686 void
2687 recording::memento_of_get_aligned::replay_into (replayer *)
2689 set_playback_obj
2690 (m_other_type->playback_type ()->get_aligned (m_alignment_in_bytes));
2693 /* Implementation of recording::memento::make_debug_string for
2694 results of get_aligned. */
2696 recording::string *
2697 recording::memento_of_get_aligned::make_debug_string ()
2699 return string::from_printf (m_ctxt,
2700 "%s __attribute__((aligned(%zi)))",
2701 m_other_type->get_debug_string (),
2702 m_alignment_in_bytes);
2705 /* Implementation of recording::memento::write_reproducer for aligned
2706 types. */
2708 void
2709 recording::memento_of_get_aligned::write_reproducer (reproducer &r)
2711 const char *id = r.make_identifier (this, "type");
2712 r.write (" gcc_jit_type *%s =\n"
2713 " gcc_jit_type_get_aligned (%s, %zi);\n",
2715 r.get_identifier_as_type (m_other_type),
2716 m_alignment_in_bytes);
2719 /* The implementation of class gcc::jit::recording::vector_type. */
2721 /* Implementation of pure virtual hook recording::memento::replay_into
2722 for recording::vector_type. */
2724 void
2725 recording::vector_type::replay_into (replayer *)
2727 set_playback_obj
2728 (m_other_type->playback_type ()->get_vector (m_num_units));
2731 /* Implementation of recording::memento::make_debug_string for
2732 results of get_vector. */
2734 recording::string *
2735 recording::vector_type::make_debug_string ()
2737 return string::from_printf
2738 (m_ctxt,
2739 "%s __attribute__((vector_size(sizeof (%s) * %zi)))",
2740 m_other_type->get_debug_string (),
2741 m_other_type->get_debug_string (),
2742 m_num_units);
2745 /* Implementation of recording::memento::write_reproducer for vector types. */
2747 void
2748 recording::vector_type::write_reproducer (reproducer &r)
2750 const char *id = r.make_identifier (this, "type");
2751 r.write (" gcc_jit_type *%s =\n"
2752 " gcc_jit_type_get_vector (%s, %zi);\n",
2754 r.get_identifier_as_type (m_other_type),
2755 m_num_units);
2758 /* The implementation of class gcc::jit::recording::array_type */
2760 /* Implementation of pure virtual hook recording::type::dereference for
2761 recording::array_type. */
2763 recording::type *
2764 recording::array_type::dereference ()
2766 return m_element_type;
2769 /* Implementation of pure virtual hook recording::memento::replay_into
2770 for recording::array_type. */
2772 void
2773 recording::array_type::replay_into (replayer *r)
2775 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
2776 m_element_type->playback_type (),
2777 m_num_elements));
2780 /* Implementation of recording::memento::make_debug_string for
2781 results of new_array_type. */
2783 recording::string *
2784 recording::array_type::make_debug_string ()
2786 return string::from_printf (m_ctxt,
2787 "%s[%d]",
2788 m_element_type->get_debug_string (),
2789 m_num_elements);
2792 /* Implementation of recording::memento::write_reproducer for array
2793 types. */
2795 void
2796 recording::array_type::write_reproducer (reproducer &r)
2798 const char *id = r.make_identifier (this, "array_type");
2799 r.write (" gcc_jit_type *%s =\n"
2800 " gcc_jit_context_new_array_type (%s,\n"
2801 " %s, /* gcc_jit_location *loc */\n"
2802 " %s, /* gcc_jit_type *element_type */\n"
2803 " %i); /* int num_elements */\n",
2805 r.get_identifier (get_context ()),
2806 r.get_identifier (m_loc),
2807 r.get_identifier_as_type (m_element_type),
2808 m_num_elements);
2811 /* The implementation of class gcc::jit::recording::function_type */
2813 /* Constructor for gcc::jit::recording::function_type. */
2815 recording::function_type::function_type (context *ctxt,
2816 type *return_type,
2817 int num_params,
2818 type **param_types,
2819 int is_variadic)
2820 : type (ctxt),
2821 m_return_type (return_type),
2822 m_param_types (),
2823 m_is_variadic (is_variadic)
2825 for (int i = 0; i< num_params; i++)
2826 m_param_types.safe_push (param_types[i]);
2829 /* Implementation of pure virtual hook recording::type::dereference for
2830 recording::function_type. */
2832 recording::type *
2833 recording::function_type::dereference ()
2835 return NULL;
2838 /* Implementation of virtual hook recording::type::is_same_type_as for
2839 recording::function_type.
2841 We override this to avoid requiring identity of function pointer types,
2842 so that if client code has obtained the same signature in
2843 different ways (e.g. via gcc_jit_context_new_function_ptr_type
2844 vs gcc_jit_function_get_address), the different function_type
2845 instances are treated as compatible.
2847 We can't use type::accepts_writes_from for this as we need a stronger
2848 notion of "sameness": if we have a fn_ptr type that has args that are
2849 themselves fn_ptr types, then those args still need to match exactly.
2851 Alternatively, we could consolidate attempts to create identical
2852 function_type instances so that pointer equality works, but that runs
2853 into issues about the lifetimes of the cache (w.r.t. nested contexts). */
2855 bool
2856 recording::function_type::is_same_type_as (type *other)
2858 gcc_assert (other);
2860 function_type *other_fn_type = other->dyn_cast_function_type ();
2861 if (!other_fn_type)
2862 return false;
2864 /* Everything must match. */
2866 if (!m_return_type->is_same_type_as (other_fn_type->m_return_type))
2867 return false;
2869 if (m_param_types.length () != other_fn_type->m_param_types.length ())
2870 return false;
2872 unsigned i;
2873 type *param_type;
2874 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2875 if (!param_type->is_same_type_as (other_fn_type->m_param_types[i]))
2876 return false;
2878 if (m_is_variadic != other_fn_type->m_is_variadic)
2879 return false;
2881 /* Passed all tests. */
2882 return true;
2885 /* Implementation of pure virtual hook recording::memento::replay_into
2886 for recording::function_type. */
2888 void
2889 recording::function_type::replay_into (replayer *r)
2891 /* Convert m_param_types to a vec of playback type. */
2892 auto_vec <playback::type *> param_types;
2893 int i;
2894 recording::type *type;
2895 param_types.create (m_param_types.length ());
2896 FOR_EACH_VEC_ELT (m_param_types, i, type)
2897 param_types.safe_push (type->playback_type ());
2899 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
2900 &param_types,
2901 m_is_variadic));
2904 /* Special-casing for make_debug_string for get_pointer results for
2905 handling (one level) of pointers to functions. */
2907 recording::string *
2908 recording::function_type::make_debug_string_with_ptr ()
2910 return make_debug_string_with ("(*) ");
2913 /* Implementation of recording::memento::make_debug_string for
2914 results of new_function_type. */
2916 recording::string *
2917 recording::function_type::make_debug_string ()
2919 return make_debug_string_with ("");
2922 /* Build a debug string representation of the form:
2924 RESULT_TYPE INSERT (PARAM_TYPES)
2926 for use when handling 0 and 1 level of indirection to this
2927 function type. */
2929 recording::string *
2930 recording::function_type::make_debug_string_with (const char *insert)
2932 /* First, build a buffer for the arguments. */
2933 /* Calculate length of said buffer. */
2934 size_t sz = 1; /* nil terminator */
2935 for (unsigned i = 0; i< m_param_types.length (); i++)
2937 sz += strlen (m_param_types[i]->get_debug_string ());
2938 sz += 2; /* ", " separator */
2940 if (m_is_variadic)
2941 sz += 5; /* ", ..." separator and ellipsis */
2943 /* Now allocate and populate the buffer. */
2944 char *argbuf = new char[sz];
2945 size_t len = 0;
2947 for (unsigned i = 0; i< m_param_types.length (); i++)
2949 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
2950 len += strlen (m_param_types[i]->get_debug_string ());
2951 if (i + 1 < m_param_types.length ())
2953 strcpy (argbuf + len, ", ");
2954 len += 2;
2957 if (m_is_variadic)
2959 if (m_param_types.length ())
2961 strcpy (argbuf + len, ", ");
2962 len += 2;
2964 strcpy (argbuf + len, "...");
2965 len += 3;
2967 argbuf[len] = '\0';
2969 /* ...and use it to get the string for the call as a whole. */
2970 string *result = string::from_printf (m_ctxt,
2971 "%s %s(%s)",
2972 m_return_type->get_debug_string (),
2973 insert,
2974 argbuf);
2976 delete[] argbuf;
2978 return result;
2981 /* Implementation of recording::memento::write_reproducer for function
2982 types. */
2984 void
2985 recording::function_type::write_reproducer (reproducer &)
2987 /* see notes below. */
2990 /* There's a get_pointer within context::new_function_ptr_type:
2991 the type received by client code isn't the memento for the
2992 function_type, but instead the result of get_pointer on it.
2994 Hence we can't directly write a reproducer that gives function_type.
2995 Instead we special-case things within get_pointer, detecting this
2996 case, calling the following function. */
2998 void
2999 recording::function_type::write_deferred_reproducer (reproducer &r,
3000 memento *ptr_type)
3002 gcc_assert (ptr_type);
3003 r.make_identifier (this, "function_type");
3004 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
3005 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
3006 r.write (" gcc_jit_type *%s[%i] = {\n",
3007 param_types_id,
3008 m_param_types.length ());
3009 int i;
3010 type *param_type;
3011 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
3012 r.write (" %s,\n", r.get_identifier_as_type (param_type));
3013 r.write (" };\n");
3014 r.write (" gcc_jit_type *%s =\n"
3015 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
3016 " %s, /* gcc_jit_location *loc */\n"
3017 " %s, /* gcc_jit_type *return_type */\n"
3018 " %i, /* int num_params */\n"
3019 " %s, /* gcc_jit_type **param_types */\n"
3020 " %i); /* int is_variadic */\n",
3021 ptr_id,
3022 r.get_identifier (get_context ()),
3023 "NULL", /* location is not stored */
3024 r.get_identifier_as_type (m_return_type),
3025 m_param_types.length (),
3026 param_types_id,
3027 m_is_variadic);
3030 /* The implementation of class gcc::jit::recording::field. */
3032 /* Implementation of pure virtual hook recording::memento::replay_into
3033 for recording::field. */
3035 void
3036 recording::field::replay_into (replayer *r)
3038 set_playback_obj (r->new_field (playback_location (r, m_loc),
3039 m_type->playback_type (),
3040 playback_string (m_name)));
3043 /* Override the default implementation of
3044 recording::memento::write_to_dump. Dump each field
3045 by dumping a line of the form:
3046 TYPE NAME;
3047 so that we can build up a struct/union field by field. */
3049 void
3050 recording::field::write_to_dump (dump &d)
3052 d.write (" %s %s;\n",
3053 m_type->get_debug_string (),
3054 m_name->c_str ());
3057 /* Implementation of recording::memento::make_debug_string for
3058 results of new_field. */
3060 recording::string *
3061 recording::field::make_debug_string ()
3063 return m_name;
3066 /* Implementation of recording::memento::write_reproducer for fields. */
3068 void
3069 recording::field::write_reproducer (reproducer &r)
3071 const char *id = r.make_identifier (this, "field");
3072 r.write(" gcc_jit_field *%s =\n"
3073 " gcc_jit_context_new_field (%s,\n"
3074 " %s, /* gcc_jit_location *loc */\n"
3075 " %s, /* gcc_jit_type *type, */\n"
3076 " %s); /* const char *name */\n",
3078 r.get_identifier (get_context ()),
3079 r.get_identifier (m_loc),
3080 r.get_identifier_as_type (m_type),
3081 m_name->get_debug_string ());
3084 /* The implementation of class gcc::jit::recording::bitfield. */
3086 /* Implementation of pure virtual hook recording::memento::replay_into
3087 for recording::bitfield. */
3089 void
3090 recording::bitfield::replay_into (replayer *r)
3092 set_playback_obj (r->new_bitfield (playback_location (r, m_loc),
3093 m_type->playback_type (),
3094 m_width,
3095 playback_string (m_name)));
3098 /* Override the default implementation of
3099 recording::memento::write_to_dump. Dump each bit field
3100 by dumping a line of the form:
3101 TYPE NAME:WIDTH;
3102 so that we can build up a struct/union field by field. */
3104 void
3105 recording::bitfield::write_to_dump (dump &d)
3107 d.write (" %s %s:%d;\n",
3108 m_type->get_debug_string (),
3109 m_name->c_str (),
3110 m_width);
3113 /* Implementation of recording::memento::make_debug_string for
3114 results of new_bitfield. */
3116 recording::string *
3117 recording::bitfield::make_debug_string ()
3119 return string::from_printf (m_ctxt,
3120 "%s:%d",
3121 m_name->c_str (), m_width);
3124 /* Implementation of recording::memento::write_reproducer for bitfields. */
3126 void
3127 recording::bitfield::write_reproducer (reproducer &r)
3129 const char *id = r.make_identifier (this, "bitfield");
3130 r.write (" gcc_jit_field *%s =\n"
3131 " gcc_jit_context_new_bitfield (%s,\n"
3132 " %s, /* gcc_jit_location *loc */\n"
3133 " %s, /* gcc_jit_type *type, */\n"
3134 " %d, /* int width, */\n"
3135 " %s); /* const char *name */\n",
3137 r.get_identifier (get_context ()),
3138 r.get_identifier (m_loc),
3139 r.get_identifier_as_type (m_type),
3140 m_width,
3141 m_name->get_debug_string ());
3144 /* The implementation of class gcc::jit::recording::compound_type */
3146 /* The constructor for gcc::jit::recording::compound_type. */
3148 recording::compound_type::compound_type (context *ctxt,
3149 location *loc,
3150 string *name)
3151 : type (ctxt),
3152 m_loc (loc),
3153 m_name (name),
3154 m_fields (NULL)
3158 /* Set the fields of a compound type.
3160 Implements the post-error-checking part of
3161 gcc_jit_struct_set_fields, and is also used by
3162 gcc_jit_context_new_union_type. */
3164 void
3165 recording::compound_type::set_fields (location *loc,
3166 int num_fields,
3167 field **field_array)
3169 m_loc = loc;
3170 gcc_assert (m_fields == NULL);
3172 m_fields = new fields (this, num_fields, field_array);
3173 m_ctxt->record (m_fields);
3176 /* Implementation of pure virtual hook recording::type::dereference for
3177 recording::compound_type. */
3179 recording::type *
3180 recording::compound_type::dereference ()
3182 return NULL; /* not a pointer */
3185 /* The implementation of class gcc::jit::recording::struct_. */
3187 /* The constructor for gcc::jit::recording::struct_. */
3189 recording::struct_::struct_ (context *ctxt,
3190 location *loc,
3191 string *name)
3192 : compound_type (ctxt, loc, name)
3196 /* Implementation of pure virtual hook recording::memento::replay_into
3197 for recording::struct_. */
3199 void
3200 recording::struct_::replay_into (replayer *r)
3202 set_playback_obj (
3203 r->new_compound_type (playback_location (r, get_loc ()),
3204 get_name ()->c_str (),
3205 true /* is_struct */));
3208 const char *
3209 recording::struct_::access_as_type (reproducer &r)
3211 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
3212 r.get_identifier (this));
3215 /* Implementation of recording::memento::make_debug_string for
3216 structs. */
3218 recording::string *
3219 recording::struct_::make_debug_string ()
3221 return string::from_printf (m_ctxt,
3222 "struct %s", get_name ()->c_str ());
3225 void
3226 recording::struct_::write_reproducer (reproducer &r)
3228 const char *id = r.make_identifier (this, "struct");
3229 r.write (" gcc_jit_struct *%s =\n"
3230 " gcc_jit_context_new_opaque_struct (%s,\n"
3231 " %s, /* gcc_jit_location *loc */\n"
3232 " %s); /* const char *name */\n",
3234 r.get_identifier (get_context ()),
3235 r.get_identifier (get_loc ()),
3236 get_name ()->get_debug_string ());
3239 /* The implementation of class gcc::jit::recording::union_. */
3241 /* The constructor for gcc::jit::recording::union_. */
3243 recording::union_::union_ (context *ctxt,
3244 location *loc,
3245 string *name)
3246 : compound_type (ctxt, loc, name)
3250 /* Implementation of pure virtual hook recording::memento::replay_into
3251 for recording::union_. */
3253 void
3254 recording::union_::replay_into (replayer *r)
3256 set_playback_obj (
3257 r->new_compound_type (playback_location (r, get_loc ()),
3258 get_name ()->c_str (),
3259 false /* is_struct */));
3262 /* Implementation of recording::memento::make_debug_string for
3263 unions. */
3265 recording::string *
3266 recording::union_::make_debug_string ()
3268 return string::from_printf (m_ctxt,
3269 "union %s", get_name ()->c_str ());
3272 /* Implementation of recording::memento::write_reproducer for unions. */
3274 void
3275 recording::union_::write_reproducer (reproducer &r)
3277 const char *id = r.make_identifier (this, "union");
3279 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
3280 r.write (" gcc_jit_field *%s[%i] = {\n",
3281 fields_id,
3282 get_fields ()->length ());
3283 for (int i = 0; i < get_fields ()->length (); i++)
3284 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
3285 r.write (" };\n");
3287 r.write (" gcc_jit_type *%s =\n"
3288 " gcc_jit_context_new_union_type (%s,\n"
3289 " %s, /* gcc_jit_location *loc */\n"
3290 " %s, /* const char *name */\n"
3291 " %i, /* int num_fields */\n"
3292 " %s); /* gcc_jit_field **fields */\n",
3294 r.get_identifier (get_context ()),
3295 r.get_identifier (get_loc ()),
3296 get_name ()->get_debug_string (),
3297 get_fields ()->length (),
3298 fields_id);
3301 /* The implementation of class gcc::jit::recording::fields. */
3303 /* The constructor for gcc::jit::recording::fields. */
3305 recording::fields::fields (compound_type *struct_or_union,
3306 int num_fields,
3307 field **fields)
3308 : memento (struct_or_union->m_ctxt),
3309 m_struct_or_union (struct_or_union),
3310 m_fields ()
3312 for (int i = 0; i < num_fields; i++)
3314 gcc_assert (fields[i]->get_container () == NULL);
3315 fields[i]->set_container (m_struct_or_union);
3316 m_fields.safe_push (fields[i]);
3320 /* Implementation of pure virtual hook recording::memento::replay_into
3321 for recording::fields. */
3323 void
3324 recording::fields::replay_into (replayer *)
3326 auto_vec<playback::field *> playback_fields;
3327 playback_fields.create (m_fields.length ());
3328 for (unsigned i = 0; i < m_fields.length (); i++)
3329 playback_fields.safe_push (m_fields[i]->playback_field ());
3330 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
3333 /* Override the default implementation of
3334 recording::memento::write_to_dump by writing a union/struct
3335 declaration of this form:
3337 struct/union NAME {
3338 TYPE_1 NAME_1;
3339 TYPE_2 NAME_2;
3340 ....
3341 TYPE_N NAME_N;
3344 to the dump. */
3346 void
3347 recording::fields::write_to_dump (dump &d)
3349 int i;
3350 field *f;
3352 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
3353 FOR_EACH_VEC_ELT (m_fields, i, f)
3354 f->write_to_dump (d);
3355 d.write ("};\n");
3358 /* Implementation of recording::memento::write_reproducer for the fields
3359 subclass. */
3361 void
3362 recording::fields::write_reproducer (reproducer &r)
3364 if (m_struct_or_union)
3365 if (m_struct_or_union->dyn_cast_struct () == NULL)
3366 /* We have a union; the fields have already been written by
3367 union::write_reproducer. */
3368 return;
3370 const char *fields_id = r.make_identifier (this, "fields");
3371 r.write (" gcc_jit_field *%s[%i] = {\n",
3372 fields_id,
3373 m_fields.length ());
3374 int i;
3375 field *field;
3376 FOR_EACH_VEC_ELT (m_fields, i, field)
3377 r.write (" %s,\n", r.get_identifier (field));
3378 r.write (" };\n");
3380 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
3381 " %s, /* gcc_jit_location *loc */\n"
3382 " %i, /* int num_fields */\n"
3383 " %s); /* gcc_jit_field **fields */\n",
3384 r.get_identifier (m_struct_or_union),
3385 r.get_identifier ((memento *)NULL),
3386 m_fields.length (),
3387 fields_id);
3390 /* Implementation of recording::memento::make_debug_string for
3391 field tables. */
3393 recording::string *
3394 recording::fields::make_debug_string ()
3396 return string::from_printf (m_ctxt,
3397 "fields");
3400 /* The implementation of class gcc::jit::recording::rvalue. */
3402 /* Create a recording::access_field_rvalue instance and add it to
3403 the rvalue's context's list of mementos.
3405 Implements the post-error-checking part of
3406 gcc_jit_rvalue_access_field. */
3408 recording::rvalue *
3409 recording::rvalue::access_field (recording::location *loc,
3410 field *field)
3412 recording::rvalue *result =
3413 new access_field_rvalue (m_ctxt, loc, this, field);
3414 m_ctxt->record (result);
3415 return result;
3418 /* Create a recording::dereference_field_rvalue instance and add it to
3419 the rvalue's context's list of mementos.
3421 Implements the post-error-checking part of
3422 gcc_jit_rvalue_dereference_field. */
3424 recording::lvalue *
3425 recording::rvalue::dereference_field (recording::location *loc,
3426 field *field)
3428 recording::lvalue *result =
3429 new dereference_field_rvalue (m_ctxt, loc, this, field);
3430 m_ctxt->record (result);
3431 return result;
3434 /* Create a recording::dereference_rvalue instance and add it to the
3435 rvalue's context's list of mementos.
3437 Implements the post-error-checking part of
3438 gcc_jit_rvalue_dereference. */
3440 recording::lvalue *
3441 recording::rvalue::dereference (recording::location *loc)
3443 recording::lvalue *result =
3444 new dereference_rvalue (m_ctxt, loc, this);
3445 m_ctxt->record (result);
3446 return result;
3449 /* An rvalue visitor, for validating that every rvalue within an expression
3450 trees within "STMT" has the correct scope (e.g. no access to locals
3451 of a different function). */
3453 class rvalue_usage_validator : public recording::rvalue_visitor
3455 public:
3456 rvalue_usage_validator (const char *api_funcname,
3457 recording::context *ctxt,
3458 recording::statement *stmt);
3460 void
3461 visit (recording::rvalue *rvalue) FINAL OVERRIDE;
3463 private:
3464 const char *m_api_funcname;
3465 recording::context *m_ctxt;
3466 recording::statement *m_stmt;
3469 /* The trivial constructor for rvalue_usage_validator. */
3471 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
3472 recording::context *ctxt,
3473 recording::statement *stmt)
3474 : m_api_funcname (api_funcname),
3475 m_ctxt (ctxt),
3476 m_stmt (stmt)
3480 /* Verify that the given rvalue is in the correct scope. */
3482 void
3483 rvalue_usage_validator::visit (recording::rvalue *rvalue)
3485 gcc_assert (m_stmt->get_block ());
3486 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
3488 /* Most rvalues don't have a scope (only locals and params). */
3489 if (rvalue->get_scope ())
3491 if (rvalue->get_scope () != stmt_scope)
3492 m_ctxt->add_error
3493 (rvalue->get_loc (),
3494 "%s:"
3495 " rvalue %s (type: %s)"
3496 " has scope limited to function %s"
3497 " but was used within function %s"
3498 " (in statement: %s)",
3499 m_api_funcname,
3500 rvalue->get_debug_string (),
3501 rvalue->get_type ()->get_debug_string (),
3502 rvalue->get_scope ()->get_debug_string (),
3503 stmt_scope->get_debug_string (),
3504 m_stmt->get_debug_string ());
3506 else
3508 if (rvalue->dyn_cast_param ())
3509 m_ctxt->add_error
3510 (rvalue->get_loc (),
3511 "%s:"
3512 " param %s (type: %s)"
3513 " was used within function %s"
3514 " (in statement: %s)"
3515 " but is not associated with any function",
3516 m_api_funcname,
3517 rvalue->get_debug_string (),
3518 rvalue->get_type ()->get_debug_string (),
3519 stmt_scope->get_debug_string (),
3520 m_stmt->get_debug_string ());
3524 /* Verify that it's valid to use this rvalue (and all expressions
3525 in the tree below it) within the given statement.
3527 For example, we must reject attempts to use a local from one
3528 function within a different function here, or we'll get
3529 an ICE deep inside toplev::main. */
3531 void
3532 recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
3534 rvalue_usage_validator v (api_funcname,
3535 s->get_context (),
3538 /* Verify that it's OK to use this rvalue within s. */
3539 v.visit (this);
3541 /* Traverse the expression tree below "this", verifying all rvalues
3542 within it. */
3543 visit_children (&v);
3546 /* Set the scope of this rvalue to be the given function. This can only
3547 be done once on a given rvalue. */
3549 void
3550 recording::rvalue::set_scope (function *scope)
3552 gcc_assert (scope);
3553 gcc_assert (m_scope == NULL);
3554 m_scope = scope;
3558 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3559 themselves.
3560 Instances of rvalue don't need an upcast call. */
3562 const char *
3563 recording::rvalue::access_as_rvalue (reproducer &r)
3565 return r.get_identifier (this);
3568 /* Return a debug string for the given rvalue, wrapping it in parentheses
3569 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3570 stronger precedence that this rvalue's precedence.
3572 For example, given:
3574 MULT
3576 PLUS MINUS
3577 / \ / \
3578 A B C D
3580 we want to emit:
3582 (A + B) * (C - D)
3584 since MULT has strong precedence than PLUS and MINUS, whereas for:
3586 PLUS
3588 MULT DIVIDE
3589 / \ / \
3590 A B C D
3592 we can simply emit:
3594 A * B + C / D
3596 since PLUS has weaker precedence than MULT and DIVIDE. */
3598 const char *
3599 recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
3601 enum precedence this_prec = get_precedence ();
3603 /* If this_prec has stronger precedence than outer_prec, we don't
3604 need to wrap this in parens within the outer debug string.
3605 Stronger precedences occur earlier than weaker within the enum,
3606 so this is a less than test. Equal precedences don't need
3607 parentheses. */
3608 if (this_prec <= outer_prec)
3609 return get_debug_string();
3611 /* Otherwise, we need parentheses. */
3613 /* Lazily-build and cache m_parenthesized_string. */
3614 if (!m_parenthesized_string)
3616 const char *debug_string = get_debug_string ();
3617 m_parenthesized_string = string::from_printf (get_context (),
3618 "(%s)",
3619 debug_string);
3621 gcc_assert (m_parenthesized_string);
3622 return m_parenthesized_string->c_str ();
3626 /* The implementation of class gcc::jit::recording::lvalue. */
3628 /* Create a recording::new_access_field_of_lvalue instance and add it to
3629 the lvalue's context's list of mementos.
3631 Implements the post-error-checking part of
3632 gcc_jit_lvalue_access_field. */
3634 recording::lvalue *
3635 recording::lvalue::access_field (recording::location *loc,
3636 field *field)
3638 recording::lvalue *result =
3639 new access_field_of_lvalue (m_ctxt, loc, this, field);
3640 m_ctxt->record (result);
3641 return result;
3644 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3645 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3646 upcast call. */
3648 const char *
3649 recording::lvalue::access_as_rvalue (reproducer &r)
3651 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3652 r.get_identifier (this));
3655 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3656 Instances of lvalue don't need to be upcast. */
3658 const char *
3659 recording::lvalue::access_as_lvalue (reproducer &r)
3661 return r.get_identifier (this);
3664 /* Create a recording::get_address_of_lvalue instance and add it to
3665 the lvalue's context's list of mementos.
3667 Implements the post-error-checking part of
3668 gcc_jit_lvalue_get_address. */
3670 recording::rvalue *
3671 recording::lvalue::get_address (recording::location *loc)
3673 recording::rvalue *result =
3674 new get_address_of_lvalue (m_ctxt, loc, this);
3675 m_ctxt->record (result);
3676 return result;
3679 /* The implementation of class gcc::jit::recording::param. */
3681 /* Implementation of pure virtual hook recording::memento::replay_into
3682 for recording::param. */
3684 void
3685 recording::param::replay_into (replayer *r)
3687 set_playback_obj (r->new_param (playback_location (r, m_loc),
3688 m_type->playback_type (),
3689 m_name->c_str ()));
3692 /* Implementation of recording::rvalue::access_as_rvalue for params.
3693 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3694 upcast call. */
3696 const char *
3697 recording::param::access_as_rvalue (reproducer &r)
3699 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3700 r.get_identifier (this));
3703 /* Implementation of recording::lvalue::access_as_lvalue for params.
3704 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3705 upcast call. */
3707 const char *
3708 recording::param::access_as_lvalue (reproducer &r)
3710 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3711 r.get_identifier (this));
3714 /* Implementation of recording::memento::write_reproducer for params. */
3716 void
3717 recording::param::write_reproducer (reproducer &r)
3719 const char *id = r.make_identifier (this, "param");
3720 r.write (" gcc_jit_param *%s =\n"
3721 " gcc_jit_context_new_param (%s,\n"
3722 " %s, /* gcc_jit_location *loc */\n"
3723 " %s, /*gcc_jit_type *type */\n"
3724 " %s); /* const char *name */\n",
3726 r.get_identifier (get_context ()),
3727 r.get_identifier (m_loc),
3728 r.get_identifier_as_type (m_type),
3729 m_name->get_debug_string ());
3732 /* The implementation of class gcc::jit::recording::function. */
3734 /* gcc::jit::recording::function's constructor. */
3736 recording::function::function (context *ctxt,
3737 recording::location *loc,
3738 enum gcc_jit_function_kind kind,
3739 type *return_type,
3740 recording::string *name,
3741 int num_params,
3742 recording::param **params,
3743 int is_variadic,
3744 enum built_in_function builtin_id)
3745 : memento (ctxt),
3746 m_loc (loc),
3747 m_kind (kind),
3748 m_return_type (return_type),
3749 m_name (name),
3750 m_params (),
3751 m_is_variadic (is_variadic),
3752 m_builtin_id (builtin_id),
3753 m_locals (),
3754 m_blocks (),
3755 m_fn_ptr_type (NULL)
3757 for (int i = 0; i< num_params; i++)
3759 param *param = params[i];
3760 gcc_assert (param);
3762 /* Associate each param with this function.
3764 Verify that the param doesn't already have a function. */
3765 if (param->get_scope ())
3767 /* We've already rejected attempts to reuse a param between
3768 different functions (within gcc_jit_context_new_function), so
3769 if the param *does* already have a function, it must be being
3770 reused within the params array for this function. We must
3771 produce an error for this reuse (blocking the compile), since
3772 otherwise we'd have an ICE later on. */
3773 gcc_assert (this == param->get_scope ());
3774 ctxt->add_error
3775 (loc,
3776 "gcc_jit_context_new_function:"
3777 " parameter %s (type: %s)"
3778 " is used more than once when creating function %s",
3779 param->get_debug_string (),
3780 param->get_type ()->get_debug_string (),
3781 name->c_str ());
3783 else
3785 /* The normal, non-error case: associate this function with the
3786 param. */
3787 param->set_scope (this);
3790 m_params.safe_push (param);
3794 /* Implementation of pure virtual hook recording::memento::replay_into
3795 for recording::function. */
3797 void
3798 recording::function::replay_into (replayer *r)
3800 /* Convert m_params to a vec of playback param. */
3801 auto_vec <playback::param *> params;
3802 int i;
3803 recording::param *param;
3804 params.create (m_params.length ());
3805 FOR_EACH_VEC_ELT (m_params, i, param)
3806 params.safe_push (param->playback_param ());
3808 set_playback_obj (r->new_function (playback_location (r, m_loc),
3809 m_kind,
3810 m_return_type->playback_type (),
3811 m_name->c_str (),
3812 &params,
3813 m_is_variadic,
3814 m_builtin_id));
3817 /* Create a recording::local instance and add it to
3818 the functions's context's list of mementos, and to the function's
3819 list of locals.
3821 Implements the post-error-checking part of
3822 gcc_jit_function_new_local. */
3824 recording::lvalue *
3825 recording::function::new_local (recording::location *loc,
3826 type *type,
3827 const char *name)
3829 local *result = new local (this, loc, type, new_string (name));
3830 m_ctxt->record (result);
3831 m_locals.safe_push (result);
3832 return result;
3835 /* Create a recording::block instance and add it to
3836 the functions's context's list of mementos, and to the function's
3837 list of blocks.
3839 Implements the post-error-checking part of
3840 gcc_jit_function_new_block. */
3842 recording::block*
3843 recording::function::new_block (const char *name)
3845 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
3847 recording::block *result =
3848 new recording::block (this, m_blocks.length (), new_string (name));
3849 m_ctxt->record (result);
3850 m_blocks.safe_push (result);
3851 return result;
3854 /* Override the default implementation of
3855 recording::memento::write_to_dump by dumping a C-like
3856 representation of the function; either like a prototype
3857 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3858 all other kinds of function. */
3860 void
3861 recording::function::write_to_dump (dump &d)
3863 switch (m_kind)
3865 default: gcc_unreachable ();
3866 case GCC_JIT_FUNCTION_EXPORTED:
3867 case GCC_JIT_FUNCTION_IMPORTED:
3868 d.write ("extern ");
3869 break;
3870 case GCC_JIT_FUNCTION_INTERNAL:
3871 d.write ("static ");
3872 break;
3873 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
3874 d.write ("static inline ");
3875 break;
3877 d.write ("%s\n", m_return_type->get_debug_string ());
3879 if (d.update_locations ())
3880 m_loc = d.make_location ();
3882 d.write ("%s (", get_debug_string ());
3884 int i;
3885 recording::param *param;
3886 FOR_EACH_VEC_ELT (m_params, i, param)
3888 if (i > 0)
3889 d.write (", ");
3890 d.write ("%s %s",
3891 param->get_type ()->get_debug_string (),
3892 param->get_debug_string ());
3894 d.write (")");
3895 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
3897 d.write ("; /* (imported) */\n\n");
3899 else
3901 int i;
3902 local *var = NULL;
3903 block *b;
3904 d.write ("\n{\n");
3906 /* Write locals: */
3907 FOR_EACH_VEC_ELT (m_locals, i, var)
3908 var->write_to_dump (d);
3909 if (m_locals.length ())
3910 d.write ("\n");
3912 /* Write each block: */
3913 FOR_EACH_VEC_ELT (m_blocks, i, b)
3915 if (i > 0)
3916 d.write ("\n");
3917 b->write_to_dump (d);
3920 d.write ("}\n\n");
3924 /* Pre-compilation validation of a function, for those things we can't
3925 check until the context is (supposedly) fully-populated. */
3927 void
3928 recording::function::validate ()
3930 /* Complain about empty functions with non-void return type. */
3931 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
3932 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
3933 if (m_blocks.length () == 0)
3934 m_ctxt->add_error (m_loc,
3935 "function %s returns non-void (type: %s)"
3936 " but has no blocks",
3937 get_debug_string (),
3938 m_return_type->get_debug_string ());
3940 /* Check that all blocks are terminated. */
3941 int num_invalid_blocks = 0;
3943 int i;
3944 block *b;
3946 FOR_EACH_VEC_ELT (m_blocks, i, b)
3947 if (!b->validate ())
3948 num_invalid_blocks++;
3951 /* Check that all blocks are reachable. */
3952 if (!m_ctxt->get_inner_bool_option
3953 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
3954 && m_blocks.length () > 0 && num_invalid_blocks == 0)
3956 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3957 flag, starting at the initial block. */
3958 auto_vec<block *> worklist (m_blocks.length ());
3959 worklist.safe_push (m_blocks[0]);
3960 while (worklist.length () > 0)
3962 block *b = worklist.pop ();
3963 b->m_is_reachable = true;
3965 /* Add successor blocks that aren't yet marked to the worklist. */
3966 /* We checked that each block has a terminating statement above . */
3967 vec <block *> successors = b->get_successor_blocks ();
3968 int i;
3969 block *succ;
3970 FOR_EACH_VEC_ELT (successors, i, succ)
3971 if (!succ->m_is_reachable)
3972 worklist.safe_push (succ);
3973 successors.release ();
3976 /* Now complain about any blocks that haven't been marked. */
3978 int i;
3979 block *b;
3980 FOR_EACH_VEC_ELT (m_blocks, i, b)
3981 if (!b->m_is_reachable)
3982 m_ctxt->add_error (b->get_loc (),
3983 "unreachable block: %s",
3984 b->get_debug_string ());
3989 /* Implements the post-error-checking part of
3990 gcc_jit_function_dump_to_dot. */
3992 void
3993 recording::function::dump_to_dot (const char *path)
3995 FILE *fp = fopen (path, "w");
3996 if (!fp)
3997 return;
3999 pretty_printer the_pp;
4000 the_pp.buffer->stream = fp;
4002 pretty_printer *pp = &the_pp;
4004 pp_printf (pp,
4005 "digraph %s {\n", get_debug_string ());
4007 /* Blocks: */
4009 int i;
4010 block *b;
4011 FOR_EACH_VEC_ELT (m_blocks, i, b)
4012 b->dump_to_dot (pp);
4015 /* Edges: */
4017 int i;
4018 block *b;
4019 FOR_EACH_VEC_ELT (m_blocks, i, b)
4020 b->dump_edges_to_dot (pp);
4023 pp_printf (pp, "}\n");
4024 pp_flush (pp);
4025 fclose (fp);
4028 /* Implements the post-error-checking part of
4029 gcc_jit_function_get_address. */
4031 recording::rvalue *
4032 recording::function::get_address (recording::location *loc)
4034 /* Lazily create and cache the function pointer type. */
4035 if (!m_fn_ptr_type)
4037 /* Make a recording::function_type for this function. */
4038 auto_vec <recording::type *> param_types (m_params.length ());
4039 unsigned i;
4040 recording::param *param;
4041 FOR_EACH_VEC_ELT (m_params, i, param)
4042 param_types.safe_push (param->get_type ());
4043 recording::function_type *fn_type
4044 = m_ctxt->new_function_type (m_return_type,
4045 m_params.length (),
4046 param_types.address (),
4047 m_is_variadic);
4048 m_fn_ptr_type = fn_type->get_pointer ();
4050 gcc_assert (m_fn_ptr_type);
4052 rvalue *result = new function_pointer (get_context (), loc, this, m_fn_ptr_type);
4053 m_ctxt->record (result);
4054 return result;
4057 /* Implementation of recording::memento::make_debug_string for
4058 functions. */
4060 recording::string *
4061 recording::function::make_debug_string ()
4063 return m_name;
4066 /* A table of enum gcc_jit_function_kind values expressed in string
4067 form. */
4069 static const char * const names_of_function_kinds[] = {
4070 "GCC_JIT_FUNCTION_EXPORTED",
4071 "GCC_JIT_FUNCTION_INTERNAL",
4072 "GCC_JIT_FUNCTION_IMPORTED",
4073 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
4076 /* Implementation of recording::memento::write_reproducer for functions. */
4078 void
4079 recording::function::write_reproducer (reproducer &r)
4081 const char *id = r.make_identifier (this, "func");
4083 if (m_builtin_id)
4085 r.write (" gcc_jit_function *%s =\n"
4086 " gcc_jit_context_get_builtin_function (%s,\n"
4087 " %s);\n",
4089 r.get_identifier (get_context ()),
4090 m_name->get_debug_string ());
4091 return;
4093 const char *params_id = r.make_tmp_identifier ("params_for", this);
4094 r.write (" gcc_jit_param *%s[%i] = {\n",
4095 params_id,
4096 m_params.length ());
4097 int i;
4098 param *param;
4099 FOR_EACH_VEC_ELT (m_params, i, param)
4100 r.write (" %s,\n", r.get_identifier (param));
4101 r.write (" };\n");
4102 r.write (" gcc_jit_function *%s =\n"
4103 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
4104 " %s, /* gcc_jit_location *loc */\n"
4105 " %s, /* enum gcc_jit_function_kind kind */\n"
4106 " %s, /* gcc_jit_type *return_type */\n"
4107 " %s, /* const char *name */\n"
4108 " %i, /* int num_params */\n"
4109 " %s, /* gcc_jit_param **params */\n"
4110 " %i); /* int is_variadic */\n",
4112 r.get_identifier (get_context ()),
4113 r.get_identifier (m_loc),
4114 names_of_function_kinds[m_kind],
4115 r.get_identifier_as_type (m_return_type),
4116 m_name->get_debug_string (),
4117 m_params.length (),
4118 params_id,
4119 m_is_variadic);
4123 /* The implementation of class gcc::jit::recording::block. */
4125 /* Create a recording::eval instance and add it to
4126 the block's context's list of mementos, and to the block's
4127 list of statements.
4129 Implements the heart of gcc_jit_block_add_eval. */
4131 recording::statement *
4132 recording::block::add_eval (recording::location *loc,
4133 recording::rvalue *rvalue)
4135 statement *result = new eval (this, loc, rvalue);
4136 m_ctxt->record (result);
4137 m_statements.safe_push (result);
4138 return result;
4141 /* Create a recording::assignment instance and add it to
4142 the block's context's list of mementos, and to the block's
4143 list of statements.
4145 Implements the heart of gcc_jit_block_add_assignment. */
4147 recording::statement *
4148 recording::block::add_assignment (recording::location *loc,
4149 recording::lvalue *lvalue,
4150 recording::rvalue *rvalue)
4152 statement *result = new assignment (this, loc, lvalue, rvalue);
4153 m_ctxt->record (result);
4154 m_statements.safe_push (result);
4155 return result;
4158 /* Create a recording::assignment_op instance and add it to
4159 the block's context's list of mementos, and to the block's
4160 list of statements.
4162 Implements the heart of gcc_jit_block_add_assignment_op. */
4164 recording::statement *
4165 recording::block::add_assignment_op (recording::location *loc,
4166 recording::lvalue *lvalue,
4167 enum gcc_jit_binary_op op,
4168 recording::rvalue *rvalue)
4170 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
4171 m_ctxt->record (result);
4172 m_statements.safe_push (result);
4173 return result;
4176 /* Create a recording::comment instance and add it to
4177 the block's context's list of mementos, and to the block's
4178 list of statements.
4180 Implements the heart of gcc_jit_block_add_comment. */
4182 recording::statement *
4183 recording::block::add_comment (recording::location *loc,
4184 const char *text)
4186 statement *result = new comment (this, loc, new_string (text));
4187 m_ctxt->record (result);
4188 m_statements.safe_push (result);
4189 return result;
4192 /* Create a recording::end_with_conditional instance and add it to
4193 the block's context's list of mementos, and to the block's
4194 list of statements.
4196 Implements the heart of gcc_jit_block_end_with_conditional. */
4198 recording::statement *
4199 recording::block::end_with_conditional (recording::location *loc,
4200 recording::rvalue *boolval,
4201 recording::block *on_true,
4202 recording::block *on_false)
4204 statement *result = new conditional (this, loc, boolval, on_true, on_false);
4205 m_ctxt->record (result);
4206 m_statements.safe_push (result);
4207 m_has_been_terminated = true;
4208 return result;
4211 /* Create a recording::end_with_jump instance and add it to
4212 the block's context's list of mementos, and to the block's
4213 list of statements.
4215 Implements the heart of gcc_jit_block_end_with_jump. */
4217 recording::statement *
4218 recording::block::end_with_jump (recording::location *loc,
4219 recording::block *target)
4221 statement *result = new jump (this, loc, target);
4222 m_ctxt->record (result);
4223 m_statements.safe_push (result);
4224 m_has_been_terminated = true;
4225 return result;
4228 /* Create a recording::end_with_return instance and add it to
4229 the block's context's list of mementos, and to the block's
4230 list of statements.
4232 Implements the post-error-checking parts of
4233 gcc_jit_block_end_with_return and
4234 gcc_jit_block_end_with_void_return. */
4236 recording::statement *
4237 recording::block::end_with_return (recording::location *loc,
4238 recording::rvalue *rvalue)
4240 /* This is used by both gcc_jit_function_add_return and
4241 gcc_jit_function_add_void_return; rvalue will be non-NULL for
4242 the former and NULL for the latter. */
4243 statement *result = new return_ (this, loc, rvalue);
4244 m_ctxt->record (result);
4245 m_statements.safe_push (result);
4246 m_has_been_terminated = true;
4247 return result;
4250 /* Create a recording::switch_ instance and add it to
4251 the block's context's list of mementos, and to the block's
4252 list of statements.
4254 Implements the heart of gcc_jit_block_end_with_switch. */
4256 recording::statement *
4257 recording::block::end_with_switch (recording::location *loc,
4258 recording::rvalue *expr,
4259 recording::block *default_block,
4260 int num_cases,
4261 recording::case_ **cases)
4263 statement *result = new switch_ (this, loc,
4264 expr,
4265 default_block,
4266 num_cases,
4267 cases);
4268 m_ctxt->record (result);
4269 m_statements.safe_push (result);
4270 m_has_been_terminated = true;
4271 return result;
4274 /* Override the default implementation of
4275 recording::memento::write_to_dump for blocks by writing
4276 an unindented block name as a label, followed by the indented
4277 statements:
4279 BLOCK_NAME:
4280 STATEMENT_1;
4281 STATEMENT_2;
4283 STATEMENT_N; */
4285 void
4286 recording::block::write_to_dump (dump &d)
4288 d.write ("%s:\n", get_debug_string ());
4290 int i;
4291 statement *s;
4292 FOR_EACH_VEC_ELT (m_statements, i, s)
4293 s->write_to_dump (d);
4296 /* Validate a block by ensuring that it has been terminated. */
4298 bool
4299 recording::block::validate ()
4301 /* Check for termination. */
4302 if (!has_been_terminated ())
4304 statement *stmt = get_last_statement ();
4305 location *loc = stmt ? stmt->get_loc () : NULL;
4306 m_func->get_context ()->add_error (loc,
4307 "unterminated block in %s: %s",
4308 m_func->get_debug_string (),
4309 get_debug_string ());
4310 return false;
4313 return true;
4316 /* Get the source-location of a block by using that of the first
4317 statement within it, if any. */
4319 recording::location *
4320 recording::block::get_loc () const
4322 recording::statement *stmt = get_first_statement ();
4323 if (stmt)
4324 return stmt->get_loc ();
4325 else
4326 return NULL;
4329 /* Get the first statement within a block, if any. */
4331 recording::statement *
4332 recording::block::get_first_statement () const
4334 if (m_statements.length ())
4335 return m_statements[0];
4336 else
4337 return NULL;
4340 /* Get the last statement within a block, if any. */
4342 recording::statement *
4343 recording::block::get_last_statement () const
4345 if (m_statements.length ())
4346 return m_statements[m_statements.length () - 1];
4347 else
4348 return NULL;
4351 /* Assuming that this block has been terminated, get the successor blocks
4352 as a vector. Ownership of the vector transfers to the caller, which
4353 must call its release () method.
4355 Used when validating functions, and when dumping dot representations
4356 of them. */
4358 vec <recording::block *>
4359 recording::block::get_successor_blocks () const
4361 gcc_assert (m_has_been_terminated);
4362 statement *last_statement = get_last_statement ();
4363 gcc_assert (last_statement);
4364 return last_statement->get_successor_blocks ();
4367 /* Implementation of pure virtual hook recording::memento::replay_into
4368 for recording::block. */
4370 void
4371 recording::block::replay_into (replayer *)
4373 set_playback_obj (m_func->playback_function ()
4374 ->new_block (playback_string (m_name)));
4377 /* Implementation of recording::memento::make_debug_string for
4378 blocks. */
4380 recording::string *
4381 recording::block::make_debug_string ()
4383 if (m_name)
4384 return m_name;
4385 else
4386 return string::from_printf (m_ctxt,
4387 "<UNNAMED BLOCK %p>",
4388 (void *)this);
4391 /* Implementation of recording::memento::write_reproducer for blocks. */
4393 void
4394 recording::block::write_reproducer (reproducer &r)
4396 const char *id = r.make_identifier (this, "block");
4397 r.write (" gcc_jit_block *%s =\n"
4398 " gcc_jit_function_new_block (%s, %s);\n",
4400 r.get_identifier (m_func),
4401 m_name ? m_name->get_debug_string () : "NULL");
4404 /* Dump a block in graphviz form into PP, capturing the block name (if
4405 any) and the statements. */
4407 void
4408 recording::block::dump_to_dot (pretty_printer *pp)
4410 pp_printf (pp,
4411 ("\tblock_%d "
4412 "[shape=record,style=filled,fillcolor=white,label=\"{"),
4413 m_index);
4414 pp_write_text_to_stream (pp);
4415 if (m_name)
4417 pp_string (pp, m_name->c_str ());
4418 pp_string (pp, ":");
4419 pp_newline (pp);
4420 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4423 int i;
4424 statement *s;
4425 FOR_EACH_VEC_ELT (m_statements, i, s)
4427 pp_string (pp, s->get_debug_string ());
4428 pp_newline (pp);
4429 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4432 pp_printf (pp,
4433 "}\"];\n\n");
4434 pp_flush (pp);
4437 /* Dump the out-edges of the block in graphviz form into PP. */
4439 void
4440 recording::block::dump_edges_to_dot (pretty_printer *pp)
4442 vec <block *> successors = get_successor_blocks ();
4443 int i;
4444 block *succ;
4445 FOR_EACH_VEC_ELT (successors, i, succ)
4446 pp_printf (pp,
4447 "\tblock_%d:s -> block_%d:n;\n",
4448 m_index, succ->m_index);
4449 successors.release ();
4452 /* The implementation of class gcc::jit::recording::global. */
4454 /* Implementation of pure virtual hook recording::memento::replay_into
4455 for recording::global. */
4457 void
4458 recording::global::replay_into (replayer *r)
4460 set_playback_obj (
4461 m_initializer
4462 ? r->new_global_initialized (playback_location (r, m_loc),
4463 m_kind,
4464 m_type->playback_type (),
4465 m_type->dereference ()->get_size (),
4466 m_initializer_num_bytes
4467 / m_type->dereference ()->get_size (),
4468 m_initializer,
4469 playback_string (m_name))
4470 : r->new_global (playback_location (r, m_loc),
4471 m_kind,
4472 m_type->playback_type (),
4473 playback_string (m_name)));
4476 /* Override the default implementation of
4477 recording::memento::write_to_dump for globals.
4478 This will be of the form:
4480 GCC_JIT_GLOBAL_EXPORTED:
4481 "TYPE NAME;"
4482 e.g. "int foo;"
4484 GCC_JIT_GLOBAL_INTERNAL:
4485 "static TYPE NAME;"
4486 e.g. "static int foo;"
4488 GCC_JIT_GLOBAL_IMPORTED:
4489 "extern TYPE NAME;"
4490 e.g. "extern int foo;"
4492 These are written to the top of the dump by
4493 recording::context::dump_to_file. */
4495 void
4496 recording::global::write_to_dump (dump &d)
4498 if (d.update_locations ())
4499 m_loc = d.make_location ();
4501 switch (m_kind)
4503 default:
4504 gcc_unreachable ();
4506 case GCC_JIT_GLOBAL_EXPORTED:
4507 break;
4509 case GCC_JIT_GLOBAL_INTERNAL:
4510 d.write ("static ");
4511 break;
4513 case GCC_JIT_GLOBAL_IMPORTED:
4514 d.write ("extern ");
4515 break;
4518 d.write ("%s %s",
4519 m_type->get_debug_string (),
4520 get_debug_string ());
4522 if (!m_initializer)
4524 d.write (";\n");
4525 return;
4528 d.write ("=\n { ");
4529 const unsigned char *p = (const unsigned char *)m_initializer;
4530 for (size_t i = 0; i < m_initializer_num_bytes; i++)
4532 d.write ("0x%x, ", p[i]);
4533 if (i && !(i % 64))
4534 d.write ("\n ");
4536 d.write ("};\n");
4539 /* A table of enum gcc_jit_global_kind values expressed in string
4540 form. */
4542 static const char * const global_kind_reproducer_strings[] = {
4543 "GCC_JIT_GLOBAL_EXPORTED",
4544 "GCC_JIT_GLOBAL_INTERNAL",
4545 "GCC_JIT_GLOBAL_IMPORTED"
4548 template <typename T>
4549 void
4550 recording::global::write_initializer_reproducer (const char *id, reproducer &r)
4552 const char *init_id = r.make_tmp_identifier ("init_for", this);
4553 r.write (" %s %s[] =\n {",
4554 m_type->dereference ()->get_debug_string (),
4555 init_id);
4557 const T *p = (const T *)m_initializer;
4558 for (size_t i = 0; i < m_initializer_num_bytes / sizeof (T); i++)
4560 r.write ("%" PRIu64 ", ", (uint64_t)p[i]);
4561 if (i && !(i % 64))
4562 r.write ("\n ");
4564 r.write ("};\n");
4565 r.write (" gcc_jit_global_set_initializer (%s, %s, sizeof (%s));\n",
4566 id, init_id, init_id);
4569 /* Implementation of recording::memento::write_reproducer for globals. */
4571 void
4572 recording::global::write_reproducer (reproducer &r)
4574 const char *id = r.make_identifier (this, "block");
4575 r.write (" gcc_jit_lvalue *%s =\n"
4576 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4577 " %s, /* gcc_jit_location *loc */\n"
4578 " %s, /* enum gcc_jit_global_kind kind */\n"
4579 " %s, /* gcc_jit_type *type */\n"
4580 " %s); /* const char *name */\n",
4582 r.get_identifier (get_context ()),
4583 r.get_identifier (m_loc),
4584 global_kind_reproducer_strings[m_kind],
4585 r.get_identifier_as_type (get_type ()),
4586 m_name->get_debug_string ());
4588 if (m_initializer)
4589 switch (m_type->dereference ()->get_size ())
4591 case 1:
4592 write_initializer_reproducer<uint8_t> (id, r);
4593 break;
4594 case 2:
4595 write_initializer_reproducer<uint16_t> (id, r);
4596 break;
4597 case 4:
4598 write_initializer_reproducer<uint32_t> (id, r);
4599 break;
4600 case 8:
4601 write_initializer_reproducer<uint64_t> (id, r);
4602 break;
4603 default:
4604 /* This function is serving on sizes returned by 'get_size',
4605 these are all covered by the previous cases. */
4606 gcc_unreachable ();
4610 /* The implementation of the various const-handling classes:
4611 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4613 /* Explicit specialization of the various mementos we're interested in. */
4614 template class recording::memento_of_new_rvalue_from_const <int>;
4615 template class recording::memento_of_new_rvalue_from_const <long>;
4616 template class recording::memento_of_new_rvalue_from_const <double>;
4617 template class recording::memento_of_new_rvalue_from_const <void *>;
4619 /* Implementation of the pure virtual hook recording::memento::replay_into
4620 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4622 template <typename HOST_TYPE>
4623 void
4624 recording::
4625 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
4627 set_playback_obj
4628 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
4629 m_value));
4632 /* The make_debug_string and write_reproducer methods vary between the
4633 various
4634 memento_of_new_rvalue_from_const <HOST_TYPE>
4635 classes, so we explicitly write specializations of them.
4637 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4638 namespaces are written out explicitly, which is why most of this file
4639 doesn't abbreviate things by entering the "recording" namespace.
4641 However, these specializations are required to be in the same namespace
4642 as the template, hence we now have to enter the gcc::jit::recording
4643 namespace. */
4645 namespace recording
4648 /* The make_debug_string specialization for <int>, which renders it as
4649 (TARGET_TYPE)LITERAL
4650 e.g.
4651 "(int)42". */
4653 template <>
4654 string *
4655 memento_of_new_rvalue_from_const <int>::make_debug_string ()
4657 return string::from_printf (m_ctxt,
4658 "(%s)%i",
4659 m_type->get_debug_string (),
4660 m_value);
4663 /* The get_wide_int specialization for <int>. */
4665 template <>
4666 bool
4667 memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const
4669 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4670 return true;
4673 /* The write_reproducer specialization for <int>. */
4675 template <>
4676 void
4677 memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
4679 const char *id = r.make_identifier (this, "rvalue");
4680 r.write (" gcc_jit_rvalue *%s =\n"
4681 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4682 " %s, /* gcc_jit_type *numeric_type */\n"
4683 " %i); /* int value */\n",
4685 r.get_identifier (get_context ()),
4686 r.get_identifier_as_type (m_type),
4687 m_value);
4690 /* The make_debug_string specialization for <long>, rendering it as
4691 (TARGET_TYPE)LITERAL
4692 e.g.
4693 "(long)42". */
4695 template <>
4696 string *
4697 memento_of_new_rvalue_from_const <long>::make_debug_string ()
4699 return string::from_printf (m_ctxt,
4700 "(%s)%li",
4701 m_type->get_debug_string (),
4702 m_value);
4705 /* The get_wide_int specialization for <long>. */
4707 template <>
4708 bool
4709 memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const
4711 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4712 return true;
4715 /* The write_reproducer specialization for <long>. */
4717 template <>
4718 void
4719 recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
4721 const char *id = r.make_identifier (this, "rvalue");
4723 /* We have to special-case LONG_MIN, since e.g.
4724 -9223372036854775808L
4725 is parsed as
4726 -(9223372036854775808L)
4727 and hence we'd get:
4728 error: integer constant is so large that it is unsigned [-Werror]
4729 Workaround this by writing (LONG_MIN + 1) - 1. */
4730 if (m_value == LONG_MIN)
4732 r.write (" gcc_jit_rvalue *%s =\n"
4733 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4734 " %s, /* gcc_jit_type *numeric_type */\n"
4735 " %ldL - 1); /* long value */\n",
4737 r.get_identifier (get_context ()),
4738 r.get_identifier_as_type (m_type),
4739 m_value + 1);
4740 return;
4743 r.write (" gcc_jit_rvalue *%s =\n"
4744 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4745 " %s, /* gcc_jit_type *numeric_type */\n"
4746 " %ldL); /* long value */\n",
4748 r.get_identifier (get_context ()),
4749 r.get_identifier_as_type (m_type),
4750 m_value);
4753 /* The make_debug_string specialization for <double>, rendering it as
4754 (TARGET_TYPE)LITERAL
4755 e.g.
4756 "(float)42.0". */
4758 template <>
4759 string *
4760 memento_of_new_rvalue_from_const <double>::make_debug_string ()
4762 return string::from_printf (m_ctxt,
4763 "(%s)%f",
4764 m_type->get_debug_string (),
4765 m_value);
4768 /* The get_wide_int specialization for <double>. */
4770 template <>
4771 bool
4772 memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
4774 return false;
4777 /* The write_reproducer specialization for <double>. */
4779 template <>
4780 void
4781 recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
4783 const char *id = r.make_identifier (this, "rvalue");
4784 r.write (" gcc_jit_rvalue *%s =\n"
4785 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4786 " %s, /* gcc_jit_type *numeric_type */\n"
4787 " %f); /* double value */\n",
4789 r.get_identifier (get_context ()),
4790 r.get_identifier_as_type (m_type),
4791 m_value);
4794 /* The make_debug_string specialization for <void *>, rendering it as
4795 (TARGET_TYPE)HEX
4796 e.g.
4797 "(int *)0xdeadbeef"
4799 Zero is rendered as NULL e.g.
4800 "(int *)NULL". */
4802 template <>
4803 string *
4804 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
4806 if (m_value != NULL)
4807 return string::from_printf (m_ctxt,
4808 "(%s)%p",
4809 m_type->get_debug_string (), m_value);
4810 else
4811 return string::from_printf (m_ctxt,
4812 "(%s)NULL",
4813 m_type->get_debug_string ());
4816 /* The get_wide_int specialization for <void *>. */
4818 template <>
4819 bool
4820 memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const
4822 return false;
4825 /* Implementation of recording::memento::write_reproducer for <void *>
4826 values. */
4828 template <>
4829 void
4830 memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
4832 const char *id = r.make_identifier (this, "rvalue");
4833 if (m_value)
4834 r.write (" gcc_jit_rvalue *%s =\n"
4835 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4836 " %s, /* gcc_jit_type *pointer_type */\n"
4837 " (void *)%p); /* void *value */\n",
4839 r.get_identifier (get_context ()),
4840 r.get_identifier_as_type (m_type),
4841 m_value);
4842 else
4843 r.write (" gcc_jit_rvalue *%s =\n"
4844 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4845 " %s); /* gcc_jit_type *pointer_type */\n",
4847 r.get_identifier (get_context ()),
4848 r.get_identifier_as_type (m_type));
4851 /* We're done specializing make_debug_string and write_reproducer, so we
4852 can exit the gcc::jit::recording namespace. */
4854 } // namespace recording
4856 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4858 /* Implementation of pure virtual hook recording::memento::replay_into
4859 for recording::memento_of_new_string_literal. */
4861 void
4862 recording::memento_of_new_string_literal::replay_into (replayer *r)
4864 set_playback_obj (r->new_string_literal (m_value->c_str ()));
4867 /* Implementation of recording::memento::make_debug_string for
4868 string literals. */
4870 recording::string *
4871 recording::memento_of_new_string_literal::make_debug_string ()
4873 return string::from_printf (m_ctxt,
4874 "%s",
4875 m_value->get_debug_string ());
4878 /* Implementation of recording::memento::write_reproducer for string literal
4879 values. */
4881 void
4882 recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
4884 const char *id = r.make_identifier (this, "rvalue");
4885 r.write (" gcc_jit_rvalue *%s =\n"
4886 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4887 " %s); /* const char *value */\n",
4889 r.get_identifier (get_context ()),
4890 m_value->get_debug_string ());
4893 /* The implementation of class
4894 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
4896 /* The constructor for
4897 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
4899 recording::memento_of_new_rvalue_from_vector::
4900 memento_of_new_rvalue_from_vector (context *ctxt,
4901 location *loc,
4902 vector_type *type,
4903 rvalue **elements)
4904 : rvalue (ctxt, loc, type),
4905 m_vector_type (type),
4906 m_elements ()
4908 for (unsigned i = 0; i < type->get_num_units (); i++)
4909 m_elements.safe_push (elements[i]);
4912 /* Implementation of pure virtual hook recording::memento::replay_into
4913 for recording::memento_of_new_rvalue_from_vector. */
4915 void
4916 recording::memento_of_new_rvalue_from_vector::replay_into (replayer *r)
4918 auto_vec<playback::rvalue *> playback_elements;
4919 playback_elements.create (m_elements.length ());
4920 for (unsigned i = 0; i< m_elements.length (); i++)
4921 playback_elements.safe_push (m_elements[i]->playback_rvalue ());
4923 set_playback_obj (r->new_rvalue_from_vector (playback_location (r, m_loc),
4924 m_type->playback_type (),
4925 playback_elements));
4928 /* Implementation of pure virtual hook recording::rvalue::visit_children
4929 for recording::memento_of_new_rvalue_from_vector. */
4931 void
4932 recording::memento_of_new_rvalue_from_vector::visit_children (rvalue_visitor *v)
4934 for (unsigned i = 0; i< m_elements.length (); i++)
4935 v->visit (m_elements[i]);
4938 /* Implementation of recording::memento::make_debug_string for
4939 vectors. */
4941 recording::string *
4942 recording::memento_of_new_rvalue_from_vector::make_debug_string ()
4944 comma_separated_string elements (m_elements, get_precedence ());
4946 /* Now build a string. */
4947 string *result = string::from_printf (m_ctxt,
4948 "{%s}",
4949 elements.as_char_ptr ());
4951 return result;
4955 /* Implementation of recording::memento::write_reproducer for
4956 vectors. */
4958 void
4959 recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer &r)
4961 const char *id = r.make_identifier (this, "vector");
4962 const char *elements_id = r.make_tmp_identifier ("elements_for_", this);
4963 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4964 elements_id,
4965 m_elements.length ());
4966 for (unsigned i = 0; i< m_elements.length (); i++)
4967 r.write (" %s,\n", r.get_identifier_as_rvalue (m_elements[i]));
4968 r.write (" };\n");
4969 r.write (" gcc_jit_rvalue *%s =\n"
4970 " gcc_jit_context_new_rvalue_from_vector (%s, /* gcc_jit_context *ctxt */\n"
4971 " %s, /* gcc_jit_location *loc */\n"
4972 " %s, /* gcc_jit_type *vec_type */\n"
4973 " %i, /* size_t num_elements */ \n"
4974 " %s); /* gcc_jit_rvalue **elements*/\n",
4976 r.get_identifier (get_context ()),
4977 r.get_identifier (m_loc),
4978 r.get_identifier (m_vector_type),
4979 m_elements.length (),
4980 elements_id);
4983 /* The implementation of class gcc::jit::recording::unary_op. */
4985 /* Implementation of pure virtual hook recording::memento::replay_into
4986 for recording::unary_op. */
4988 void
4989 recording::unary_op::replay_into (replayer *r)
4991 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
4992 m_op,
4993 get_type ()->playback_type (),
4994 m_a->playback_rvalue ()));
4997 /* Implementation of pure virtual hook recording::rvalue::visit_children
4998 for recording::unary_op. */
4999 void
5000 recording::unary_op::visit_children (rvalue_visitor *v)
5002 v->visit (m_a);
5005 /* Implementation of recording::memento::make_debug_string for
5006 unary ops. */
5008 static const char * const unary_op_strings[] = {
5009 "-", /* GCC_JIT_UNARY_OP_MINUS */
5010 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
5011 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
5012 "abs ", /* GCC_JIT_UNARY_OP_ABS */
5015 recording::string *
5016 recording::unary_op::make_debug_string ()
5018 return string::from_printf (m_ctxt,
5019 "%s(%s)",
5020 unary_op_strings[m_op],
5021 m_a->get_debug_string ());
5024 const char * const unary_op_reproducer_strings[] = {
5025 "GCC_JIT_UNARY_OP_MINUS",
5026 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
5027 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
5028 "GCC_JIT_UNARY_OP_ABS"
5031 /* Implementation of recording::memento::write_reproducer for unary ops. */
5033 void
5034 recording::unary_op::write_reproducer (reproducer &r)
5036 const char *id = r.make_identifier (this, "rvalue");
5037 r.write (" gcc_jit_rvalue *%s =\n"
5038 " gcc_jit_context_new_unary_op (%s,\n"
5039 " %s, /* gcc_jit_location *loc */\n"
5040 " %s, /* enum gcc_jit_unary_op op */\n"
5041 " %s, /* gcc_jit_type *result_type */\n"
5042 " %s); /* gcc_jit_rvalue *a */\n",
5044 r.get_identifier (get_context ()),
5045 r.get_identifier (m_loc),
5046 unary_op_reproducer_strings[m_op],
5047 r.get_identifier_as_type (get_type ()),
5048 r.get_identifier_as_rvalue (m_a));
5051 /* The implementation of class gcc::jit::recording::binary_op. */
5053 /* Implementation of pure virtual hook recording::memento::replay_into
5054 for recording::binary_op. */
5056 void
5057 recording::binary_op::replay_into (replayer *r)
5059 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
5060 m_op,
5061 get_type ()->playback_type (),
5062 m_a->playback_rvalue (),
5063 m_b->playback_rvalue ()));
5066 /* Implementation of pure virtual hook recording::rvalue::visit_children
5067 for recording::binary_op. */
5068 void
5069 recording::binary_op::visit_children (rvalue_visitor *v)
5071 v->visit (m_a);
5072 v->visit (m_b);
5075 /* Implementation of recording::memento::make_debug_string for
5076 binary ops. */
5078 static const char * const binary_op_strings[] = {
5079 "+", /* GCC_JIT_BINARY_OP_PLUS */
5080 "-", /* GCC_JIT_BINARY_OP_MINUS */
5081 "*", /* GCC_JIT_BINARY_OP_MULT */
5082 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
5083 "%", /* GCC_JIT_BINARY_OP_MODULO */
5084 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
5085 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
5086 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
5087 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
5088 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
5089 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
5090 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
5093 recording::string *
5094 recording::binary_op::make_debug_string ()
5096 enum precedence prec = get_precedence ();
5097 return string::from_printf (m_ctxt,
5098 "%s %s %s",
5099 m_a->get_debug_string_parens (prec),
5100 binary_op_strings[m_op],
5101 m_b->get_debug_string_parens (prec));
5104 const char * const binary_op_reproducer_strings[] = {
5105 "GCC_JIT_BINARY_OP_PLUS",
5106 "GCC_JIT_BINARY_OP_MINUS",
5107 "GCC_JIT_BINARY_OP_MULT",
5108 "GCC_JIT_BINARY_OP_DIVIDE",
5109 "GCC_JIT_BINARY_OP_MODULO",
5110 "GCC_JIT_BINARY_OP_BITWISE_AND",
5111 "GCC_JIT_BINARY_OP_BITWISE_XOR",
5112 "GCC_JIT_BINARY_OP_BITWISE_OR",
5113 "GCC_JIT_BINARY_OP_LOGICAL_AND",
5114 "GCC_JIT_BINARY_OP_LOGICAL_OR",
5115 "GCC_JIT_BINARY_OP_LSHIFT",
5116 "GCC_JIT_BINARY_OP_RSHIFT"
5119 /* Implementation of recording::memento::write_reproducer for binary ops. */
5121 void
5122 recording::binary_op::write_reproducer (reproducer &r)
5124 const char *id = r.make_identifier (this, "rvalue");
5125 r.write (" gcc_jit_rvalue *%s =\n"
5126 " gcc_jit_context_new_binary_op (%s,\n"
5127 " %s, /* gcc_jit_location *loc */\n"
5128 " %s, /* enum gcc_jit_binary_op op */\n"
5129 " %s, /* gcc_jit_type *result_type */\n"
5130 " %s, /* gcc_jit_rvalue *a */\n"
5131 " %s); /* gcc_jit_rvalue *b */\n",
5133 r.get_identifier (get_context ()),
5134 r.get_identifier (m_loc),
5135 binary_op_reproducer_strings[m_op],
5136 r.get_identifier_as_type (get_type ()),
5137 r.get_identifier_as_rvalue (m_a),
5138 r.get_identifier_as_rvalue (m_b));
5141 namespace recording {
5142 static const enum precedence binary_op_precedence[] = {
5143 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
5144 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
5146 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
5147 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
5148 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
5150 PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
5151 PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
5152 PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
5153 PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
5154 PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
5155 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
5156 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
5158 } /* namespace recording */
5160 enum recording::precedence
5161 recording::binary_op::get_precedence () const
5163 return binary_op_precedence[m_op];
5166 /* The implementation of class gcc::jit::recording::comparison. */
5168 /* Implementation of recording::memento::make_debug_string for
5169 comparisons. */
5171 static const char * const comparison_strings[] =
5173 "==", /* GCC_JIT_COMPARISON_EQ */
5174 "!=", /* GCC_JIT_COMPARISON_NE */
5175 "<", /* GCC_JIT_COMPARISON_LT */
5176 "<=", /* GCC_JIT_COMPARISON_LE */
5177 ">", /* GCC_JIT_COMPARISON_GT */
5178 ">=", /* GCC_JIT_COMPARISON_GE */
5181 recording::string *
5182 recording::comparison::make_debug_string ()
5184 enum precedence prec = get_precedence ();
5185 return string::from_printf (m_ctxt,
5186 "%s %s %s",
5187 m_a->get_debug_string_parens (prec),
5188 comparison_strings[m_op],
5189 m_b->get_debug_string_parens (prec));
5192 /* A table of enum gcc_jit_comparison values expressed in string
5193 form. */
5195 static const char * const comparison_reproducer_strings[] =
5197 "GCC_JIT_COMPARISON_EQ",
5198 "GCC_JIT_COMPARISON_NE",
5199 "GCC_JIT_COMPARISON_LT",
5200 "GCC_JIT_COMPARISON_LE",
5201 "GCC_JIT_COMPARISON_GT",
5202 "GCC_JIT_COMPARISON_GE"
5205 /* Implementation of recording::memento::write_reproducer for comparisons. */
5207 void
5208 recording::comparison::write_reproducer (reproducer &r)
5210 const char *id = r.make_identifier (this, "rvalue");
5211 r.write (" gcc_jit_rvalue *%s =\n"
5212 " gcc_jit_context_new_comparison (%s,\n"
5213 " %s, /* gcc_jit_location *loc */\n"
5214 " %s, /* enum gcc_jit_comparison op */\n"
5215 " %s, /* gcc_jit_rvalue *a */\n"
5216 " %s); /* gcc_jit_rvalue *b */\n",
5218 r.get_identifier (get_context ()),
5219 r.get_identifier (m_loc),
5220 comparison_reproducer_strings[m_op],
5221 r.get_identifier_as_rvalue (m_a),
5222 r.get_identifier_as_rvalue (m_b));
5225 /* Implementation of pure virtual hook recording::memento::replay_into
5226 for recording::comparison. */
5228 void
5229 recording::comparison::replay_into (replayer *r)
5231 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
5232 m_op,
5233 m_a->playback_rvalue (),
5234 m_b->playback_rvalue ()));
5237 /* Implementation of pure virtual hook recording::rvalue::visit_children
5238 for recording::comparison. */
5240 void
5241 recording::comparison::visit_children (rvalue_visitor *v)
5243 v->visit (m_a);
5244 v->visit (m_b);
5247 namespace recording {
5248 static const enum precedence comparison_precedence[] =
5250 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
5251 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
5253 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LT */
5254 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
5255 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GT */
5256 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
5258 } /* namespace recording */
5260 enum recording::precedence
5261 recording::comparison::get_precedence () const
5263 return comparison_precedence[m_op];
5266 /* Implementation of pure virtual hook recording::memento::replay_into
5267 for recording::cast. */
5269 void
5270 recording::cast::replay_into (replayer *r)
5272 set_playback_obj (r->new_cast (playback_location (r, m_loc),
5273 m_rvalue->playback_rvalue (),
5274 get_type ()->playback_type ()));
5277 /* Implementation of pure virtual hook recording::rvalue::visit_children
5278 for recording::cast. */
5279 void
5280 recording::cast::visit_children (rvalue_visitor *v)
5282 v->visit (m_rvalue);
5285 /* Implementation of recording::memento::make_debug_string for
5286 casts. */
5288 recording::string *
5289 recording::cast::make_debug_string ()
5291 enum precedence prec = get_precedence ();
5292 return string::from_printf (m_ctxt,
5293 "(%s)%s",
5294 get_type ()->get_debug_string (),
5295 m_rvalue->get_debug_string_parens (prec));
5298 /* Implementation of recording::memento::write_reproducer for casts. */
5300 void
5301 recording::cast::write_reproducer (reproducer &r)
5303 const char *id = r.make_identifier (this, "rvalue");
5304 r.write (" gcc_jit_rvalue *%s =\n"
5305 " gcc_jit_context_new_cast (%s,\n"
5306 " %s, /* gcc_jit_location *loc */\n"
5307 " %s, /* gcc_jit_rvalue *rvalue */\n"
5308 " %s); /* gcc_jit_type *type */\n",
5310 r.get_identifier (get_context ()),
5311 r.get_identifier (m_loc),
5312 r.get_identifier_as_rvalue (m_rvalue),
5313 r.get_identifier_as_type (get_type ()));
5316 /* The implementation of class gcc::jit::recording::base_call. */
5318 /* The constructor for gcc::jit::recording::base_call. */
5320 recording::base_call::base_call (context *ctxt,
5321 location *loc,
5322 type *type_,
5323 int numargs,
5324 rvalue **args)
5325 : rvalue (ctxt, loc, type_),
5326 m_args (),
5327 m_require_tail_call (0)
5329 for (int i = 0; i< numargs; i++)
5330 m_args.safe_push (args[i]);
5333 /* Subroutine for use by call and call_though_ptr's write_reproducer
5334 methods. */
5336 void
5337 recording::base_call::write_reproducer_tail_call (reproducer &r,
5338 const char *id)
5340 if (m_require_tail_call)
5342 r.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
5343 " %i); /* int require_tail_call*/\n",
5349 /* The implementation of class gcc::jit::recording::call. */
5351 /* The constructor for gcc::jit::recording::call. */
5353 recording::call::call (recording::context *ctxt,
5354 recording::location *loc,
5355 recording::function *func,
5356 int numargs,
5357 rvalue **args)
5358 : base_call (ctxt, loc, func->get_return_type (), numargs, args),
5359 m_func (func)
5363 /* Implementation of pure virtual hook recording::memento::replay_into
5364 for recording::call. */
5366 void
5367 recording::call::replay_into (replayer *r)
5369 auto_vec<playback::rvalue *> playback_args;
5370 playback_args.create (m_args.length ());
5371 for (unsigned i = 0; i< m_args.length (); i++)
5372 playback_args.safe_push (m_args[i]->playback_rvalue ());
5374 set_playback_obj (r->new_call (playback_location (r, m_loc),
5375 m_func->playback_function (),
5376 &playback_args,
5377 m_require_tail_call));
5380 /* Implementation of pure virtual hook recording::rvalue::visit_children
5381 for recording::call. */
5383 void
5384 recording::call::visit_children (rvalue_visitor *v)
5386 for (unsigned i = 0; i< m_args.length (); i++)
5387 v->visit (m_args[i]);
5390 /* Implementation of recording::memento::make_debug_string for
5391 function calls. */
5393 recording::string *
5394 recording::call::make_debug_string ()
5396 /* First, build a buffer for the arguments. */
5397 comma_separated_string args (m_args, get_precedence ());
5399 /* ...and use it to get the string for the call as a whole. */
5400 string *result = string::from_printf (m_ctxt,
5401 "%s (%s)",
5402 m_func->get_debug_string (),
5403 args.as_char_ptr ());
5405 return result;
5408 void
5409 recording::call::write_reproducer (reproducer &r)
5411 const char *id = r.make_identifier (this, "call");
5412 const char *args_id = r.make_tmp_identifier ("args_for_", this);
5413 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
5414 args_id,
5415 m_args.length ());
5416 for (unsigned i = 0; i< m_args.length (); i++)
5417 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
5418 r.write (" };\n");
5419 r.write (" gcc_jit_rvalue *%s =\n"
5420 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
5421 " %s, /* gcc_jit_location *loc */\n"
5422 " %s, /* gcc_jit_function *func */\n"
5423 " %i, /* int numargs */ \n"
5424 " %s); /* gcc_jit_rvalue **args*/\n",
5426 r.get_identifier (get_context ()),
5427 r.get_identifier (m_loc),
5428 r.get_identifier (m_func),
5429 m_args.length (),
5430 args_id);
5431 write_reproducer_tail_call (r, id);
5434 /* The implementation of class gcc::jit::recording::call_through_ptr. */
5436 /* The constructor for recording::call_through_ptr. */
5438 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
5439 recording::location *loc,
5440 recording::rvalue *fn_ptr,
5441 int numargs,
5442 rvalue **args)
5443 : base_call (ctxt, loc,
5444 fn_ptr->get_type ()->dereference ()
5445 ->as_a_function_type ()->get_return_type (),
5446 numargs, args),
5447 m_fn_ptr (fn_ptr)
5451 /* Implementation of pure virtual hook recording::memento::replay_into
5452 for recording::call_through_ptr. */
5454 void
5455 recording::call_through_ptr::replay_into (replayer *r)
5457 auto_vec<playback::rvalue *> playback_args;
5458 playback_args.create (m_args.length ());
5459 for (unsigned i = 0; i< m_args.length (); i++)
5460 playback_args.safe_push (m_args[i]->playback_rvalue ());
5462 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
5463 m_fn_ptr->playback_rvalue (),
5464 &playback_args,
5465 m_require_tail_call));
5468 /* Implementation of pure virtual hook recording::rvalue::visit_children
5469 for recording::call_through_ptr. */
5471 void
5472 recording::call_through_ptr::visit_children (rvalue_visitor *v)
5474 v->visit (m_fn_ptr);
5475 for (unsigned i = 0; i< m_args.length (); i++)
5476 v->visit (m_args[i]);
5479 /* Implementation of recording::memento::make_debug_string for
5480 calls through function ptrs. */
5482 recording::string *
5483 recording::call_through_ptr::make_debug_string ()
5485 enum precedence prec = get_precedence ();
5486 /* First, build a buffer for the arguments. */
5487 /* Calculate length of said buffer. */
5488 size_t sz = 1; /* nil terminator */
5489 for (unsigned i = 0; i< m_args.length (); i++)
5491 sz += strlen (m_args[i]->get_debug_string_parens (prec));
5492 sz += 2; /* ", " separator */
5495 /* Now allocate and populate the buffer. */
5496 char *argbuf = new char[sz];
5497 size_t len = 0;
5499 for (unsigned i = 0; i< m_args.length (); i++)
5501 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
5502 len += strlen (m_args[i]->get_debug_string_parens (prec));
5503 if (i + 1 < m_args.length ())
5505 strcpy (argbuf + len, ", ");
5506 len += 2;
5509 argbuf[len] = '\0';
5511 /* ...and use it to get the string for the call as a whole. */
5512 string *result = string::from_printf (m_ctxt,
5513 "%s (%s)",
5514 m_fn_ptr->get_debug_string_parens (prec),
5515 argbuf);
5517 delete[] argbuf;
5519 return result;
5522 /* Implementation of recording::memento::write_reproducer for
5523 call_through_ptr. */
5525 void
5526 recording::call_through_ptr::write_reproducer (reproducer &r)
5528 const char *id = r.make_identifier (this, "call");
5529 const char *args_id = r.make_tmp_identifier ("args_for_", this);
5530 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
5531 args_id,
5532 m_args.length ());
5533 for (unsigned i = 0; i< m_args.length (); i++)
5534 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
5535 r.write (" };\n");
5536 r.write (" gcc_jit_rvalue *%s =\n"
5537 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
5538 " %s, /* gcc_jit_location *loc */\n"
5539 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
5540 " %i, /* int numargs */ \n"
5541 " %s); /* gcc_jit_rvalue **args*/\n",
5543 r.get_identifier (get_context ()),
5544 r.get_identifier (m_loc),
5545 r.get_identifier_as_rvalue (m_fn_ptr),
5546 m_args.length (),
5547 args_id);
5548 write_reproducer_tail_call (r, id);
5551 /* The implementation of class gcc::jit::recording::array_access. */
5553 /* Implementation of pure virtual hook recording::memento::replay_into
5554 for recording::array_access. */
5556 void
5557 recording::array_access::replay_into (replayer *r)
5559 set_playback_obj (
5560 r->new_array_access (playback_location (r, m_loc),
5561 m_ptr->playback_rvalue (),
5562 m_index->playback_rvalue ()));
5565 /* Implementation of pure virtual hook recording::rvalue::visit_children
5566 for recording::array_access. */
5568 void
5569 recording::array_access::visit_children (rvalue_visitor *v)
5571 v->visit (m_ptr);
5572 v->visit (m_index);
5575 /* Implementation of recording::memento::make_debug_string for
5576 array accesses. */
5578 recording::string *
5579 recording::array_access::make_debug_string ()
5581 enum precedence prec = get_precedence ();
5582 return string::from_printf (m_ctxt,
5583 "%s[%s]",
5584 m_ptr->get_debug_string_parens (prec),
5585 m_index->get_debug_string_parens (prec));
5588 /* Implementation of recording::memento::write_reproducer for
5589 array_access. */
5591 void
5592 recording::array_access::write_reproducer (reproducer &r)
5594 const char *id = r.make_identifier (this, "lvalue");
5595 r.write (" gcc_jit_lvalue *%s = \n"
5596 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
5597 " %s, /*gcc_jit_location *loc */\n"
5598 " %s, /* gcc_jit_rvalue *ptr */\n"
5599 " %s); /* gcc_jit_rvalue *index */\n",
5601 r.get_identifier (get_context ()),
5602 r.get_identifier (m_loc),
5603 r.get_identifier_as_rvalue (m_ptr),
5604 r.get_identifier_as_rvalue (m_index));
5607 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
5609 /* Implementation of pure virtual hook recording::memento::replay_into
5610 for recording::access_field_of_lvalue. */
5612 void
5613 recording::access_field_of_lvalue::replay_into (replayer *r)
5615 set_playback_obj (
5616 m_lvalue->playback_lvalue ()
5617 ->access_field (playback_location (r, m_loc),
5618 m_field->playback_field ()));
5622 /* Implementation of pure virtual hook recording::rvalue::visit_children
5623 for recording::access_field_of_lvalue. */
5625 void
5626 recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
5628 v->visit (m_lvalue);
5631 /* Implementation of recording::memento::make_debug_string for
5632 accessing a field of an lvalue. */
5634 recording::string *
5635 recording::access_field_of_lvalue::make_debug_string ()
5637 enum precedence prec = get_precedence ();
5638 return string::from_printf (m_ctxt,
5639 "%s.%s",
5640 m_lvalue->get_debug_string_parens (prec),
5641 m_field->get_debug_string ());
5644 /* Implementation of recording::memento::write_reproducer for
5645 access_field_of_lvalue. */
5647 void
5648 recording::access_field_of_lvalue::write_reproducer (reproducer &r)
5650 const char *id = r.make_identifier (this, "lvalue");
5651 r.write (" gcc_jit_lvalue *%s = \n"
5652 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5653 " %s, /*gcc_jit_location *loc */\n"
5654 " %s);\n",
5656 r.get_identifier_as_lvalue (m_lvalue),
5657 r.get_identifier (m_loc),
5658 r.get_identifier (m_field));
5661 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
5663 /* Implementation of pure virtual hook recording::memento::replay_into
5664 for recording::access_field_rvalue. */
5666 void
5667 recording::access_field_rvalue::replay_into (replayer *r)
5669 set_playback_obj (
5670 m_rvalue->playback_rvalue ()
5671 ->access_field (playback_location (r, m_loc),
5672 m_field->playback_field ()));
5675 /* Implementation of pure virtual hook recording::rvalue::visit_children
5676 for recording::access_field_rvalue. */
5678 void
5679 recording::access_field_rvalue::visit_children (rvalue_visitor *v)
5681 v->visit (m_rvalue);
5684 /* Implementation of recording::memento::make_debug_string for
5685 accessing a field of an rvalue. */
5687 recording::string *
5688 recording::access_field_rvalue::make_debug_string ()
5690 enum precedence prec = get_precedence ();
5691 return string::from_printf (m_ctxt,
5692 "%s.%s",
5693 m_rvalue->get_debug_string_parens (prec),
5694 m_field->get_debug_string ());
5697 /* Implementation of recording::memento::write_reproducer for
5698 access_field_rvalue. */
5700 void
5701 recording::access_field_rvalue::write_reproducer (reproducer &r)
5703 const char *id = r.make_identifier (this, "rvalue");
5704 r.write (" gcc_jit_rvalue *%s = \n"
5705 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5706 " %s, /*gcc_jit_location *loc */\n"
5707 " %s);\n",
5709 r.get_identifier_as_rvalue (m_rvalue),
5710 r.get_identifier (m_loc),
5711 r.get_identifier (m_field));
5714 /* The implementation of class
5715 gcc::jit::recording::dereference_field_rvalue. */
5717 /* Implementation of pure virtual hook recording::memento::replay_into
5718 for recording::dereference_field_rvalue. */
5720 void
5721 recording::dereference_field_rvalue::replay_into (replayer *r)
5723 set_playback_obj (
5724 m_rvalue->playback_rvalue ()->
5725 dereference_field (playback_location (r, m_loc),
5726 m_field->playback_field ()));
5729 /* Implementation of pure virtual hook recording::rvalue::visit_children
5730 for recording::dereference_field_rvalue. */
5732 void
5733 recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
5735 v->visit (m_rvalue);
5738 /* Implementation of recording::memento::make_debug_string for
5739 dereferencing a field of an rvalue. */
5741 recording::string *
5742 recording::dereference_field_rvalue::make_debug_string ()
5744 enum precedence prec = get_precedence ();
5745 return string::from_printf (m_ctxt,
5746 "%s->%s",
5747 m_rvalue->get_debug_string_parens (prec),
5748 m_field->get_debug_string ());
5751 /* Implementation of recording::memento::write_reproducer for
5752 dereference_field_rvalue. */
5754 void
5755 recording::dereference_field_rvalue::write_reproducer (reproducer &r)
5757 const char *id = r.make_identifier (this, "lvalue");
5758 r.write (" gcc_jit_lvalue *%s=\n"
5759 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5760 " %s, /* gcc_jit_location *loc */\n"
5761 " %s); /* gcc_jit_field *field */\n",
5763 r.get_identifier_as_rvalue (m_rvalue),
5764 r.get_identifier (m_loc),
5765 r.get_identifier (m_field));
5768 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5770 /* Implementation of pure virtual hook recording::memento::replay_into
5771 for recording::dereference_rvalue. */
5773 void
5774 recording::dereference_rvalue::replay_into (replayer *r)
5776 set_playback_obj (
5777 m_rvalue->playback_rvalue ()->
5778 dereference (playback_location (r, m_loc)));
5781 /* Implementation of pure virtual hook recording::rvalue::visit_children
5782 for recording::dereference_rvalue. */
5784 void
5785 recording::dereference_rvalue::visit_children (rvalue_visitor *v)
5787 v->visit (m_rvalue);
5790 /* Implementation of recording::memento::make_debug_string for
5791 dereferencing an rvalue. */
5793 recording::string *
5794 recording::dereference_rvalue::make_debug_string ()
5796 enum precedence prec = get_precedence ();
5797 return string::from_printf (m_ctxt,
5798 "*%s",
5799 m_rvalue->get_debug_string_parens (prec));
5802 /* Implementation of recording::memento::write_reproducer for
5803 dereference_rvalue. */
5805 void
5806 recording::dereference_rvalue::write_reproducer (reproducer &r)
5808 const char *id = r.make_identifier (this, "dereference");
5809 r.write (" gcc_jit_lvalue *%s =\n"
5810 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5811 " %s); /* gcc_jit_location *loc */\n",
5813 r.get_identifier_as_rvalue (m_rvalue),
5814 r.get_identifier (m_loc));
5817 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5819 /* Implementation of pure virtual hook recording::memento::replay_into
5820 for recording::get_address_of_lvalue. */
5822 void
5823 recording::get_address_of_lvalue::replay_into (replayer *r)
5825 set_playback_obj (
5826 m_lvalue->playback_lvalue ()->
5827 get_address (playback_location (r, m_loc)));
5830 /* Implementation of pure virtual hook recording::rvalue::visit_children
5831 for recording::get_address_of_lvalue. */
5833 void
5834 recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
5836 v->visit (m_lvalue);
5839 /* Implementation of recording::memento::make_debug_string for
5840 getting the address of an lvalue. */
5842 recording::string *
5843 recording::get_address_of_lvalue::make_debug_string ()
5845 enum precedence prec = get_precedence ();
5846 return string::from_printf (m_ctxt,
5847 "&%s",
5848 m_lvalue->get_debug_string_parens (prec));
5851 /* Implementation of recording::memento::write_reproducer for
5852 get_address_of_lvalue. */
5854 void
5855 recording::get_address_of_lvalue::write_reproducer (reproducer &r)
5857 const char *id = r.make_identifier (this, "address_of");
5858 r.write (" gcc_jit_rvalue *%s =\n"
5859 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5860 " %s); /* gcc_jit_location *loc */\n",
5862 r.get_identifier_as_lvalue (m_lvalue),
5863 r.get_identifier (m_loc));
5866 /* The implementation of class gcc::jit::recording::function_pointer. */
5868 /* Implementation of pure virtual hook recording::memento::replay_into
5869 for recording::function_pointer. */
5871 void
5872 recording::function_pointer::replay_into (replayer *r)
5874 set_playback_obj (
5875 m_fn->playback_function ()->
5876 get_address (playback_location (r, m_loc)));
5879 void
5880 recording::function_pointer::visit_children (rvalue_visitor *)
5882 /* Empty. */
5885 /* Implementation of recording::memento::make_debug_string for
5886 getting the address of an lvalue. */
5888 recording::string *
5889 recording::function_pointer::make_debug_string ()
5891 return string::from_printf (m_ctxt,
5892 "%s",
5893 m_fn->get_debug_string ());
5896 /* Implementation of recording::memento::write_reproducer for
5897 function_pointer. */
5899 void
5900 recording::function_pointer::write_reproducer (reproducer &r)
5902 const char *id = r.make_identifier (this, "address_of");
5903 r.write (" gcc_jit_rvalue *%s =\n"
5904 " gcc_jit_function_get_address (%s, /* gcc_jit_function *fn */\n"
5905 " %s); /* gcc_jit_location *loc */\n",
5907 r.get_identifier (m_fn),
5908 r.get_identifier (m_loc));
5911 /* The implementation of class gcc::jit::recording::local. */
5913 /* Implementation of pure virtual hook recording::memento::replay_into
5914 for recording::local. */
5916 void
5917 recording::local::replay_into (replayer *r)
5919 set_playback_obj (
5920 m_func->playback_function ()
5921 ->new_local (playback_location (r, m_loc),
5922 m_type->playback_type (),
5923 playback_string (m_name)));
5926 /* Override the default implementation of
5927 recording::memento::write_to_dump for locals by writing
5928 TYPE NAME;
5929 for use at the top of the function body as if it were a
5930 declaration. */
5932 void
5933 recording::local::write_to_dump (dump &d)
5935 if (d.update_locations ())
5936 m_loc = d.make_location ();
5937 d.write(" %s %s;\n",
5938 m_type->get_debug_string (),
5939 get_debug_string ());
5942 void
5943 recording::local::write_reproducer (reproducer &r)
5945 const char *id = r.make_identifier (this, "local");
5946 r.write (" gcc_jit_lvalue *%s =\n"
5947 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5948 " %s, /* gcc_jit_location *loc */\n"
5949 " %s, /* gcc_jit_type *type */\n"
5950 " %s); /* const char *name */\n",
5952 r.get_identifier (m_func),
5953 r.get_identifier (m_loc),
5954 r.get_identifier_as_type (m_type),
5955 m_name->get_debug_string ());
5958 /* The implementation of class gcc::jit::recording::statement. */
5960 /* We poison the default implementation of
5961 gcc::jit::recording::statement::get_successor_blocks
5962 since this vfunc must only ever be called on terminator
5963 statements. */
5965 vec <recording::block *>
5966 recording::statement::get_successor_blocks () const
5968 /* The base class implementation is for non-terminating statements,
5969 and thus should never be called. */
5970 gcc_unreachable ();
5971 vec <block *> result;
5972 result.create (0);
5973 return result;
5976 /* Extend the default implementation of
5977 recording::memento::write_to_dump for statements by (if requested)
5978 updating the location of the statement to the current location in
5979 the dumpfile. */
5981 void
5982 recording::statement::write_to_dump (dump &d)
5984 memento::write_to_dump (d);
5985 if (d.update_locations ())
5986 m_loc = d.make_location ();
5989 /* The implementation of class gcc::jit::recording::eval. */
5991 /* Implementation of pure virtual hook recording::memento::replay_into
5992 for recording::eval. */
5994 void
5995 recording::eval::replay_into (replayer *r)
5997 playback_block (get_block ())
5998 ->add_eval (playback_location (r),
5999 m_rvalue->playback_rvalue ());
6002 /* Implementation of recording::memento::make_debug_string for
6003 an eval statement. */
6005 recording::string *
6006 recording::eval::make_debug_string ()
6008 return string::from_printf (m_ctxt,
6009 "(void)%s;",
6010 m_rvalue->get_debug_string ());
6013 /* Implementation of recording::memento::write_reproducer for
6014 eval statements. */
6016 void
6017 recording::eval::write_reproducer (reproducer &r)
6019 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
6020 " %s, /* gcc_jit_location *loc */\n"
6021 " %s); /* gcc_jit_rvalue *rvalue */\n",
6022 r.get_identifier (get_block ()),
6023 r.get_identifier (get_loc ()),
6024 r.get_identifier_as_rvalue (m_rvalue));
6027 /* The implementation of class gcc::jit::recording::assignment. */
6029 /* Implementation of pure virtual hook recording::memento::replay_into
6030 for recording::assignment. */
6032 void
6033 recording::assignment::replay_into (replayer *r)
6035 playback_block (get_block ())
6036 ->add_assignment (playback_location (r),
6037 m_lvalue->playback_lvalue (),
6038 m_rvalue->playback_rvalue ());
6041 /* Implementation of recording::memento::make_debug_string for
6042 an assignment statement. */
6044 recording::string *
6045 recording::assignment::make_debug_string ()
6047 return string::from_printf (m_ctxt,
6048 "%s = %s;",
6049 m_lvalue->get_debug_string (),
6050 m_rvalue->get_debug_string ());
6053 /* Implementation of recording::memento::write_reproducer for
6054 assignment statements. */
6056 void
6057 recording::assignment::write_reproducer (reproducer &r)
6059 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
6060 " %s, /* gcc_jit_location *loc */\n"
6061 " %s, /* gcc_jit_lvalue *lvalue */\n"
6062 " %s); /* gcc_jit_rvalue *rvalue */\n",
6063 r.get_identifier (get_block ()),
6064 r.get_identifier (get_loc ()),
6065 r.get_identifier_as_lvalue (m_lvalue),
6066 r.get_identifier_as_rvalue (m_rvalue));
6069 /* The implementation of class gcc::jit::recording::assignment_op. */
6071 /* Implementation of pure virtual hook recording::memento::replay_into
6072 for recording::assignment_op. */
6074 void
6075 recording::assignment_op::replay_into (replayer *r)
6077 playback::type *result_type =
6078 m_lvalue->playback_lvalue ()->get_type ();
6080 playback::rvalue *binary_op =
6081 r->new_binary_op (playback_location (r),
6082 m_op,
6083 result_type,
6084 m_lvalue->playback_rvalue (),
6085 m_rvalue->playback_rvalue ());
6087 playback_block (get_block ())
6088 ->add_assignment (playback_location (r),
6089 m_lvalue->playback_lvalue (),
6090 binary_op);
6093 /* Implementation of recording::memento::make_debug_string for
6094 an assignment_op statement. */
6096 recording::string *
6097 recording::assignment_op::make_debug_string ()
6099 return string::from_printf (m_ctxt,
6100 "%s %s= %s;",
6101 m_lvalue->get_debug_string (),
6102 binary_op_strings[m_op],
6103 m_rvalue->get_debug_string ());
6106 /* Implementation of recording::memento::write_reproducer for
6107 assignment_op statements. */
6109 void
6110 recording::assignment_op::write_reproducer (reproducer &r)
6112 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
6113 " %s, /* gcc_jit_location *loc */\n"
6114 " %s, /* gcc_jit_lvalue *lvalue */\n"
6115 " %s, /* enum gcc_jit_binary_op op */\n"
6116 " %s); /* gcc_jit_rvalue *rvalue */\n",
6117 r.get_identifier (get_block ()),
6118 r.get_identifier (get_loc ()),
6119 r.get_identifier_as_lvalue (m_lvalue),
6120 binary_op_reproducer_strings[m_op],
6121 r.get_identifier_as_rvalue (m_rvalue));
6124 /* The implementation of class gcc::jit::recording::comment. */
6126 /* Implementation of pure virtual hook recording::memento::replay_into
6127 for recording::comment. */
6129 void
6130 recording::comment::replay_into (replayer *r)
6132 playback_block (get_block ())
6133 ->add_comment (playback_location (r),
6134 m_text->c_str ());
6137 /* Implementation of recording::memento::make_debug_string for
6138 a comment "statement". */
6140 recording::string *
6141 recording::comment::make_debug_string ()
6143 return string::from_printf (m_ctxt,
6144 "/* %s */",
6145 m_text->c_str ());
6148 /* Implementation of recording::memento::write_reproducer for
6149 comments. */
6151 void
6152 recording::comment::write_reproducer (reproducer &r)
6154 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
6155 " %s, /* gcc_jit_location *loc */\n"
6156 " %s); /* const char *text */\n",
6157 r.get_identifier (get_block ()),
6158 r.get_identifier (get_loc ()),
6159 m_text->get_debug_string ());
6162 /* The implementation of class gcc::jit::recording::conditional. */
6164 /* Implementation of pure virtual hook recording::memento::replay_into
6165 for recording::conditional. */
6167 void
6168 recording::conditional::replay_into (replayer *r)
6170 playback_block (get_block ())
6171 ->add_conditional (playback_location (r),
6172 m_boolval->playback_rvalue (),
6173 playback_block (m_on_true),
6174 playback_block (m_on_false));
6177 /* Override the poisoned default implementation of
6178 gcc::jit::recording::statement::get_successor_blocks
6180 A conditional jump has 2 successor blocks. */
6182 vec <recording::block *>
6183 recording::conditional::get_successor_blocks () const
6185 vec <block *> result;
6186 result.create (2);
6187 result.quick_push (m_on_true);
6188 result.quick_push (m_on_false);
6189 return result;
6192 /* Implementation of recording::memento::make_debug_string for
6193 a conditional jump statement. */
6195 recording::string *
6196 recording::conditional::make_debug_string ()
6198 if (m_on_false)
6199 return string::from_printf (m_ctxt,
6200 "if (%s) goto %s; else goto %s;",
6201 m_boolval->get_debug_string (),
6202 m_on_true->get_debug_string (),
6203 m_on_false->get_debug_string ());
6204 else
6205 return string::from_printf (m_ctxt,
6206 "if (%s) goto %s;",
6207 m_boolval->get_debug_string (),
6208 m_on_true->get_debug_string ());
6211 /* Implementation of recording::memento::write_reproducer for
6212 conditional statements. */
6214 void
6215 recording::conditional::write_reproducer (reproducer &r)
6217 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
6218 " %s, /* gcc_jit_location *loc */\n"
6219 " %s, /* gcc_jit_rvalue *boolval */\n"
6220 " %s, /* gcc_jit_block *on_true */\n"
6221 " %s); /* gcc_jit_block *on_false */\n",
6222 r.get_identifier (get_block ()),
6223 r.get_identifier (get_loc ()),
6224 r.get_identifier_as_rvalue (m_boolval),
6225 r.get_identifier (m_on_true),
6226 r.get_identifier (m_on_false));
6229 /* The implementation of class gcc::jit::recording::jump. */
6231 /* Implementation of pure virtual hook recording::memento::replay_into
6232 for recording::jump. */
6234 void
6235 recording::jump::replay_into (replayer *r)
6237 playback_block (get_block ())
6238 ->add_jump (playback_location (r),
6239 m_target->playback_block ());
6242 /* Override the poisoned default implementation of
6243 gcc::jit::recording::statement::get_successor_blocks
6245 An unconditional jump has 1 successor block. */
6247 vec <recording::block *>
6248 recording::jump::get_successor_blocks () const
6250 vec <block *> result;
6251 result.create (1);
6252 result.quick_push (m_target);
6253 return result;
6256 /* Implementation of recording::memento::make_debug_string for
6257 a unconditional jump statement. */
6259 recording::string *
6260 recording::jump::make_debug_string ()
6262 return string::from_printf (m_ctxt,
6263 "goto %s;",
6264 m_target->get_debug_string ());
6267 /* Implementation of recording::memento::write_reproducer for
6268 jump statements. */
6270 void
6271 recording::jump::write_reproducer (reproducer &r)
6273 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
6274 " %s, /* gcc_jit_location *loc */\n"
6275 " %s); /* gcc_jit_block *target */\n",
6276 r.get_identifier (get_block ()),
6277 r.get_identifier (get_loc ()),
6278 r.get_identifier (m_target));
6281 /* The implementation of class gcc::jit::recording::return_. */
6283 /* Implementation of pure virtual hook recording::memento::replay_into
6284 for recording::return_. */
6286 void
6287 recording::return_::replay_into (replayer *r)
6289 playback_block (get_block ())
6290 ->add_return (playback_location (r),
6291 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
6294 /* Override the poisoned default implementation of
6295 gcc::jit::recording::statement::get_successor_blocks
6297 A return statement has no successor block. */
6299 vec <recording::block *>
6300 recording::return_::get_successor_blocks () const
6302 vec <block *> result;
6303 result.create (0);
6304 return result;
6307 /* Implementation of recording::memento::make_debug_string for
6308 a return statement (covers both those with and without rvalues). */
6310 recording::string *
6311 recording::return_::make_debug_string ()
6313 if (m_rvalue)
6314 return string::from_printf (m_ctxt,
6315 "return %s;",
6316 m_rvalue->get_debug_string ());
6317 else
6318 return string::from_printf (m_ctxt,
6319 "return;");
6322 /* Implementation of recording::memento::write_reproducer for
6323 return statements. */
6325 void
6326 recording::return_::write_reproducer (reproducer &r)
6328 if (m_rvalue)
6329 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
6330 " %s, /* gcc_jit_location *loc */\n"
6331 " %s); /* gcc_jit_rvalue *rvalue */\n",
6332 r.get_identifier (get_block ()),
6333 r.get_identifier (get_loc ()),
6334 r.get_identifier_as_rvalue (m_rvalue));
6335 else
6336 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
6337 " %s); /* gcc_jit_location *loc */\n",
6338 r.get_identifier (get_block ()),
6339 r.get_identifier (get_loc ()));
6342 /* The implementation of class gcc::jit::recording::case_. */
6344 void
6345 recording::case_::write_reproducer (reproducer &r)
6347 const char *id = r.make_identifier (this, "case");
6348 const char *fmt =
6349 " gcc_jit_case *%s = \n"
6350 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
6351 " %s, /* gcc_jit_rvalue *min_value */\n"
6352 " %s, /* gcc_jit_rvalue *max_value */\n"
6353 " %s); /* gcc_jit_block *dest_block */\n";
6354 r.write (fmt,
6356 r.get_identifier (get_context ()),
6357 r.get_identifier_as_rvalue (m_min_value),
6358 r.get_identifier_as_rvalue (m_max_value),
6359 r.get_identifier (m_dest_block));
6362 recording::string *
6363 recording::case_::make_debug_string ()
6365 return string::from_printf (get_context (),
6366 "case %s ... %s: goto %s;",
6367 m_min_value->get_debug_string (),
6368 m_max_value->get_debug_string (),
6369 m_dest_block->get_debug_string ());
6372 /* The implementation of class gcc::jit::recording::switch_. */
6374 /* gcc::jit::recording::switch_'s constructor. */
6376 recording::switch_::switch_ (block *b,
6377 location *loc,
6378 rvalue *expr,
6379 block *default_block,
6380 int num_cases,
6381 case_ **cases)
6382 : statement (b, loc),
6383 m_expr (expr),
6384 m_default_block (default_block)
6386 m_cases.reserve_exact (num_cases);
6387 for (int i = 0; i< num_cases; i++)
6388 m_cases.quick_push (cases[i]);
6391 /* Implementation of pure virtual hook recording::memento::replay_into
6392 for recording::switch_. */
6394 void
6395 recording::switch_::replay_into (replayer *r)
6397 auto_vec <playback::case_> pcases;
6398 int i;
6399 recording::case_ *rcase;
6400 pcases.reserve_exact (m_cases.length ());
6401 FOR_EACH_VEC_ELT (m_cases, i, rcase)
6403 playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (),
6404 rcase->get_max_value ()->playback_rvalue (),
6405 rcase->get_dest_block ()->playback_block ());
6406 pcases.safe_push (pcase);
6408 playback_block (get_block ())
6409 ->add_switch (playback_location (r),
6410 m_expr->playback_rvalue (),
6411 m_default_block->playback_block (),
6412 &pcases);
6415 /* Override the poisoned default implementation of
6416 gcc::jit::recording::statement::get_successor_blocks
6418 A switch statement has (NUM_CASES + 1) successor blocks. */
6420 vec <recording::block *>
6421 recording::switch_::get_successor_blocks () const
6423 vec <block *> result;
6424 result.create (m_cases.length () + 1);
6425 result.quick_push (m_default_block);
6426 int i;
6427 case_ *c;
6428 FOR_EACH_VEC_ELT (m_cases, i, c)
6429 result.quick_push (c->get_dest_block ());
6430 return result;
6433 /* Implementation of recording::memento::make_debug_string for
6434 a switch statement. */
6436 recording::string *
6437 recording::switch_::make_debug_string ()
6439 auto_vec <char> cases_str;
6440 int i;
6441 case_ *c;
6442 FOR_EACH_VEC_ELT (m_cases, i, c)
6444 size_t len = strlen (c->get_debug_string ());
6445 unsigned idx = cases_str.length ();
6446 cases_str.safe_grow (idx + 1 + len, true);
6447 cases_str[idx] = ' ';
6448 memcpy (&(cases_str[idx + 1]),
6449 c->get_debug_string (),
6450 len);
6452 cases_str.safe_push ('\0');
6454 return string::from_printf (m_ctxt,
6455 "switch (%s) {default: goto %s;%s}",
6456 m_expr->get_debug_string (),
6457 m_default_block->get_debug_string (),
6458 &cases_str[0]);
6461 /* Implementation of recording::memento::write_reproducer for
6462 switch statements. */
6464 void
6465 recording::switch_::write_reproducer (reproducer &r)
6467 r.make_identifier (this, "switch");
6468 int i;
6469 case_ *c;
6470 const char *cases_id =
6471 r.make_tmp_identifier ("cases_for", this);
6472 r.write (" gcc_jit_case *%s[%i] = {\n",
6473 cases_id,
6474 m_cases.length ());
6475 FOR_EACH_VEC_ELT (m_cases, i, c)
6476 r.write (" %s,\n", r.get_identifier (c));
6477 r.write (" };\n");
6478 const char *fmt =
6479 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
6480 " %s, /* gcc_jit_location *loc */\n"
6481 " %s, /* gcc_jit_rvalue *expr */\n"
6482 " %s, /* gcc_jit_block *default_block */\n"
6483 " %i, /* int num_cases */\n"
6484 " %s); /* gcc_jit_case **cases */\n";
6485 r.write (fmt,
6486 r.get_identifier (get_block ()),
6487 r.get_identifier (get_loc ()),
6488 r.get_identifier_as_rvalue (m_expr),
6489 r.get_identifier (m_default_block),
6490 m_cases.length (),
6491 cases_id);
6494 } // namespace gcc::jit
6496 } // namespace gcc