xfail scan-tree-dump-not throw in g++.dg/pr99966.C on hppa*64*-*-*
[official-gcc.git] / gcc / jit / jit-recording.cc
blob6ffadbea127a5d374680988cbe9403575540732b
1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2024 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"
29 #include "jit-builtins.h"
30 #include "jit-recording.h"
31 #include "jit-playback.h"
32 #include <sstream>
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; i < ARRAY_SIZE (m_str_options); i++)
573 const char *parent_opt = parent_ctxt->m_str_options[i];
574 m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
576 memcpy (m_int_options,
577 parent_ctxt->m_int_options,
578 sizeof (m_int_options));
579 memcpy (m_bool_options,
580 parent_ctxt->m_bool_options,
581 sizeof (m_bool_options));
582 memcpy (m_inner_bool_options,
583 parent_ctxt->m_inner_bool_options,
584 sizeof (m_inner_bool_options));
585 set_logger (parent_ctxt->get_logger ());
587 else
589 memset (m_str_options, 0, sizeof (m_str_options));
590 memset (m_int_options, 0, sizeof (m_int_options));
591 memset (m_bool_options, 0, sizeof (m_bool_options));
592 memset (m_inner_bool_options, 0, sizeof (m_inner_bool_options));
593 m_inner_bool_options[INNER_BOOL_OPTION_PRINT_ERRORS_TO_STDERR] = true;
596 memset (m_basic_types, 0, sizeof (m_basic_types));
599 /* The destructor for gcc::jit::recording::context, implicitly used by
600 gcc_jit_context_release. */
602 recording::context::~context ()
604 JIT_LOG_SCOPE (get_logger ());
605 int i;
606 memento *m;
607 FOR_EACH_VEC_ELT (m_mementos, i, m)
609 delete m;
612 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
613 free (m_str_options[i]);
615 char *optname;
616 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
617 free (optname);
618 FOR_EACH_VEC_ELT (m_driver_options, i, optname)
619 free (optname);
621 if (m_builtins_manager)
622 delete m_builtins_manager;
624 if (m_owns_first_error_str)
625 free (m_first_error_str);
627 if (m_owns_last_error_str)
628 if (m_last_error_str != m_first_error_str)
629 free (m_last_error_str);
632 /* Add the given mememto to the list of those tracked by this
633 gcc::jit::recording::context, so that e.g. it can be deleted
634 when this context is released. */
636 void
637 recording::context::record (memento *m)
639 gcc_assert (m);
641 m_mementos.safe_push (m);
644 /* Replay this context (and any parents) into the given replayer. */
646 void
647 recording::context::replay_into (replayer *r)
649 JIT_LOG_SCOPE (get_logger ());
650 int i;
651 memento *m;
653 /* If we have a parent context, we must replay it. This will
654 recursively walk backwards up the historical tree, then replay things
655 forwards "in historical order", starting with the ultimate parent
656 context, until we reach the "this" context.
658 Note that we fully replay the parent, then fully replay the child,
659 which means that inter-context references can only exist from child
660 to parent, not the other way around.
662 All of this replaying is suboptimal - it would be better to do the
663 work for the parent context *once*, rather than replaying the parent
664 every time we replay each child. However, fixing this requires deep
665 surgery to lifetime-management: we'd need every context family tree
666 to have its own GC heap, and to initialize the GCC code to use that
667 heap (with a mutex on such a heap). */
668 if (m_parent_ctxt)
669 m_parent_ctxt->replay_into (r);
671 if (r->errors_occurred ())
672 return;
674 /* Replay this context's saved operations into r. */
675 FOR_EACH_VEC_ELT (m_mementos, i, m)
677 /* Disabled low-level debugging, here if we need it: print what
678 we're replaying.
679 Note that the calls to get_debug_string might lead to more
680 mementos being created for the strings.
681 This can also be used to exercise the debug_string
682 machinery. */
683 if (0)
684 printf ("context %p replaying (%p): %s\n",
685 (void *)this, (void *)m, m->get_debug_string ());
687 m->replay_into (r);
689 if (r->errors_occurred ())
690 return;
694 /* During a playback, we associate objects from the recording with
695 their counterparts during this playback.
697 For simplicity, we store this within the recording objects.
699 The following method cleans away these associations, to ensure that
700 we never have out-of-date associations lingering on subsequent
701 playbacks (the objects pointed to are GC-managed, but the
702 recording objects don't own refs to them). */
704 void
705 recording::context::disassociate_from_playback ()
707 JIT_LOG_SCOPE (get_logger ());
708 int i;
709 memento *m;
711 if (m_parent_ctxt)
712 m_parent_ctxt->disassociate_from_playback ();
714 FOR_EACH_VEC_ELT (m_mementos, i, m)
716 m->set_playback_obj (NULL);
720 /* Create a recording::string instance and add it to this context's list
721 of mementos.
723 This creates a fresh copy of the given 0-terminated buffer. */
725 recording::string *
726 recording::context::new_string (const char *text, bool escaped)
728 if (!text)
729 return NULL;
731 recording::string *result = new string (this, text, escaped);
732 record (result);
733 return result;
736 /* Create a recording::location instance and add it to this context's
737 list of mementos.
739 Implements the post-error-checking part of
740 gcc_jit_context_new_location. */
742 recording::location *
743 recording::context::new_location (const char *filename,
744 int line,
745 int column,
746 bool created_by_user)
748 recording::location *result =
749 new recording::location (this,
750 new_string (filename),
751 line, column,
752 created_by_user);
753 record (result);
754 return result;
757 /* If we haven't seen this enum value yet, create a recording::type
758 instance and add it to this context's list of mementos.
760 If we have seen it before, reuse our cached value, so that repeated
761 calls on the context give the same object.
763 If we have a parent context, the cache is within the ultimate
764 ancestor context.
766 Implements the post-error-checking part of
767 gcc_jit_context_get_type. */
769 recording::type *
770 recording::context::get_type (enum gcc_jit_types kind)
772 if (!m_basic_types[kind])
774 if (m_parent_ctxt)
775 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
776 else
778 recording::type *result = new memento_of_get_type (this, kind);
779 record (result);
780 m_basic_types[kind] = result;
784 return m_basic_types[kind];
787 /* Get a recording::type instance for the given size and signedness.
788 This is implemented in terms of recording::context::get_type
789 above.
791 Implements the post-error-checking part of
792 gcc_jit_context_get_int_type. */
794 recording::type *
795 recording::context::get_int_type (int num_bytes, int is_signed)
797 /* We can't use a switch here since some of the values are macros affected
798 by options; e.g. i386.h has
799 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
800 Compare with tree.cc's make_or_reuse_type. Note that the _SIZE macros
801 are in bits, rather than bytes.
803 const int num_bits = num_bytes * 8;
804 if (num_bits == INT_TYPE_SIZE)
805 return get_type (is_signed
806 ? GCC_JIT_TYPE_INT
807 : GCC_JIT_TYPE_UNSIGNED_INT);
808 if (num_bits == CHAR_TYPE_SIZE)
809 return get_type (is_signed
810 ? GCC_JIT_TYPE_SIGNED_CHAR
811 : GCC_JIT_TYPE_UNSIGNED_CHAR);
812 if (num_bits == SHORT_TYPE_SIZE)
813 return get_type (is_signed
814 ? GCC_JIT_TYPE_SHORT
815 : GCC_JIT_TYPE_UNSIGNED_SHORT);
816 if (num_bits == LONG_TYPE_SIZE)
817 return get_type (is_signed
818 ? GCC_JIT_TYPE_LONG
819 : GCC_JIT_TYPE_UNSIGNED_LONG);
820 if (num_bits == LONG_LONG_TYPE_SIZE)
821 return get_type (is_signed
822 ? GCC_JIT_TYPE_LONG_LONG
823 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
824 if (num_bits == 128)
825 return get_type (is_signed
826 ? GCC_JIT_TYPE_INT128_T
827 : GCC_JIT_TYPE_UINT128_T);
829 /* Some other size, not corresponding to the C int types. */
830 /* To be written: support arbitrary other sizes, sharing by
831 memoizing at the recording::context level? */
832 gcc_unreachable ();
835 /* Create a recording::type instance and add it to this context's list
836 of mementos.
838 Implements the post-error-checking part of
839 gcc_jit_context_new_array_type. */
841 recording::type *
842 recording::context::new_array_type (recording::location *loc,
843 recording::type *element_type,
844 int num_elements)
846 if (struct_ *s = element_type->dyn_cast_struct ())
847 if (!s->get_fields ())
849 add_error (NULL,
850 "cannot create an array of type %s"
851 " until the fields have been set",
852 s->get_name ()->c_str ());
853 return NULL;
855 recording::type *result =
856 new recording::array_type (this, loc, element_type, num_elements);
857 record (result);
858 return result;
861 /* Create a recording::field instance and add it to this context's list
862 of mementos.
864 Implements the post-error-checking part of
865 gcc_jit_context_new_field. */
867 recording::field *
868 recording::context::new_field (recording::location *loc,
869 recording::type *type,
870 const char *name)
872 recording::field *result =
873 new recording::field (this, loc, type, new_string (name));
874 record (result);
875 return result;
878 /* Create a recording::bitfield instance and add it to this context's list
879 of mementos.
881 Implements the post-error-checking part of
882 gcc_jit_context_new_bitfield. */
884 recording::field *
885 recording::context::new_bitfield (recording::location *loc,
886 recording::type *type,
887 int width,
888 const char *name)
890 recording::field *result =
891 new recording::bitfield (this, loc, type, width, new_string (name));
892 record (result);
893 return result;
896 /* Create a recording::struct_ instance and add it to this context's
897 list of mementos and list of compound types.
899 Implements the post-error-checking part of
900 gcc_jit_context_new_struct_type. */
902 recording::struct_ *
903 recording::context::new_struct_type (recording::location *loc,
904 const char *name)
906 recording::struct_ *result = new struct_ (this, loc, new_string (name));
907 record (result);
908 m_compound_types.safe_push (result);
909 return result;
912 /* Create a recording::union_ instance and add it to this context's
913 list of mementos and list of compound types.
915 Implements the first post-error-checking part of
916 gcc_jit_context_new_union_type. */
918 recording::union_ *
919 recording::context::new_union_type (recording::location *loc,
920 const char *name)
922 recording::union_ *result = new union_ (this, loc, new_string (name));
923 record (result);
924 m_compound_types.safe_push (result);
925 return result;
928 /* Create a recording::function_type instance and add it to this context's
929 list of mementos.
931 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
933 recording::function_type *
934 recording::context::new_function_type (recording::type *return_type,
935 int num_params,
936 recording::type **param_types,
937 int is_variadic)
939 recording::function_type *fn_type
940 = new function_type (this,
941 return_type,
942 num_params,
943 param_types,
944 is_variadic);
945 record (fn_type);
946 return fn_type;
949 /* Create a recording::type instance and add it to this context's list
950 of mementos.
952 Implements the post-error-checking part of
953 gcc_jit_context_new_function_ptr_type. */
955 recording::type *
956 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
957 recording::type *return_type,
958 int num_params,
959 recording::type **param_types,
960 int is_variadic)
962 recording::function_type *fn_type
963 = new_function_type (return_type,
964 num_params,
965 param_types,
966 is_variadic);
968 /* Return a pointer-type to the function type. */
969 return fn_type->get_pointer ();
972 /* Create a recording::param instance and add it to this context's list
973 of mementos.
975 Implements the post-error-checking part of
976 gcc_jit_context_new_param. */
978 recording::param *
979 recording::context::new_param (recording::location *loc,
980 recording::type *type,
981 const char *name)
983 recording::param *result = new recording::param (this, loc, type, new_string (name));
984 record (result);
985 return result;
988 /* Create a recording::function instance and add it to this context's list
989 of mementos and list of functions.
991 Implements the post-error-checking part of
992 gcc_jit_context_new_function. */
994 recording::function *
995 recording::context::new_function (recording::location *loc,
996 enum gcc_jit_function_kind kind,
997 recording::type *return_type,
998 const char *name,
999 int num_params,
1000 recording::param **params,
1001 int is_variadic,
1002 enum built_in_function builtin_id)
1004 recording::function *result =
1005 new recording::function (this,
1006 loc, kind, return_type,
1007 new_string (name),
1008 num_params, params, is_variadic,
1009 builtin_id);
1010 record (result);
1011 m_functions.safe_push (result);
1013 return result;
1016 /* Locate the builtins_manager (if any) for this family of contexts,
1017 creating it if it doesn't exist already.
1019 All of the recording contexts in a family share one builtins_manager:
1020 if we have a child context, follow the parent links to get the
1021 ultimate ancestor context, and look for it/store it there. */
1023 builtins_manager *
1024 recording::context::get_builtins_manager ()
1026 if (m_parent_ctxt)
1027 return m_parent_ctxt->get_builtins_manager ();
1029 if (!m_builtins_manager)
1030 m_builtins_manager = new builtins_manager (this);
1032 return m_builtins_manager;
1035 /* Get a recording::function instance, which is lazily-created and added
1036 to the context's lists of mementos.
1038 Implements the post-error-checking part of
1039 gcc_jit_context_get_builtin_function. */
1041 recording::function *
1042 recording::context::get_builtin_function (const char *name)
1044 builtins_manager *bm = get_builtins_manager ();
1045 return bm->get_builtin_function (name);
1048 /* Create a recording::global instance and add it to this context's list
1049 of mementos.
1051 Implements the post-error-checking part of
1052 gcc_jit_context_new_global. */
1054 recording::lvalue *
1055 recording::context::new_global (recording::location *loc,
1056 enum gcc_jit_global_kind kind,
1057 recording::type *type,
1058 const char *name)
1060 recording::global *result =
1061 new recording::global (this, loc, kind, type, new_string (name));
1062 record (result);
1063 m_globals.safe_push (result);
1065 return result;
1068 void
1069 recording::context::new_global_init_rvalue (lvalue *variable,
1070 rvalue *init)
1072 recording::global_init_rvalue *obj =
1073 new recording::global_init_rvalue (this, variable, init);
1074 record (obj);
1076 global *gbl = (global *) variable;
1077 gbl->set_rvalue_init (init); /* Needed by the global for write dump. */
1080 /* Create a recording::memento_of_new_string_literal 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_string_literal. */
1086 recording::rvalue *
1087 recording::context::new_string_literal (const char *value)
1089 recording::rvalue *result =
1090 new memento_of_new_string_literal (this, NULL, new_string (value));
1091 record (result);
1092 return result;
1095 /* Create a recording::memento_of_new_rvalue_from_vector instance and add it
1096 to this context's list of mementos.
1098 Implements the post-error-checking part of
1099 gcc_jit_context_new_rvalue_from_vector. */
1101 recording::rvalue *
1102 recording::context::new_rvalue_from_vector (location *loc,
1103 vector_type *type,
1104 rvalue **elements)
1106 recording::rvalue *result
1107 = new memento_of_new_rvalue_from_vector (this, loc, type, elements);
1108 record (result);
1109 return result;
1112 recording::rvalue *
1113 recording::context::new_ctor (recording::location *loc,
1114 recording::type *type,
1115 size_t num_values,
1116 field **fields,
1117 rvalue **values)
1119 recording::ctor *result = new ctor (this, loc, type);
1121 /* Short cut for zero init. */
1122 if (!num_values)
1124 record (result);
1125 return result;
1128 bool is_struct_or_union = type->is_struct () || type->is_union ();
1130 /* We need to copy fields and values into result's auto_vec:s.
1131 Both for structs and unions and only values for arrays. */
1132 if (type->is_array () != NULL)
1134 result->m_values.reserve (num_values, false);
1136 for (size_t i = 0; i < num_values; i++)
1137 result->m_values.quick_push (values[i]);
1139 else if (is_struct_or_union && fields)
1141 /* ctor values are paired with user specified fields. */
1143 result->m_values.reserve (num_values, false);
1144 result->m_fields.reserve (num_values, false);
1146 for (size_t i = 0; i < num_values; i++)
1148 result->m_values.quick_push (values[i]);
1149 result->m_fields.quick_push (fields[i]);
1152 else if (is_struct_or_union && !fields)
1154 /* ctor values are in definition order one by one,
1155 so take the fields from the type object. */
1157 result->m_values.reserve (num_values, false);
1158 result->m_fields.reserve (num_values, false);
1160 compound_type *ct = reinterpret_cast<compound_type *>(type);
1161 recording::fields *fields = ct->get_fields ();
1163 /* The entry point checks that num_values is not greater than
1164 the amount of fields in 'fields'. */
1165 for (size_t i = 0; i < num_values; i++)
1167 result->m_values.quick_push (values[i]);
1168 result->m_fields.quick_push (fields->get_field (i));
1171 else
1172 gcc_unreachable ();
1174 record (result);
1175 return result;
1178 /* Create a recording::unary_op instance and add it to this context's
1179 list of mementos.
1181 Implements the post-error-checking part of
1182 gcc_jit_context_new_unary_op. */
1184 recording::rvalue *
1185 recording::context::new_unary_op (recording::location *loc,
1186 enum gcc_jit_unary_op op,
1187 recording::type *result_type,
1188 recording::rvalue *a)
1190 recording::rvalue *result =
1191 new unary_op (this, loc, op, result_type, a);
1192 record (result);
1193 return result;
1196 /* Create a recording::binary_op instance and add it to this context's
1197 list of mementos.
1199 Implements the post-error-checking part of
1200 gcc_jit_context_new_binary_op. */
1202 recording::rvalue *
1203 recording::context::new_binary_op (recording::location *loc,
1204 enum gcc_jit_binary_op op,
1205 recording::type *result_type,
1206 recording::rvalue *a,
1207 recording::rvalue *b)
1209 recording::rvalue *result =
1210 new binary_op (this, loc, op, result_type, a, b);
1211 record (result);
1212 return result;
1215 /* Create a recording::comparison instance and add it to this context's
1216 list of mementos.
1218 Implements the post-error-checking part of
1219 gcc_jit_context_new_comparison. */
1221 recording::rvalue *
1222 recording::context::new_comparison (recording::location *loc,
1223 enum gcc_jit_comparison op,
1224 recording::rvalue *a,
1225 recording::rvalue *b)
1227 recording::rvalue *result = new comparison (this, loc, op, a, b);
1228 record (result);
1229 return result;
1232 /* Create a recording::cast instance and add it to this context's list
1233 of mementos.
1235 Implements the post-error-checking part of
1236 gcc_jit_context_new_cast. */
1238 recording::rvalue *
1239 recording::context::new_cast (recording::location *loc,
1240 recording::rvalue *expr,
1241 recording::type *type_)
1243 recording::rvalue *result = new cast (this, loc, expr, type_);
1244 record (result);
1245 return result;
1248 /* Create a recording::bitcast instance and add it to this context's list
1249 of mementos.
1251 Implements the post-error-checking part of
1252 gcc_jit_context_new_bitcast. */
1254 recording::rvalue *
1255 recording::context::new_bitcast (location *loc,
1256 rvalue *expr,
1257 type *type_)
1259 recording::rvalue *result = new bitcast (this, loc, expr, type_);
1260 record (result);
1261 return result;
1264 /* Create a recording::call instance and add it to this context's list
1265 of mementos.
1267 Implements the post-error-checking part of
1268 gcc_jit_context_new_call. */
1270 recording::rvalue *
1271 recording::context::new_call (recording::location *loc,
1272 function *func,
1273 int numargs , recording::rvalue **args)
1275 recording::rvalue *result = new call (this, loc, func, numargs, args);
1276 record (result);
1277 return result;
1280 /* Create a recording::call_through_ptr instance and add it to this
1281 context's list of mementos.
1283 Implements the post-error-checking part of
1284 gcc_jit_context_new_call_through_ptr. */
1286 recording::rvalue *
1287 recording::context::new_call_through_ptr (recording::location *loc,
1288 recording::rvalue *fn_ptr,
1289 int numargs,
1290 recording::rvalue **args)
1292 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
1293 record (result);
1294 return result;
1297 /* Create a recording::array_access instance and add it to this context's list
1298 of mementos.
1300 Implements the post-error-checking part of
1301 gcc_jit_context_new_array_access. */
1303 recording::lvalue *
1304 recording::context::new_array_access (recording::location *loc,
1305 recording::rvalue *ptr,
1306 recording::rvalue *index)
1308 recording::lvalue *result = new array_access (this, loc, ptr, index);
1309 record (result);
1310 return result;
1313 /* Create a recording::case_ instance and add it to this context's list
1314 of mementos.
1316 Implements the post-error-checking part of
1317 gcc_jit_context_new_case. */
1319 recording::case_ *
1320 recording::context::new_case (recording::rvalue *min_value,
1321 recording::rvalue *max_value,
1322 recording::block *block)
1324 recording::case_ *result = new case_ (this, min_value, max_value, block);
1325 record (result);
1326 return result;
1329 /* Set the given string option for this context, or add an error if
1330 it's not recognized.
1332 Implements the post-error-checking part of
1333 gcc_jit_context_set_str_option. */
1335 void
1336 recording::context::set_str_option (enum gcc_jit_str_option opt,
1337 const char *value)
1339 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
1341 add_error (NULL,
1342 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
1343 return;
1345 free (m_str_options[opt]);
1346 m_str_options[opt] = value ? xstrdup (value) : NULL;
1347 log_str_option (opt);
1350 /* Set the given integer option for this context, or add an error if
1351 it's not recognized.
1353 Implements the post-error-checking part of
1354 gcc_jit_context_set_int_option. */
1356 void
1357 recording::context::set_int_option (enum gcc_jit_int_option opt,
1358 int value)
1360 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
1362 add_error (NULL,
1363 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
1364 return;
1366 m_int_options[opt] = value;
1367 log_int_option (opt);
1370 /* Set the given boolean option for this context, or add an error if
1371 it's not recognized.
1373 Implements the post-error-checking part of
1374 gcc_jit_context_set_bool_option. */
1376 void
1377 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
1378 int value)
1380 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
1382 add_error (NULL,
1383 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
1384 return;
1386 m_bool_options[opt] = value ? true : false;
1387 log_bool_option (opt);
1390 void
1391 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt,
1392 int value)
1394 gcc_assert (inner_opt >= 0 && inner_opt < NUM_INNER_BOOL_OPTIONS);
1395 m_inner_bool_options[inner_opt] = value ? true : false;
1396 log_inner_bool_option (inner_opt);
1400 /* Add the given optname to this context's list of extra options.
1402 Implements the post-error-checking part of
1403 gcc_jit_context_add_command_line_option. */
1405 void
1406 recording::context::add_command_line_option (const char *optname)
1408 m_command_line_options.safe_push (xstrdup (optname));
1411 /* Add any user-provided extra options, starting with any from
1412 parent contexts.
1413 Called by playback::context::make_fake_args. */
1415 void
1416 recording::context::append_command_line_options (vec <char *> *argvec)
1418 if (m_parent_ctxt)
1419 m_parent_ctxt->append_command_line_options (argvec);
1421 int i;
1422 char *optname;
1423 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1424 argvec->safe_push (xstrdup (optname));
1427 /* Add the given optname to this context's list of extra driver options. */
1429 void
1430 recording::context::add_driver_option (const char *optname)
1432 m_driver_options.safe_push (xstrdup (optname));
1435 /* Add any user-provided driver options, starting with any from
1436 parent contexts.
1437 Called by playback::context::invoke_driver. */
1439 void
1440 recording::context::append_driver_options (auto_string_vec *argvec)
1442 if (m_parent_ctxt)
1443 m_parent_ctxt->append_driver_options (argvec);
1445 int i;
1446 char *optname;
1448 FOR_EACH_VEC_ELT (m_driver_options, i, optname)
1449 argvec->safe_push (xstrdup (optname));
1452 /* Add the given dumpname/out_ptr pair to this context's list of requested
1453 dumps.
1455 Implements the post-error-checking part of
1456 gcc_jit_context_enable_dump. */
1458 void
1459 recording::context::enable_dump (const char *dumpname,
1460 char **out_ptr)
1462 requested_dump d;
1463 gcc_assert (dumpname);
1464 gcc_assert (out_ptr);
1466 d.m_dumpname = dumpname;
1467 d.m_out_ptr = out_ptr;
1468 *out_ptr = NULL;
1469 m_requested_dumps.safe_push (d);
1472 /* Validate this context, and if it passes, compile it to memory
1473 (within a mutex).
1475 Implements the post-error-checking part of
1476 gcc_jit_context_compile. */
1478 result *
1479 recording::context::compile ()
1481 JIT_LOG_SCOPE (get_logger ());
1483 log_all_options ();
1485 validate ();
1487 if (errors_occurred ())
1488 return NULL;
1490 /* Set up a compile_to_memory playback context. */
1491 ::gcc::jit::playback::compile_to_memory replayer (this);
1493 /* Use it. */
1494 replayer.compile ();
1496 /* Get the jit::result (or NULL) from the
1497 compile_to_memory playback context. */
1498 return replayer.get_result_obj ();
1501 /* Validate this context, and if it passes, compile it to a file
1502 (within a mutex).
1504 Implements the post-error-checking part of
1505 gcc_jit_context_compile_to_file. */
1507 void
1508 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
1509 const char *output_path)
1511 JIT_LOG_SCOPE (get_logger ());
1513 log_all_options ();
1515 validate ();
1517 if (errors_occurred ())
1518 return;
1520 /* Set up a compile_to_file playback context. */
1521 ::gcc::jit::playback::compile_to_file replayer (this,
1522 output_kind,
1523 output_path);
1525 /* Use it. */
1526 replayer.compile ();
1529 /* Format the given error using printf's conventions, print
1530 it to stderr, and add it to the context. */
1532 void
1533 recording::context::add_error (location *loc, const char *fmt, ...)
1535 va_list ap;
1536 va_start (ap, fmt);
1537 add_error_va (loc, fmt, ap);
1538 va_end (ap);
1541 /* Format the given error using printf's conventions, print
1542 it to stderr, and add it to the context. */
1544 void
1545 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
1547 int len;
1548 char *malloced_msg;
1549 const char *errmsg;
1550 bool has_ownership;
1552 JIT_LOG_SCOPE (get_logger ());
1554 len = vasprintf (&malloced_msg, fmt, ap);
1555 if (malloced_msg == NULL || len < 0)
1557 errmsg = "out of memory generating error message";
1558 has_ownership = false;
1560 else
1562 errmsg = malloced_msg;
1563 has_ownership = true;
1565 if (get_logger ())
1566 get_logger ()->log ("error %i: %s", m_error_count, errmsg);
1568 const char *ctxt_progname =
1569 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
1570 if (!ctxt_progname)
1571 ctxt_progname = "libgccjit.so";
1573 bool print_errors_to_stderr =
1574 get_inner_bool_option (INNER_BOOL_OPTION_PRINT_ERRORS_TO_STDERR);
1575 if (print_errors_to_stderr)
1577 if (loc)
1578 fprintf (stderr, "%s: %s: error: %s\n",
1579 ctxt_progname,
1580 loc->get_debug_string (),
1581 errmsg);
1582 else
1583 fprintf (stderr, "%s: error: %s\n",
1584 ctxt_progname,
1585 errmsg);
1588 if (!m_error_count)
1590 m_first_error_str = const_cast <char *> (errmsg);
1591 m_owns_first_error_str = has_ownership;
1594 if (m_owns_last_error_str)
1595 if (m_last_error_str != m_first_error_str)
1596 free (m_last_error_str);
1597 m_last_error_str = const_cast <char *> (errmsg);
1598 m_owns_last_error_str = has_ownership;
1600 m_error_count++;
1603 /* Get the message for the first error that occurred on this context, or
1604 NULL if no errors have occurred on it.
1606 Implements the post-error-checking part of
1607 gcc_jit_context_get_first_error. */
1609 const char *
1610 recording::context::get_first_error () const
1612 return m_first_error_str;
1615 /* Get the message for the last error that occurred on this context, or
1616 NULL if no errors have occurred on it.
1618 Implements the post-error-checking part of
1619 gcc_jit_context_get_last_error. */
1621 const char *
1622 recording::context::get_last_error () const
1624 return m_last_error_str;
1627 /* Lazily generate and record a recording::type representing an opaque
1628 struct named "FILE".
1630 For use if client code tries to dereference the result of
1631 get_type (GCC_JIT_TYPE_FILE_PTR). */
1633 recording::type *
1634 recording::context::get_opaque_FILE_type ()
1636 if (!m_FILE_type)
1637 m_FILE_type = new_struct_type (NULL, "FILE");
1638 return m_FILE_type;
1641 /* Dump a C-like representation of the given context to the given path.
1642 If UPDATE_LOCATIONS is true, update the locations within the
1643 context's mementos to point to the dumpfile.
1645 Implements the post-error-checking part of
1646 gcc_jit_context_dump_to_file. */
1648 void
1649 recording::context::dump_to_file (const char *path, bool update_locations)
1651 int i;
1652 dump d (*this, path, update_locations);
1654 /* Forward declaration of structs and unions. */
1655 compound_type *st;
1656 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1658 d.write ("%s;\n\n", st->get_debug_string ());
1661 /* Content of structs, where set. */
1662 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1663 if (st->get_fields ())
1665 st->get_fields ()->write_to_dump (d);
1666 d.write ("\n");
1669 /* Globals. */
1670 global *g;
1671 FOR_EACH_VEC_ELT (m_globals, i, g)
1673 g->write_to_dump (d);
1675 if (!m_globals.is_empty ())
1676 d.write ("\n");
1678 function *fn;
1679 FOR_EACH_VEC_ELT (m_functions, i, fn)
1681 fn->write_to_dump (d);
1684 top_level_asm *tla;
1685 FOR_EACH_VEC_ELT (m_top_level_asms, i, tla)
1686 tla->write_to_dump (d);
1689 static const char * const
1690 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
1691 "GCC_JIT_STR_OPTION_PROGNAME"
1694 static const char * const
1695 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
1696 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1699 static const char * const
1700 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
1701 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1702 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1703 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1704 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1705 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1706 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1707 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1708 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1711 static const char * const
1712 inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = {
1713 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1714 "gcc_jit_context_set_bool_use_external_driver",
1715 "gcc_jit_context_set_bool_print_errors_to_stderr",
1718 /* Write the current value of all options to the log file (if any). */
1720 void
1721 recording::context::log_all_options () const
1723 int opt_idx;
1725 if (!get_logger ())
1726 return;
1728 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1729 log_str_option ((enum gcc_jit_str_option)opt_idx);
1731 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1732 log_int_option ((enum gcc_jit_int_option)opt_idx);
1734 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1735 log_bool_option ((enum gcc_jit_bool_option)opt_idx);
1736 for (opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1737 log_inner_bool_option ((enum inner_bool_option)opt_idx);
1740 /* Write the current value of the given string option to the
1741 log file (if any). */
1743 void
1744 recording::context::log_str_option (enum gcc_jit_str_option opt) const
1746 gcc_assert (opt < GCC_JIT_NUM_STR_OPTIONS);
1747 if (get_logger ())
1749 if (m_str_options[opt])
1750 log ("%s: \"%s\"",
1751 str_option_reproducer_strings[opt],
1752 m_str_options[opt]);
1753 else
1754 log ("%s: NULL",
1755 str_option_reproducer_strings[opt]);
1759 /* Write the current value of the given int option to the
1760 log file (if any). */
1762 void
1763 recording::context::log_int_option (enum gcc_jit_int_option opt) const
1765 gcc_assert (opt < GCC_JIT_NUM_INT_OPTIONS);
1766 if (get_logger ())
1767 log ("%s: %i",
1768 int_option_reproducer_strings[opt],
1769 m_int_options[opt]);
1772 /* Write the current value of the given bool option to the
1773 log file (if any). */
1775 void
1776 recording::context::log_bool_option (enum gcc_jit_bool_option opt) const
1778 gcc_assert (opt < GCC_JIT_NUM_BOOL_OPTIONS);
1779 if (get_logger ())
1780 log ("%s: %s",
1781 bool_option_reproducer_strings[opt],
1782 m_bool_options[opt] ? "true" : "false");
1785 /* Write the current value of the given "inner" bool option to the
1786 log file (if any). */
1788 void
1789 recording::context::log_inner_bool_option (enum inner_bool_option opt) const
1791 gcc_assert (opt < NUM_INNER_BOOL_OPTIONS);
1792 if (get_logger ())
1793 log ("%s: %s",
1794 inner_bool_option_reproducer_strings[opt],
1795 m_inner_bool_options[opt] ? "true" : "false");
1798 /* Write C source code to PATH that attempts to replay the API
1799 calls made to this context (and its parents), for use in
1800 minimizing test cases for libgccjit.
1802 Implements the post-error-checking part of
1803 gcc_jit_context_dump_reproducer_to_file. */
1805 void
1806 recording::context::dump_reproducer_to_file (const char *path)
1808 JIT_LOG_SCOPE (get_logger ());
1809 reproducer r (*this, path);
1811 /* Generate the "ancestry" of this context, as a list. */
1812 auto_vec <context *> ascending_contexts;
1813 for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
1814 ascending_contexts.safe_push (ctxt);
1816 /* Reverse the list, giving a list of contexts from
1817 top-most parent context down through to youngest child context.
1818 We will use this list as the parameters of the functions in
1819 our generated file. */
1820 unsigned num_ctxts = ascending_contexts.length ();
1821 auto_vec <context *> contexts (num_ctxts);
1822 for (unsigned i = 0; i < num_ctxts; i++)
1823 contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
1825 /* contexts[0] should be the top-level context. */
1826 gcc_assert (contexts[0]);
1827 gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
1829 /* The final element in contexts should be "this". */
1830 gcc_assert (contexts[contexts.length () - 1] == this);
1831 gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
1832 == contexts[0]);
1834 r.write ("/* This code was autogenerated by"
1835 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1836 print_version (r.get_file (), " ", false);
1837 r.write ("*/\n");
1838 r.write ("#include <libgccjit.h>\n\n");
1839 r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1840 r.write ("static void\nset_options (");
1841 r.write_params (contexts);
1842 r.write (");\n\n");
1843 r.write ("static void\ncreate_code (");
1844 r.write_params (contexts);
1845 r.write (");\n\n");
1846 r.write ("int\nmain (int argc, const char **argv)\n");
1847 r.write ("{\n");
1848 for (unsigned i = 0; i < num_ctxts; i++)
1849 r.write (" gcc_jit_context *%s;\n",
1850 r.get_identifier (contexts[i]));
1851 r.write (" gcc_jit_result *result;\n"
1852 "\n");
1854 /* Create the contexts.
1855 The top-level context is acquired from a clean slate, the others as
1856 children of the prior context. */
1857 r.write (" %s = gcc_jit_context_acquire ();\n",
1858 r.get_identifier (contexts[0]));
1859 for (unsigned i = 1; i < num_ctxts; i++)
1860 r.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1861 r.get_identifier (contexts[i]),
1862 r.get_identifier (contexts[i - 1]));
1863 r.write (" set_options (");
1864 r.write_args (contexts);
1865 r.write (");\n");
1866 r.write (" create_code (");
1867 r.write_args (contexts);
1868 r.write (");\n");
1870 r.write (" result = gcc_jit_context_compile (%s);\n",
1871 r.get_identifier (this));
1873 for (unsigned i = num_ctxts; i > 0; i--)
1874 r.write (" gcc_jit_context_release (%s);\n",
1875 r.get_identifier (contexts[i - 1]));
1877 r.write (" gcc_jit_result_release (result);\n"
1878 " return 0;\n"
1879 "}\n\n");
1881 /* Define (char *) variables for use in calls to
1882 gcc_jit_context_enable_dump. */
1883 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1885 if (m_requested_dumps.length ())
1887 r.write ("/* Requested dumps for %s. */\n",
1888 r.get_identifier (contexts[ctxt_idx]));
1889 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1890 r.write ("static char *dump_%p;\n",
1891 (void *)&m_requested_dumps[i]);
1892 r.write ("\n");
1896 /* Write out values of options. */
1897 r.write ("static void\nset_options (");
1898 r.write_params (contexts);
1899 r.write (")\n{\n");
1900 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1902 if (ctxt_idx > 0)
1903 r.write ("\n");
1905 r.write (" /* Set options for %s. */\n",
1906 r.get_identifier (contexts[ctxt_idx]));
1908 r.write (" /* String options. */\n");
1909 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1911 r.write (" gcc_jit_context_set_str_option (%s,\n"
1912 " %s,\n",
1913 r.get_identifier (contexts[ctxt_idx]),
1914 str_option_reproducer_strings[opt_idx]);
1915 if (m_str_options[opt_idx])
1916 r.write (" \"%s\");\n",
1917 m_str_options[opt_idx]);
1918 else
1919 r.write (" NULL);\n");
1921 r.write (" /* Int options. */\n");
1922 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1923 r.write (" gcc_jit_context_set_int_option (%s,\n"
1924 " %s,\n"
1925 " %i);\n",
1926 r.get_identifier (contexts[ctxt_idx]),
1927 int_option_reproducer_strings[opt_idx],
1928 m_int_options[opt_idx]);
1929 r.write (" /* Boolean options. */\n");
1930 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1931 r.write (" gcc_jit_context_set_bool_option (%s,\n"
1932 " %s,\n"
1933 " %i);\n",
1934 r.get_identifier (contexts[ctxt_idx]),
1935 bool_option_reproducer_strings[opt_idx],
1936 m_bool_options[opt_idx]);
1937 for (int opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1938 r.write (" %s (%s, %i);\n",
1939 inner_bool_option_reproducer_strings[opt_idx],
1940 r.get_identifier (contexts[ctxt_idx]),
1941 m_inner_bool_options[opt_idx]);
1943 if (!m_command_line_options.is_empty ())
1945 int i;
1946 char *optname;
1947 r.write (" /* User-provided command-line options. */\n");
1948 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1949 r.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1950 r.get_identifier (contexts[ctxt_idx]),
1951 optname);
1954 if (!m_driver_options.is_empty ())
1956 int i;
1957 char *optname;
1958 r.write (" /* User-provided driver options. */\n");
1959 FOR_EACH_VEC_ELT (m_driver_options, i, optname)
1960 r.write (" gcc_jit_context_add_driver_option (%s, \"%s\");\n",
1961 r.get_identifier (contexts[ctxt_idx]),
1962 optname);
1965 if (m_requested_dumps.length ())
1967 r.write (" /* Requested dumps. */\n");
1968 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1969 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1971 r.write (" gcc_jit_context_enable_dump (%s,\n"
1972 " \"%s\",\n"
1973 " &dump_%p);\n",
1974 r.get_identifier (contexts[ctxt_idx]),
1975 m_requested_dumps[i].m_dumpname,
1976 (void *)&m_requested_dumps[i]);
1980 r.write ("}\n\n");
1982 r.write ("static void\ncreate_code (");
1983 r.write_params (contexts);
1984 r.write (")\n"
1985 "{\n");
1986 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1988 memento *m;
1989 int i;
1990 if (ctxt_idx > 0)
1991 r.write ("\n\n");
1993 r.write (" /* Replay of API calls for %s. */\n",
1994 r.get_identifier (contexts[ctxt_idx]));
1995 FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
1996 m->write_reproducer (r);
1998 r.write ("}\n");
2001 /* Copy the requested dumps within this context and all ancestors into
2002 OUT. */
2004 void
2005 recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
2007 if (m_parent_ctxt)
2008 m_parent_ctxt->get_all_requested_dumps (out);
2010 out->reserve (m_requested_dumps.length ());
2011 out->splice (m_requested_dumps);
2014 /* Create a recording::top_level_asm instance and add it to this
2015 context's list of mementos and to m_top_level_asms.
2017 Implements the post-error-checking part of
2018 gcc_jit_context_add_top_level_asm. */
2020 void
2021 recording::context::add_top_level_asm (recording::location *loc,
2022 const char *asm_stmts)
2024 recording::top_level_asm *asm_obj
2025 = new recording::top_level_asm (this, loc, new_string (asm_stmts));
2026 record (asm_obj);
2027 m_top_level_asms.safe_push (asm_obj);
2030 /* This is a pre-compilation check for the context (and any parents).
2032 Detect errors within the context, adding errors if any are found. */
2034 void
2035 recording::context::validate ()
2037 JIT_LOG_SCOPE (get_logger ());
2039 if (m_parent_ctxt)
2040 m_parent_ctxt->validate ();
2042 int i;
2043 function *fn;
2044 FOR_EACH_VEC_ELT (m_functions, i, fn)
2045 fn->validate ();
2048 /* The implementation of class gcc::jit::recording::memento. */
2050 /* Get a (const char *) debug description of the given memento, by
2051 calling the pure-virtual make_debug_string hook, caching the
2052 result.
2054 It is intended that this should only be called in debugging and
2055 error-handling paths, so this doesn't need to be particularly
2056 optimized. */
2058 const char *
2059 recording::memento::get_debug_string ()
2061 if (!m_debug_string)
2062 m_debug_string = make_debug_string ();
2063 return m_debug_string->c_str ();
2066 /* Default implementation of recording::memento::write_to_dump, writing
2067 an indented form of the memento's debug string to the dump. */
2069 void
2070 recording::memento::write_to_dump (dump &d)
2072 d.write (" %s\n", get_debug_string ());
2075 /* The implementation of class gcc::jit::recording::string. */
2077 /* Constructor for gcc::jit::recording::string::string, allocating a
2078 copy of the given text using new char[]. */
2080 recording::string::string (context *ctxt, const char *text, bool escaped)
2081 : memento (ctxt),
2082 m_escaped (escaped)
2084 m_len = strlen (text);
2085 m_buffer = new char[m_len + 1];
2086 strcpy (m_buffer, text);
2089 /* Destructor for gcc::jit::recording::string::string. */
2091 recording::string::~string ()
2093 delete[] m_buffer;
2096 /* Function for making gcc::jit::recording::string instances on a
2097 context via printf-style formatting.
2099 It is intended that this should only be called in debugging and
2100 error-handling paths, so this doesn't need to be particularly
2101 optimized, hence the double-copy of the string is acceptable. */
2103 recording::string *
2104 recording::string::from_printf (context *ctxt, const char *fmt, ...)
2106 int len;
2107 va_list ap;
2108 char *buf;
2109 recording::string *result;
2111 va_start (ap, fmt);
2112 len = vasprintf (&buf, fmt, ap);
2113 va_end (ap);
2115 if (buf == NULL || len < 0)
2117 ctxt->add_error (NULL, "malloc failure");
2118 return NULL;
2121 result = ctxt->new_string (buf);
2122 free (buf);
2123 return result;
2126 /* Implementation of recording::memento::make_debug_string for strings,
2127 wrapping the given string in quotes and escaping as necessary. */
2129 recording::string *
2130 recording::string::make_debug_string ()
2132 /* Avoid infinite recursion into strings when logging all mementos:
2133 don't re-escape strings: */
2134 if (m_escaped)
2135 return this;
2137 /* Wrap in quotes and do escaping etc */
2139 size_t sz = (1 /* opening quote */
2140 + (m_len * 2) /* each char might get escaped */
2141 + 1 /* closing quote */
2142 + 1); /* nil termintator */
2143 char *tmp = new char[sz];
2144 size_t len = 0;
2146 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
2147 APPEND('"'); /* opening quote */
2148 for (size_t i = 0; i < m_len ; i++)
2150 char ch = m_buffer[i];
2151 switch (ch)
2153 default:
2154 APPEND(ch);
2155 break;
2156 case '\t':
2157 APPEND('\\');
2158 APPEND('t');
2159 break;
2160 case '\n':
2161 APPEND('\\');
2162 APPEND('n');
2163 break;
2164 case '\\':
2165 case '"':
2166 APPEND('\\');
2167 APPEND(ch);
2168 break;
2171 APPEND('"'); /* closing quote */
2172 #undef APPEND
2173 tmp[len] = '\0'; /* nil termintator */
2175 string *result = m_ctxt->new_string (tmp, true);
2177 delete[] tmp;
2178 return result;
2181 /* Implementation of recording::memento::write_reproducer for strings. */
2183 void
2184 recording::string::write_reproducer (reproducer &)
2186 /* Empty. */
2189 /* The implementation of class gcc::jit::recording::location. */
2191 /* Implementation of recording::memento::replay_into for locations.
2193 Create a new playback::location and store it into the
2194 recording::location's m_playback_obj field. */
2196 void
2197 recording::location::replay_into (replayer *r)
2199 m_playback_obj = r->new_location (this,
2200 m_filename->c_str (),
2201 m_line,
2202 m_column);
2205 /* Implementation of recording::memento::make_debug_string for locations,
2206 turning them into the usual form:
2207 FILENAME:LINE:COLUMN
2208 like we do when emitting diagnostics. */
2210 recording::string *
2211 recording::location::make_debug_string ()
2213 return string::from_printf (m_ctxt,
2214 "%s:%i:%i",
2215 m_filename->c_str (), m_line, m_column);
2218 /* Implementation of recording::memento::write_reproducer for locations. */
2220 void
2221 recording::location::write_reproducer (reproducer &r)
2223 const char *id = r.make_identifier (this, "loc");
2224 r.write (" gcc_jit_location *%s =\n"
2225 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
2226 " %s, /* const char *filename */\n"
2227 " %i, /* int line */\n"
2228 " %i);/* int column */\n",
2230 r.get_identifier (get_context ()),
2231 m_filename->get_debug_string (),
2232 m_line, m_column);
2235 /* The implementation of class gcc::jit::recording::type. */
2237 /* Given a type T, get the type T*.
2239 If this doesn't already exist, generate a new memento_of_get_pointer
2240 instance and add it to this type's context's list of mementos.
2242 Otherwise, use the cached type.
2244 Implements the post-error-checking part of
2245 gcc_jit_type_get_pointer. */
2247 recording::type *
2248 recording::type::get_pointer ()
2250 if (!m_pointer_to_this_type)
2252 m_pointer_to_this_type = new memento_of_get_pointer (this);
2253 m_ctxt->record (m_pointer_to_this_type);
2255 return m_pointer_to_this_type;
2258 /* Given a type T, get the type const T.
2260 Implements the post-error-checking part of
2261 gcc_jit_type_get_const. */
2263 recording::type *
2264 recording::type::get_const ()
2266 recording::type *result = new memento_of_get_const (this);
2267 m_ctxt->record (result);
2268 return result;
2271 /* Given a type T, get the type restrict T.
2273 Implements the post-error-checking part of
2274 gcc_jit_type_get_restrict. */
2276 recording::type *
2277 recording::type::get_restrict ()
2279 recording::type *result = new memento_of_get_restrict (this);
2280 m_ctxt->record (result);
2281 return result;
2284 /* Given a type T, get the type volatile T.
2286 Implements the post-error-checking part of
2287 gcc_jit_type_get_volatile. */
2289 recording::type *
2290 recording::type::get_volatile ()
2292 recording::type *result = new memento_of_get_volatile (this);
2293 m_ctxt->record (result);
2294 return result;
2297 /* Given a type, get an aligned version of the type.
2299 Implements the post-error-checking part of
2300 gcc_jit_type_get_aligned. */
2302 recording::type *
2303 recording::type::get_aligned (size_t alignment_in_bytes)
2305 recording::type *result
2306 = new memento_of_get_aligned (this, alignment_in_bytes);
2307 m_ctxt->record (result);
2308 return result;
2311 /* Given a type, get a vector version of the type.
2313 Implements the post-error-checking part of
2314 gcc_jit_type_get_vector. */
2316 recording::type *
2317 recording::type::get_vector (size_t num_units)
2319 recording::type *result
2320 = new vector_type (this, num_units);
2321 m_ctxt->record (result);
2322 return result;
2325 const char *
2326 recording::type::access_as_type (reproducer &r)
2328 return r.get_identifier (this);
2331 /* Override of default implementation of
2332 recording::type::get_size.
2334 Return the size in bytes. This is in use for global
2335 initialization. */
2337 size_t
2338 recording::memento_of_get_type::get_size ()
2340 int size;
2341 switch (m_kind)
2343 case GCC_JIT_TYPE_VOID:
2344 return 0;
2345 case GCC_JIT_TYPE_BOOL:
2346 case GCC_JIT_TYPE_CHAR:
2347 case GCC_JIT_TYPE_SIGNED_CHAR:
2348 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2349 return 1;
2350 case GCC_JIT_TYPE_SHORT:
2351 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2352 size = SHORT_TYPE_SIZE;
2353 break;
2354 case GCC_JIT_TYPE_INT:
2355 case GCC_JIT_TYPE_UNSIGNED_INT:
2356 size = INT_TYPE_SIZE;
2357 break;
2358 case GCC_JIT_TYPE_LONG:
2359 case GCC_JIT_TYPE_UNSIGNED_LONG:
2360 size = LONG_TYPE_SIZE;
2361 break;
2362 case GCC_JIT_TYPE_LONG_LONG:
2363 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2364 size = LONG_LONG_TYPE_SIZE;
2365 break;
2366 case GCC_JIT_TYPE_UINT8_T:
2367 case GCC_JIT_TYPE_INT8_T:
2368 size = 8;
2369 break;
2370 case GCC_JIT_TYPE_UINT16_T:
2371 case GCC_JIT_TYPE_INT16_T:
2372 size = 16;
2373 break;
2374 case GCC_JIT_TYPE_UINT32_T:
2375 case GCC_JIT_TYPE_INT32_T:
2376 size = 32;
2377 break;
2378 case GCC_JIT_TYPE_UINT64_T:
2379 case GCC_JIT_TYPE_INT64_T:
2380 size = 64;
2381 break;
2382 case GCC_JIT_TYPE_UINT128_T:
2383 case GCC_JIT_TYPE_INT128_T:
2384 size = 128;
2385 break;
2386 case GCC_JIT_TYPE_FLOAT:
2387 size = FLOAT_TYPE_SIZE;
2388 break;
2389 case GCC_JIT_TYPE_DOUBLE:
2390 size = DOUBLE_TYPE_SIZE;
2391 break;
2392 case GCC_JIT_TYPE_LONG_DOUBLE:
2393 size = LONG_DOUBLE_TYPE_SIZE;
2394 break;
2395 case GCC_JIT_TYPE_SIZE_T:
2396 size = MAX_BITS_PER_WORD;
2397 break;
2398 default:
2399 /* As this function is called by
2400 'gcc_jit_global_set_initializer' and
2401 'recording::global::write_reproducer' possible types are only
2402 integrals and are covered by the previous cases. */
2403 gcc_unreachable ();
2406 return size / BITS_PER_UNIT;
2409 /* Implementation of pure virtual hook recording::type::dereference for
2410 recording::memento_of_get_type. */
2412 recording::type *
2413 recording::memento_of_get_type::dereference ()
2415 switch (m_kind)
2417 default: gcc_unreachable ();
2419 case GCC_JIT_TYPE_VOID:
2420 return NULL;
2422 case GCC_JIT_TYPE_VOID_PTR:
2423 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
2425 case GCC_JIT_TYPE_BOOL:
2426 case GCC_JIT_TYPE_CHAR:
2427 case GCC_JIT_TYPE_SIGNED_CHAR:
2428 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2429 case GCC_JIT_TYPE_SHORT:
2430 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2431 case GCC_JIT_TYPE_INT:
2432 case GCC_JIT_TYPE_UNSIGNED_INT:
2433 case GCC_JIT_TYPE_LONG:
2434 case GCC_JIT_TYPE_UNSIGNED_LONG:
2435 case GCC_JIT_TYPE_LONG_LONG:
2436 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2437 case GCC_JIT_TYPE_UINT8_T:
2438 case GCC_JIT_TYPE_UINT16_T:
2439 case GCC_JIT_TYPE_UINT32_T:
2440 case GCC_JIT_TYPE_UINT64_T:
2441 case GCC_JIT_TYPE_UINT128_T:
2442 case GCC_JIT_TYPE_INT8_T:
2443 case GCC_JIT_TYPE_INT16_T:
2444 case GCC_JIT_TYPE_INT32_T:
2445 case GCC_JIT_TYPE_INT64_T:
2446 case GCC_JIT_TYPE_INT128_T:
2447 case GCC_JIT_TYPE_FLOAT:
2448 case GCC_JIT_TYPE_DOUBLE:
2449 case GCC_JIT_TYPE_LONG_DOUBLE:
2450 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2451 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2452 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2453 /* Not a pointer: */
2454 return NULL;
2456 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2457 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
2459 case GCC_JIT_TYPE_SIZE_T:
2460 /* Not a pointer: */
2461 return NULL;
2463 case GCC_JIT_TYPE_FILE_PTR:
2464 /* Give the client code back an opaque "struct FILE". */
2465 return m_ctxt->get_opaque_FILE_type ();
2469 /* Implementation of pure virtual hook recording::type::is_int for
2470 recording::memento_of_get_type. */
2472 bool
2473 recording::memento_of_get_type::is_int () const
2475 switch (m_kind)
2477 default: gcc_unreachable ();
2479 case GCC_JIT_TYPE_VOID:
2480 return false;
2482 case GCC_JIT_TYPE_VOID_PTR:
2483 return false;
2485 case GCC_JIT_TYPE_BOOL:
2486 return false;
2488 case GCC_JIT_TYPE_CHAR:
2489 case GCC_JIT_TYPE_SIGNED_CHAR:
2490 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2491 case GCC_JIT_TYPE_SHORT:
2492 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2493 case GCC_JIT_TYPE_INT:
2494 case GCC_JIT_TYPE_UNSIGNED_INT:
2495 case GCC_JIT_TYPE_LONG:
2496 case GCC_JIT_TYPE_UNSIGNED_LONG:
2497 case GCC_JIT_TYPE_LONG_LONG:
2498 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2499 case GCC_JIT_TYPE_UINT8_T:
2500 case GCC_JIT_TYPE_UINT16_T:
2501 case GCC_JIT_TYPE_UINT32_T:
2502 case GCC_JIT_TYPE_UINT64_T:
2503 case GCC_JIT_TYPE_UINT128_T:
2504 case GCC_JIT_TYPE_INT8_T:
2505 case GCC_JIT_TYPE_INT16_T:
2506 case GCC_JIT_TYPE_INT32_T:
2507 case GCC_JIT_TYPE_INT64_T:
2508 case GCC_JIT_TYPE_INT128_T:
2509 return true;
2511 case GCC_JIT_TYPE_FLOAT:
2512 case GCC_JIT_TYPE_DOUBLE:
2513 case GCC_JIT_TYPE_LONG_DOUBLE:
2514 return false;
2516 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2517 return false;
2519 case GCC_JIT_TYPE_SIZE_T:
2520 return true;
2522 case GCC_JIT_TYPE_FILE_PTR:
2523 return false;
2525 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2526 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2527 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2528 return false;
2532 /* Implementation of pure virtual hook recording::type::is_signed for
2533 recording::memento_of_get_type. */
2535 bool
2536 recording::memento_of_get_type::is_signed () const
2538 switch (m_kind)
2540 default: gcc_unreachable ();
2542 case GCC_JIT_TYPE_SIGNED_CHAR:
2543 case GCC_JIT_TYPE_CHAR:
2544 case GCC_JIT_TYPE_SHORT:
2545 case GCC_JIT_TYPE_INT:
2546 case GCC_JIT_TYPE_LONG:
2547 case GCC_JIT_TYPE_LONG_LONG:
2548 case GCC_JIT_TYPE_INT8_T:
2549 case GCC_JIT_TYPE_INT16_T:
2550 case GCC_JIT_TYPE_INT32_T:
2551 case GCC_JIT_TYPE_INT64_T:
2552 case GCC_JIT_TYPE_INT128_T:
2553 return true;
2555 case GCC_JIT_TYPE_VOID:
2556 case GCC_JIT_TYPE_VOID_PTR:
2557 case GCC_JIT_TYPE_BOOL:
2558 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2559 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2560 case GCC_JIT_TYPE_UNSIGNED_INT:
2561 case GCC_JIT_TYPE_UNSIGNED_LONG:
2562 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2563 case GCC_JIT_TYPE_UINT8_T:
2564 case GCC_JIT_TYPE_UINT16_T:
2565 case GCC_JIT_TYPE_UINT32_T:
2566 case GCC_JIT_TYPE_UINT64_T:
2567 case GCC_JIT_TYPE_UINT128_T:
2569 case GCC_JIT_TYPE_FLOAT:
2570 case GCC_JIT_TYPE_DOUBLE:
2571 case GCC_JIT_TYPE_LONG_DOUBLE:
2573 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2575 case GCC_JIT_TYPE_SIZE_T:
2577 case GCC_JIT_TYPE_FILE_PTR:
2579 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2580 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2581 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2582 return false;
2586 /* Implementation of pure virtual hook recording::type::is_float for
2587 recording::memento_of_get_type. */
2589 bool
2590 recording::memento_of_get_type::is_float () const
2592 switch (m_kind)
2594 default: gcc_unreachable ();
2596 case GCC_JIT_TYPE_VOID:
2597 return false;
2599 case GCC_JIT_TYPE_VOID_PTR:
2600 return false;
2602 case GCC_JIT_TYPE_BOOL:
2603 return false;
2605 case GCC_JIT_TYPE_CHAR:
2606 case GCC_JIT_TYPE_SIGNED_CHAR:
2607 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2608 case GCC_JIT_TYPE_SHORT:
2609 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2610 case GCC_JIT_TYPE_INT:
2611 case GCC_JIT_TYPE_UNSIGNED_INT:
2612 case GCC_JIT_TYPE_LONG:
2613 case GCC_JIT_TYPE_UNSIGNED_LONG:
2614 case GCC_JIT_TYPE_LONG_LONG:
2615 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2616 case GCC_JIT_TYPE_UINT8_T:
2617 case GCC_JIT_TYPE_UINT16_T:
2618 case GCC_JIT_TYPE_UINT32_T:
2619 case GCC_JIT_TYPE_UINT64_T:
2620 case GCC_JIT_TYPE_UINT128_T:
2621 case GCC_JIT_TYPE_INT8_T:
2622 case GCC_JIT_TYPE_INT16_T:
2623 case GCC_JIT_TYPE_INT32_T:
2624 case GCC_JIT_TYPE_INT64_T:
2625 case GCC_JIT_TYPE_INT128_T:
2626 return false;
2628 case GCC_JIT_TYPE_FLOAT:
2629 case GCC_JIT_TYPE_DOUBLE:
2630 case GCC_JIT_TYPE_LONG_DOUBLE:
2631 return true;
2633 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2634 return false;
2636 case GCC_JIT_TYPE_SIZE_T:
2637 return false;
2639 case GCC_JIT_TYPE_FILE_PTR:
2640 return false;
2642 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2643 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2644 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2645 return true;
2649 /* Implementation of pure virtual hook recording::type::is_bool for
2650 recording::memento_of_get_type. */
2652 bool
2653 recording::memento_of_get_type::is_bool () const
2655 switch (m_kind)
2657 default: gcc_unreachable ();
2659 case GCC_JIT_TYPE_VOID:
2660 return false;
2662 case GCC_JIT_TYPE_VOID_PTR:
2663 return false;
2665 case GCC_JIT_TYPE_BOOL:
2666 return true;
2668 case GCC_JIT_TYPE_CHAR:
2669 case GCC_JIT_TYPE_SIGNED_CHAR:
2670 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2671 case GCC_JIT_TYPE_SHORT:
2672 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2673 case GCC_JIT_TYPE_INT:
2674 case GCC_JIT_TYPE_UNSIGNED_INT:
2675 case GCC_JIT_TYPE_LONG:
2676 case GCC_JIT_TYPE_UNSIGNED_LONG:
2677 case GCC_JIT_TYPE_LONG_LONG:
2678 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2679 case GCC_JIT_TYPE_UINT8_T:
2680 case GCC_JIT_TYPE_UINT16_T:
2681 case GCC_JIT_TYPE_UINT32_T:
2682 case GCC_JIT_TYPE_UINT64_T:
2683 case GCC_JIT_TYPE_UINT128_T:
2684 case GCC_JIT_TYPE_INT8_T:
2685 case GCC_JIT_TYPE_INT16_T:
2686 case GCC_JIT_TYPE_INT32_T:
2687 case GCC_JIT_TYPE_INT64_T:
2688 case GCC_JIT_TYPE_INT128_T:
2689 return false;
2691 case GCC_JIT_TYPE_FLOAT:
2692 case GCC_JIT_TYPE_DOUBLE:
2693 case GCC_JIT_TYPE_LONG_DOUBLE:
2694 return false;
2696 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2697 return false;
2699 case GCC_JIT_TYPE_SIZE_T:
2700 return false;
2702 case GCC_JIT_TYPE_FILE_PTR:
2703 return false;
2705 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2706 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2707 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2708 return false;
2712 /* Implementation of pure virtual hook recording::memento::replay_into
2713 for recording::memento_of_get_type. */
2715 void
2716 recording::memento_of_get_type::replay_into (replayer *r)
2718 set_playback_obj (r->get_type (m_kind));
2721 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2723 /* Descriptive strings for each of enum gcc_jit_types. */
2725 static const char * const get_type_strings[] = {
2726 "void", /* GCC_JIT_TYPE_VOID */
2727 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2729 "bool", /* GCC_JIT_TYPE_BOOL */
2731 "char", /* GCC_JIT_TYPE_CHAR */
2732 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2733 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2735 "short", /* GCC_JIT_TYPE_SHORT */
2736 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2738 "int", /* GCC_JIT_TYPE_INT */
2739 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2741 "long", /* GCC_JIT_TYPE_LONG */
2742 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2744 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2745 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2747 "float", /* GCC_JIT_TYPE_FLOAT */
2748 "double", /* GCC_JIT_TYPE_DOUBLE */
2749 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2751 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2753 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2755 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2757 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2758 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2759 "complex long double", /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2761 "__uint8_t", /* GCC_JIT_TYPE_UINT8_T */
2762 "__uint16_t", /* GCC_JIT_TYPE_UINT16_T */
2763 "__uint32_t", /* GCC_JIT_TYPE_UINT32_T */
2764 "__uint64_t", /* GCC_JIT_TYPE_UINT64_T */
2765 "__uint128_t", /* GCC_JIT_TYPE_UINT128_T */
2766 "__int8_t", /* GCC_JIT_TYPE_INT8_T */
2767 "__int16_t", /* GCC_JIT_TYPE_INT16_T */
2768 "__int32_t", /* GCC_JIT_TYPE_INT32_T */
2769 "__int64_t", /* GCC_JIT_TYPE_INT64_T */
2770 "__int128_t", /* GCC_JIT_TYPE_INT128_T */
2774 /* Implementation of recording::memento::make_debug_string for
2775 results of get_type, using a simple table of type names. */
2777 recording::string *
2778 recording::memento_of_get_type::make_debug_string ()
2780 return m_ctxt->new_string (get_type_strings[m_kind]);
2783 static const char * const get_type_enum_strings[] = {
2784 "GCC_JIT_TYPE_VOID",
2785 "GCC_JIT_TYPE_VOID_PTR",
2786 "GCC_JIT_TYPE_BOOL",
2787 "GCC_JIT_TYPE_CHAR",
2788 "GCC_JIT_TYPE_SIGNED_CHAR",
2789 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2790 "GCC_JIT_TYPE_SHORT",
2791 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2792 "GCC_JIT_TYPE_INT",
2793 "GCC_JIT_TYPE_UNSIGNED_INT",
2794 "GCC_JIT_TYPE_LONG",
2795 "GCC_JIT_TYPE_UNSIGNED_LONG",
2796 "GCC_JIT_TYPE_LONG_LONG",
2797 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2798 "GCC_JIT_TYPE_FLOAT",
2799 "GCC_JIT_TYPE_DOUBLE",
2800 "GCC_JIT_TYPE_LONG_DOUBLE",
2801 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2802 "GCC_JIT_TYPE_SIZE_T",
2803 "GCC_JIT_TYPE_FILE_PTR",
2804 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2805 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2806 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE",
2807 "GCC_JIT_TYPE_UINT8_T",
2808 "GCC_JIT_TYPE_UINT16_T",
2809 "GCC_JIT_TYPE_UINT32_T",
2810 "GCC_JIT_TYPE_UINT64_T",
2811 "GCC_JIT_TYPE_UINT128_T",
2812 "GCC_JIT_TYPE_INT8_T",
2813 "GCC_JIT_TYPE_INT16_T",
2814 "GCC_JIT_TYPE_INT32_T",
2815 "GCC_JIT_TYPE_INT64_T",
2816 "GCC_JIT_TYPE_INT128_T",
2819 void
2820 recording::memento_of_get_type::write_reproducer (reproducer &r)
2822 const char *id = r.make_identifier (this, "type");
2823 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2825 r.get_identifier (get_context ()),
2826 get_type_enum_strings[m_kind]);
2829 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2831 /* Override of default implementation of
2832 recording::type::get_size for get_pointer. */
2834 size_t
2835 recording::memento_of_get_pointer::get_size ()
2837 return POINTER_SIZE / BITS_PER_UNIT;
2840 /* Override of default implementation of
2841 recording::type::accepts_writes_from for get_pointer.
2843 Require a pointer type, and allowing writes to
2844 (const T *) from a (T*), but not the other way around. */
2846 bool
2847 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2849 /* Must be a pointer type: */
2850 type *rtype_points_to = rtype->is_pointer ();
2851 if (!rtype_points_to)
2852 return false;
2854 /* It's OK to assign to a (const T *) from a (T *). */
2855 if (m_other_type->unqualified ()->accepts_writes_from (rtype_points_to))
2857 return true;
2860 /* It's OK to assign to a (volatile const T *) from a (volatile const T *). */
2861 return m_other_type->is_same_type_as (rtype_points_to);
2864 /* Implementation of pure virtual hook recording::memento::replay_into
2865 for recording::memento_of_get_pointer. */
2867 void
2868 recording::memento_of_get_pointer::replay_into (replayer *)
2870 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2873 /* Implementation of recording::memento::make_debug_string for
2874 results of get_pointer, adding " *" to the underlying type,
2875 with special-casing to handle function pointer types. */
2877 recording::string *
2878 recording::memento_of_get_pointer::make_debug_string ()
2880 /* Special-case function pointer types, to put the "*" in parens between
2881 the return type and the params (for one level of dereferencing, at
2882 least). */
2883 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2884 return fn_type->make_debug_string_with_ptr ();
2886 return string::from_printf (m_ctxt,
2887 "%s *", m_other_type->get_debug_string ());
2890 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2892 void
2893 recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2895 /* We need to special-case function pointer types; see the notes in
2896 recording::function_type::write_deferred_reproducer. */
2897 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2899 fn_type->write_deferred_reproducer (r, this);
2900 return;
2903 const char *id = r.make_identifier (this, "type");
2904 r.write (" gcc_jit_type *%s =\n"
2905 " gcc_jit_type_get_pointer (%s);\n",
2907 r.get_identifier_as_type (m_other_type));
2910 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2912 /* Implementation of pure virtual hook recording::memento::replay_into
2913 for recording::memento_of_get_const. */
2915 void
2916 recording::memento_of_get_const::replay_into (replayer *)
2918 set_playback_obj (m_other_type->playback_type ()->get_const ());
2921 /* Implementation of recording::memento::make_debug_string for
2922 results of get_const, prepending "const ". */
2924 recording::string *
2925 recording::memento_of_get_const::make_debug_string ()
2927 return string::from_printf (m_ctxt,
2928 "const %s", m_other_type->get_debug_string ());
2931 /* Implementation of recording::memento::write_reproducer for const types. */
2933 void
2934 recording::memento_of_get_const::write_reproducer (reproducer &r)
2936 const char *id = r.make_identifier (this, "type");
2937 r.write (" gcc_jit_type *%s =\n"
2938 " gcc_jit_type_get_const (%s);\n",
2940 r.get_identifier_as_type (m_other_type));
2943 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2945 /* Implementation of pure virtual hook recording::memento::replay_into
2946 for recording::memento_of_get_volatile. */
2948 void
2949 recording::memento_of_get_volatile::replay_into (replayer *)
2951 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2954 /* Implementation of recording::memento::make_debug_string for
2955 results of get_volatile, prepending "volatile ". */
2957 recording::string *
2958 recording::memento_of_get_volatile::make_debug_string ()
2960 return string::from_printf (m_ctxt,
2961 "volatile %s", m_other_type->get_debug_string ());
2964 /* Implementation of recording::memento::write_reproducer for volatile
2965 types. */
2967 void
2968 recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2970 const char *id = r.make_identifier (this, "type");
2971 r.write (" gcc_jit_type *%s =\n"
2972 " gcc_jit_type_get_volatile (%s);\n",
2974 r.get_identifier_as_type (m_other_type));
2977 /* The implementation of class gcc::jit::recording::memento_of_get_restrict. */
2979 /* Implementation of pure virtual hook recording::memento::replay_into
2980 for recording::memento_of_get_restrict. */
2982 void
2983 recording::memento_of_get_restrict::replay_into (replayer *)
2985 set_playback_obj (m_other_type->playback_type ()->get_restrict ());
2988 /* Implementation of recording::memento::make_debug_string for
2989 results of get_restrict, prepending "restrict ". */
2991 recording::string *
2992 recording::memento_of_get_restrict::make_debug_string ()
2994 return string::from_printf (m_ctxt,
2995 "restrict %s", m_other_type->get_debug_string ());
2998 /* Implementation of recording::memento::write_reproducer for restrict
2999 types. */
3001 void
3002 recording::memento_of_get_restrict::write_reproducer (reproducer &r)
3004 const char *id = r.make_identifier (this, "type");
3005 r.write (" gcc_jit_type *%s =\n"
3006 " gcc_jit_type_get_restrict (%s);\n",
3008 r.get_identifier_as_type (m_other_type));
3011 /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
3013 /* Implementation of pure virtual hook recording::memento::replay_into
3014 for recording::memento_of_get_aligned. */
3016 void
3017 recording::memento_of_get_aligned::replay_into (replayer *)
3019 set_playback_obj
3020 (m_other_type->playback_type ()->get_aligned (m_alignment_in_bytes));
3023 /* Implementation of recording::memento::make_debug_string for
3024 results of get_aligned. */
3026 recording::string *
3027 recording::memento_of_get_aligned::make_debug_string ()
3029 return string::from_printf (m_ctxt,
3030 "%s __attribute__((aligned(%zi)))",
3031 m_other_type->get_debug_string (),
3032 m_alignment_in_bytes);
3035 /* Implementation of recording::memento::write_reproducer for aligned
3036 types. */
3038 void
3039 recording::memento_of_get_aligned::write_reproducer (reproducer &r)
3041 const char *id = r.make_identifier (this, "type");
3042 r.write (" gcc_jit_type *%s =\n"
3043 " gcc_jit_type_get_aligned (%s, %zi);\n",
3045 r.get_identifier_as_type (m_other_type),
3046 m_alignment_in_bytes);
3049 /* The implementation of class gcc::jit::recording::vector_type. */
3051 /* Implementation of pure virtual hook recording::memento::replay_into
3052 for recording::vector_type. */
3054 void
3055 recording::vector_type::replay_into (replayer *)
3057 set_playback_obj
3058 (m_other_type->playback_type ()->get_vector (m_num_units));
3061 /* Implementation of recording::memento::make_debug_string for
3062 results of get_vector. */
3064 recording::string *
3065 recording::vector_type::make_debug_string ()
3067 return string::from_printf
3068 (m_ctxt,
3069 "%s __attribute__((vector_size(sizeof (%s) * %zi)))",
3070 m_other_type->get_debug_string (),
3071 m_other_type->get_debug_string (),
3072 m_num_units);
3075 /* Implementation of recording::memento::write_reproducer for vector types. */
3077 void
3078 recording::vector_type::write_reproducer (reproducer &r)
3080 const char *id = r.make_identifier (this, "type");
3081 r.write (" gcc_jit_type *%s =\n"
3082 " gcc_jit_type_get_vector (%s, %zi);\n",
3084 r.get_identifier_as_type (m_other_type),
3085 m_num_units);
3088 /* The implementation of class gcc::jit::recording::array_type */
3090 /* Implementation of pure virtual hook recording::type::dereference for
3091 recording::array_type. */
3093 recording::type *
3094 recording::array_type::dereference ()
3096 return m_element_type;
3099 /* Implementation of pure virtual hook recording::memento::replay_into
3100 for recording::array_type. */
3102 void
3103 recording::array_type::replay_into (replayer *r)
3105 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
3106 m_element_type->playback_type (),
3107 m_num_elements));
3110 /* Implementation of recording::memento::make_debug_string for
3111 results of new_array_type. */
3113 recording::string *
3114 recording::array_type::make_debug_string ()
3116 return string::from_printf (m_ctxt,
3117 "%s[%d]",
3118 m_element_type->get_debug_string (),
3119 m_num_elements);
3122 /* Implementation of recording::memento::write_reproducer for array
3123 types. */
3125 void
3126 recording::array_type::write_reproducer (reproducer &r)
3128 const char *id = r.make_identifier (this, "array_type");
3129 r.write (" gcc_jit_type *%s =\n"
3130 " gcc_jit_context_new_array_type (%s,\n"
3131 " %s, /* gcc_jit_location *loc */\n"
3132 " %s, /* gcc_jit_type *element_type */\n"
3133 " %i); /* int num_elements */\n",
3135 r.get_identifier (get_context ()),
3136 r.get_identifier (m_loc),
3137 r.get_identifier_as_type (m_element_type),
3138 m_num_elements);
3141 /* The implementation of class gcc::jit::recording::function_type */
3143 /* Constructor for gcc::jit::recording::function_type. */
3145 recording::function_type::function_type (context *ctxt,
3146 type *return_type,
3147 int num_params,
3148 type **param_types,
3149 int is_variadic)
3150 : type (ctxt),
3151 m_return_type (return_type),
3152 m_param_types (),
3153 m_is_variadic (is_variadic)
3155 for (int i = 0; i< num_params; i++)
3156 m_param_types.safe_push (param_types[i]);
3159 /* Implementation of pure virtual hook recording::type::dereference for
3160 recording::function_type. */
3162 recording::type *
3163 recording::function_type::dereference ()
3165 return NULL;
3168 /* Implementation of virtual hook recording::type::is_same_type_as for
3169 recording::function_type.
3171 We override this to avoid requiring identity of function pointer types,
3172 so that if client code has obtained the same signature in
3173 different ways (e.g. via gcc_jit_context_new_function_ptr_type
3174 vs gcc_jit_function_get_address), the different function_type
3175 instances are treated as compatible.
3177 We can't use type::accepts_writes_from for this as we need a stronger
3178 notion of "sameness": if we have a fn_ptr type that has args that are
3179 themselves fn_ptr types, then those args still need to match exactly.
3181 Alternatively, we could consolidate attempts to create identical
3182 function_type instances so that pointer equality works, but that runs
3183 into issues about the lifetimes of the cache (w.r.t. nested contexts). */
3185 bool
3186 recording::function_type::is_same_type_as (type *other)
3188 gcc_assert (other);
3190 function_type *other_fn_type = other->dyn_cast_function_type ();
3191 if (!other_fn_type)
3192 return false;
3194 /* Everything must match. */
3196 if (!m_return_type->is_same_type_as (other_fn_type->m_return_type))
3197 return false;
3199 if (m_param_types.length () != other_fn_type->m_param_types.length ())
3200 return false;
3202 unsigned i;
3203 type *param_type;
3204 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
3205 if (!param_type->is_same_type_as (other_fn_type->m_param_types[i]))
3206 return false;
3208 if (m_is_variadic != other_fn_type->m_is_variadic)
3209 return false;
3211 /* Passed all tests. */
3212 return true;
3215 /* Implementation of pure virtual hook recording::memento::replay_into
3216 for recording::function_type. */
3218 void
3219 recording::function_type::replay_into (replayer *r)
3221 /* Convert m_param_types to a vec of playback type. */
3222 auto_vec <playback::type *> param_types;
3223 int i;
3224 recording::type *type;
3225 param_types.create (m_param_types.length ());
3226 FOR_EACH_VEC_ELT (m_param_types, i, type)
3227 param_types.safe_push (type->playback_type ());
3229 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
3230 &param_types,
3231 m_is_variadic));
3234 /* Special-casing for make_debug_string for get_pointer results for
3235 handling (one level) of pointers to functions. */
3237 recording::string *
3238 recording::function_type::make_debug_string_with_ptr ()
3240 return make_debug_string_with ("(*) ");
3243 /* Implementation of recording::memento::make_debug_string for
3244 results of new_function_type. */
3246 recording::string *
3247 recording::function_type::make_debug_string ()
3249 return make_debug_string_with ("");
3252 /* Build a debug string representation of the form:
3254 RESULT_TYPE INSERT (PARAM_TYPES)
3256 for use when handling 0 and 1 level of indirection to this
3257 function type. */
3259 recording::string *
3260 recording::function_type::make_debug_string_with (const char *insert)
3262 /* First, build a buffer for the arguments. */
3263 /* Calculate length of said buffer. */
3264 size_t sz = 1; /* nil terminator */
3265 for (unsigned i = 0; i< m_param_types.length (); i++)
3267 sz += strlen (m_param_types[i]->get_debug_string ());
3268 sz += 2; /* ", " separator */
3270 if (m_is_variadic)
3271 sz += 5; /* ", ..." separator and ellipsis */
3273 /* Now allocate and populate the buffer. */
3274 char *argbuf = new char[sz];
3275 size_t len = 0;
3277 for (unsigned i = 0; i< m_param_types.length (); i++)
3279 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
3280 len += strlen (m_param_types[i]->get_debug_string ());
3281 if (i + 1 < m_param_types.length ())
3283 strcpy (argbuf + len, ", ");
3284 len += 2;
3287 if (m_is_variadic)
3289 if (m_param_types.length ())
3291 strcpy (argbuf + len, ", ");
3292 len += 2;
3294 strcpy (argbuf + len, "...");
3295 len += 3;
3297 argbuf[len] = '\0';
3299 /* ...and use it to get the string for the call as a whole. */
3300 string *result = string::from_printf (m_ctxt,
3301 "%s %s(%s)",
3302 m_return_type->get_debug_string (),
3303 insert,
3304 argbuf);
3306 delete[] argbuf;
3308 return result;
3311 /* Implementation of recording::memento::write_reproducer for function
3312 types. */
3314 void
3315 recording::function_type::write_reproducer (reproducer &)
3317 /* see notes below. */
3320 /* There's a get_pointer within context::new_function_ptr_type:
3321 the type received by client code isn't the memento for the
3322 function_type, but instead the result of get_pointer on it.
3324 Hence we can't directly write a reproducer that gives function_type.
3325 Instead we special-case things within get_pointer, detecting this
3326 case, calling the following function. */
3328 void
3329 recording::function_type::write_deferred_reproducer (reproducer &r,
3330 memento *ptr_type)
3332 gcc_assert (ptr_type);
3333 r.make_identifier (this, "function_type");
3334 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
3335 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
3336 r.write (" gcc_jit_type *%s[%i] = {\n",
3337 param_types_id,
3338 m_param_types.length ());
3339 int i;
3340 type *param_type;
3341 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
3342 r.write (" %s,\n", r.get_identifier_as_type (param_type));
3343 r.write (" };\n");
3344 r.write (" gcc_jit_type *%s =\n"
3345 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
3346 " %s, /* gcc_jit_location *loc */\n"
3347 " %s, /* gcc_jit_type *return_type */\n"
3348 " %i, /* int num_params */\n"
3349 " %s, /* gcc_jit_type **param_types */\n"
3350 " %i); /* int is_variadic */\n",
3351 ptr_id,
3352 r.get_identifier (get_context ()),
3353 "NULL", /* location is not stored */
3354 r.get_identifier_as_type (m_return_type),
3355 m_param_types.length (),
3356 param_types_id,
3357 m_is_variadic);
3360 /* The implementation of class gcc::jit::recording::field. */
3362 /* Implementation of pure virtual hook recording::memento::replay_into
3363 for recording::field. */
3365 void
3366 recording::field::replay_into (replayer *r)
3368 set_playback_obj (r->new_field (playback_location (r, m_loc),
3369 m_type->playback_type (),
3370 playback_string (m_name)));
3373 /* Override the default implementation of
3374 recording::memento::write_to_dump. Dump each field
3375 by dumping a line of the form:
3376 TYPE NAME;
3377 so that we can build up a struct/union field by field. */
3379 void
3380 recording::field::write_to_dump (dump &d)
3382 d.write (" %s %s;\n",
3383 m_type->get_debug_string (),
3384 m_name->c_str ());
3387 /* Implementation of recording::memento::make_debug_string for
3388 results of new_field. */
3390 recording::string *
3391 recording::field::make_debug_string ()
3393 return m_name;
3396 /* Implementation of recording::memento::write_reproducer for fields. */
3398 void
3399 recording::field::write_reproducer (reproducer &r)
3401 const char *id = r.make_identifier (this, "field");
3402 r.write(" gcc_jit_field *%s =\n"
3403 " gcc_jit_context_new_field (%s,\n"
3404 " %s, /* gcc_jit_location *loc */\n"
3405 " %s, /* gcc_jit_type *type, */\n"
3406 " %s); /* const char *name */\n",
3408 r.get_identifier (get_context ()),
3409 r.get_identifier (m_loc),
3410 r.get_identifier_as_type (m_type),
3411 m_name->get_debug_string ());
3414 /* The implementation of class gcc::jit::recording::bitfield. */
3416 /* Implementation of pure virtual hook recording::memento::replay_into
3417 for recording::bitfield. */
3419 void
3420 recording::bitfield::replay_into (replayer *r)
3422 set_playback_obj (r->new_bitfield (playback_location (r, m_loc),
3423 m_type->playback_type (),
3424 m_width,
3425 playback_string (m_name)));
3428 /* Override the default implementation of
3429 recording::memento::write_to_dump. Dump each bit field
3430 by dumping a line of the form:
3431 TYPE NAME:WIDTH;
3432 so that we can build up a struct/union field by field. */
3434 void
3435 recording::bitfield::write_to_dump (dump &d)
3437 d.write (" %s %s:%d;\n",
3438 m_type->get_debug_string (),
3439 m_name->c_str (),
3440 m_width);
3443 /* Implementation of recording::memento::make_debug_string for
3444 results of new_bitfield. */
3446 recording::string *
3447 recording::bitfield::make_debug_string ()
3449 return string::from_printf (m_ctxt,
3450 "%s:%d",
3451 m_name->c_str (), m_width);
3454 /* Implementation of recording::memento::write_reproducer for bitfields. */
3456 void
3457 recording::bitfield::write_reproducer (reproducer &r)
3459 const char *id = r.make_identifier (this, "bitfield");
3460 r.write (" gcc_jit_field *%s =\n"
3461 " gcc_jit_context_new_bitfield (%s,\n"
3462 " %s, /* gcc_jit_location *loc */\n"
3463 " %s, /* gcc_jit_type *type, */\n"
3464 " %d, /* int width, */\n"
3465 " %s); /* const char *name */\n",
3467 r.get_identifier (get_context ()),
3468 r.get_identifier (m_loc),
3469 r.get_identifier_as_type (m_type),
3470 m_width,
3471 m_name->get_debug_string ());
3474 /* The implementation of class gcc::jit::recording::compound_type */
3476 /* The constructor for gcc::jit::recording::compound_type. */
3478 recording::compound_type::compound_type (context *ctxt,
3479 location *loc,
3480 string *name)
3481 : type (ctxt),
3482 m_loc (loc),
3483 m_name (name),
3484 m_fields (NULL)
3488 /* Set the fields of a compound type.
3490 Implements the post-error-checking part of
3491 gcc_jit_struct_set_fields, and is also used by
3492 gcc_jit_context_new_union_type. */
3494 void
3495 recording::compound_type::set_fields (location *loc,
3496 int num_fields,
3497 field **field_array)
3499 m_loc = loc;
3500 gcc_assert (m_fields == NULL);
3502 m_fields = new fields (this, num_fields, field_array);
3503 m_ctxt->record (m_fields);
3506 /* Implementation of pure virtual hook recording::type::dereference for
3507 recording::compound_type. */
3509 recording::type *
3510 recording::compound_type::dereference ()
3512 return NULL; /* not a pointer */
3515 /* The implementation of class gcc::jit::recording::struct_. */
3517 /* The constructor for gcc::jit::recording::struct_. */
3519 recording::struct_::struct_ (context *ctxt,
3520 location *loc,
3521 string *name)
3522 : compound_type (ctxt, loc, name)
3526 /* Implementation of pure virtual hook recording::memento::replay_into
3527 for recording::struct_. */
3529 void
3530 recording::struct_::replay_into (replayer *r)
3532 set_playback_obj (
3533 r->new_compound_type (playback_location (r, get_loc ()),
3534 get_name ()->c_str (),
3535 true /* is_struct */));
3538 const char *
3539 recording::struct_::access_as_type (reproducer &r)
3541 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
3542 r.get_identifier (this));
3545 /* Implementation of recording::memento::make_debug_string for
3546 structs. */
3548 recording::string *
3549 recording::struct_::make_debug_string ()
3551 return string::from_printf (m_ctxt,
3552 "struct %s", get_name ()->c_str ());
3555 void
3556 recording::struct_::write_reproducer (reproducer &r)
3558 const char *id = r.make_identifier (this, "struct");
3559 r.write (" gcc_jit_struct *%s =\n"
3560 " gcc_jit_context_new_opaque_struct (%s,\n"
3561 " %s, /* gcc_jit_location *loc */\n"
3562 " %s); /* const char *name */\n",
3564 r.get_identifier (get_context ()),
3565 r.get_identifier (get_loc ()),
3566 get_name ()->get_debug_string ());
3569 /* The implementation of class gcc::jit::recording::union_. */
3571 /* The constructor for gcc::jit::recording::union_. */
3573 recording::union_::union_ (context *ctxt,
3574 location *loc,
3575 string *name)
3576 : compound_type (ctxt, loc, name)
3580 /* Implementation of pure virtual hook recording::memento::replay_into
3581 for recording::union_. */
3583 void
3584 recording::union_::replay_into (replayer *r)
3586 set_playback_obj (
3587 r->new_compound_type (playback_location (r, get_loc ()),
3588 get_name ()->c_str (),
3589 false /* is_struct */));
3592 /* Implementation of recording::memento::make_debug_string for
3593 unions. */
3595 recording::string *
3596 recording::union_::make_debug_string ()
3598 return string::from_printf (m_ctxt,
3599 "union %s", get_name ()->c_str ());
3602 /* Implementation of recording::memento::write_reproducer for unions. */
3604 void
3605 recording::union_::write_reproducer (reproducer &r)
3607 const char *id = r.make_identifier (this, "union");
3609 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
3610 r.write (" gcc_jit_field *%s[%i] = {\n",
3611 fields_id,
3612 get_fields ()->length ());
3613 for (int i = 0; i < get_fields ()->length (); i++)
3614 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
3615 r.write (" };\n");
3617 r.write (" gcc_jit_type *%s =\n"
3618 " gcc_jit_context_new_union_type (%s,\n"
3619 " %s, /* gcc_jit_location *loc */\n"
3620 " %s, /* const char *name */\n"
3621 " %i, /* int num_fields */\n"
3622 " %s); /* gcc_jit_field **fields */\n",
3624 r.get_identifier (get_context ()),
3625 r.get_identifier (get_loc ()),
3626 get_name ()->get_debug_string (),
3627 get_fields ()->length (),
3628 fields_id);
3631 /* The implementation of class gcc::jit::recording::fields. */
3633 /* The constructor for gcc::jit::recording::fields. */
3635 recording::fields::fields (compound_type *struct_or_union,
3636 int num_fields,
3637 field **fields)
3638 : memento (struct_or_union->m_ctxt),
3639 m_struct_or_union (struct_or_union),
3640 m_fields ()
3642 for (int i = 0; i < num_fields; i++)
3644 gcc_assert (fields[i]->get_container () == NULL);
3645 fields[i]->set_container (m_struct_or_union);
3646 m_fields.safe_push (fields[i]);
3650 /* Implementation of pure virtual hook recording::memento::replay_into
3651 for recording::fields. */
3653 void
3654 recording::fields::replay_into (replayer *)
3656 auto_vec<playback::field *> playback_fields;
3657 playback_fields.create (m_fields.length ());
3658 for (unsigned i = 0; i < m_fields.length (); i++)
3659 playback_fields.safe_push (m_fields[i]->playback_field ());
3660 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
3663 /* Override the default implementation of
3664 recording::memento::write_to_dump by writing a union/struct
3665 declaration of this form:
3667 struct/union NAME {
3668 TYPE_1 NAME_1;
3669 TYPE_2 NAME_2;
3670 ....
3671 TYPE_N NAME_N;
3674 to the dump. */
3676 void
3677 recording::fields::write_to_dump (dump &d)
3679 int i;
3680 field *f;
3682 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
3683 FOR_EACH_VEC_ELT (m_fields, i, f)
3684 f->write_to_dump (d);
3685 d.write ("};\n");
3688 /* Implementation of recording::memento::write_reproducer for the fields
3689 subclass. */
3691 void
3692 recording::fields::write_reproducer (reproducer &r)
3694 if (m_struct_or_union)
3695 if (m_struct_or_union->dyn_cast_struct () == NULL)
3696 /* We have a union; the fields have already been written by
3697 union::write_reproducer. */
3698 return;
3700 const char *fields_id = r.make_identifier (this, "fields");
3701 r.write (" gcc_jit_field *%s[%i] = {\n",
3702 fields_id,
3703 m_fields.length ());
3704 int i;
3705 field *field;
3706 FOR_EACH_VEC_ELT (m_fields, i, field)
3707 r.write (" %s,\n", r.get_identifier (field));
3708 r.write (" };\n");
3710 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
3711 " %s, /* gcc_jit_location *loc */\n"
3712 " %i, /* int num_fields */\n"
3713 " %s); /* gcc_jit_field **fields */\n",
3714 r.get_identifier (m_struct_or_union),
3715 r.get_identifier ((memento *)NULL),
3716 m_fields.length (),
3717 fields_id);
3720 /* Implementation of recording::memento::make_debug_string for
3721 field tables. */
3723 recording::string *
3724 recording::fields::make_debug_string ()
3726 return string::from_printf (m_ctxt,
3727 "fields");
3730 /* The implementation of class gcc::jit::recording::rvalue. */
3732 /* Create a recording::access_field_rvalue instance and add it to
3733 the rvalue's context's list of mementos.
3735 Implements the post-error-checking part of
3736 gcc_jit_rvalue_access_field. */
3738 recording::rvalue *
3739 recording::rvalue::access_field (recording::location *loc,
3740 field *field)
3742 recording::rvalue *result =
3743 new access_field_rvalue (m_ctxt, loc, this, field);
3744 m_ctxt->record (result);
3745 return result;
3748 /* Create a recording::dereference_field_rvalue instance and add it to
3749 the rvalue's context's list of mementos.
3751 Implements the post-error-checking part of
3752 gcc_jit_rvalue_dereference_field. */
3754 recording::lvalue *
3755 recording::rvalue::dereference_field (recording::location *loc,
3756 field *field)
3758 recording::lvalue *result =
3759 new dereference_field_rvalue (m_ctxt, loc, this, field);
3760 m_ctxt->record (result);
3761 return result;
3764 /* Create a recording::dereference_rvalue instance and add it to the
3765 rvalue's context's list of mementos.
3767 Implements the post-error-checking part of
3768 gcc_jit_rvalue_dereference. */
3770 recording::lvalue *
3771 recording::rvalue::dereference (recording::location *loc)
3773 recording::lvalue *result =
3774 new dereference_rvalue (m_ctxt, loc, this);
3775 m_ctxt->record (result);
3776 return result;
3779 /* An rvalue visitor, for validating that every rvalue within an expression
3780 trees within "STMT" has the correct scope (e.g. no access to locals
3781 of a different function). */
3783 class rvalue_usage_validator : public recording::rvalue_visitor
3785 public:
3786 rvalue_usage_validator (const char *api_funcname,
3787 recording::context *ctxt,
3788 recording::statement *stmt);
3790 void
3791 visit (recording::rvalue *rvalue) final override;
3793 private:
3794 const char *m_api_funcname;
3795 recording::context *m_ctxt;
3796 recording::statement *m_stmt;
3799 /* The trivial constructor for rvalue_usage_validator. */
3801 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
3802 recording::context *ctxt,
3803 recording::statement *stmt)
3804 : m_api_funcname (api_funcname),
3805 m_ctxt (ctxt),
3806 m_stmt (stmt)
3810 /* Verify that the given rvalue is in the correct scope. */
3812 void
3813 rvalue_usage_validator::visit (recording::rvalue *rvalue)
3815 gcc_assert (m_stmt->get_block ());
3816 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
3818 /* Most rvalues don't have a scope (only locals and params). */
3819 if (rvalue->get_scope ())
3821 if (rvalue->get_scope () != stmt_scope)
3822 m_ctxt->add_error
3823 (rvalue->get_loc (),
3824 "%s:"
3825 " rvalue %s (type: %s)"
3826 " has scope limited to function %s"
3827 " but was used within function %s"
3828 " (in statement: %s)",
3829 m_api_funcname,
3830 rvalue->get_debug_string (),
3831 rvalue->get_type ()->get_debug_string (),
3832 rvalue->get_scope ()->get_debug_string (),
3833 stmt_scope->get_debug_string (),
3834 m_stmt->get_debug_string ());
3836 else
3838 if (rvalue->dyn_cast_param ())
3839 m_ctxt->add_error
3840 (rvalue->get_loc (),
3841 "%s:"
3842 " param %s (type: %s)"
3843 " was used within function %s"
3844 " (in statement: %s)"
3845 " but is not associated with any function",
3846 m_api_funcname,
3847 rvalue->get_debug_string (),
3848 rvalue->get_type ()->get_debug_string (),
3849 stmt_scope->get_debug_string (),
3850 m_stmt->get_debug_string ());
3854 /* Verify that it's valid to use this rvalue (and all expressions
3855 in the tree below it) within the given statement.
3857 For example, we must reject attempts to use a local from one
3858 function within a different function here, or we'll get
3859 an ICE deep inside toplev::main. */
3861 void
3862 recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
3864 rvalue_usage_validator v (api_funcname,
3865 s->get_context (),
3868 /* Verify that it's OK to use this rvalue within s. */
3869 v.visit (this);
3871 /* Traverse the expression tree below "this", verifying all rvalues
3872 within it. */
3873 visit_children (&v);
3876 /* Set the scope of this rvalue to be the given function. This can only
3877 be done once on a given rvalue. */
3879 void
3880 recording::rvalue::set_scope (function *scope)
3882 gcc_assert (scope);
3883 gcc_assert (m_scope == NULL);
3884 m_scope = scope;
3888 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3889 themselves.
3890 Instances of rvalue don't need an upcast call. */
3892 const char *
3893 recording::rvalue::access_as_rvalue (reproducer &r)
3895 return r.get_identifier (this);
3898 /* Return a debug string for the given rvalue, wrapping it in parentheses
3899 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3900 stronger precedence that this rvalue's precedence.
3902 For example, given:
3904 MULT
3906 PLUS MINUS
3907 / \ / \
3908 A B C D
3910 we want to emit:
3912 (A + B) * (C - D)
3914 since MULT has strong precedence than PLUS and MINUS, whereas for:
3916 PLUS
3918 MULT DIVIDE
3919 / \ / \
3920 A B C D
3922 we can simply emit:
3924 A * B + C / D
3926 since PLUS has weaker precedence than MULT and DIVIDE. */
3928 const char *
3929 recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
3931 enum precedence this_prec = get_precedence ();
3933 /* If this_prec has stronger precedence than outer_prec, we don't
3934 need to wrap this in parens within the outer debug string.
3935 Stronger precedences occur earlier than weaker within the enum,
3936 so this is a less than test. Equal precedences don't need
3937 parentheses. */
3938 if (this_prec <= outer_prec)
3939 return get_debug_string();
3941 /* Otherwise, we need parentheses. */
3943 /* Lazily-build and cache m_parenthesized_string. */
3944 if (!m_parenthesized_string)
3946 const char *debug_string = get_debug_string ();
3947 m_parenthesized_string = string::from_printf (get_context (),
3948 "(%s)",
3949 debug_string);
3951 gcc_assert (m_parenthesized_string);
3952 return m_parenthesized_string->c_str ();
3956 /* The implementation of class gcc::jit::recording::lvalue. */
3958 /* Create a recording::new_access_field_of_lvalue instance and add it to
3959 the lvalue's context's list of mementos.
3961 Implements the post-error-checking part of
3962 gcc_jit_lvalue_access_field. */
3964 recording::lvalue *
3965 recording::lvalue::access_field (recording::location *loc,
3966 field *field)
3968 recording::lvalue *result =
3969 new access_field_of_lvalue (m_ctxt, loc, this, field);
3970 m_ctxt->record (result);
3971 return result;
3974 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3975 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3976 upcast call. */
3978 const char *
3979 recording::lvalue::access_as_rvalue (reproducer &r)
3981 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3982 r.get_identifier (this));
3985 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3986 Instances of lvalue don't need to be upcast. */
3988 const char *
3989 recording::lvalue::access_as_lvalue (reproducer &r)
3991 return r.get_identifier (this);
3994 /* Create a recording::get_address_of_lvalue instance and add it to
3995 the lvalue's context's list of mementos.
3997 Implements the post-error-checking part of
3998 gcc_jit_lvalue_get_address. */
4000 recording::rvalue *
4001 recording::lvalue::get_address (recording::location *loc)
4003 recording::rvalue *result =
4004 new get_address_of_lvalue (m_ctxt, loc, this);
4005 m_ctxt->record (result);
4006 return result;
4009 void
4010 recording::lvalue::set_tls_model (enum gcc_jit_tls_model model)
4012 m_tls_model = model;
4015 void recording::lvalue::set_link_section (const char *name)
4017 m_link_section = new_string (name);
4020 void recording::lvalue::set_register_name (const char *reg_name)
4022 m_reg_name = new_string (reg_name);
4025 void recording::lvalue::set_alignment (unsigned bytes)
4027 m_alignment = bytes;
4030 void recording::lvalue::add_string_attribute (
4031 gcc_jit_variable_attribute attribute,
4032 const char* value)
4034 m_string_attributes.push_back (std::make_pair (attribute, std::string (value)));
4037 /* The implementation of class gcc::jit::recording::param. */
4039 /* Implementation of pure virtual hook recording::memento::replay_into
4040 for recording::param. */
4042 void
4043 recording::param::replay_into (replayer *r)
4045 set_playback_obj (r->new_param (playback_location (r, m_loc),
4046 m_type->playback_type (),
4047 m_name->c_str ()));
4050 /* Implementation of recording::rvalue::access_as_rvalue for params.
4051 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
4052 upcast call. */
4054 const char *
4055 recording::param::access_as_rvalue (reproducer &r)
4057 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
4058 r.get_identifier (this));
4061 /* Implementation of recording::lvalue::access_as_lvalue for params.
4062 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
4063 upcast call. */
4065 const char *
4066 recording::param::access_as_lvalue (reproducer &r)
4068 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
4069 r.get_identifier (this));
4072 /* Implementation of recording::memento::write_reproducer for params. */
4074 void
4075 recording::param::write_reproducer (reproducer &r)
4077 const char *id = r.make_identifier (this, "param");
4078 r.write (" gcc_jit_param *%s =\n"
4079 " gcc_jit_context_new_param (%s,\n"
4080 " %s, /* gcc_jit_location *loc */\n"
4081 " %s, /*gcc_jit_type *type */\n"
4082 " %s); /* const char *name */\n",
4084 r.get_identifier (get_context ()),
4085 r.get_identifier (m_loc),
4086 r.get_identifier_as_type (m_type),
4087 m_name->get_debug_string ());
4090 /* The implementation of class gcc::jit::recording::function. */
4092 /* gcc::jit::recording::function's constructor. */
4094 recording::function::function (context *ctxt,
4095 recording::location *loc,
4096 enum gcc_jit_function_kind kind,
4097 type *return_type,
4098 recording::string *name,
4099 int num_params,
4100 recording::param **params,
4101 int is_variadic,
4102 enum built_in_function builtin_id)
4103 : memento (ctxt),
4104 m_loc (loc),
4105 m_kind (kind),
4106 m_return_type (return_type),
4107 m_name (name),
4108 m_params (),
4109 m_is_variadic (is_variadic),
4110 m_builtin_id (builtin_id),
4111 m_locals (),
4112 m_blocks (),
4113 m_fn_ptr_type (NULL),
4114 m_attributes (),
4115 m_string_attributes (),
4116 m_int_array_attributes ()
4118 for (int i = 0; i< num_params; i++)
4120 param *param = params[i];
4121 gcc_assert (param);
4123 /* Associate each param with this function.
4125 Verify that the param doesn't already have a function. */
4126 if (param->get_scope ())
4128 /* We've already rejected attempts to reuse a param between
4129 different functions (within gcc_jit_context_new_function), so
4130 if the param *does* already have a function, it must be being
4131 reused within the params array for this function. We must
4132 produce an error for this reuse (blocking the compile), since
4133 otherwise we'd have an ICE later on. */
4134 gcc_assert (this == param->get_scope ());
4135 ctxt->add_error
4136 (loc,
4137 "gcc_jit_context_new_function:"
4138 " parameter %s (type: %s)"
4139 " is used more than once when creating function %s",
4140 param->get_debug_string (),
4141 param->get_type ()->get_debug_string (),
4142 name->c_str ());
4144 else
4146 /* The normal, non-error case: associate this function with the
4147 param. */
4148 param->set_scope (this);
4151 m_params.safe_push (param);
4155 /* Implementation of pure virtual hook recording::memento::replay_into
4156 for recording::function. */
4158 void
4159 recording::function::replay_into (replayer *r)
4161 /* Convert m_params to a vec of playback param. */
4162 auto_vec <playback::param *> params;
4163 int i;
4164 recording::param *param;
4165 params.create (m_params.length ());
4166 FOR_EACH_VEC_ELT (m_params, i, param)
4167 params.safe_push (param->playback_param ());
4169 set_playback_obj (r->new_function (playback_location (r, m_loc),
4170 m_kind,
4171 m_return_type->playback_type (),
4172 m_name->c_str (),
4173 &params,
4174 m_is_variadic,
4175 m_builtin_id,
4176 m_attributes,
4177 m_string_attributes,
4178 m_int_array_attributes));
4181 /* Create a recording::local instance and add it to
4182 the functions's context's list of mementos, and to the function's
4183 list of locals.
4185 Implements the post-error-checking part of
4186 gcc_jit_function_new_local. */
4188 recording::lvalue *
4189 recording::function::new_local (recording::location *loc,
4190 type *type,
4191 const char *name)
4193 local *result = new local (this, loc, type, new_string (name));
4194 m_ctxt->record (result);
4195 m_locals.safe_push (result);
4196 return result;
4199 /* Create a recording::block instance and add it to
4200 the functions's context's list of mementos, and to the function's
4201 list of blocks.
4203 Implements the post-error-checking part of
4204 gcc_jit_function_new_block. */
4206 recording::block*
4207 recording::function::new_block (const char *name)
4209 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
4211 recording::block *result =
4212 new recording::block (this, m_blocks.length (), new_string (name));
4213 m_ctxt->record (result);
4214 m_blocks.safe_push (result);
4215 return result;
4218 /* Override the default implementation of
4219 recording::memento::write_to_dump by dumping a C-like
4220 representation of the function; either like a prototype
4221 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
4222 all other kinds of function. */
4224 void
4225 recording::function::write_to_dump (dump &d)
4227 for (auto attr: m_attributes)
4229 const char* attribute = fn_attribute_to_string (attr);
4230 if (attribute)
4231 d.write ("__attribute(%s)__\n", attribute);
4233 for (auto attr: m_string_attributes)
4235 gcc_jit_fn_attribute& name = std::get<0>(attr);
4236 std::string& value = std::get<1>(attr);
4237 const char* attribute = fn_attribute_to_string (name);
4239 if (attribute)
4240 d.write ("__attribute(%s(\"%s\"))__\n", attribute, value.c_str());
4242 for (auto attr: m_int_array_attributes)
4244 gcc_jit_fn_attribute& name = std::get<0>(attr);
4245 std::vector<int>& values = std::get<1>(attr);
4246 const char* attribute = fn_attribute_to_string (name);
4247 if (attribute)
4249 d.write ("__attribute(%s(", attribute);
4250 for (size_t i = 0; i < values.size(); ++i)
4252 if (i > 0)
4253 d.write (", %d", values[i]);
4254 else
4255 d.write ("%d", values[i]);
4257 d.write ("))__\n");
4261 switch (m_kind)
4263 default: gcc_unreachable ();
4264 case GCC_JIT_FUNCTION_EXPORTED:
4265 case GCC_JIT_FUNCTION_IMPORTED:
4266 d.write ("extern ");
4267 break;
4268 case GCC_JIT_FUNCTION_INTERNAL:
4269 d.write ("static ");
4270 break;
4271 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
4272 d.write ("static inline ");
4273 break;
4275 d.write ("%s\n", m_return_type->get_debug_string ());
4277 if (d.update_locations ())
4278 m_loc = d.make_location ();
4280 d.write ("%s (", get_debug_string ());
4282 int i;
4283 recording::param *param;
4284 FOR_EACH_VEC_ELT (m_params, i, param)
4286 if (i > 0)
4287 d.write (", ");
4288 d.write ("%s %s",
4289 param->get_type ()->get_debug_string (),
4290 param->get_debug_string ());
4292 d.write (")");
4293 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
4295 d.write ("; /* (imported) */\n\n");
4297 else
4299 int i;
4300 local *var = NULL;
4301 block *b;
4302 d.write ("\n{\n");
4304 /* Write locals: */
4305 FOR_EACH_VEC_ELT (m_locals, i, var)
4306 var->write_to_dump (d);
4307 if (m_locals.length ())
4308 d.write ("\n");
4310 /* Write each block: */
4311 FOR_EACH_VEC_ELT (m_blocks, i, b)
4313 if (i > 0)
4314 d.write ("\n");
4315 b->write_to_dump (d);
4318 d.write ("}\n\n");
4322 /* Pre-compilation validation of a function, for those things we can't
4323 check until the context is (supposedly) fully-populated. */
4325 void
4326 recording::function::validate ()
4328 /* Complain about empty functions with non-void return type. */
4329 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
4330 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
4331 if (m_blocks.length () == 0)
4332 m_ctxt->add_error (m_loc,
4333 "function %s returns non-void (type: %s)"
4334 " but has no blocks",
4335 get_debug_string (),
4336 m_return_type->get_debug_string ());
4338 /* Check that all blocks are terminated. */
4339 int num_invalid_blocks = 0;
4341 int i;
4342 block *b;
4344 FOR_EACH_VEC_ELT (m_blocks, i, b)
4345 if (!b->validate ())
4346 num_invalid_blocks++;
4349 /* Check that all blocks are reachable. */
4350 if (!m_ctxt->get_inner_bool_option
4351 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
4352 && m_blocks.length () > 0 && num_invalid_blocks == 0)
4354 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
4355 flag, starting at the initial block. */
4356 auto_vec<block *> worklist (m_blocks.length ());
4357 worklist.safe_push (m_blocks[0]);
4358 while (worklist.length () > 0)
4360 block *b = worklist.pop ();
4361 b->m_is_reachable = true;
4363 /* Add successor blocks that aren't yet marked to the worklist. */
4364 /* We checked that each block has a terminating statement above . */
4365 vec <block *> successors = b->get_successor_blocks ();
4366 int i;
4367 block *succ;
4368 FOR_EACH_VEC_ELT (successors, i, succ)
4369 if (!succ->m_is_reachable)
4370 worklist.safe_push (succ);
4371 successors.release ();
4374 /* Now complain about any blocks that haven't been marked. */
4376 int i;
4377 block *b;
4378 FOR_EACH_VEC_ELT (m_blocks, i, b)
4379 if (!b->m_is_reachable)
4380 m_ctxt->add_error (b->get_loc (),
4381 "unreachable block: %s",
4382 b->get_debug_string ());
4387 /* Implements the post-error-checking part of
4388 gcc_jit_function_dump_to_dot. */
4390 void
4391 recording::function::dump_to_dot (const char *path)
4393 FILE *fp = fopen (path, "w");
4394 if (!fp)
4395 return;
4397 pretty_printer the_pp;
4398 the_pp.buffer->stream = fp;
4400 pretty_printer *pp = &the_pp;
4402 pp_printf (pp, "digraph %s", get_debug_string ());
4403 pp_string (pp, " {\n");
4405 /* Blocks: */
4407 int i;
4408 block *b;
4409 FOR_EACH_VEC_ELT (m_blocks, i, b)
4410 b->dump_to_dot (pp);
4413 /* Edges: */
4415 int i;
4416 block *b;
4417 FOR_EACH_VEC_ELT (m_blocks, i, b)
4418 b->dump_edges_to_dot (pp);
4421 pp_string (pp, "}\n");
4422 pp_flush (pp);
4423 fclose (fp);
4426 /* Implements the post-error-checking part of
4427 gcc_jit_function_get_address. */
4429 recording::rvalue *
4430 recording::function::get_address (recording::location *loc)
4432 /* Lazily create and cache the function pointer type. */
4433 if (!m_fn_ptr_type)
4435 /* Make a recording::function_type for this function. */
4436 auto_vec <recording::type *> param_types (m_params.length ());
4437 unsigned i;
4438 recording::param *param;
4439 FOR_EACH_VEC_ELT (m_params, i, param)
4440 param_types.safe_push (param->get_type ());
4441 recording::function_type *fn_type
4442 = m_ctxt->new_function_type (m_return_type,
4443 m_params.length (),
4444 param_types.address (),
4445 m_is_variadic);
4446 m_fn_ptr_type = fn_type->get_pointer ();
4448 gcc_assert (m_fn_ptr_type);
4450 rvalue *result = new function_pointer (get_context (), loc, this, m_fn_ptr_type);
4451 m_ctxt->record (result);
4452 return result;
4455 void
4456 recording::function::add_attribute (gcc_jit_fn_attribute attribute)
4458 m_attributes.push_back (attribute);
4461 void
4462 recording::function::add_string_attribute (gcc_jit_fn_attribute attribute,
4463 const char* value)
4465 m_string_attributes.push_back (
4466 std::make_pair (attribute, std::string (value)));
4469 void
4470 recording::function::add_integer_array_attribute (
4471 gcc_jit_fn_attribute attribute,
4472 const int* value,
4473 size_t length)
4475 m_int_array_attributes.push_back (std::make_pair (
4476 attribute,
4477 std::vector<int> (value, value + length)));
4480 /* Implementation of recording::memento::make_debug_string for
4481 functions. */
4483 recording::string *
4484 recording::function::make_debug_string ()
4486 return m_name;
4489 /* A table of enum gcc_jit_function_kind values expressed in string
4490 form. */
4492 static const char * const names_of_function_kinds[] = {
4493 "GCC_JIT_FUNCTION_EXPORTED",
4494 "GCC_JIT_FUNCTION_INTERNAL",
4495 "GCC_JIT_FUNCTION_IMPORTED",
4496 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
4499 /* Implementation of recording::memento::write_reproducer for functions. */
4501 static const char * const fn_attribute_reproducer_strings[] =
4503 "GCC_JIT_FN_ATTRIBUTE_ALIAS",
4504 "GCC_JIT_FN_ATTRIBUTE_ALWAYS_INLINE",
4505 "GCC_JIT_FN_ATTRIBUTE_INLINE",
4506 "GCC_JIT_FN_ATTRIBUTE_NOINLINE",
4507 "GCC_JIT_FN_ATTRIBUTE_TARGET",
4508 "GCC_JIT_FN_ATTRIBUTE_USED",
4509 "GCC_JIT_FN_ATTRIBUTE_VISIBILITY",
4510 "GCC_JIT_FN_ATTRIBUTE_COLD",
4511 "GCC_JIT_FN_ATTRIBUTE_RETURNS_TWICE",
4512 "GCC_JIT_FN_ATTRIBUTE_PURE",
4513 "GCC_JIT_FN_ATTRIBUTE_CONST",
4514 "GCC_JIT_FN_ATTRIBUTE_WEAK",
4515 "GCC_JIT_FN_ATTRIBUTE_NONNULL",
4518 std::string
4519 get_vector_int_debug (std::vector<int> &values)
4521 std::stringstream s;
4523 s << "{";
4524 for(auto it = values.begin(); it != values.end(); ++it)
4526 if (it != values.begin() )
4527 s << ", ";
4528 s << *it;
4530 s << "}";
4531 return s.str();
4534 void
4535 recording::function::write_reproducer (reproducer &r)
4537 const char *id = r.make_identifier (this, "func");
4539 if (m_builtin_id)
4541 r.write (" gcc_jit_function *%s =\n"
4542 " gcc_jit_context_get_builtin_function (%s,\n"
4543 " %s);\n",
4545 r.get_identifier (get_context ()),
4546 m_name->get_debug_string ());
4547 return;
4549 const char *params_id = r.make_tmp_identifier ("params_for", this);
4550 r.write (" gcc_jit_param *%s[%i] = {\n",
4551 params_id,
4552 m_params.length ());
4553 int i;
4554 param *param;
4555 FOR_EACH_VEC_ELT (m_params, i, param)
4556 r.write (" %s,\n", r.get_identifier (param));
4557 r.write (" };\n");
4558 r.write (" gcc_jit_function *%s =\n"
4559 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
4560 " %s, /* gcc_jit_location *loc */\n"
4561 " %s, /* enum gcc_jit_function_kind kind */\n"
4562 " %s, /* gcc_jit_type *return_type */\n"
4563 " %s, /* const char *name */\n"
4564 " %i, /* int num_params */\n"
4565 " %s, /* gcc_jit_param **params */\n"
4566 " %i); /* int is_variadic */\n",
4568 r.get_identifier (get_context ()),
4569 r.get_identifier (m_loc),
4570 names_of_function_kinds[m_kind],
4571 r.get_identifier_as_type (m_return_type),
4572 m_name->get_debug_string (),
4573 m_params.length (),
4574 params_id,
4575 m_is_variadic);
4576 for (auto attribute : m_attributes)
4577 r.write(" gcc_jit_function_add_attribute (%s, %s);\n",
4579 fn_attribute_reproducer_strings[attribute]);
4580 for (auto attribute : m_string_attributes)
4581 r.write(" gcc_jit_function_add_string_attribute (%s, %s, \"%s\");\n",
4583 fn_attribute_reproducer_strings[std::get<0>(attribute)],
4584 std::get<1>(attribute).c_str());
4585 for (auto attribute : m_int_array_attributes) {
4586 r.write(" gcc_jit_function_add_integer_array_attribute (%s,\n"
4587 " %s,\n"
4588 " (int[])%s,\n"
4589 " %lu);\n",
4591 fn_attribute_reproducer_strings[std::get<0>(attribute)],
4592 get_vector_int_debug (std::get<1>(attribute)).c_str(),
4593 std::get<1>(attribute).size ());
4598 /* The implementation of class gcc::jit::recording::block. */
4600 /* Create a recording::eval instance and add it to
4601 the block's context's list of mementos, and to the block's
4602 list of statements.
4604 Implements the heart of gcc_jit_block_add_eval. */
4606 recording::statement *
4607 recording::block::add_eval (recording::location *loc,
4608 recording::rvalue *rvalue)
4610 statement *result = new eval (this, loc, rvalue);
4611 m_ctxt->record (result);
4612 m_statements.safe_push (result);
4613 return result;
4616 /* Create a recording::assignment instance and add it to
4617 the block's context's list of mementos, and to the block's
4618 list of statements.
4620 Implements the heart of gcc_jit_block_add_assignment. */
4622 recording::statement *
4623 recording::block::add_assignment (recording::location *loc,
4624 recording::lvalue *lvalue,
4625 recording::rvalue *rvalue)
4627 statement *result = new assignment (this, loc, lvalue, rvalue);
4628 m_ctxt->record (result);
4629 m_statements.safe_push (result);
4630 return result;
4633 /* Create a recording::assignment_op instance and add it to
4634 the block's context's list of mementos, and to the block's
4635 list of statements.
4637 Implements the heart of gcc_jit_block_add_assignment_op. */
4639 recording::statement *
4640 recording::block::add_assignment_op (recording::location *loc,
4641 recording::lvalue *lvalue,
4642 enum gcc_jit_binary_op op,
4643 recording::rvalue *rvalue)
4645 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
4646 m_ctxt->record (result);
4647 m_statements.safe_push (result);
4648 return result;
4651 /* Create a recording::comment instance and add it to
4652 the block's context's list of mementos, and to the block's
4653 list of statements.
4655 Implements the heart of gcc_jit_block_add_comment. */
4657 recording::statement *
4658 recording::block::add_comment (recording::location *loc,
4659 const char *text)
4661 statement *result = new comment (this, loc, new_string (text));
4662 m_ctxt->record (result);
4663 m_statements.safe_push (result);
4664 return result;
4667 /* Create a recording::extended_asm_simple instance and add it to
4668 the block's context's list of mementos, and to the block's
4669 list of statements.
4671 Implements the heart of gcc_jit_block_add_extended_asm. */
4673 recording::extended_asm *
4674 recording::block::add_extended_asm (location *loc,
4675 const char *asm_template)
4677 extended_asm *result
4678 = new extended_asm_simple (this, loc, new_string (asm_template));
4679 m_ctxt->record (result);
4680 m_statements.safe_push (result);
4681 return result;
4684 /* Create a recording::end_with_conditional instance and add it to
4685 the block's context's list of mementos, and to the block's
4686 list of statements.
4688 Implements the heart of gcc_jit_block_end_with_conditional. */
4690 recording::statement *
4691 recording::block::end_with_conditional (recording::location *loc,
4692 recording::rvalue *boolval,
4693 recording::block *on_true,
4694 recording::block *on_false)
4696 statement *result = new conditional (this, loc, boolval, on_true, on_false);
4697 m_ctxt->record (result);
4698 m_statements.safe_push (result);
4699 m_has_been_terminated = true;
4700 return result;
4703 /* Create a recording::end_with_jump instance and add it to
4704 the block's context's list of mementos, and to the block's
4705 list of statements.
4707 Implements the heart of gcc_jit_block_end_with_jump. */
4709 recording::statement *
4710 recording::block::end_with_jump (recording::location *loc,
4711 recording::block *target)
4713 statement *result = new jump (this, loc, target);
4714 m_ctxt->record (result);
4715 m_statements.safe_push (result);
4716 m_has_been_terminated = true;
4717 return result;
4720 /* Create a recording::end_with_return instance and add it to
4721 the block's context's list of mementos, and to the block's
4722 list of statements.
4724 Implements the post-error-checking parts of
4725 gcc_jit_block_end_with_return and
4726 gcc_jit_block_end_with_void_return. */
4728 recording::statement *
4729 recording::block::end_with_return (recording::location *loc,
4730 recording::rvalue *rvalue)
4732 /* This is used by both gcc_jit_function_add_return and
4733 gcc_jit_function_add_void_return; rvalue will be non-NULL for
4734 the former and NULL for the latter. */
4735 statement *result = new return_ (this, loc, rvalue);
4736 m_ctxt->record (result);
4737 m_statements.safe_push (result);
4738 m_has_been_terminated = true;
4739 return result;
4742 /* Create a recording::switch_ instance and add it to
4743 the block's context's list of mementos, and to the block's
4744 list of statements.
4746 Implements the heart of gcc_jit_block_end_with_switch. */
4748 recording::statement *
4749 recording::block::end_with_switch (recording::location *loc,
4750 recording::rvalue *expr,
4751 recording::block *default_block,
4752 int num_cases,
4753 recording::case_ **cases)
4755 statement *result = new switch_ (this, loc,
4756 expr,
4757 default_block,
4758 num_cases,
4759 cases);
4760 m_ctxt->record (result);
4761 m_statements.safe_push (result);
4762 m_has_been_terminated = true;
4763 return result;
4766 /* Create a recording::extended_asm_goto instance and add it to
4767 the block's context's list of mementos, and to the block's
4768 list of statements.
4770 Implements the heart of gcc_jit_block_end_with_extended_asm_goto. */
4773 recording::extended_asm *
4774 recording::block::end_with_extended_asm_goto (location *loc,
4775 const char *asm_template,
4776 int num_goto_blocks,
4777 block **goto_blocks,
4778 block *fallthrough_block)
4780 extended_asm *result
4781 = new extended_asm_goto (this, loc, new_string (asm_template),
4782 num_goto_blocks, goto_blocks,
4783 fallthrough_block);
4784 m_ctxt->record (result);
4785 m_statements.safe_push (result);
4786 m_has_been_terminated = true;
4787 return result;
4790 /* Override the default implementation of
4791 recording::memento::write_to_dump for blocks by writing
4792 an unindented block name as a label, followed by the indented
4793 statements:
4795 BLOCK_NAME:
4796 STATEMENT_1;
4797 STATEMENT_2;
4799 STATEMENT_N; */
4801 void
4802 recording::block::write_to_dump (dump &d)
4804 d.write ("%s:\n", get_debug_string ());
4806 int i;
4807 statement *s;
4808 FOR_EACH_VEC_ELT (m_statements, i, s)
4809 s->write_to_dump (d);
4812 /* Validate a block by ensuring that it has been terminated. */
4814 bool
4815 recording::block::validate ()
4817 /* Check for termination. */
4818 if (!has_been_terminated ())
4820 statement *stmt = get_last_statement ();
4821 location *loc = stmt ? stmt->get_loc () : NULL;
4822 m_func->get_context ()->add_error (loc,
4823 "unterminated block in %s: %s",
4824 m_func->get_debug_string (),
4825 get_debug_string ());
4826 return false;
4829 return true;
4832 /* Get the source-location of a block by using that of the first
4833 statement within it, if any. */
4835 recording::location *
4836 recording::block::get_loc () const
4838 recording::statement *stmt = get_first_statement ();
4839 if (stmt)
4840 return stmt->get_loc ();
4841 else
4842 return NULL;
4845 /* Get the first statement within a block, if any. */
4847 recording::statement *
4848 recording::block::get_first_statement () const
4850 if (m_statements.length ())
4851 return m_statements[0];
4852 else
4853 return NULL;
4856 /* Get the last statement within a block, if any. */
4858 recording::statement *
4859 recording::block::get_last_statement () const
4861 if (m_statements.length ())
4862 return m_statements[m_statements.length () - 1];
4863 else
4864 return NULL;
4867 /* Assuming that this block has been terminated, get the successor blocks
4868 as a vector. Ownership of the vector transfers to the caller, which
4869 must call its release () method.
4871 Used when validating functions, and when dumping dot representations
4872 of them. */
4874 vec <recording::block *>
4875 recording::block::get_successor_blocks () const
4877 gcc_assert (m_has_been_terminated);
4878 statement *last_statement = get_last_statement ();
4879 gcc_assert (last_statement);
4880 return last_statement->get_successor_blocks ();
4883 /* Implementation of pure virtual hook recording::memento::replay_into
4884 for recording::block. */
4886 void
4887 recording::block::replay_into (replayer *)
4889 set_playback_obj (m_func->playback_function ()
4890 ->new_block (playback_string (m_name)));
4893 /* Implementation of recording::memento::make_debug_string for
4894 blocks. */
4896 recording::string *
4897 recording::block::make_debug_string ()
4899 if (m_name)
4900 return m_name;
4901 else
4902 return string::from_printf (m_ctxt,
4903 "<UNNAMED BLOCK %p>",
4904 (void *)this);
4907 /* Implementation of recording::memento::write_reproducer for blocks. */
4909 void
4910 recording::block::write_reproducer (reproducer &r)
4912 const char *id = r.make_identifier (this, "block");
4913 r.write (" gcc_jit_block *%s =\n"
4914 " gcc_jit_function_new_block (%s, %s);\n",
4916 r.get_identifier (m_func),
4917 m_name ? m_name->get_debug_string () : "NULL");
4920 /* Disable warnings about missing quoting in GCC diagnostics for
4921 the pp_printf calls. Their format strings deliberately don't
4922 follow GCC diagnostic conventions. */
4923 #if __GNUC__ >= 10
4924 # pragma GCC diagnostic push
4925 # pragma GCC diagnostic ignored "-Wformat-diag"
4926 #endif
4928 /* Dump a block in graphviz form into PP, capturing the block name (if
4929 any) and the statements. */
4931 void
4932 recording::block::dump_to_dot (pretty_printer *pp)
4934 pp_printf (pp,
4935 ("\tblock_%d "
4936 "[shape=record,style=filled,fillcolor=white,label=\"{"),
4937 m_index);
4938 pp_write_text_to_stream (pp);
4939 if (m_name)
4941 pp_string (pp, m_name->c_str ());
4942 pp_string (pp, ":");
4943 pp_newline (pp);
4944 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4947 int i;
4948 statement *s;
4949 FOR_EACH_VEC_ELT (m_statements, i, s)
4951 pp_string (pp, s->get_debug_string ());
4952 pp_newline (pp);
4953 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4956 pp_string (pp,
4957 "}\"];\n\n");
4958 pp_flush (pp);
4961 /* Dump the out-edges of the block in graphviz form into PP. */
4963 void
4964 recording::block::dump_edges_to_dot (pretty_printer *pp)
4966 vec <block *> successors = get_successor_blocks ();
4967 int i;
4968 block *succ;
4969 FOR_EACH_VEC_ELT (successors, i, succ)
4970 pp_printf (pp,
4971 "\tblock_%d:s -> block_%d:n;\n",
4972 m_index, succ->m_index);
4973 successors.release ();
4976 #if __GNUC__ >= 10
4977 # pragma GCC diagnostic pop
4978 #endif
4980 namespace recording {
4981 static const enum tls_model tls_models[] = {
4982 TLS_MODEL_NONE, /* GCC_JIT_TLS_MODEL_NONE */
4983 TLS_MODEL_GLOBAL_DYNAMIC, /* GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC */
4984 TLS_MODEL_LOCAL_DYNAMIC, /* GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC */
4985 TLS_MODEL_INITIAL_EXEC, /* GCC_JIT_TLS_MODEL_INITIAL_EXEC */
4986 TLS_MODEL_LOCAL_EXEC, /* GCC_JIT_TLS_MODEL_LOCAL_EXEC */
4988 } /* namespace recording */
4990 /* The implementation of class gcc::jit::recording::global. */
4992 /* Implementation of pure virtual hook recording::memento::replay_into
4993 for recording::global. */
4995 void
4996 recording::global::replay_into (replayer *r)
4998 playback::lvalue *global = m_initializer
4999 ? r->new_global_initialized (playback_location (r, m_loc),
5000 m_kind,
5001 m_type->playback_type (),
5002 m_type->dereference ()->get_size (),
5003 m_initializer_num_bytes
5004 / m_type->dereference ()->get_size (),
5005 m_initializer,
5006 playback_string (m_name),
5007 m_flags,
5008 m_string_attributes)
5009 : r->new_global (playback_location (r, m_loc),
5010 m_kind,
5011 m_type->playback_type (),
5012 playback_string (m_name),
5013 m_flags,
5014 m_string_attributes);
5016 if (m_tls_model != GCC_JIT_TLS_MODEL_NONE)
5017 global->set_tls_model (recording::tls_models[m_tls_model]);
5019 if (m_link_section != NULL)
5020 global->set_link_section (m_link_section->c_str ());
5022 if (m_reg_name != NULL)
5023 global->set_register_name (m_reg_name->c_str ());
5025 if (m_alignment != 0)
5026 global->set_alignment (m_alignment);
5028 set_playback_obj (global);
5031 /* Override the default implementation of
5032 recording::memento::write_to_dump for globals.
5033 This will be of the form:
5035 GCC_JIT_GLOBAL_EXPORTED:
5036 "TYPE NAME;"
5037 e.g. "int foo;"
5039 GCC_JIT_GLOBAL_INTERNAL:
5040 "static TYPE NAME;"
5041 e.g. "static int foo;"
5043 GCC_JIT_GLOBAL_IMPORTED:
5044 "extern TYPE NAME;"
5045 e.g. "extern int foo;"
5047 These are written to the top of the dump by
5048 recording::context::dump_to_file. */
5050 void
5051 recording::global::write_to_dump (dump &d)
5053 if (d.update_locations ())
5054 m_loc = d.make_location ();
5056 switch (m_kind)
5058 default:
5059 gcc_unreachable ();
5061 case GCC_JIT_GLOBAL_EXPORTED:
5062 break;
5064 case GCC_JIT_GLOBAL_INTERNAL:
5065 d.write ("static ");
5066 break;
5068 case GCC_JIT_GLOBAL_IMPORTED:
5069 d.write ("extern ");
5070 break;
5073 for (auto attr: m_string_attributes)
5075 gcc_jit_variable_attribute& name = std::get<0>(attr);
5076 std::string& value = std::get<1>(attr);
5077 const char* attribute = variable_attribute_to_string (name);
5079 if (attribute)
5080 d.write ("__attribute(%s(\"%s\"))__\n", attribute, value.c_str());
5082 d.write ("%s %s",
5083 m_type->get_debug_string (),
5084 get_debug_string ());
5086 if (!m_initializer && !m_rvalue_init)
5088 d.write (";\n");
5090 else if (m_initializer)
5092 d.write ("=\n { ");
5093 const unsigned char *p = (const unsigned char *)m_initializer;
5094 for (size_t i = 0; i < m_initializer_num_bytes; i++)
5096 d.write ("0x%x, ", p[i]);
5097 if (i && !(i % 64))
5098 d.write ("\n ");
5100 d.write ("};\n");
5102 else if (m_rvalue_init)
5104 d.write (" = ");
5105 d.write ("%s", m_rvalue_init->get_debug_string ());
5106 d.write (";\n");
5109 return;
5112 /* A table of enum gcc_jit_global_kind values expressed in string
5113 form. */
5115 static const char * const global_kind_reproducer_strings[] = {
5116 "GCC_JIT_GLOBAL_EXPORTED",
5117 "GCC_JIT_GLOBAL_INTERNAL",
5118 "GCC_JIT_GLOBAL_IMPORTED"
5121 template <typename T>
5122 void
5123 recording::global::write_initializer_reproducer (const char *id, reproducer &r)
5125 const char *init_id = r.make_tmp_identifier ("init_for", this);
5126 r.write (" %s %s[] =\n {",
5127 m_type->dereference ()->get_debug_string (),
5128 init_id);
5130 const T *p = (const T *)m_initializer;
5131 for (size_t i = 0; i < m_initializer_num_bytes / sizeof (T); i++)
5133 r.write ("%" PRIu64 ", ", (uint64_t)p[i]);
5134 if (i && !(i % 64))
5135 r.write ("\n ");
5137 r.write ("};\n");
5138 r.write (" gcc_jit_global_set_initializer (%s, %s, sizeof (%s));\n",
5139 id, init_id, init_id);
5142 /* Implementation of recording::memento::write_reproducer for globals. */
5144 static const char * const tls_model_enum_strings[] = {
5145 "GCC_JIT_TLS_MODEL_NONE",
5146 "GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC",
5147 "GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC",
5148 "GCC_JIT_TLS_MODEL_INITIAL_EXEC",
5149 "GCC_JIT_TLS_MODEL_LOCAL_EXEC",
5152 static const char * const gcc_jit_variable_attribute_enum_strings[] = {
5153 "GCC_JIT_VARIABLE_ATTRIBUTE_VISIBILITY",
5156 void
5157 recording::global::write_reproducer (reproducer &r)
5159 const char *id = r.make_identifier (this, "block");
5160 r.write (" gcc_jit_lvalue *%s =\n"
5161 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
5162 " %s, /* gcc_jit_location *loc */\n"
5163 " %s, /* enum gcc_jit_global_kind kind */\n"
5164 " %s, /* gcc_jit_type *type */\n"
5165 " %s); /* const char *name */\n",
5167 r.get_identifier (get_context ()),
5168 r.get_identifier (m_loc),
5169 global_kind_reproducer_strings[m_kind],
5170 r.get_identifier_as_type (get_type ()),
5171 m_name->get_debug_string ());
5173 if (m_tls_model != GCC_JIT_TLS_MODEL_NONE)
5174 r.write (" gcc_jit_lvalue_set_tls_model (%s, /* gcc_jit_lvalue *lvalue */\n"
5175 " %s); /* enum gcc_jit_tls_model model */\n",
5177 tls_model_enum_strings[m_tls_model]);
5179 if (m_link_section != NULL)
5180 r.write (" gcc_jit_lvalue_set_link_section (%s, /* gcc_jit_lvalue *lvalue */\n"
5181 " \"%s\"); /* */\n",
5183 m_link_section->c_str ());
5185 for (auto attribute : m_string_attributes)
5186 r.write(" gcc_jit_lvalue_add_string_attribute (%s, %s, \"%s\");\n",
5188 gcc_jit_variable_attribute_enum_strings[std::get<0>(attribute)],
5189 std::get<1>(attribute).c_str());
5192 if (m_initializer)
5193 switch (m_type->dereference ()->get_size ())
5195 case 1:
5196 write_initializer_reproducer<uint8_t> (id, r);
5197 break;
5198 case 2:
5199 write_initializer_reproducer<uint16_t> (id, r);
5200 break;
5201 case 4:
5202 write_initializer_reproducer<uint32_t> (id, r);
5203 break;
5204 case 8:
5205 write_initializer_reproducer<uint64_t> (id, r);
5206 break;
5207 default:
5208 /* This function is serving on sizes returned by 'get_size',
5209 these are all covered by the previous cases. */
5210 gcc_unreachable ();
5214 /* The implementation of the various const-handling classes:
5215 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
5217 /* Explicit specialization of the various mementos we're interested in. */
5218 template class recording::memento_of_new_rvalue_from_const <int>;
5219 template class recording::memento_of_new_rvalue_from_const <long>;
5220 template class recording::memento_of_new_rvalue_from_const <double>;
5221 template class recording::memento_of_new_rvalue_from_const <void *>;
5223 /* Implementation of the pure virtual hook recording::memento::replay_into
5224 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
5226 template <typename HOST_TYPE>
5227 void
5228 recording::
5229 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
5231 set_playback_obj
5232 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
5233 m_value));
5236 /* The make_debug_string and write_reproducer methods vary between the
5237 various
5238 memento_of_new_rvalue_from_const <HOST_TYPE>
5239 classes, so we explicitly write specializations of them.
5241 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
5242 namespaces are written out explicitly, which is why most of this file
5243 doesn't abbreviate things by entering the "recording" namespace.
5245 However, these specializations are required to be in the same namespace
5246 as the template, hence we now have to enter the gcc::jit::recording
5247 namespace. */
5249 namespace recording
5252 /* The make_debug_string specialization for <int>, which renders it as
5253 (TARGET_TYPE)LITERAL
5254 e.g.
5255 "(int)42". */
5257 template <>
5258 string *
5259 memento_of_new_rvalue_from_const <int>::make_debug_string ()
5261 return string::from_printf (m_ctxt,
5262 "(%s)%i",
5263 m_type->get_debug_string (),
5264 m_value);
5267 /* The get_wide_int specialization for <int>. */
5269 template <>
5270 bool
5271 memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const
5273 *out = wi::shwi (m_value, sizeof (m_value) * 8);
5274 return true;
5277 /* The write_reproducer specialization for <int>. */
5279 template <>
5280 void
5281 memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
5283 const char *id = r.make_identifier (this, "rvalue");
5284 r.write (" gcc_jit_rvalue *%s =\n"
5285 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
5286 " %s, /* gcc_jit_type *numeric_type */\n"
5287 " %i); /* int value */\n",
5289 r.get_identifier (get_context ()),
5290 r.get_identifier_as_type (m_type),
5291 m_value);
5294 /* The make_debug_string specialization for <long>, rendering it as
5295 (TARGET_TYPE)LITERAL
5296 e.g.
5297 "(long)42". */
5299 template <>
5300 string *
5301 memento_of_new_rvalue_from_const <long>::make_debug_string ()
5303 return string::from_printf (m_ctxt,
5304 "(%s)%li",
5305 m_type->get_debug_string (),
5306 m_value);
5309 /* The get_wide_int specialization for <long>. */
5311 template <>
5312 bool
5313 memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const
5315 *out = wi::shwi (m_value, sizeof (m_value) * 8);
5316 return true;
5319 /* The write_reproducer specialization for <long>. */
5321 template <>
5322 void
5323 recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
5325 const char *id = r.make_identifier (this, "rvalue");
5327 /* We have to special-case LONG_MIN, since e.g.
5328 -9223372036854775808L
5329 is parsed as
5330 -(9223372036854775808L)
5331 and hence we'd get:
5332 error: integer constant is so large that it is unsigned [-Werror]
5333 Workaround this by writing (LONG_MIN + 1) - 1. */
5334 if (m_value == LONG_MIN)
5336 r.write (" gcc_jit_rvalue *%s =\n"
5337 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
5338 " %s, /* gcc_jit_type *numeric_type */\n"
5339 " %ldL - 1); /* long value */\n",
5341 r.get_identifier (get_context ()),
5342 r.get_identifier_as_type (m_type),
5343 m_value + 1);
5344 return;
5347 r.write (" gcc_jit_rvalue *%s =\n"
5348 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
5349 " %s, /* gcc_jit_type *numeric_type */\n"
5350 " %ldL); /* long value */\n",
5352 r.get_identifier (get_context ()),
5353 r.get_identifier_as_type (m_type),
5354 m_value);
5357 /* The make_debug_string specialization for <double>, rendering it as
5358 (TARGET_TYPE)LITERAL
5359 e.g.
5360 "(float)42.0". */
5362 template <>
5363 string *
5364 memento_of_new_rvalue_from_const <double>::make_debug_string ()
5366 return string::from_printf (m_ctxt,
5367 "(%s)%f",
5368 m_type->get_debug_string (),
5369 m_value);
5372 /* The get_wide_int specialization for <double>. */
5374 template <>
5375 bool
5376 memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
5378 return false;
5381 /* The write_reproducer specialization for <double>. */
5383 template <>
5384 void
5385 recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
5387 const char *id = r.make_identifier (this, "rvalue");
5388 r.write (" gcc_jit_rvalue *%s =\n"
5389 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
5390 " %s, /* gcc_jit_type *numeric_type */\n"
5391 " %f); /* double value */\n",
5393 r.get_identifier (get_context ()),
5394 r.get_identifier_as_type (m_type),
5395 m_value);
5398 /* The make_debug_string specialization for <void *>, rendering it as
5399 (TARGET_TYPE)HEX
5400 e.g.
5401 "(int *)0xdeadbeef"
5403 Zero is rendered as NULL e.g.
5404 "(int *)NULL". */
5406 template <>
5407 string *
5408 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
5410 if (m_value != NULL)
5411 return string::from_printf (m_ctxt,
5412 "(%s)%p",
5413 m_type->get_debug_string (), m_value);
5414 else
5415 return string::from_printf (m_ctxt,
5416 "(%s)NULL",
5417 m_type->get_debug_string ());
5420 /* The get_wide_int specialization for <void *>. */
5422 template <>
5423 bool
5424 memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const
5426 return false;
5429 /* Implementation of recording::memento::write_reproducer for <void *>
5430 values. */
5432 template <>
5433 void
5434 memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
5436 const char *id = r.make_identifier (this, "rvalue");
5437 if (m_value)
5438 r.write (" gcc_jit_rvalue *%s =\n"
5439 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
5440 " %s, /* gcc_jit_type *pointer_type */\n"
5441 " (void *)%p); /* void *value */\n",
5443 r.get_identifier (get_context ()),
5444 r.get_identifier_as_type (m_type),
5445 m_value);
5446 else
5447 r.write (" gcc_jit_rvalue *%s =\n"
5448 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
5449 " %s); /* gcc_jit_type *pointer_type */\n",
5451 r.get_identifier (get_context ()),
5452 r.get_identifier_as_type (m_type));
5455 /* We're done specializing make_debug_string and write_reproducer, so we
5456 can exit the gcc::jit::recording namespace. */
5458 } // namespace recording
5460 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
5462 /* Implementation of pure virtual hook recording::memento::replay_into
5463 for recording::memento_of_new_string_literal. */
5465 void
5466 recording::memento_of_new_string_literal::replay_into (replayer *r)
5468 set_playback_obj (r->new_string_literal (m_value->c_str ()));
5471 /* Implementation of recording::memento::make_debug_string for
5472 string literals. */
5474 recording::string *
5475 recording::memento_of_new_string_literal::make_debug_string ()
5477 return string::from_printf (m_ctxt,
5478 "%s",
5479 m_value->get_debug_string ());
5482 /* Implementation of recording::memento::write_reproducer for string literal
5483 values. */
5485 void
5486 recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
5488 const char *id = r.make_identifier (this, "rvalue");
5489 r.write (" gcc_jit_rvalue *%s =\n"
5490 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
5491 " %s); /* const char *value */\n",
5493 r.get_identifier (get_context ()),
5494 m_value->get_debug_string ());
5497 /* The implementation of class
5498 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
5500 /* The constructor for
5501 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
5503 recording::memento_of_new_rvalue_from_vector::
5504 memento_of_new_rvalue_from_vector (context *ctxt,
5505 location *loc,
5506 vector_type *type,
5507 rvalue **elements)
5508 : rvalue (ctxt, loc, type),
5509 m_vector_type (type),
5510 m_elements ()
5512 for (unsigned i = 0; i < type->get_num_units (); i++)
5513 m_elements.safe_push (elements[i]);
5516 /* Implementation of pure virtual hook recording::memento::replay_into
5517 for recording::memento_of_new_rvalue_from_vector. */
5519 void
5520 recording::memento_of_new_rvalue_from_vector::replay_into (replayer *r)
5522 auto_vec<playback::rvalue *> playback_elements;
5523 playback_elements.create (m_elements.length ());
5524 for (unsigned i = 0; i< m_elements.length (); i++)
5525 playback_elements.safe_push (m_elements[i]->playback_rvalue ());
5527 set_playback_obj (r->new_rvalue_from_vector (playback_location (r, m_loc),
5528 m_type->playback_type (),
5529 playback_elements));
5532 /* Implementation of pure virtual hook recording::rvalue::visit_children
5533 for recording::memento_of_new_rvalue_from_vector. */
5535 void
5536 recording::memento_of_new_rvalue_from_vector::visit_children (rvalue_visitor *v)
5538 for (unsigned i = 0; i< m_elements.length (); i++)
5539 v->visit (m_elements[i]);
5542 /* Implementation of recording::memento::make_debug_string for
5543 vectors. */
5545 recording::string *
5546 recording::memento_of_new_rvalue_from_vector::make_debug_string ()
5548 comma_separated_string elements (m_elements, get_precedence ());
5550 /* Now build a string. */
5551 string *result = string::from_printf (m_ctxt,
5552 "{%s}",
5553 elements.as_char_ptr ());
5555 return result;
5559 /* Implementation of recording::memento::write_reproducer for
5560 vectors. */
5562 void
5563 recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer &r)
5565 const char *id = r.make_identifier (this, "vector");
5566 const char *elements_id = r.make_tmp_identifier ("elements_for_", this);
5567 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
5568 elements_id,
5569 m_elements.length ());
5570 for (unsigned i = 0; i< m_elements.length (); i++)
5571 r.write (" %s,\n", r.get_identifier_as_rvalue (m_elements[i]));
5572 r.write (" };\n");
5573 r.write (" gcc_jit_rvalue *%s =\n"
5574 " gcc_jit_context_new_rvalue_from_vector (%s, /* gcc_jit_context *ctxt */\n"
5575 " %s, /* gcc_jit_location *loc */\n"
5576 " %s, /* gcc_jit_type *vec_type */\n"
5577 " %i, /* size_t num_elements */ \n"
5578 " %s); /* gcc_jit_rvalue **elements*/\n",
5580 r.get_identifier (get_context ()),
5581 r.get_identifier (m_loc),
5582 r.get_identifier (m_vector_type),
5583 m_elements.length (),
5584 elements_id);
5587 void
5588 recording::ctor::visit_children (rvalue_visitor *v)
5590 for (unsigned int i = 0; i < m_values.length (); i++)
5591 v->visit (m_values[i]);
5594 recording::string *
5595 recording::ctor::make_debug_string ()
5597 //Make a compound literal-ish
5598 pretty_printer pp;
5600 pp_string (&pp, "(");
5601 pp_string (&pp, m_type->get_debug_string ());
5602 pp_string (&pp, ") {");
5604 size_t field_n = m_fields.length ();
5605 size_t values_n = m_values.length ();
5607 if (!field_n && !values_n)
5609 else if (!field_n && values_n)
5611 for (size_t i = 0; i < values_n; i++)
5613 if (m_values[i])
5614 pp_string (&pp, m_values[i]->get_debug_string ());
5615 else
5616 pp_string (&pp, "0");
5617 if (i + 1 != values_n)
5618 pp_string (&pp, ", ");
5621 else if (field_n && values_n)
5623 for (size_t i = 0; i < values_n; i++)
5625 pp_string (&pp, ".");
5626 pp_string (&pp, m_fields[i]->get_debug_string ());
5627 pp_string (&pp, "=");
5628 if (m_values[i])
5629 pp_string (&pp, m_values[i]->get_debug_string ());
5630 else
5631 pp_string (&pp, "0");
5632 if (i + 1 != values_n)
5633 pp_string (&pp, ", ");
5636 /* m_fields are never populated with m_values empty. */
5638 pp_string (&pp, "}");
5640 return new_string (pp_formatted_text (&pp));
5643 void
5644 recording::ctor::write_reproducer (reproducer &r)
5646 const char *id = r.make_identifier (this, "rvalue");
5647 type *type = get_type ();
5649 r.write (" gcc_jit_rvalue *%s;\n", id);
5650 r.write (" {\n"); /* Open scope for locals. */
5652 if (type->is_union ())
5654 if (m_values.length () == 0)
5655 r.write (" gcc_jit_rvalue *value = NULL;\n");
5656 else
5657 r.write (" gcc_jit_rvalue *value = %s;\n",
5658 r.get_identifier (m_values[0]));
5660 if (m_fields.length () == 0)
5661 r.write (" gcc_jit_field *field = NULL;\n");
5662 else
5663 r.write (" gcc_jit_field *field = %s;\n",
5664 r.get_identifier (m_fields[0]));
5666 else
5668 /* Write the array of values. */
5669 if (m_values.length () == 0)
5670 r.write (" gcc_jit_rvalue **values = NULL;\n");
5671 else
5673 r.write (" gcc_jit_rvalue *values[] = {\n");
5674 for (size_t i = 0; i < m_values.length (); i++)
5675 r.write (" %s,\n", r.get_identifier (m_values[i]));
5676 r.write (" };\n");
5678 /* Write the array of fields. */
5679 if (m_fields.length () == 0)
5680 r.write (" gcc_jit_field **fields = NULL;\n");
5681 else
5683 r.write (" gcc_jit_field *fields[] = {\n");
5684 for (size_t i = 0; i < m_fields.length (); i++)
5685 r.write (" %s,\n", r.get_identifier (m_fields[i]));
5686 r.write (" };\n");
5689 if (type->is_array ())
5690 r.write (
5691 " %s =\n"
5692 " gcc_jit_context_new_array_constructor (%s,\n"
5693 " %s, /* gcc_jit_location *loc */\n"
5694 " %s, /* gcc_jit_type *type */\n"
5695 " %i, /* int num_values */\n"
5696 " values);\n",
5698 r.get_identifier (get_context ()),
5699 r.get_identifier (m_loc),
5700 r.get_identifier_as_type (get_type ()),
5701 m_values.length ());
5702 else if (type->is_struct ())
5703 r.write (
5704 " %s =\n"
5705 " gcc_jit_context_new_struct_constructor (%s,\n"
5706 " %s, /* loc */\n"
5707 " %s, /* gcc_jit_type *type */\n"
5708 " %i, /* int num_values */\n"
5709 " fields,\n"
5710 " values);\n",
5712 r.get_identifier (get_context ()),
5713 r.get_identifier (m_loc),
5714 r.get_identifier_as_type (get_type ()),
5715 m_values.length ());
5716 else if (type->is_union ())
5717 r.write (
5718 " %s =\n"
5719 " gcc_jit_context_new_union_constructor (%s,\n"
5720 " %s, /* loc */\n"
5721 " %s, /* gcc_jit_type *type */\n"
5722 " field,\n"
5723 " value);\n",
5725 r.get_identifier (get_context ()),
5726 r.get_identifier (m_loc),
5727 r.get_identifier_as_type (get_type ()));
5728 else
5729 gcc_unreachable ();
5731 r.write (" }\n"); /* Close scope for locals. */
5734 void
5735 recording::ctor::replay_into (replayer *r)
5737 auto_vec<playback::rvalue *> playback_values;
5738 auto_vec<playback::field *> playback_fields;
5740 int n = m_values.length ();
5742 type *type = get_type ();
5744 /* Handle arrays, and return. */
5745 if (type->is_array ())
5747 playback_values.reserve (n, false);
5749 for (int i = 0; i < n; i++)
5751 /* null m_values element indicates zero ctor. */
5752 playback_values.quick_push (m_values[i] ?
5753 m_values[i]->playback_rvalue () :
5754 NULL);
5756 set_playback_obj (r->new_ctor (playback_location (r, m_loc),
5757 get_type ()->playback_type (),
5758 NULL,
5759 &playback_values));
5760 return;
5762 /* ... else handle unions and structs. */
5764 playback_values.reserve (n, false);
5765 playback_fields.reserve (n, false);
5767 for (int i = 0; i < n; i++)
5769 /* null m_values element indicates zero ctor. */
5770 playback_values.quick_push (m_values[i] ?
5771 m_values[i]->playback_rvalue () :
5772 NULL);
5773 playback_fields.quick_push (m_fields[i]->playback_field ());
5776 set_playback_obj (r->new_ctor (playback_location (r, m_loc),
5777 get_type ()->playback_type (),
5778 &playback_fields,
5779 &playback_values));
5782 /* The implementation of class gcc::jit::recording::unary_op. */
5784 /* Implementation of pure virtual hook recording::memento::replay_into
5785 for recording::unary_op. */
5787 void
5788 recording::unary_op::replay_into (replayer *r)
5790 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
5791 m_op,
5792 get_type ()->playback_type (),
5793 m_a->playback_rvalue ()));
5796 /* Implementation of pure virtual hook recording::rvalue::visit_children
5797 for recording::unary_op. */
5798 void
5799 recording::unary_op::visit_children (rvalue_visitor *v)
5801 v->visit (m_a);
5804 /* Implementation of recording::memento::make_debug_string for
5805 unary ops. */
5807 static const char * const unary_op_strings[] = {
5808 "-", /* GCC_JIT_UNARY_OP_MINUS */
5809 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
5810 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
5811 "abs ", /* GCC_JIT_UNARY_OP_ABS */
5814 recording::string *
5815 recording::unary_op::make_debug_string ()
5817 return string::from_printf (m_ctxt,
5818 "%s(%s)",
5819 unary_op_strings[m_op],
5820 m_a->get_debug_string ());
5823 const char * const unary_op_reproducer_strings[] = {
5824 "GCC_JIT_UNARY_OP_MINUS",
5825 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
5826 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
5827 "GCC_JIT_UNARY_OP_ABS"
5830 /* Implementation of recording::memento::write_reproducer for unary ops. */
5832 void
5833 recording::unary_op::write_reproducer (reproducer &r)
5835 const char *id = r.make_identifier (this, "rvalue");
5836 r.write (" gcc_jit_rvalue *%s =\n"
5837 " gcc_jit_context_new_unary_op (%s,\n"
5838 " %s, /* gcc_jit_location *loc */\n"
5839 " %s, /* enum gcc_jit_unary_op op */\n"
5840 " %s, /* gcc_jit_type *result_type */\n"
5841 " %s); /* gcc_jit_rvalue *a */\n",
5843 r.get_identifier (get_context ()),
5844 r.get_identifier (m_loc),
5845 unary_op_reproducer_strings[m_op],
5846 r.get_identifier_as_type (get_type ()),
5847 r.get_identifier_as_rvalue (m_a));
5850 /* The implementation of class gcc::jit::recording::binary_op. */
5852 /* Implementation of pure virtual hook recording::memento::replay_into
5853 for recording::binary_op. */
5855 void
5856 recording::binary_op::replay_into (replayer *r)
5858 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
5859 m_op,
5860 get_type ()->playback_type (),
5861 m_a->playback_rvalue (),
5862 m_b->playback_rvalue ()));
5865 /* Implementation of pure virtual hook recording::rvalue::visit_children
5866 for recording::binary_op. */
5867 void
5868 recording::binary_op::visit_children (rvalue_visitor *v)
5870 v->visit (m_a);
5871 v->visit (m_b);
5874 /* Implementation of recording::memento::make_debug_string for
5875 binary ops. */
5877 static const char * const binary_op_strings[] = {
5878 "+", /* GCC_JIT_BINARY_OP_PLUS */
5879 "-", /* GCC_JIT_BINARY_OP_MINUS */
5880 "*", /* GCC_JIT_BINARY_OP_MULT */
5881 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
5882 "%", /* GCC_JIT_BINARY_OP_MODULO */
5883 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
5884 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
5885 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
5886 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
5887 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
5888 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
5889 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
5892 recording::string *
5893 recording::binary_op::make_debug_string ()
5895 enum precedence prec = get_precedence ();
5896 return string::from_printf (m_ctxt,
5897 "%s %s %s",
5898 m_a->get_debug_string_parens (prec),
5899 binary_op_strings[m_op],
5900 m_b->get_debug_string_parens (prec));
5903 const char * const binary_op_reproducer_strings[] = {
5904 "GCC_JIT_BINARY_OP_PLUS",
5905 "GCC_JIT_BINARY_OP_MINUS",
5906 "GCC_JIT_BINARY_OP_MULT",
5907 "GCC_JIT_BINARY_OP_DIVIDE",
5908 "GCC_JIT_BINARY_OP_MODULO",
5909 "GCC_JIT_BINARY_OP_BITWISE_AND",
5910 "GCC_JIT_BINARY_OP_BITWISE_XOR",
5911 "GCC_JIT_BINARY_OP_BITWISE_OR",
5912 "GCC_JIT_BINARY_OP_LOGICAL_AND",
5913 "GCC_JIT_BINARY_OP_LOGICAL_OR",
5914 "GCC_JIT_BINARY_OP_LSHIFT",
5915 "GCC_JIT_BINARY_OP_RSHIFT"
5918 /* Implementation of recording::memento::write_reproducer for binary ops. */
5920 void
5921 recording::binary_op::write_reproducer (reproducer &r)
5923 const char *id = r.make_identifier (this, "rvalue");
5924 r.write (" gcc_jit_rvalue *%s =\n"
5925 " gcc_jit_context_new_binary_op (%s,\n"
5926 " %s, /* gcc_jit_location *loc */\n"
5927 " %s, /* enum gcc_jit_binary_op op */\n"
5928 " %s, /* gcc_jit_type *result_type */\n"
5929 " %s, /* gcc_jit_rvalue *a */\n"
5930 " %s); /* gcc_jit_rvalue *b */\n",
5932 r.get_identifier (get_context ()),
5933 r.get_identifier (m_loc),
5934 binary_op_reproducer_strings[m_op],
5935 r.get_identifier_as_type (get_type ()),
5936 r.get_identifier_as_rvalue (m_a),
5937 r.get_identifier_as_rvalue (m_b));
5940 namespace recording {
5941 static const enum precedence binary_op_precedence[] = {
5942 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
5943 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
5945 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
5946 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
5947 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
5949 PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
5950 PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
5951 PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
5952 PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
5953 PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
5954 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
5955 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
5957 } /* namespace recording */
5959 enum recording::precedence
5960 recording::binary_op::get_precedence () const
5962 return binary_op_precedence[m_op];
5965 /* The implementation of class gcc::jit::recording::comparison. */
5967 /* Implementation of recording::memento::make_debug_string for
5968 comparisons. */
5970 static const char * const comparison_strings[] =
5972 "==", /* GCC_JIT_COMPARISON_EQ */
5973 "!=", /* GCC_JIT_COMPARISON_NE */
5974 "<", /* GCC_JIT_COMPARISON_LT */
5975 "<=", /* GCC_JIT_COMPARISON_LE */
5976 ">", /* GCC_JIT_COMPARISON_GT */
5977 ">=", /* GCC_JIT_COMPARISON_GE */
5980 recording::string *
5981 recording::comparison::make_debug_string ()
5983 enum precedence prec = get_precedence ();
5984 return string::from_printf (m_ctxt,
5985 "%s %s %s",
5986 m_a->get_debug_string_parens (prec),
5987 comparison_strings[m_op],
5988 m_b->get_debug_string_parens (prec));
5991 /* A table of enum gcc_jit_comparison values expressed in string
5992 form. */
5994 static const char * const comparison_reproducer_strings[] =
5996 "GCC_JIT_COMPARISON_EQ",
5997 "GCC_JIT_COMPARISON_NE",
5998 "GCC_JIT_COMPARISON_LT",
5999 "GCC_JIT_COMPARISON_LE",
6000 "GCC_JIT_COMPARISON_GT",
6001 "GCC_JIT_COMPARISON_GE"
6004 /* Implementation of recording::memento::write_reproducer for comparisons. */
6006 void
6007 recording::comparison::write_reproducer (reproducer &r)
6009 const char *id = r.make_identifier (this, "rvalue");
6010 r.write (" gcc_jit_rvalue *%s =\n"
6011 " gcc_jit_context_new_comparison (%s,\n"
6012 " %s, /* gcc_jit_location *loc */\n"
6013 " %s, /* enum gcc_jit_comparison op */\n"
6014 " %s, /* gcc_jit_rvalue *a */\n"
6015 " %s); /* gcc_jit_rvalue *b */\n",
6017 r.get_identifier (get_context ()),
6018 r.get_identifier (m_loc),
6019 comparison_reproducer_strings[m_op],
6020 r.get_identifier_as_rvalue (m_a),
6021 r.get_identifier_as_rvalue (m_b));
6024 /* Implementation of pure virtual hook recording::memento::replay_into
6025 for recording::comparison. */
6027 void
6028 recording::comparison::replay_into (replayer *r)
6030 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
6031 m_op,
6032 m_a->playback_rvalue (),
6033 m_b->playback_rvalue (),
6034 m_type->playback_type ()));
6037 /* Implementation of pure virtual hook recording::rvalue::visit_children
6038 for recording::comparison. */
6040 void
6041 recording::comparison::visit_children (rvalue_visitor *v)
6043 v->visit (m_a);
6044 v->visit (m_b);
6047 namespace recording {
6048 static const enum precedence comparison_precedence[] =
6050 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
6051 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
6053 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LT */
6054 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
6055 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GT */
6056 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
6058 } /* namespace recording */
6060 enum recording::precedence
6061 recording::comparison::get_precedence () const
6063 return comparison_precedence[m_op];
6066 /* Implementation of pure virtual hook recording::memento::replay_into
6067 for recording::cast. */
6069 void
6070 recording::cast::replay_into (replayer *r)
6072 set_playback_obj (r->new_cast (playback_location (r, m_loc),
6073 m_rvalue->playback_rvalue (),
6074 get_type ()->playback_type ()));
6077 /* Implementation of pure virtual hook recording::rvalue::visit_children
6078 for recording::cast. */
6079 void
6080 recording::cast::visit_children (rvalue_visitor *v)
6082 v->visit (m_rvalue);
6085 /* Implementation of recording::memento::make_debug_string for
6086 casts. */
6088 recording::string *
6089 recording::cast::make_debug_string ()
6091 enum precedence prec = get_precedence ();
6092 return string::from_printf (m_ctxt,
6093 "(%s)%s",
6094 get_type ()->get_debug_string (),
6095 m_rvalue->get_debug_string_parens (prec));
6098 /* Implementation of recording::memento::write_reproducer for casts. */
6100 void
6101 recording::cast::write_reproducer (reproducer &r)
6103 const char *id = r.make_identifier (this, "rvalue");
6104 r.write (" gcc_jit_rvalue *%s =\n"
6105 " gcc_jit_context_new_cast (%s,\n"
6106 " %s, /* gcc_jit_location *loc */\n"
6107 " %s, /* gcc_jit_rvalue *rvalue */\n"
6108 " %s); /* gcc_jit_type *type */\n",
6110 r.get_identifier (get_context ()),
6111 r.get_identifier (m_loc),
6112 r.get_identifier_as_rvalue (m_rvalue),
6113 r.get_identifier_as_type (get_type ()));
6116 /* Implementation of pure virtual hook recording::memento::replay_into
6117 for recording::bitcast. */
6119 void
6120 recording::bitcast::replay_into (replayer *r)
6122 set_playback_obj (r->new_bitcast (playback_location (r, m_loc),
6123 m_rvalue->playback_rvalue (),
6124 get_type ()->playback_type ()));
6127 /* Implementation of pure virtual hook recording::rvalue::visit_children
6128 for recording::bitcast. */
6129 void
6130 recording::bitcast::visit_children (rvalue_visitor *v)
6132 v->visit (m_rvalue);
6135 /* Implementation of recording::memento::make_debug_string for
6136 casts. */
6138 recording::string *
6139 recording::bitcast::make_debug_string ()
6141 enum precedence prec = get_precedence ();
6142 return string::from_printf (m_ctxt,
6143 "bitcast(%s, %s)",
6144 m_rvalue->get_debug_string_parens (prec),
6145 get_type ()->get_debug_string ());
6148 /* Implementation of recording::memento::write_reproducer for casts. */
6150 void
6151 recording::bitcast::write_reproducer (reproducer &r)
6153 const char *id = r.make_identifier (this, "rvalue");
6154 r.write (" gcc_jit_rvalue *%s =\n"
6155 " gcc_jit_context_new_bitcast (%s,\n"
6156 " %s, /* gcc_jit_location *loc */\n"
6157 " %s, /* gcc_jit_rvalue *rvalue */\n"
6158 " %s); /* gcc_jit_type *type */\n",
6160 r.get_identifier (get_context ()),
6161 r.get_identifier (m_loc),
6162 r.get_identifier_as_rvalue (m_rvalue),
6163 r.get_identifier_as_type (get_type ()));
6166 /* The implementation of class gcc::jit::recording::base_call. */
6168 /* The constructor for gcc::jit::recording::base_call. */
6170 recording::base_call::base_call (context *ctxt,
6171 location *loc,
6172 type *type_,
6173 int numargs,
6174 rvalue **args)
6175 : rvalue (ctxt, loc, type_),
6176 m_args (),
6177 m_require_tail_call (0)
6179 for (int i = 0; i< numargs; i++)
6180 m_args.safe_push (args[i]);
6183 /* Subroutine for use by call and call_though_ptr's write_reproducer
6184 methods. */
6186 void
6187 recording::base_call::write_reproducer_tail_call (reproducer &r,
6188 const char *id)
6190 if (m_require_tail_call)
6192 r.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
6193 " %i); /* int require_tail_call*/\n",
6199 /* The implementation of class gcc::jit::recording::call. */
6201 /* The constructor for gcc::jit::recording::call. */
6203 recording::call::call (recording::context *ctxt,
6204 recording::location *loc,
6205 recording::function *func,
6206 int numargs,
6207 rvalue **args)
6208 : base_call (ctxt, loc, func->get_return_type (), numargs, args),
6209 m_func (func)
6213 /* Implementation of pure virtual hook recording::memento::replay_into
6214 for recording::call. */
6216 void
6217 recording::call::replay_into (replayer *r)
6219 auto_vec<playback::rvalue *> playback_args;
6220 playback_args.create (m_args.length ());
6221 for (unsigned i = 0; i< m_args.length (); i++)
6222 playback_args.safe_push (m_args[i]->playback_rvalue ());
6224 set_playback_obj (r->new_call (playback_location (r, m_loc),
6225 m_func->playback_function (),
6226 &playback_args,
6227 m_require_tail_call));
6230 /* Implementation of pure virtual hook recording::rvalue::visit_children
6231 for recording::call. */
6233 void
6234 recording::call::visit_children (rvalue_visitor *v)
6236 for (unsigned i = 0; i< m_args.length (); i++)
6237 v->visit (m_args[i]);
6240 /* Implementation of recording::memento::make_debug_string for
6241 function calls. */
6243 recording::string *
6244 recording::call::make_debug_string ()
6246 /* First, build a buffer for the arguments. */
6247 comma_separated_string args (m_args, get_precedence ());
6249 /* ...and use it to get the string for the call as a whole. */
6250 string *result = string::from_printf (m_ctxt,
6251 "%s (%s)",
6252 m_func->get_debug_string (),
6253 args.as_char_ptr ());
6255 return result;
6258 void
6259 recording::call::write_reproducer (reproducer &r)
6261 const char *id = r.make_identifier (this, "call");
6262 const char *args_id = r.make_tmp_identifier ("args_for_", this);
6263 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
6264 args_id,
6265 m_args.length ());
6266 for (unsigned i = 0; i< m_args.length (); i++)
6267 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
6268 r.write (" };\n");
6269 r.write (" gcc_jit_rvalue *%s =\n"
6270 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
6271 " %s, /* gcc_jit_location *loc */\n"
6272 " %s, /* gcc_jit_function *func */\n"
6273 " %i, /* int numargs */ \n"
6274 " %s); /* gcc_jit_rvalue **args*/\n",
6276 r.get_identifier (get_context ()),
6277 r.get_identifier (m_loc),
6278 r.get_identifier (m_func),
6279 m_args.length (),
6280 args_id);
6281 write_reproducer_tail_call (r, id);
6284 /* The implementation of class gcc::jit::recording::call_through_ptr. */
6286 /* The constructor for recording::call_through_ptr. */
6288 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
6289 recording::location *loc,
6290 recording::rvalue *fn_ptr,
6291 int numargs,
6292 rvalue **args)
6293 : base_call (ctxt, loc,
6294 fn_ptr->get_type ()->dereference ()
6295 ->as_a_function_type ()->get_return_type (),
6296 numargs, args),
6297 m_fn_ptr (fn_ptr)
6301 /* Implementation of pure virtual hook recording::memento::replay_into
6302 for recording::call_through_ptr. */
6304 void
6305 recording::call_through_ptr::replay_into (replayer *r)
6307 auto_vec<playback::rvalue *> playback_args;
6308 playback_args.create (m_args.length ());
6309 for (unsigned i = 0; i< m_args.length (); i++)
6310 playback_args.safe_push (m_args[i]->playback_rvalue ());
6312 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
6313 m_fn_ptr->playback_rvalue (),
6314 &playback_args,
6315 m_require_tail_call));
6318 /* Implementation of pure virtual hook recording::rvalue::visit_children
6319 for recording::call_through_ptr. */
6321 void
6322 recording::call_through_ptr::visit_children (rvalue_visitor *v)
6324 v->visit (m_fn_ptr);
6325 for (unsigned i = 0; i< m_args.length (); i++)
6326 v->visit (m_args[i]);
6329 /* Implementation of recording::memento::make_debug_string for
6330 calls through function ptrs. */
6332 recording::string *
6333 recording::call_through_ptr::make_debug_string ()
6335 enum precedence prec = get_precedence ();
6336 /* First, build a buffer for the arguments. */
6337 /* Calculate length of said buffer. */
6338 size_t sz = 1; /* nil terminator */
6339 for (unsigned i = 0; i< m_args.length (); i++)
6341 sz += strlen (m_args[i]->get_debug_string_parens (prec));
6342 sz += 2; /* ", " separator */
6345 /* Now allocate and populate the buffer. */
6346 char *argbuf = new char[sz];
6347 size_t len = 0;
6349 for (unsigned i = 0; i< m_args.length (); i++)
6351 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
6352 len += strlen (m_args[i]->get_debug_string_parens (prec));
6353 if (i + 1 < m_args.length ())
6355 strcpy (argbuf + len, ", ");
6356 len += 2;
6359 argbuf[len] = '\0';
6361 /* ...and use it to get the string for the call as a whole. */
6362 string *result = string::from_printf (m_ctxt,
6363 "%s (%s)",
6364 m_fn_ptr->get_debug_string_parens (prec),
6365 argbuf);
6367 delete[] argbuf;
6369 return result;
6372 /* Implementation of recording::memento::write_reproducer for
6373 call_through_ptr. */
6375 void
6376 recording::call_through_ptr::write_reproducer (reproducer &r)
6378 const char *id = r.make_identifier (this, "call");
6379 const char *args_id = r.make_tmp_identifier ("args_for_", this);
6380 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
6381 args_id,
6382 m_args.length ());
6383 for (unsigned i = 0; i< m_args.length (); i++)
6384 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
6385 r.write (" };\n");
6386 r.write (" gcc_jit_rvalue *%s =\n"
6387 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
6388 " %s, /* gcc_jit_location *loc */\n"
6389 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
6390 " %i, /* int numargs */ \n"
6391 " %s); /* gcc_jit_rvalue **args*/\n",
6393 r.get_identifier (get_context ()),
6394 r.get_identifier (m_loc),
6395 r.get_identifier_as_rvalue (m_fn_ptr),
6396 m_args.length (),
6397 args_id);
6398 write_reproducer_tail_call (r, id);
6401 /* The implementation of class gcc::jit::recording::array_access. */
6403 /* Implementation of pure virtual hook recording::memento::replay_into
6404 for recording::array_access. */
6406 void
6407 recording::array_access::replay_into (replayer *r)
6409 set_playback_obj (
6410 r->new_array_access (playback_location (r, m_loc),
6411 m_ptr->playback_rvalue (),
6412 m_index->playback_rvalue ()));
6415 /* Implementation of pure virtual hook recording::rvalue::visit_children
6416 for recording::array_access. */
6418 void
6419 recording::array_access::visit_children (rvalue_visitor *v)
6421 v->visit (m_ptr);
6422 v->visit (m_index);
6425 /* Implementation of recording::memento::make_debug_string for
6426 array accesses. */
6428 recording::string *
6429 recording::array_access::make_debug_string ()
6431 enum precedence prec = get_precedence ();
6432 return string::from_printf (m_ctxt,
6433 "%s[%s]",
6434 m_ptr->get_debug_string_parens (prec),
6435 m_index->get_debug_string_parens (prec));
6438 /* Implementation of recording::memento::write_reproducer for
6439 array_access. */
6441 void
6442 recording::array_access::write_reproducer (reproducer &r)
6444 const char *id = r.make_identifier (this, "lvalue");
6445 r.write (" gcc_jit_lvalue *%s = \n"
6446 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
6447 " %s, /*gcc_jit_location *loc */\n"
6448 " %s, /* gcc_jit_rvalue *ptr */\n"
6449 " %s); /* gcc_jit_rvalue *index */\n",
6451 r.get_identifier (get_context ()),
6452 r.get_identifier (m_loc),
6453 r.get_identifier_as_rvalue (m_ptr),
6454 r.get_identifier_as_rvalue (m_index));
6457 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
6459 /* Implementation of pure virtual hook recording::memento::replay_into
6460 for recording::access_field_of_lvalue. */
6462 void
6463 recording::access_field_of_lvalue::replay_into (replayer *r)
6465 set_playback_obj (
6466 m_lvalue->playback_lvalue ()
6467 ->access_field (playback_location (r, m_loc),
6468 m_field->playback_field ()));
6472 /* Implementation of pure virtual hook recording::rvalue::visit_children
6473 for recording::access_field_of_lvalue. */
6475 void
6476 recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
6478 v->visit (m_lvalue);
6481 /* Implementation of recording::memento::make_debug_string for
6482 accessing a field of an lvalue. */
6484 recording::string *
6485 recording::access_field_of_lvalue::make_debug_string ()
6487 enum precedence prec = get_precedence ();
6488 return string::from_printf (m_ctxt,
6489 "%s.%s",
6490 m_lvalue->get_debug_string_parens (prec),
6491 m_field->get_debug_string ());
6494 /* Implementation of recording::memento::write_reproducer for
6495 access_field_of_lvalue. */
6497 void
6498 recording::access_field_of_lvalue::write_reproducer (reproducer &r)
6500 const char *id = r.make_identifier (this, "lvalue");
6501 r.write (" gcc_jit_lvalue *%s = \n"
6502 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
6503 " %s, /*gcc_jit_location *loc */\n"
6504 " %s);\n",
6506 r.get_identifier_as_lvalue (m_lvalue),
6507 r.get_identifier (m_loc),
6508 r.get_identifier (m_field));
6511 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
6513 /* Implementation of pure virtual hook recording::memento::replay_into
6514 for recording::access_field_rvalue. */
6516 void
6517 recording::access_field_rvalue::replay_into (replayer *r)
6519 set_playback_obj (
6520 m_rvalue->playback_rvalue ()
6521 ->access_field (playback_location (r, m_loc),
6522 m_field->playback_field ()));
6525 /* Implementation of pure virtual hook recording::rvalue::visit_children
6526 for recording::access_field_rvalue. */
6528 void
6529 recording::access_field_rvalue::visit_children (rvalue_visitor *v)
6531 v->visit (m_rvalue);
6534 /* Implementation of recording::memento::make_debug_string for
6535 accessing a field of an rvalue. */
6537 recording::string *
6538 recording::access_field_rvalue::make_debug_string ()
6540 enum precedence prec = get_precedence ();
6541 return string::from_printf (m_ctxt,
6542 "%s.%s",
6543 m_rvalue->get_debug_string_parens (prec),
6544 m_field->get_debug_string ());
6547 /* Implementation of recording::memento::write_reproducer for
6548 access_field_rvalue. */
6550 void
6551 recording::access_field_rvalue::write_reproducer (reproducer &r)
6553 const char *id = r.make_identifier (this, "rvalue");
6554 r.write (" gcc_jit_rvalue *%s = \n"
6555 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
6556 " %s, /*gcc_jit_location *loc */\n"
6557 " %s);\n",
6559 r.get_identifier_as_rvalue (m_rvalue),
6560 r.get_identifier (m_loc),
6561 r.get_identifier (m_field));
6564 /* The implementation of class
6565 gcc::jit::recording::dereference_field_rvalue. */
6567 /* Implementation of pure virtual hook recording::memento::replay_into
6568 for recording::dereference_field_rvalue. */
6570 void
6571 recording::dereference_field_rvalue::replay_into (replayer *r)
6573 set_playback_obj (
6574 m_rvalue->playback_rvalue ()->
6575 dereference_field (playback_location (r, m_loc),
6576 m_field->playback_field ()));
6579 /* Implementation of pure virtual hook recording::rvalue::visit_children
6580 for recording::dereference_field_rvalue. */
6582 void
6583 recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
6585 v->visit (m_rvalue);
6588 /* Implementation of recording::memento::make_debug_string for
6589 dereferencing a field of an rvalue. */
6591 recording::string *
6592 recording::dereference_field_rvalue::make_debug_string ()
6594 enum precedence prec = get_precedence ();
6595 return string::from_printf (m_ctxt,
6596 "%s->%s",
6597 m_rvalue->get_debug_string_parens (prec),
6598 m_field->get_debug_string ());
6601 /* Implementation of recording::memento::write_reproducer for
6602 dereference_field_rvalue. */
6604 void
6605 recording::dereference_field_rvalue::write_reproducer (reproducer &r)
6607 const char *id = r.make_identifier (this, "lvalue");
6608 r.write (" gcc_jit_lvalue *%s=\n"
6609 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
6610 " %s, /* gcc_jit_location *loc */\n"
6611 " %s); /* gcc_jit_field *field */\n",
6613 r.get_identifier_as_rvalue (m_rvalue),
6614 r.get_identifier (m_loc),
6615 r.get_identifier (m_field));
6618 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
6620 /* Implementation of pure virtual hook recording::memento::replay_into
6621 for recording::dereference_rvalue. */
6623 void
6624 recording::dereference_rvalue::replay_into (replayer *r)
6626 set_playback_obj (
6627 m_rvalue->playback_rvalue ()->
6628 dereference (playback_location (r, m_loc)));
6631 /* Implementation of pure virtual hook recording::rvalue::visit_children
6632 for recording::dereference_rvalue. */
6634 void
6635 recording::dereference_rvalue::visit_children (rvalue_visitor *v)
6637 v->visit (m_rvalue);
6640 /* Implementation of recording::memento::make_debug_string for
6641 dereferencing an rvalue. */
6643 recording::string *
6644 recording::dereference_rvalue::make_debug_string ()
6646 enum precedence prec = get_precedence ();
6647 return string::from_printf (m_ctxt,
6648 "*%s",
6649 m_rvalue->get_debug_string_parens (prec));
6652 /* Implementation of recording::memento::write_reproducer for
6653 dereference_rvalue. */
6655 void
6656 recording::dereference_rvalue::write_reproducer (reproducer &r)
6658 const char *id = r.make_identifier (this, "dereference");
6659 r.write (" gcc_jit_lvalue *%s =\n"
6660 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
6661 " %s); /* gcc_jit_location *loc */\n",
6663 r.get_identifier_as_rvalue (m_rvalue),
6664 r.get_identifier (m_loc));
6667 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
6669 /* Implementation of pure virtual hook recording::memento::replay_into
6670 for recording::get_address_of_lvalue. */
6672 void
6673 recording::get_address_of_lvalue::replay_into (replayer *r)
6675 set_playback_obj (
6676 m_lvalue->playback_lvalue ()->
6677 get_address (playback_location (r, m_loc)));
6680 /* Implementation of pure virtual hook recording::rvalue::visit_children
6681 for recording::get_address_of_lvalue. */
6683 void
6684 recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
6686 v->visit (m_lvalue);
6689 /* Implementation of recording::memento::make_debug_string for
6690 getting the address of an lvalue. */
6692 recording::string *
6693 recording::get_address_of_lvalue::make_debug_string ()
6695 enum precedence prec = get_precedence ();
6696 return string::from_printf (m_ctxt,
6697 "&%s",
6698 m_lvalue->get_debug_string_parens (prec));
6701 /* Implementation of recording::memento::write_reproducer for
6702 get_address_of_lvalue. */
6704 void
6705 recording::get_address_of_lvalue::write_reproducer (reproducer &r)
6707 const char *id = r.make_identifier (this, "address_of");
6708 r.write (" gcc_jit_rvalue *%s =\n"
6709 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
6710 " %s); /* gcc_jit_location *loc */\n",
6712 r.get_identifier_as_lvalue (m_lvalue),
6713 r.get_identifier (m_loc));
6716 /* The implementation of class gcc::jit::recording::function_pointer. */
6718 /* Implementation of pure virtual hook recording::memento::replay_into
6719 for recording::function_pointer. */
6721 void
6722 recording::function_pointer::replay_into (replayer *r)
6724 set_playback_obj (
6725 m_fn->playback_function ()->
6726 get_address (playback_location (r, m_loc)));
6729 void
6730 recording::function_pointer::visit_children (rvalue_visitor *)
6732 /* Empty. */
6735 /* Implementation of recording::memento::make_debug_string for
6736 getting the address of an lvalue. */
6738 recording::string *
6739 recording::function_pointer::make_debug_string ()
6741 return string::from_printf (m_ctxt,
6742 "%s",
6743 m_fn->get_debug_string ());
6746 /* Implementation of recording::memento::write_reproducer for
6747 function_pointer. */
6749 void
6750 recording::function_pointer::write_reproducer (reproducer &r)
6752 const char *id = r.make_identifier (this, "address_of");
6753 r.write (" gcc_jit_rvalue *%s =\n"
6754 " gcc_jit_function_get_address (%s, /* gcc_jit_function *fn */\n"
6755 " %s); /* gcc_jit_location *loc */\n",
6757 r.get_identifier (m_fn),
6758 r.get_identifier (m_loc));
6761 /* The implementation of class gcc::jit::recording::local. */
6763 /* Implementation of pure virtual hook recording::memento::replay_into
6764 for recording::local. */
6766 void
6767 recording::local::replay_into (replayer *r)
6769 playback::lvalue *obj = m_func->playback_function ()
6770 ->new_local (playback_location (r, m_loc),
6771 m_type->playback_type (),
6772 playback_string (m_name),
6773 m_string_attributes);
6775 if (m_reg_name != NULL)
6776 obj->set_register_name (m_reg_name->c_str ());
6778 if (m_alignment != 0)
6779 obj->set_alignment (m_alignment);
6781 set_playback_obj (obj);
6784 /* Override the default implementation of
6785 recording::memento::write_to_dump for locals by writing
6786 TYPE NAME;
6787 for use at the top of the function body as if it were a
6788 declaration. */
6790 void
6791 recording::local::write_to_dump (dump &d)
6793 if (d.update_locations ())
6794 m_loc = d.make_location ();
6795 d.write (" %s %s;\n",
6796 m_type->get_debug_string (),
6797 get_debug_string ());
6800 void
6801 recording::local::write_reproducer (reproducer &r)
6803 const char *id = r.make_identifier (this, "local");
6804 r.write (" gcc_jit_lvalue *%s =\n"
6805 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
6806 " %s, /* gcc_jit_location *loc */\n"
6807 " %s, /* gcc_jit_type *type */\n"
6808 " %s); /* const char *name */\n",
6810 r.get_identifier (m_func),
6811 r.get_identifier (m_loc),
6812 r.get_identifier_as_type (m_type),
6813 m_name->get_debug_string ());
6816 /* The implementation of class gcc::jit::recording::statement. */
6818 /* We poison the default implementation of
6819 gcc::jit::recording::statement::get_successor_blocks
6820 since this vfunc must only ever be called on terminator
6821 statements. */
6823 vec <recording::block *>
6824 recording::statement::get_successor_blocks () const
6826 /* The base class implementation is for non-terminating statements,
6827 and thus should never be called. */
6828 gcc_unreachable ();
6829 vec <block *> result;
6830 result.create (0);
6831 return result;
6834 /* Extend the default implementation of
6835 recording::memento::write_to_dump for statements by (if requested)
6836 updating the location of the statement to the current location in
6837 the dumpfile. */
6839 void
6840 recording::statement::write_to_dump (dump &d)
6842 memento::write_to_dump (d);
6843 if (d.update_locations ())
6844 m_loc = d.make_location ();
6847 /* The implementation of class gcc::jit::recording::eval. */
6849 /* Implementation of pure virtual hook recording::memento::replay_into
6850 for recording::eval. */
6852 void
6853 recording::eval::replay_into (replayer *r)
6855 playback_block (get_block ())
6856 ->add_eval (playback_location (r),
6857 m_rvalue->playback_rvalue ());
6860 /* Implementation of recording::memento::make_debug_string for
6861 an eval statement. */
6863 recording::string *
6864 recording::eval::make_debug_string ()
6866 return string::from_printf (m_ctxt,
6867 "(void)%s;",
6868 m_rvalue->get_debug_string ());
6871 /* Implementation of recording::memento::write_reproducer for
6872 eval statements. */
6874 void
6875 recording::eval::write_reproducer (reproducer &r)
6877 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
6878 " %s, /* gcc_jit_location *loc */\n"
6879 " %s); /* gcc_jit_rvalue *rvalue */\n",
6880 r.get_identifier (get_block ()),
6881 r.get_identifier (get_loc ()),
6882 r.get_identifier_as_rvalue (m_rvalue));
6885 /* The implementation of class gcc::jit::recording::assignment. */
6887 /* Implementation of pure virtual hook recording::memento::replay_into
6888 for recording::assignment. */
6890 void
6891 recording::assignment::replay_into (replayer *r)
6893 playback_block (get_block ())
6894 ->add_assignment (playback_location (r),
6895 m_lvalue->playback_lvalue (),
6896 m_rvalue->playback_rvalue ());
6899 /* Implementation of recording::memento::make_debug_string for
6900 an assignment statement. */
6902 recording::string *
6903 recording::assignment::make_debug_string ()
6905 return string::from_printf (m_ctxt,
6906 "%s = %s;",
6907 m_lvalue->get_debug_string (),
6908 m_rvalue->get_debug_string ());
6911 /* Implementation of recording::memento::write_reproducer for
6912 assignment statements. */
6914 void
6915 recording::assignment::write_reproducer (reproducer &r)
6917 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
6918 " %s, /* gcc_jit_location *loc */\n"
6919 " %s, /* gcc_jit_lvalue *lvalue */\n"
6920 " %s); /* gcc_jit_rvalue *rvalue */\n",
6921 r.get_identifier (get_block ()),
6922 r.get_identifier (get_loc ()),
6923 r.get_identifier_as_lvalue (m_lvalue),
6924 r.get_identifier_as_rvalue (m_rvalue));
6927 /* The implementation of class gcc::jit::recording::assignment_op. */
6929 /* Implementation of pure virtual hook recording::memento::replay_into
6930 for recording::assignment_op. */
6932 void
6933 recording::assignment_op::replay_into (replayer *r)
6935 playback::type *result_type =
6936 m_lvalue->playback_lvalue ()->get_type ();
6938 playback::rvalue *binary_op =
6939 r->new_binary_op (playback_location (r),
6940 m_op,
6941 result_type,
6942 m_lvalue->playback_rvalue (),
6943 m_rvalue->playback_rvalue ());
6945 playback_block (get_block ())
6946 ->add_assignment (playback_location (r),
6947 m_lvalue->playback_lvalue (),
6948 binary_op);
6951 /* Implementation of recording::memento::make_debug_string for
6952 an assignment_op statement. */
6954 recording::string *
6955 recording::assignment_op::make_debug_string ()
6957 return string::from_printf (m_ctxt,
6958 "%s %s= %s;",
6959 m_lvalue->get_debug_string (),
6960 binary_op_strings[m_op],
6961 m_rvalue->get_debug_string ());
6964 /* Implementation of recording::memento::write_reproducer for
6965 assignment_op statements. */
6967 void
6968 recording::assignment_op::write_reproducer (reproducer &r)
6970 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
6971 " %s, /* gcc_jit_location *loc */\n"
6972 " %s, /* gcc_jit_lvalue *lvalue */\n"
6973 " %s, /* enum gcc_jit_binary_op op */\n"
6974 " %s); /* gcc_jit_rvalue *rvalue */\n",
6975 r.get_identifier (get_block ()),
6976 r.get_identifier (get_loc ()),
6977 r.get_identifier_as_lvalue (m_lvalue),
6978 binary_op_reproducer_strings[m_op],
6979 r.get_identifier_as_rvalue (m_rvalue));
6982 /* The implementation of class gcc::jit::recording::comment. */
6984 /* Implementation of pure virtual hook recording::memento::replay_into
6985 for recording::comment. */
6987 void
6988 recording::comment::replay_into (replayer *r)
6990 playback_block (get_block ())
6991 ->add_comment (playback_location (r),
6992 m_text->c_str ());
6995 /* Implementation of recording::memento::make_debug_string for
6996 a comment "statement". */
6998 recording::string *
6999 recording::comment::make_debug_string ()
7001 return string::from_printf (m_ctxt,
7002 "/* %s */",
7003 m_text->c_str ());
7006 /* Implementation of recording::memento::write_reproducer for
7007 comments. */
7009 void
7010 recording::comment::write_reproducer (reproducer &r)
7012 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
7013 " %s, /* gcc_jit_location *loc */\n"
7014 " %s); /* const char *text */\n",
7015 r.get_identifier (get_block ()),
7016 r.get_identifier (get_loc ()),
7017 m_text->get_debug_string ());
7020 /* The implementation of class gcc::jit::recording::conditional. */
7022 /* Implementation of pure virtual hook recording::memento::replay_into
7023 for recording::conditional. */
7025 void
7026 recording::conditional::replay_into (replayer *r)
7028 playback_block (get_block ())
7029 ->add_conditional (playback_location (r),
7030 m_boolval->playback_rvalue (),
7031 playback_block (m_on_true),
7032 playback_block (m_on_false));
7035 /* Override the poisoned default implementation of
7036 gcc::jit::recording::statement::get_successor_blocks
7038 A conditional jump has 2 successor blocks. */
7040 vec <recording::block *>
7041 recording::conditional::get_successor_blocks () const
7043 vec <block *> result;
7044 result.create (2);
7045 result.quick_push (m_on_true);
7046 result.quick_push (m_on_false);
7047 return result;
7050 /* Implementation of recording::memento::make_debug_string for
7051 a conditional jump statement. */
7053 recording::string *
7054 recording::conditional::make_debug_string ()
7056 if (m_on_false)
7057 return string::from_printf (m_ctxt,
7058 "if (%s) goto %s; else goto %s;",
7059 m_boolval->get_debug_string (),
7060 m_on_true->get_debug_string (),
7061 m_on_false->get_debug_string ());
7062 else
7063 return string::from_printf (m_ctxt,
7064 "if (%s) goto %s;",
7065 m_boolval->get_debug_string (),
7066 m_on_true->get_debug_string ());
7069 /* Implementation of recording::memento::write_reproducer for
7070 conditional statements. */
7072 void
7073 recording::conditional::write_reproducer (reproducer &r)
7075 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
7076 " %s, /* gcc_jit_location *loc */\n"
7077 " %s, /* gcc_jit_rvalue *boolval */\n"
7078 " %s, /* gcc_jit_block *on_true */\n"
7079 " %s); /* gcc_jit_block *on_false */\n",
7080 r.get_identifier (get_block ()),
7081 r.get_identifier (get_loc ()),
7082 r.get_identifier_as_rvalue (m_boolval),
7083 r.get_identifier (m_on_true),
7084 r.get_identifier (m_on_false));
7087 /* The implementation of class gcc::jit::recording::jump. */
7089 /* Implementation of pure virtual hook recording::memento::replay_into
7090 for recording::jump. */
7092 void
7093 recording::jump::replay_into (replayer *r)
7095 playback_block (get_block ())
7096 ->add_jump (playback_location (r),
7097 m_target->playback_block ());
7100 /* Override the poisoned default implementation of
7101 gcc::jit::recording::statement::get_successor_blocks
7103 An unconditional jump has 1 successor block. */
7105 vec <recording::block *>
7106 recording::jump::get_successor_blocks () const
7108 vec <block *> result;
7109 result.create (1);
7110 result.quick_push (m_target);
7111 return result;
7114 /* Implementation of recording::memento::make_debug_string for
7115 a unconditional jump statement. */
7117 recording::string *
7118 recording::jump::make_debug_string ()
7120 return string::from_printf (m_ctxt,
7121 "goto %s;",
7122 m_target->get_debug_string ());
7125 /* Implementation of recording::memento::write_reproducer for
7126 jump statements. */
7128 void
7129 recording::jump::write_reproducer (reproducer &r)
7131 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
7132 " %s, /* gcc_jit_location *loc */\n"
7133 " %s); /* gcc_jit_block *target */\n",
7134 r.get_identifier (get_block ()),
7135 r.get_identifier (get_loc ()),
7136 r.get_identifier (m_target));
7139 /* The implementation of class gcc::jit::recording::return_. */
7141 /* Implementation of pure virtual hook recording::memento::replay_into
7142 for recording::return_. */
7144 void
7145 recording::return_::replay_into (replayer *r)
7147 playback_block (get_block ())
7148 ->add_return (playback_location (r),
7149 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
7152 /* Override the poisoned default implementation of
7153 gcc::jit::recording::statement::get_successor_blocks
7155 A return statement has no successor block. */
7157 vec <recording::block *>
7158 recording::return_::get_successor_blocks () const
7160 vec <block *> result;
7161 result.create (0);
7162 return result;
7165 /* Implementation of recording::memento::make_debug_string for
7166 a return statement (covers both those with and without rvalues). */
7168 recording::string *
7169 recording::return_::make_debug_string ()
7171 if (m_rvalue)
7172 return string::from_printf (m_ctxt,
7173 "return %s;",
7174 m_rvalue->get_debug_string ());
7175 else
7176 return string::from_printf (m_ctxt,
7177 "return;");
7180 /* Implementation of recording::memento::write_reproducer for
7181 return statements. */
7183 void
7184 recording::return_::write_reproducer (reproducer &r)
7186 if (m_rvalue)
7187 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
7188 " %s, /* gcc_jit_location *loc */\n"
7189 " %s); /* gcc_jit_rvalue *rvalue */\n",
7190 r.get_identifier (get_block ()),
7191 r.get_identifier (get_loc ()),
7192 r.get_identifier_as_rvalue (m_rvalue));
7193 else
7194 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
7195 " %s); /* gcc_jit_location *loc */\n",
7196 r.get_identifier (get_block ()),
7197 r.get_identifier (get_loc ()));
7200 /* The implementation of class gcc::jit::recording::case_. */
7202 void
7203 recording::case_::write_reproducer (reproducer &r)
7205 const char *id = r.make_identifier (this, "case");
7206 const char *fmt =
7207 " gcc_jit_case *%s = \n"
7208 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
7209 " %s, /* gcc_jit_rvalue *min_value */\n"
7210 " %s, /* gcc_jit_rvalue *max_value */\n"
7211 " %s); /* gcc_jit_block *dest_block */\n";
7212 r.write (fmt,
7214 r.get_identifier (get_context ()),
7215 r.get_identifier_as_rvalue (m_min_value),
7216 r.get_identifier_as_rvalue (m_max_value),
7217 r.get_identifier (m_dest_block));
7220 recording::string *
7221 recording::case_::make_debug_string ()
7223 return string::from_printf (get_context (),
7224 "case %s ... %s: goto %s;",
7225 m_min_value->get_debug_string (),
7226 m_max_value->get_debug_string (),
7227 m_dest_block->get_debug_string ());
7230 /* The implementation of class gcc::jit::recording::switch_. */
7232 /* gcc::jit::recording::switch_'s constructor. */
7234 recording::switch_::switch_ (block *b,
7235 location *loc,
7236 rvalue *expr,
7237 block *default_block,
7238 int num_cases,
7239 case_ **cases)
7240 : statement (b, loc),
7241 m_expr (expr),
7242 m_default_block (default_block)
7244 m_cases.reserve_exact (num_cases);
7245 for (int i = 0; i< num_cases; i++)
7246 m_cases.quick_push (cases[i]);
7249 /* Implementation of pure virtual hook recording::memento::replay_into
7250 for recording::switch_. */
7252 void
7253 recording::switch_::replay_into (replayer *r)
7255 auto_vec <playback::case_> pcases;
7256 int i;
7257 recording::case_ *rcase;
7258 pcases.reserve_exact (m_cases.length ());
7259 FOR_EACH_VEC_ELT (m_cases, i, rcase)
7261 playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (),
7262 rcase->get_max_value ()->playback_rvalue (),
7263 rcase->get_dest_block ()->playback_block ());
7264 pcases.safe_push (pcase);
7266 playback_block (get_block ())
7267 ->add_switch (playback_location (r),
7268 m_expr->playback_rvalue (),
7269 m_default_block->playback_block (),
7270 &pcases);
7273 /* Override the poisoned default implementation of
7274 gcc::jit::recording::statement::get_successor_blocks
7276 A switch statement has (NUM_CASES + 1) successor blocks. */
7278 vec <recording::block *>
7279 recording::switch_::get_successor_blocks () const
7281 vec <block *> result;
7282 result.create (m_cases.length () + 1);
7283 result.quick_push (m_default_block);
7284 int i;
7285 case_ *c;
7286 FOR_EACH_VEC_ELT (m_cases, i, c)
7287 result.quick_push (c->get_dest_block ());
7288 return result;
7291 /* Implementation of recording::memento::make_debug_string for
7292 a switch statement. */
7294 recording::string *
7295 recording::switch_::make_debug_string ()
7297 auto_vec <char> cases_str;
7298 int i;
7299 case_ *c;
7300 FOR_EACH_VEC_ELT (m_cases, i, c)
7302 size_t len = strlen (c->get_debug_string ());
7303 unsigned idx = cases_str.length ();
7304 cases_str.safe_grow (idx + 1 + len, true);
7305 cases_str[idx] = ' ';
7306 memcpy (&(cases_str[idx + 1]),
7307 c->get_debug_string (),
7308 len);
7310 cases_str.safe_push ('\0');
7312 return string::from_printf (m_ctxt,
7313 "switch (%s) {default: goto %s;%s}",
7314 m_expr->get_debug_string (),
7315 m_default_block->get_debug_string (),
7316 &cases_str[0]);
7319 /* Implementation of recording::memento::write_reproducer for
7320 switch statements. */
7322 void
7323 recording::switch_::write_reproducer (reproducer &r)
7325 r.make_identifier (this, "switch");
7326 int i;
7327 case_ *c;
7328 const char *cases_id =
7329 r.make_tmp_identifier ("cases_for", this);
7330 r.write (" gcc_jit_case *%s[%i] = {\n",
7331 cases_id,
7332 m_cases.length ());
7333 FOR_EACH_VEC_ELT (m_cases, i, c)
7334 r.write (" %s,\n", r.get_identifier (c));
7335 r.write (" };\n");
7336 const char *fmt =
7337 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
7338 " %s, /* gcc_jit_location *loc */\n"
7339 " %s, /* gcc_jit_rvalue *expr */\n"
7340 " %s, /* gcc_jit_block *default_block */\n"
7341 " %i, /* int num_cases */\n"
7342 " %s); /* gcc_jit_case **cases */\n";
7343 r.write (fmt,
7344 r.get_identifier (get_block ()),
7345 r.get_identifier (get_loc ()),
7346 r.get_identifier_as_rvalue (m_expr),
7347 r.get_identifier (m_default_block),
7348 m_cases.length (),
7349 cases_id);
7352 /* class asm_operand : public memento. */
7354 recording::asm_operand::asm_operand (extended_asm *ext_asm,
7355 string *asm_symbolic_name,
7356 string *constraint)
7357 : memento (ext_asm->get_context ()),
7358 m_ext_asm (ext_asm),
7359 m_asm_symbolic_name (asm_symbolic_name),
7360 m_constraint (constraint)
7364 void
7365 recording::asm_operand::print (pretty_printer *pp) const
7367 if (m_asm_symbolic_name)
7369 pp_character (pp, '[');
7370 pp_string (pp, m_asm_symbolic_name->c_str ());
7371 pp_character (pp, ']');
7372 pp_space (pp);
7374 pp_string (pp, m_constraint->get_debug_string ());
7375 /* Subclass will add lvalue/rvalue. */
7378 recording::string *
7379 recording::asm_operand::make_debug_string ()
7381 pretty_printer pp;
7382 print (&pp);
7383 return m_ctxt->new_string (pp_formatted_text (&pp), false);
7386 /* class output_asm_operand : public asm_operand. */
7388 void
7389 recording::output_asm_operand::write_reproducer (reproducer &r)
7391 const char *fmt =
7392 " gcc_jit_extended_asm_add_output_operand (%s, /* gcc_jit_extended_asm *ext_asm */\n"
7393 " %s, /* const char *asm_symbolic_name */\n"
7394 " %s, /* const char *constraint */\n"
7395 " %s); /* gcc_jit_lvalue *dest */\n";
7396 r.write (fmt,
7397 r.get_identifier (m_ext_asm),
7398 (m_asm_symbolic_name
7399 ? m_asm_symbolic_name->get_debug_string () : "NULL"),
7400 m_constraint->get_debug_string (),
7401 r.get_identifier (m_dest));
7404 void
7405 recording::output_asm_operand::print (pretty_printer *pp) const
7407 asm_operand::print (pp);
7408 pp_string (pp, " (");
7409 pp_string (pp, m_dest->get_debug_string ());
7410 pp_string (pp, ")");
7413 /* class input_asm_operand : public asm_operand. */
7415 void
7416 recording::input_asm_operand::write_reproducer (reproducer &r)
7418 const char *fmt =
7419 " gcc_jit_extended_asm_add_input_operand (%s, /* gcc_jit_extended_asm *ext_asm */\n"
7420 " %s, /* const char *asm_symbolic_name */\n"
7421 " %s, /* const char *constraint */\n"
7422 " %s); /* gcc_jit_rvalue *src */\n";
7423 r.write (fmt,
7424 r.get_identifier (m_ext_asm),
7425 (m_asm_symbolic_name
7426 ? m_asm_symbolic_name->get_debug_string () : "NULL"),
7427 m_constraint->get_debug_string (),
7428 r.get_identifier_as_rvalue (m_src));
7431 void
7432 recording::input_asm_operand::print (pretty_printer *pp) const
7434 asm_operand::print (pp);
7435 pp_string (pp, " (");
7436 pp_string (pp, m_src->get_debug_string ());
7437 pp_string (pp, ")");
7440 /* The implementation of class gcc::jit::recording::extended_asm. */
7442 void
7443 recording::extended_asm::add_output_operand (const char *asm_symbolic_name,
7444 const char *constraint,
7445 lvalue *dest)
7447 output_asm_operand *op
7448 = new output_asm_operand (this,
7449 new_string (asm_symbolic_name),
7450 new_string (constraint),
7451 dest);
7452 m_ctxt->record (op);
7453 m_output_ops.safe_push (op);
7456 void
7457 recording::extended_asm::add_input_operand (const char *asm_symbolic_name,
7458 const char *constraint,
7459 rvalue *src)
7461 input_asm_operand *op
7462 = new input_asm_operand (this,
7463 new_string (asm_symbolic_name),
7464 new_string (constraint),
7465 src);
7466 m_ctxt->record (op);
7467 m_input_ops.safe_push (op);
7470 void
7471 recording::extended_asm::add_clobber (const char *victim)
7473 m_clobbers.safe_push (new_string (victim));
7476 /* Implementation of recording::memento::replay_into
7477 for recording::extended_asm. */
7479 void
7480 recording::extended_asm::replay_into (replayer *r)
7482 auto_vec<playback::asm_operand> playback_output_ops;
7483 auto_vec<playback::asm_operand> playback_input_ops;
7484 auto_vec<const char *> playback_clobbers;
7485 auto_vec<playback::block *> playback_goto_blocks;
7487 /* Populate outputs. */
7489 output_asm_operand *rec_asm_op;
7490 unsigned i;
7491 FOR_EACH_VEC_ELT (m_output_ops, i, rec_asm_op)
7493 playback::asm_operand playback_asm_op
7494 (rec_asm_op->get_symbolic_name (),
7495 rec_asm_op->get_constraint (),
7496 rec_asm_op->get_lvalue ()->playback_lvalue ()->as_tree ());
7497 playback_output_ops.safe_push (playback_asm_op);
7501 /* Populate inputs. */
7503 input_asm_operand *rec_asm_op;
7504 unsigned i;
7505 FOR_EACH_VEC_ELT (m_input_ops, i, rec_asm_op)
7507 playback::asm_operand playback_asm_op
7508 (rec_asm_op->get_symbolic_name (),
7509 rec_asm_op->get_constraint (),
7510 rec_asm_op->get_rvalue ()->playback_rvalue ()->as_tree ());
7511 playback_input_ops.safe_push (playback_asm_op);
7515 /* Populate clobbers. */
7517 string *rec_clobber;
7518 unsigned i;
7519 FOR_EACH_VEC_ELT (m_clobbers, i, rec_clobber)
7520 playback_clobbers.safe_push (rec_clobber->c_str ());
7523 /* Populate playback blocks if an "asm goto". */
7524 maybe_populate_playback_blocks (&playback_goto_blocks);
7526 playback_block (get_block ())
7527 ->add_extended_asm (playback_location (r),
7528 m_asm_template->c_str (),
7529 m_is_volatile, m_is_inline,
7530 &playback_output_ops,
7531 &playback_input_ops,
7532 &playback_clobbers,
7533 &playback_goto_blocks);
7536 /* Implementation of recording::memento::make_debug_string for
7537 an extended_asm "statement". */
7539 recording::string *
7540 recording::extended_asm::make_debug_string ()
7542 pretty_printer pp;
7543 pp_string (&pp, "asm ");
7544 if (m_is_volatile)
7545 pp_string (&pp, "volatile ");
7546 if (m_is_inline)
7547 pp_string (&pp, "inline ");
7548 if (is_goto ())
7549 pp_string (&pp, "goto ");
7550 pp_character (&pp, '(');
7551 pp_string (&pp, m_asm_template->get_debug_string ());
7552 pp_string (&pp, " : ");
7553 unsigned i;
7555 output_asm_operand *asm_op;
7556 FOR_EACH_VEC_ELT (m_output_ops, i, asm_op)
7558 if (i > 0)
7559 pp_string (&pp, ", ");
7560 asm_op->print (&pp);
7563 pp_string (&pp, " : ");
7565 input_asm_operand *asm_op;
7566 FOR_EACH_VEC_ELT (m_input_ops, i, asm_op)
7568 if (i > 0)
7569 pp_string (&pp, ", ");
7570 asm_op->print (&pp);
7573 pp_string (&pp, " : ");
7574 string *rec_clobber;
7575 FOR_EACH_VEC_ELT (m_clobbers, i, rec_clobber)
7577 if (i > 0)
7578 pp_string (&pp, ", ");
7579 pp_string (&pp, rec_clobber->get_debug_string ());
7581 maybe_print_gotos (&pp);
7582 pp_character (&pp, ')');
7583 return new_string (pp_formatted_text (&pp));
7586 void
7587 recording::extended_asm::write_flags (reproducer &r)
7589 if (m_is_volatile)
7590 r.write (" gcc_jit_extended_asm_set_volatile_flag (%s, 1);\n",
7591 r.get_identifier (this));
7592 if (m_is_inline)
7593 r.write (" gcc_jit_extended_asm_set_inline_flag (%s, 1);\n",
7594 r.get_identifier (this));
7597 void
7598 recording::extended_asm::write_clobbers (reproducer &r)
7600 string *clobber;
7601 unsigned i;
7602 FOR_EACH_VEC_ELT (m_clobbers, i, clobber)
7603 r.write (" gcc_jit_extended_asm_add_clobber (%s, %s);\n",
7604 r.get_identifier (this),
7605 clobber->get_debug_string ());
7608 /* Implementation of recording::memento::write_reproducer for
7609 extended_asm_simple. */
7611 void
7612 recording::extended_asm_simple::write_reproducer (reproducer &r)
7614 const char *id = r.make_identifier (this, "extended_asm");
7615 r.write (" gcc_jit_extended_asm *%s =\n"
7616 " gcc_jit_block_add_extended_asm (%s, /*gcc_jit_block *block */\n"
7617 " %s, /* gcc_jit_location *loc */\n"
7618 " %s); /* const char *asm_template */\n",
7620 r.get_identifier (get_block ()),
7621 r.get_identifier (get_loc ()),
7622 m_asm_template->get_debug_string ());
7623 write_flags (r);
7624 write_clobbers (r);
7627 void
7628 recording::extended_asm::
7629 maybe_populate_playback_blocks (auto_vec <playback::block *> *)
7631 /* Do nothing; not an "asm goto". */
7634 /* The implementation of class gcc::jit::recording::extended_asm_goto. */
7636 /* recording::extended_asm_goto's ctor. */
7638 recording::extended_asm_goto::extended_asm_goto (block *b,
7639 location *loc,
7640 string *asm_template,
7641 int num_goto_blocks,
7642 block **goto_blocks,
7643 block *fallthrough_block)
7644 : extended_asm (b, loc, asm_template),
7645 m_goto_blocks (num_goto_blocks),
7646 m_fallthrough_block (fallthrough_block)
7648 for (int i = 0; i < num_goto_blocks; i++)
7649 m_goto_blocks.quick_push (goto_blocks[i]);
7652 /* Implementation of recording::memento::replay_into
7653 for recording::extended_asm_goto. */
7655 void
7656 recording::extended_asm_goto::replay_into (replayer *r)
7658 /* Chain up to base class impl. */
7659 recording::extended_asm::replay_into (r);
7661 /* ...and potentially add a goto for the fallthrough. */
7662 if (m_fallthrough_block)
7663 playback_block (get_block ())
7664 ->add_jump (playback_location (r),
7665 m_fallthrough_block->playback_block ());
7668 /* Implementation of recording::memento::write_reproducer for
7669 extended_asm_goto. */
7671 void
7672 recording::extended_asm_goto::write_reproducer (reproducer &r)
7674 const char *id = r.make_identifier (this, "extended_asm");
7675 const char *blocks_id = r.make_tmp_identifier ("blocks_for", this);
7676 r.write (" gcc_jit_block *%s[%i] = {\n",
7677 blocks_id,
7678 m_goto_blocks.length ());
7679 int i;
7680 block *b;
7681 FOR_EACH_VEC_ELT (m_goto_blocks, i, b)
7682 r.write (" %s,\n", r.get_identifier (b));
7683 r.write (" };\n");
7684 r.write (" gcc_jit_extended_asm *%s =\n"
7685 " gcc_jit_block_end_with_extended_asm_goto (%s, /*gcc_jit_block *block */\n"
7686 " %s, /* gcc_jit_location *loc */\n"
7687 " %s, /* const char *asm_template */\n"
7688 " %i, /* int num_goto_blocks */\n"
7689 " %s, /* gcc_jit_block **goto_blocks */\n"
7690 " %s); /* gcc_jit_block *fallthrough_block */\n",
7692 r.get_identifier (get_block ()),
7693 r.get_identifier (get_loc ()),
7694 m_asm_template->get_debug_string (),
7695 m_goto_blocks.length (),
7696 blocks_id,
7697 (m_fallthrough_block
7698 ? r.get_identifier (m_fallthrough_block)
7699 : "NULL"));
7700 write_flags (r);
7701 write_clobbers (r);
7704 /* Override the poisoned default implementation of
7705 gcc::jit::recording::statement::get_successor_blocks
7707 An extended_asm_goto can jump to the m_goto_blocks, and to
7708 the (optional) m_fallthrough_block. */
7710 vec <recording::block *>
7711 recording::extended_asm_goto::get_successor_blocks () const
7713 vec <block *> result;
7714 result.create (m_goto_blocks.length () + 1);
7715 if (m_fallthrough_block)
7716 result.quick_push (m_fallthrough_block);
7717 result.splice (m_goto_blocks);
7718 return result;
7721 /* Vfunc for use by recording::extended_asm::make_debug_string. */
7723 void
7724 recording::extended_asm_goto::maybe_print_gotos (pretty_printer *pp) const
7726 pp_string (pp, " : ");
7727 unsigned i;
7728 block *b;
7729 FOR_EACH_VEC_ELT (m_goto_blocks, i, b)
7731 if (i > 0)
7732 pp_string (pp, ", ");
7733 pp_string (pp, b->get_debug_string ());
7735 /* Non-C syntax here. */
7736 if (m_fallthrough_block)
7737 pp_printf (pp, " [fallthrough: %s]",
7738 m_fallthrough_block->get_debug_string ());
7741 /* Vfunc for use by recording::extended_asm::replay_into. */
7743 void
7744 recording::extended_asm_goto::
7745 maybe_populate_playback_blocks (auto_vec <playback::block *> *out)
7747 unsigned i;
7748 block *b;
7749 FOR_EACH_VEC_ELT (m_goto_blocks, i, b)
7750 out->safe_push (b->playback_block ());
7753 /* class top_level_asm : public memento. */
7755 recording::top_level_asm::top_level_asm (context *ctxt,
7756 location *loc,
7757 string *asm_stmts)
7758 : memento (ctxt),
7759 m_loc (loc),
7760 m_asm_stmts (asm_stmts)
7764 /* Implementation of recording::memento::replay_into for top-level asm. */
7766 void
7767 recording::top_level_asm::replay_into (replayer *r)
7769 r->add_top_level_asm (m_asm_stmts->c_str ());
7772 /* Implementation of recording::memento::make_debug_string for
7773 top-level asm. */
7775 recording::string *
7776 recording::top_level_asm::make_debug_string ()
7778 return string::from_printf (m_ctxt, "asm (%s)",
7779 m_asm_stmts->get_debug_string ());
7782 /* Override the default implementation of
7783 recording::memento::write_to_dump.
7784 Don't indent the string. */
7786 void
7787 recording::top_level_asm::write_to_dump (dump &d)
7789 d.write ("%s;\n", get_debug_string ());
7792 /* Implementation of recording::memento::write_reproducer for top-level asm. */
7794 void
7795 recording::top_level_asm::write_reproducer (reproducer &r)
7797 r.write (" gcc_jit_context_add_top_level_asm (%s, /* gcc_jit_context *ctxt */\n"
7798 " %s, /* gcc_jit_location *loc */\n"
7799 " %s); /* const char *asm_stmts */\n",
7800 r.get_identifier (get_context ()),
7801 r.get_identifier (m_loc),
7802 m_asm_stmts->get_debug_string ());
7805 void
7806 recording::global_init_rvalue::replay_into (replayer *r)
7808 r->global_set_init_rvalue (m_variable->playback_lvalue (),
7809 m_init->playback_rvalue ());
7812 void
7813 recording::global_init_rvalue::write_reproducer (reproducer &r)
7815 r.write (
7816 " gcc_jit_global_set_initializer_rvalue (%s, /* lvalue *global */\n"
7817 " %s);/* rvalue *init */\n",
7818 r.get_identifier (m_variable),
7819 r.get_identifier_as_rvalue (m_init));
7822 void
7823 recording::global_init_rvalue::write_to_dump (dump &d)
7825 d.write ("%s;\n", get_debug_string ());
7828 recording::string *
7829 recording::global_init_rvalue::make_debug_string ()
7831 return string::from_printf (m_ctxt, "%s = %s",
7832 m_variable->get_debug_string (),
7833 m_init->get_debug_string ());
7836 enum strip_flags {
7837 STRIP_FLAG_NONE,
7838 STRIP_FLAG_ARR,
7839 STRIP_FLAG_VEC
7842 /* Strips type down to array, vector or base type (whichever comes first)
7844 Also saves 'ptr_depth' and sets 'flags' for array or vector types. */
7845 static
7846 recording::type *
7847 strip_and_count (recording::type *type_to_strip,
7848 int &ptr_depth,
7849 strip_flags &flags)
7851 recording::type *t = type_to_strip;
7853 while (true)
7855 if (!t)
7856 gcc_unreachable (); /* Should only happen on corrupt input. */
7858 recording::type *pointed_to_type = t->is_pointer ();
7859 if (pointed_to_type != NULL)
7861 ptr_depth++;
7862 t = pointed_to_type;
7863 continue;
7866 recording::type *array_el = t->is_array ();
7867 if (array_el != NULL)
7869 flags = STRIP_FLAG_ARR;
7870 break;
7873 recording::type *vec = t->dyn_cast_vector_type ();
7874 if (vec != NULL)
7876 flags = STRIP_FLAG_VEC;
7877 break;
7880 /* unqualified () returns 'this' on base types. */
7881 recording::type *next = t->unqualified ();
7882 if (next == t)
7884 break;
7886 t = next;
7889 return t;
7892 /* Strip qualifiers and count pointer depth, returning true
7893 if the types' base type and pointer depth are
7894 the same, otherwise false.
7896 For array and vector types the number of element also
7897 has to match.
7899 Do not call this directly. Call 'types_kinda_same'. */
7900 bool
7901 types_kinda_same_internal (recording::type *a, recording::type *b)
7903 int ptr_depth_a = 0;
7904 int ptr_depth_b = 0;
7905 recording::type *base_a;
7906 recording::type *base_b;
7908 strip_flags flags_a = STRIP_FLAG_NONE;
7909 strip_flags flags_b = STRIP_FLAG_NONE;
7911 base_a = strip_and_count (a, ptr_depth_a, flags_a);
7912 base_b = strip_and_count (b, ptr_depth_b, flags_b);
7914 if (ptr_depth_a != ptr_depth_b)
7915 return false;
7917 if (base_a == base_b)
7918 return true;
7920 if (flags_a != flags_b)
7921 return false;
7923 /* If the "base type" is an array or vector we might need to
7924 check deeper. */
7925 if (flags_a == STRIP_FLAG_ARR)
7927 recording::array_type *arr_a =
7928 static_cast<recording::array_type*> (base_a);
7929 recording::array_type *arr_b =
7930 static_cast<recording::array_type*> (base_b);
7932 if (arr_a->num_elements () != arr_b->num_elements ())
7933 return false;
7935 /* is_array returns element type. */
7936 recording::type *el_a = arr_a->is_array ();
7937 recording::type *el_b = arr_b->is_array ();
7939 if (el_a == el_b)
7940 return true;
7942 return types_kinda_same_internal (el_a, el_b);
7944 if (flags_a == STRIP_FLAG_VEC)
7946 recording::vector_type *arr_a =
7947 static_cast<recording::vector_type*> (base_a);
7948 recording::vector_type *arr_b =
7949 static_cast<recording::vector_type*> (base_b);
7951 if (arr_a->get_num_units () != arr_b->get_num_units ())
7952 return false;
7954 recording::type *el_a = arr_a->get_element_type ();
7955 recording::type *el_b = arr_b->get_element_type ();
7957 if (el_a == el_b)
7958 return true;
7960 return types_kinda_same_internal (el_a, el_b);
7963 return false;
7966 } // namespace gcc::jit
7968 } // namespace gcc