hppa: Export main in pr104869.C on hpux
[official-gcc.git] / gcc / jit / jit-recording.cc
blob9b5b8005ebe8b54476635c4fa17d3e0f3acc2300
1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2023 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"
33 namespace gcc {
34 namespace jit {
36 // class dump
38 dump::dump (recording::context &ctxt,
39 const char *filename,
40 bool update_locations)
41 : m_ctxt (ctxt),
42 m_filename (filename),
43 m_update_locations (update_locations),
44 m_line (0),
45 m_column (0)
47 m_file = fopen (filename, "w");
48 if (!m_file)
49 ctxt.add_error (NULL,
50 "error opening dump file %s for writing: %s",
51 filename,
52 xstrerror (errno));
55 dump::~dump ()
57 if (m_file)
59 int err = fclose (m_file);
60 if (err)
61 m_ctxt.add_error (NULL,
62 "error closing dump file %s: %s",
63 m_filename,
64 xstrerror (errno));
68 /* Write the given message to the dump, using printf-formatting
69 conventions, updating the line/column within the dump.
71 Emit an error on the context if a failure occurs. */
73 void
74 dump::write (const char *fmt, ...)
76 int len;
77 va_list ap;
78 char *buf;
80 /* If there was an error opening the file, we've already reported it.
81 Don't attempt further work. */
82 if (!m_file)
83 return;
85 va_start (ap, fmt);
86 len = vasprintf (&buf, fmt, ap);
87 va_end (ap);
89 if (buf == NULL || len < 0)
91 m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
92 m_filename);
93 return;
96 if (fwrite (buf, strlen (buf), 1, m_file) != 1)
97 m_ctxt.add_error (NULL, "error writing to dump file %s",
98 m_filename);
100 /* Flush after each line, to ease debugging crashes. */
101 fflush (m_file);
103 /* Update line/column: */
104 for (const char *ptr = buf; *ptr; ptr++)
106 if ('\n' == *ptr)
108 m_line++;
109 m_column = 0;
111 else
112 m_column++;
115 free (buf);
118 /* Construct a gcc::jit::recording::location instance for the current
119 location within the dump. */
121 recording::location *
122 dump::make_location () const
124 return m_ctxt.new_location (m_filename, m_line, m_column,
125 /* We need to flag such locations as *not*
126 created by the user, so that
127 reproducer::get_identifier can cope with
128 them appearing *after* the memento that
129 refers to them. */
130 false);
133 /* A collection of allocations, all of which can be released together, to
134 avoid needing to track and release them individually. */
136 class allocator
138 public:
139 ~allocator ();
141 char *
142 xstrdup_printf (const char *, ...)
143 ATTRIBUTE_RETURNS_NONNULL
144 GNU_PRINTF(2, 3);
146 char *
147 xstrdup_printf_va (const char *, va_list ap)
148 ATTRIBUTE_RETURNS_NONNULL
149 GNU_PRINTF(2, 0);
151 private:
152 auto_vec <void *> m_buffers;
155 /* allocator's destructor. Call "free" on all of the allocations. */
157 allocator::~allocator ()
159 unsigned i;
160 void *buffer;
161 FOR_EACH_VEC_ELT (m_buffers, i, buffer)
162 free (buffer);
165 /* Formatted printing, allocating to a buffer (or exiting the process if
166 the allocation fails).
168 The buffer exists until the allocator is cleaned up, and is freed at
169 that point, so the caller doesn't need to track the result. */
171 char *
172 allocator::xstrdup_printf (const char *fmt, ...)
174 char *result;
175 va_list ap;
176 va_start (ap, fmt);
177 result = xstrdup_printf_va (fmt, ap);
178 va_end (ap);
179 return result;
182 /* Formatted printing, allocating to a buffer (or exiting the process if
183 the allocation fails).
185 The buffer exists until the allocator is cleaned up, and is freed at
186 that point, so the caller doesn't need to track the result. */
188 char *
189 allocator::xstrdup_printf_va (const char *fmt, va_list ap)
191 char *result = xvasprintf (fmt, ap);
192 m_buffers.safe_push (result);
193 return result;
196 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
197 implementing gcc_jit_context_dump_reproducer_to_file. */
199 class reproducer : public dump
201 public:
202 reproducer (recording::context &ctxt,
203 const char *filename);
205 void
206 write_params (const vec <recording::context *> &contexts);
208 void
209 write_args (const vec <recording::context *> &contexts);
211 const char *
212 make_identifier (recording::memento *m, const char *prefix);
214 const char *
215 make_tmp_identifier (const char *prefix, recording::memento *m);
217 const char *
218 get_identifier (recording::context *ctxt);
220 const char *
221 get_identifier (recording::memento *m);
223 const char *
224 get_identifier_as_rvalue (recording::rvalue *m);
226 const char *
227 get_identifier_as_lvalue (recording::lvalue *m);
229 const char *
230 get_identifier_as_type (recording::type *m);
232 char *
233 xstrdup_printf (const char *, ...)
234 ATTRIBUTE_RETURNS_NONNULL
235 GNU_PRINTF(2, 3);
237 private:
238 const char * ensure_identifier_is_unique (const char *candidate, void *ptr);
240 private:
241 hash_map<recording::memento *, const char *> m_map_memento_to_identifier;
243 struct hash_traits : public string_hash
245 static void remove (const char *) {}
247 hash_set<const char *, false, hash_traits> m_set_identifiers;
248 allocator m_allocator;
251 /* gcc::jit::reproducer's constructor. */
253 reproducer::reproducer (recording::context &ctxt,
254 const char *filename) :
255 dump (ctxt, filename, 0),
256 m_map_memento_to_identifier (),
257 m_set_identifiers (),
258 m_allocator ()
262 /* Write out a list of contexts as a set of parameters within a
263 C function declaration. */
265 void
266 reproducer::write_params (const vec <recording::context *> &contexts)
268 unsigned i;
269 recording::context *ctxt;
270 FOR_EACH_VEC_ELT (contexts, i, ctxt)
272 write ("gcc_jit_context *%s",
273 get_identifier (ctxt));
274 if (i < contexts.length () - 1)
275 write (",\n"
276 " ");
280 /* Write out a list of contexts as a set of arguments within a call
281 to a C function. */
283 void
284 reproducer::write_args (const vec <recording::context *> &contexts)
286 unsigned i;
287 recording::context *ctxt;
288 FOR_EACH_VEC_ELT (contexts, i, ctxt)
290 write ("%s",
291 get_identifier (ctxt));
292 if (i < contexts.length () - 1)
293 write (",\n"
294 " ");
298 /* Ensure that STR is a valid C identifier by overwriting
299 any invalid chars in-place with underscores.
301 This doesn't special-case the first character. */
303 static void
304 convert_to_identifier (char *str)
306 for (char *p = str; *p; p++)
307 if (!ISALNUM (*p))
308 *p = '_';
311 /* Given CANDIDATE, a possible C identifier for use in a reproducer,
312 ensure that it is unique within the generated source file by
313 appending PTR to it if necessary. Return the resulting string.
315 The reproducer will eventually clean up the buffer in its dtor. */
317 const char *
318 reproducer::ensure_identifier_is_unique (const char *candidate, void *ptr)
320 if (m_set_identifiers.contains (candidate))
321 candidate = m_allocator.xstrdup_printf ("%s_%p", candidate, ptr);
322 gcc_assert (!m_set_identifiers.contains (candidate));
323 m_set_identifiers.add (candidate);
324 return candidate;
327 /* Generate a C identifier for the given memento, associating the generated
328 buffer with the memento (for future calls to get_identifier et al).
330 The reproducer will eventually clean up the buffer in its dtor. */
331 const char *
332 reproducer::make_identifier (recording::memento *m, const char *prefix)
334 const char *result;
335 if (strlen (m->get_debug_string ()) < 100)
337 char *buf = m_allocator.xstrdup_printf ("%s_%s",
338 prefix,
339 m->get_debug_string ());
340 convert_to_identifier (buf);
341 result = buf;
343 else
344 result = m_allocator.xstrdup_printf ("%s_%p",
345 prefix, (void *) m);
346 result = ensure_identifier_is_unique (result, m);
347 m_map_memento_to_identifier.put (m, result);
348 return result;
351 /* Generate a C identifier for a temporary variable.
352 The reproducer will eventually clean up the buffer in its dtor. */
354 const char *
355 reproducer::make_tmp_identifier (const char *prefix, recording::memento *m)
357 return m_allocator.xstrdup_printf ("%s_%s",
358 prefix, get_identifier (m));
361 /* Generate a C identifier for the given context.
362 The reproducer will eventually clean up the buffer in its dtor. */
364 const char *
365 reproducer::get_identifier (recording::context *ctxt)
367 return m_allocator.xstrdup_printf ("ctxt_%p",
368 (void *)ctxt);
371 /* Locate the C identifier for the given memento, which is assumed to
372 have already been created via make_identifier. */
374 const char *
375 reproducer::get_identifier (recording::memento *m)
377 if (!m)
378 return "NULL";
380 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
381 and hence these locations appear in the context's memento list
382 out-of-order: they appear in the context's memento list *after*
383 the memento that refers to them. For this case, it's simplest to
384 pretend that they're NULL when writing out the code to recreate the
385 memento that uses them. */
386 if (recording::location *loc = m->dyn_cast_location ())
387 if (!loc->created_by_user ())
388 return "NULL";
390 const char **slot = m_map_memento_to_identifier.get (m);
391 if (!slot)
393 get_context ().add_error (NULL,
394 "unable to find identifier for %p: %s",
395 (void *)m,
396 m->get_debug_string ());
397 gcc_unreachable ();
399 return *slot;
402 /* Locate the C identifier for the given rvalue, wrapping it within
403 a gcc_*_as_rvalue upcast if necessary. */
405 const char *
406 reproducer::get_identifier_as_rvalue (recording::rvalue *m)
408 return m->access_as_rvalue (*this);
411 /* Locate the C identifier for the given lvalue, wrapping it within
412 a gcc_*_as_lvalue upcast if necessary. */
414 const char *
415 reproducer::get_identifier_as_lvalue (recording::lvalue *m)
417 return m->access_as_lvalue (*this);
420 /* Locate the C identifier for the given type, wrapping it within
421 a gcc_*_as_type upcast if necessary. */
423 const char *
424 reproducer::get_identifier_as_type (recording::type *m)
426 return m->access_as_type (*this);
429 /* Formatted printing, allocating to a buffer (or exiting the process if
430 the allocation fails).
432 The buffer exists until the allocator is cleaned up, and is freed at
433 that point, so the caller doesn't need to track the result.
435 Note that we can't use ggc_printf since we're not within the compiler
436 proper (when within gcc_jit_context_dump_reproducer_to_file). */
438 char *
439 reproducer::xstrdup_printf (const char *fmt, ...)
441 char *result;
442 va_list ap;
443 va_start (ap, fmt);
444 result = m_allocator.xstrdup_printf_va (fmt, ap);
445 va_end (ap);
446 return result;
449 /* A helper class for implementing make_debug_string, for building
450 a temporary string from a vec of rvalues. */
452 class comma_separated_string
454 public:
455 comma_separated_string (const auto_vec<recording::rvalue *> &rvalues,
456 enum recording::precedence prec);
457 ~comma_separated_string ();
459 const char *as_char_ptr () const { return m_buf; }
461 private:
462 char *m_buf;
465 /* comma_separated_string's ctor
466 Build m_buf. */
468 comma_separated_string::comma_separated_string
469 (const auto_vec<recording::rvalue *> &rvalues,
470 enum recording::precedence prec)
471 : m_buf (NULL)
473 /* Calculate length of said buffer. */
474 size_t sz = 1; /* nil terminator */
475 for (unsigned i = 0; i< rvalues.length (); i++)
477 sz += strlen (rvalues[i]->get_debug_string_parens (prec));
478 sz += 2; /* ", " separator */
481 /* Now allocate and populate the buffer. */
482 m_buf = new char[sz];
483 size_t len = 0;
485 for (unsigned i = 0; i< rvalues.length (); i++)
487 strcpy (m_buf + len, rvalues[i]->get_debug_string_parens (prec));
488 len += strlen (rvalues[i]->get_debug_string_parens (prec));
489 if (i + 1 < rvalues.length ())
491 strcpy (m_buf + len, ", ");
492 len += 2;
495 m_buf[len] = '\0';
498 /* comma_separated_string's dtor. */
500 comma_separated_string::~comma_separated_string ()
502 delete[] m_buf;
505 /**********************************************************************
506 Recording.
507 **********************************************************************/
509 /* Get the playback::location for the given recording::location,
510 handling a NULL input with a NULL output. */
512 playback::location *
513 recording::playback_location (replayer *r, recording::location *loc)
515 if (loc)
516 return loc->playback_location (r);
517 else
518 return NULL;
521 /* Get a const char * for the given recording::string
522 handling a NULL input with a NULL output. */
524 const char *
525 recording::playback_string (recording::string *str)
527 if (str)
528 return str->c_str ();
529 else
530 return NULL;
533 /* Get the playback::block for the given recording::block,
534 handling a NULL input with a NULL output. */
536 playback::block *
537 recording::playback_block (recording::block *b)
539 if (b)
540 return b->playback_block ();
541 else
542 return NULL;
545 /* Methods of cc::jit::recording::context. */
547 /* The constructor for gcc::jit::recording::context, used by
548 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
550 recording::context::context (context *parent_ctxt)
551 : log_user (NULL),
552 m_parent_ctxt (parent_ctxt),
553 m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this),
554 m_timer (NULL),
555 m_error_count (0),
556 m_first_error_str (NULL),
557 m_owns_first_error_str (false),
558 m_last_error_str (NULL),
559 m_owns_last_error_str (false),
560 m_mementos (),
561 m_compound_types (),
562 m_globals (),
563 m_functions (),
564 m_FILE_type (NULL),
565 m_builtins_manager(NULL)
567 if (parent_ctxt)
569 /* Inherit options from parent. */
570 for (unsigned i = 0; i < ARRAY_SIZE (m_str_options); i++)
572 const char *parent_opt = parent_ctxt->m_str_options[i];
573 m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
575 memcpy (m_int_options,
576 parent_ctxt->m_int_options,
577 sizeof (m_int_options));
578 memcpy (m_bool_options,
579 parent_ctxt->m_bool_options,
580 sizeof (m_bool_options));
581 memcpy (m_inner_bool_options,
582 parent_ctxt->m_inner_bool_options,
583 sizeof (m_inner_bool_options));
584 set_logger (parent_ctxt->get_logger ());
586 else
588 memset (m_str_options, 0, sizeof (m_str_options));
589 memset (m_int_options, 0, sizeof (m_int_options));
590 memset (m_bool_options, 0, sizeof (m_bool_options));
591 memset (m_inner_bool_options, 0, sizeof (m_inner_bool_options));
592 m_inner_bool_options[INNER_BOOL_OPTION_PRINT_ERRORS_TO_STDERR] = true;
595 memset (m_basic_types, 0, sizeof (m_basic_types));
598 /* The destructor for gcc::jit::recording::context, implicitly used by
599 gcc_jit_context_release. */
601 recording::context::~context ()
603 JIT_LOG_SCOPE (get_logger ());
604 int i;
605 memento *m;
606 FOR_EACH_VEC_ELT (m_mementos, i, m)
608 delete m;
611 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
612 free (m_str_options[i]);
614 char *optname;
615 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
616 free (optname);
617 FOR_EACH_VEC_ELT (m_driver_options, i, optname)
618 free (optname);
620 if (m_builtins_manager)
621 delete m_builtins_manager;
623 if (m_owns_first_error_str)
624 free (m_first_error_str);
626 if (m_owns_last_error_str)
627 if (m_last_error_str != m_first_error_str)
628 free (m_last_error_str);
631 /* Add the given mememto to the list of those tracked by this
632 gcc::jit::recording::context, so that e.g. it can be deleted
633 when this context is released. */
635 void
636 recording::context::record (memento *m)
638 gcc_assert (m);
640 m_mementos.safe_push (m);
643 /* Replay this context (and any parents) into the given replayer. */
645 void
646 recording::context::replay_into (replayer *r)
648 JIT_LOG_SCOPE (get_logger ());
649 int i;
650 memento *m;
652 /* If we have a parent context, we must replay it. This will
653 recursively walk backwards up the historical tree, then replay things
654 forwards "in historical order", starting with the ultimate parent
655 context, until we reach the "this" context.
657 Note that we fully replay the parent, then fully replay the child,
658 which means that inter-context references can only exist from child
659 to parent, not the other way around.
661 All of this replaying is suboptimal - it would be better to do the
662 work for the parent context *once*, rather than replaying the parent
663 every time we replay each child. However, fixing this requires deep
664 surgery to lifetime-management: we'd need every context family tree
665 to have its own GC heap, and to initialize the GCC code to use that
666 heap (with a mutex on such a heap). */
667 if (m_parent_ctxt)
668 m_parent_ctxt->replay_into (r);
670 if (r->errors_occurred ())
671 return;
673 /* Replay this context's saved operations into r. */
674 FOR_EACH_VEC_ELT (m_mementos, i, m)
676 /* Disabled low-level debugging, here if we need it: print what
677 we're replaying.
678 Note that the calls to get_debug_string might lead to more
679 mementos being created for the strings.
680 This can also be used to exercise the debug_string
681 machinery. */
682 if (0)
683 printf ("context %p replaying (%p): %s\n",
684 (void *)this, (void *)m, m->get_debug_string ());
686 m->replay_into (r);
688 if (r->errors_occurred ())
689 return;
693 /* During a playback, we associate objects from the recording with
694 their counterparts during this playback.
696 For simplicity, we store this within the recording objects.
698 The following method cleans away these associations, to ensure that
699 we never have out-of-date associations lingering on subsequent
700 playbacks (the objects pointed to are GC-managed, but the
701 recording objects don't own refs to them). */
703 void
704 recording::context::disassociate_from_playback ()
706 JIT_LOG_SCOPE (get_logger ());
707 int i;
708 memento *m;
710 if (m_parent_ctxt)
711 m_parent_ctxt->disassociate_from_playback ();
713 FOR_EACH_VEC_ELT (m_mementos, i, m)
715 m->set_playback_obj (NULL);
719 /* Create a recording::string instance and add it to this context's list
720 of mementos.
722 This creates a fresh copy of the given 0-terminated buffer. */
724 recording::string *
725 recording::context::new_string (const char *text, bool escaped)
727 if (!text)
728 return NULL;
730 recording::string *result = new string (this, text, escaped);
731 record (result);
732 return result;
735 /* Create a recording::location instance and add it to this context's
736 list of mementos.
738 Implements the post-error-checking part of
739 gcc_jit_context_new_location. */
741 recording::location *
742 recording::context::new_location (const char *filename,
743 int line,
744 int column,
745 bool created_by_user)
747 recording::location *result =
748 new recording::location (this,
749 new_string (filename),
750 line, column,
751 created_by_user);
752 record (result);
753 return result;
756 /* If we haven't seen this enum value yet, create a recording::type
757 instance and add it to this context's list of mementos.
759 If we have seen it before, reuse our cached value, so that repeated
760 calls on the context give the same object.
762 If we have a parent context, the cache is within the ultimate
763 ancestor context.
765 Implements the post-error-checking part of
766 gcc_jit_context_get_type. */
768 recording::type *
769 recording::context::get_type (enum gcc_jit_types kind)
771 if (!m_basic_types[kind])
773 if (m_parent_ctxt)
774 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
775 else
777 recording::type *result = new memento_of_get_type (this, kind);
778 record (result);
779 m_basic_types[kind] = result;
783 return m_basic_types[kind];
786 /* Get a recording::type instance for the given size and signedness.
787 This is implemented in terms of recording::context::get_type
788 above.
790 Implements the post-error-checking part of
791 gcc_jit_context_get_int_type. */
793 recording::type *
794 recording::context::get_int_type (int num_bytes, int is_signed)
796 /* We can't use a switch here since some of the values are macros affected
797 by options; e.g. i386.h has
798 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
799 Compare with tree.cc's make_or_reuse_type. Note that the _SIZE macros
800 are in bits, rather than bytes.
802 const int num_bits = num_bytes * 8;
803 if (num_bits == INT_TYPE_SIZE)
804 return get_type (is_signed
805 ? GCC_JIT_TYPE_INT
806 : GCC_JIT_TYPE_UNSIGNED_INT);
807 if (num_bits == CHAR_TYPE_SIZE)
808 return get_type (is_signed
809 ? GCC_JIT_TYPE_SIGNED_CHAR
810 : GCC_JIT_TYPE_UNSIGNED_CHAR);
811 if (num_bits == SHORT_TYPE_SIZE)
812 return get_type (is_signed
813 ? GCC_JIT_TYPE_SHORT
814 : GCC_JIT_TYPE_UNSIGNED_SHORT);
815 if (num_bits == LONG_TYPE_SIZE)
816 return get_type (is_signed
817 ? GCC_JIT_TYPE_LONG
818 : GCC_JIT_TYPE_UNSIGNED_LONG);
819 if (num_bits == LONG_LONG_TYPE_SIZE)
820 return get_type (is_signed
821 ? GCC_JIT_TYPE_LONG_LONG
822 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
823 if (num_bits == 128)
824 return get_type (is_signed
825 ? GCC_JIT_TYPE_INT128_T
826 : GCC_JIT_TYPE_UINT128_T);
828 /* Some other size, not corresponding to the C int types. */
829 /* To be written: support arbitrary other sizes, sharing by
830 memoizing at the recording::context level? */
831 gcc_unreachable ();
834 /* Create a recording::type instance and add it to this context's list
835 of mementos.
837 Implements the post-error-checking part of
838 gcc_jit_context_new_array_type. */
840 recording::type *
841 recording::context::new_array_type (recording::location *loc,
842 recording::type *element_type,
843 int num_elements)
845 if (struct_ *s = element_type->dyn_cast_struct ())
846 if (!s->get_fields ())
848 add_error (NULL,
849 "cannot create an array of type %s"
850 " until the fields have been set",
851 s->get_name ()->c_str ());
852 return NULL;
854 recording::type *result =
855 new recording::array_type (this, loc, element_type, num_elements);
856 record (result);
857 return result;
860 /* Create a recording::field instance and add it to this context's list
861 of mementos.
863 Implements the post-error-checking part of
864 gcc_jit_context_new_field. */
866 recording::field *
867 recording::context::new_field (recording::location *loc,
868 recording::type *type,
869 const char *name)
871 recording::field *result =
872 new recording::field (this, loc, type, new_string (name));
873 record (result);
874 return result;
877 /* Create a recording::bitfield instance and add it to this context's list
878 of mementos.
880 Implements the post-error-checking part of
881 gcc_jit_context_new_bitfield. */
883 recording::field *
884 recording::context::new_bitfield (recording::location *loc,
885 recording::type *type,
886 int width,
887 const char *name)
889 recording::field *result =
890 new recording::bitfield (this, loc, type, width, new_string (name));
891 record (result);
892 return result;
895 /* Create a recording::struct_ instance and add it to this context's
896 list of mementos and list of compound types.
898 Implements the post-error-checking part of
899 gcc_jit_context_new_struct_type. */
901 recording::struct_ *
902 recording::context::new_struct_type (recording::location *loc,
903 const char *name)
905 recording::struct_ *result = new struct_ (this, loc, new_string (name));
906 record (result);
907 m_compound_types.safe_push (result);
908 return result;
911 /* Create a recording::union_ instance and add it to this context's
912 list of mementos and list of compound types.
914 Implements the first post-error-checking part of
915 gcc_jit_context_new_union_type. */
917 recording::union_ *
918 recording::context::new_union_type (recording::location *loc,
919 const char *name)
921 recording::union_ *result = new union_ (this, loc, new_string (name));
922 record (result);
923 m_compound_types.safe_push (result);
924 return result;
927 /* Create a recording::function_type instance and add it to this context's
928 list of mementos.
930 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
932 recording::function_type *
933 recording::context::new_function_type (recording::type *return_type,
934 int num_params,
935 recording::type **param_types,
936 int is_variadic)
938 recording::function_type *fn_type
939 = new function_type (this,
940 return_type,
941 num_params,
942 param_types,
943 is_variadic);
944 record (fn_type);
945 return fn_type;
948 /* Create a recording::type instance and add it to this context's list
949 of mementos.
951 Implements the post-error-checking part of
952 gcc_jit_context_new_function_ptr_type. */
954 recording::type *
955 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
956 recording::type *return_type,
957 int num_params,
958 recording::type **param_types,
959 int is_variadic)
961 recording::function_type *fn_type
962 = new_function_type (return_type,
963 num_params,
964 param_types,
965 is_variadic);
967 /* Return a pointer-type to the function type. */
968 return fn_type->get_pointer ();
971 /* Create a recording::param instance and add it to this context's list
972 of mementos.
974 Implements the post-error-checking part of
975 gcc_jit_context_new_param. */
977 recording::param *
978 recording::context::new_param (recording::location *loc,
979 recording::type *type,
980 const char *name)
982 recording::param *result = new recording::param (this, loc, type, new_string (name));
983 record (result);
984 return result;
987 /* Create a recording::function instance and add it to this context's list
988 of mementos and list of functions.
990 Implements the post-error-checking part of
991 gcc_jit_context_new_function. */
993 recording::function *
994 recording::context::new_function (recording::location *loc,
995 enum gcc_jit_function_kind kind,
996 recording::type *return_type,
997 const char *name,
998 int num_params,
999 recording::param **params,
1000 int is_variadic,
1001 enum built_in_function builtin_id)
1003 recording::function *result =
1004 new recording::function (this,
1005 loc, kind, return_type,
1006 new_string (name),
1007 num_params, params, is_variadic,
1008 builtin_id);
1009 record (result);
1010 m_functions.safe_push (result);
1012 return result;
1015 /* Locate the builtins_manager (if any) for this family of contexts,
1016 creating it if it doesn't exist already.
1018 All of the recording contexts in a family share one builtins_manager:
1019 if we have a child context, follow the parent links to get the
1020 ultimate ancestor context, and look for it/store it there. */
1022 builtins_manager *
1023 recording::context::get_builtins_manager ()
1025 if (m_parent_ctxt)
1026 return m_parent_ctxt->get_builtins_manager ();
1028 if (!m_builtins_manager)
1029 m_builtins_manager = new builtins_manager (this);
1031 return m_builtins_manager;
1034 /* Get a recording::function instance, which is lazily-created and added
1035 to the context's lists of mementos.
1037 Implements the post-error-checking part of
1038 gcc_jit_context_get_builtin_function. */
1040 recording::function *
1041 recording::context::get_builtin_function (const char *name)
1043 builtins_manager *bm = get_builtins_manager ();
1044 return bm->get_builtin_function (name);
1047 /* Create a recording::global instance and add it to this context's list
1048 of mementos.
1050 Implements the post-error-checking part of
1051 gcc_jit_context_new_global. */
1053 recording::lvalue *
1054 recording::context::new_global (recording::location *loc,
1055 enum gcc_jit_global_kind kind,
1056 recording::type *type,
1057 const char *name)
1059 recording::global *result =
1060 new recording::global (this, loc, kind, type, new_string (name));
1061 record (result);
1062 m_globals.safe_push (result);
1064 return result;
1067 void
1068 recording::context::new_global_init_rvalue (lvalue *variable,
1069 rvalue *init)
1071 recording::global_init_rvalue *obj =
1072 new recording::global_init_rvalue (this, variable, init);
1073 record (obj);
1075 global *gbl = (global *) variable;
1076 gbl->set_rvalue_init (init); /* Needed by the global for write dump. */
1079 /* Create a recording::memento_of_new_string_literal instance and add it
1080 to this context's list of mementos.
1082 Implements the post-error-checking part of
1083 gcc_jit_context_new_string_literal. */
1085 recording::rvalue *
1086 recording::context::new_string_literal (const char *value)
1088 recording::rvalue *result =
1089 new memento_of_new_string_literal (this, NULL, new_string (value));
1090 record (result);
1091 return result;
1094 /* Create a recording::memento_of_new_rvalue_from_vector instance and add it
1095 to this context's list of mementos.
1097 Implements the post-error-checking part of
1098 gcc_jit_context_new_rvalue_from_vector. */
1100 recording::rvalue *
1101 recording::context::new_rvalue_from_vector (location *loc,
1102 vector_type *type,
1103 rvalue **elements)
1105 recording::rvalue *result
1106 = new memento_of_new_rvalue_from_vector (this, loc, type, elements);
1107 record (result);
1108 return result;
1111 recording::rvalue *
1112 recording::context::new_ctor (recording::location *loc,
1113 recording::type *type,
1114 size_t num_values,
1115 field **fields,
1116 rvalue **values)
1118 recording::ctor *result = new ctor (this, loc, type);
1120 /* Short cut for zero init. */
1121 if (!num_values)
1123 record (result);
1124 return result;
1127 bool is_struct_or_union = type->is_struct () || type->is_union ();
1129 /* We need to copy fields and values into result's auto_vec:s.
1130 Both for structs and unions and only values for arrays. */
1131 if (type->is_array () != NULL)
1133 result->m_values.reserve (num_values, false);
1135 for (size_t i = 0; i < num_values; i++)
1136 result->m_values.quick_push (values[i]);
1138 else if (is_struct_or_union && fields)
1140 /* ctor values are paired with user specified fields. */
1142 result->m_values.reserve (num_values, false);
1143 result->m_fields.reserve (num_values, false);
1145 for (size_t i = 0; i < num_values; i++)
1147 result->m_values.quick_push (values[i]);
1148 result->m_fields.quick_push (fields[i]);
1151 else if (is_struct_or_union && !fields)
1153 /* ctor values are in definition order one by one,
1154 so take the fields from the type object. */
1156 result->m_values.reserve (num_values, false);
1157 result->m_fields.reserve (num_values, false);
1159 compound_type *ct = reinterpret_cast<compound_type *>(type);
1160 recording::fields *fields = ct->get_fields ();
1162 /* The entry point checks that num_values is not greater than
1163 the amount of fields in 'fields'. */
1164 for (size_t i = 0; i < num_values; i++)
1166 result->m_values.quick_push (values[i]);
1167 result->m_fields.quick_push (fields->get_field (i));
1170 else
1171 gcc_unreachable ();
1173 record (result);
1174 return result;
1177 /* Create a recording::unary_op instance and add it to this context's
1178 list of mementos.
1180 Implements the post-error-checking part of
1181 gcc_jit_context_new_unary_op. */
1183 recording::rvalue *
1184 recording::context::new_unary_op (recording::location *loc,
1185 enum gcc_jit_unary_op op,
1186 recording::type *result_type,
1187 recording::rvalue *a)
1189 recording::rvalue *result =
1190 new unary_op (this, loc, op, result_type, a);
1191 record (result);
1192 return result;
1195 /* Create a recording::binary_op instance and add it to this context's
1196 list of mementos.
1198 Implements the post-error-checking part of
1199 gcc_jit_context_new_binary_op. */
1201 recording::rvalue *
1202 recording::context::new_binary_op (recording::location *loc,
1203 enum gcc_jit_binary_op op,
1204 recording::type *result_type,
1205 recording::rvalue *a,
1206 recording::rvalue *b)
1208 recording::rvalue *result =
1209 new binary_op (this, loc, op, result_type, a, b);
1210 record (result);
1211 return result;
1214 /* Create a recording::comparison instance and add it to this context's
1215 list of mementos.
1217 Implements the post-error-checking part of
1218 gcc_jit_context_new_comparison. */
1220 recording::rvalue *
1221 recording::context::new_comparison (recording::location *loc,
1222 enum gcc_jit_comparison op,
1223 recording::rvalue *a,
1224 recording::rvalue *b)
1226 recording::rvalue *result = new comparison (this, loc, op, a, b);
1227 record (result);
1228 return result;
1231 /* Create a recording::cast instance and add it to this context's list
1232 of mementos.
1234 Implements the post-error-checking part of
1235 gcc_jit_context_new_cast. */
1237 recording::rvalue *
1238 recording::context::new_cast (recording::location *loc,
1239 recording::rvalue *expr,
1240 recording::type *type_)
1242 recording::rvalue *result = new cast (this, loc, expr, type_);
1243 record (result);
1244 return result;
1247 /* Create a recording::bitcast instance and add it to this context's list
1248 of mementos.
1250 Implements the post-error-checking part of
1251 gcc_jit_context_new_bitcast. */
1253 recording::rvalue *
1254 recording::context::new_bitcast (location *loc,
1255 rvalue *expr,
1256 type *type_)
1258 recording::rvalue *result = new bitcast (this, loc, expr, type_);
1259 record (result);
1260 return result;
1263 /* Create a recording::call instance and add it to this context's list
1264 of mementos.
1266 Implements the post-error-checking part of
1267 gcc_jit_context_new_call. */
1269 recording::rvalue *
1270 recording::context::new_call (recording::location *loc,
1271 function *func,
1272 int numargs , recording::rvalue **args)
1274 recording::rvalue *result = new call (this, loc, func, numargs, args);
1275 record (result);
1276 return result;
1279 /* Create a recording::call_through_ptr instance and add it to this
1280 context's list of mementos.
1282 Implements the post-error-checking part of
1283 gcc_jit_context_new_call_through_ptr. */
1285 recording::rvalue *
1286 recording::context::new_call_through_ptr (recording::location *loc,
1287 recording::rvalue *fn_ptr,
1288 int numargs,
1289 recording::rvalue **args)
1291 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
1292 record (result);
1293 return result;
1296 /* Create a recording::array_access instance and add it to this context's list
1297 of mementos.
1299 Implements the post-error-checking part of
1300 gcc_jit_context_new_array_access. */
1302 recording::lvalue *
1303 recording::context::new_array_access (recording::location *loc,
1304 recording::rvalue *ptr,
1305 recording::rvalue *index)
1307 recording::lvalue *result = new array_access (this, loc, ptr, index);
1308 record (result);
1309 return result;
1312 /* Create a recording::case_ instance and add it to this context's list
1313 of mementos.
1315 Implements the post-error-checking part of
1316 gcc_jit_context_new_case. */
1318 recording::case_ *
1319 recording::context::new_case (recording::rvalue *min_value,
1320 recording::rvalue *max_value,
1321 recording::block *block)
1323 recording::case_ *result = new case_ (this, min_value, max_value, block);
1324 record (result);
1325 return result;
1328 /* Set the given string option for this context, or add an error if
1329 it's not recognized.
1331 Implements the post-error-checking part of
1332 gcc_jit_context_set_str_option. */
1334 void
1335 recording::context::set_str_option (enum gcc_jit_str_option opt,
1336 const char *value)
1338 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
1340 add_error (NULL,
1341 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
1342 return;
1344 free (m_str_options[opt]);
1345 m_str_options[opt] = value ? xstrdup (value) : NULL;
1346 log_str_option (opt);
1349 /* Set the given integer option for this context, or add an error if
1350 it's not recognized.
1352 Implements the post-error-checking part of
1353 gcc_jit_context_set_int_option. */
1355 void
1356 recording::context::set_int_option (enum gcc_jit_int_option opt,
1357 int value)
1359 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
1361 add_error (NULL,
1362 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
1363 return;
1365 m_int_options[opt] = value;
1366 log_int_option (opt);
1369 /* Set the given boolean option for this context, or add an error if
1370 it's not recognized.
1372 Implements the post-error-checking part of
1373 gcc_jit_context_set_bool_option. */
1375 void
1376 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
1377 int value)
1379 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
1381 add_error (NULL,
1382 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
1383 return;
1385 m_bool_options[opt] = value ? true : false;
1386 log_bool_option (opt);
1389 void
1390 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt,
1391 int value)
1393 gcc_assert (inner_opt >= 0 && inner_opt < NUM_INNER_BOOL_OPTIONS);
1394 m_inner_bool_options[inner_opt] = value ? true : false;
1395 log_inner_bool_option (inner_opt);
1399 /* Add the given optname to this context's list of extra options.
1401 Implements the post-error-checking part of
1402 gcc_jit_context_add_command_line_option. */
1404 void
1405 recording::context::add_command_line_option (const char *optname)
1407 m_command_line_options.safe_push (xstrdup (optname));
1410 /* Add any user-provided extra options, starting with any from
1411 parent contexts.
1412 Called by playback::context::make_fake_args. */
1414 void
1415 recording::context::append_command_line_options (vec <char *> *argvec)
1417 if (m_parent_ctxt)
1418 m_parent_ctxt->append_command_line_options (argvec);
1420 int i;
1421 char *optname;
1422 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1423 argvec->safe_push (xstrdup (optname));
1426 /* Add the given optname to this context's list of extra driver options. */
1428 void
1429 recording::context::add_driver_option (const char *optname)
1431 m_driver_options.safe_push (xstrdup (optname));
1434 /* Add any user-provided driver options, starting with any from
1435 parent contexts.
1436 Called by playback::context::invoke_driver. */
1438 void
1439 recording::context::append_driver_options (auto_string_vec *argvec)
1441 if (m_parent_ctxt)
1442 m_parent_ctxt->append_driver_options (argvec);
1444 int i;
1445 char *optname;
1447 FOR_EACH_VEC_ELT (m_driver_options, i, optname)
1448 argvec->safe_push (xstrdup (optname));
1451 /* Add the given dumpname/out_ptr pair to this context's list of requested
1452 dumps.
1454 Implements the post-error-checking part of
1455 gcc_jit_context_enable_dump. */
1457 void
1458 recording::context::enable_dump (const char *dumpname,
1459 char **out_ptr)
1461 requested_dump d;
1462 gcc_assert (dumpname);
1463 gcc_assert (out_ptr);
1465 d.m_dumpname = dumpname;
1466 d.m_out_ptr = out_ptr;
1467 *out_ptr = NULL;
1468 m_requested_dumps.safe_push (d);
1471 /* Validate this context, and if it passes, compile it to memory
1472 (within a mutex).
1474 Implements the post-error-checking part of
1475 gcc_jit_context_compile. */
1477 result *
1478 recording::context::compile ()
1480 JIT_LOG_SCOPE (get_logger ());
1482 log_all_options ();
1484 validate ();
1486 if (errors_occurred ())
1487 return NULL;
1489 /* Set up a compile_to_memory playback context. */
1490 ::gcc::jit::playback::compile_to_memory replayer (this);
1492 /* Use it. */
1493 replayer.compile ();
1495 /* Get the jit::result (or NULL) from the
1496 compile_to_memory playback context. */
1497 return replayer.get_result_obj ();
1500 /* Validate this context, and if it passes, compile it to a file
1501 (within a mutex).
1503 Implements the post-error-checking part of
1504 gcc_jit_context_compile_to_file. */
1506 void
1507 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
1508 const char *output_path)
1510 JIT_LOG_SCOPE (get_logger ());
1512 log_all_options ();
1514 validate ();
1516 if (errors_occurred ())
1517 return;
1519 /* Set up a compile_to_file playback context. */
1520 ::gcc::jit::playback::compile_to_file replayer (this,
1521 output_kind,
1522 output_path);
1524 /* Use it. */
1525 replayer.compile ();
1528 /* Format the given error using printf's conventions, print
1529 it to stderr, and add it to the context. */
1531 void
1532 recording::context::add_error (location *loc, const char *fmt, ...)
1534 va_list ap;
1535 va_start (ap, fmt);
1536 add_error_va (loc, fmt, ap);
1537 va_end (ap);
1540 /* Format the given error using printf's conventions, print
1541 it to stderr, and add it to the context. */
1543 void
1544 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
1546 int len;
1547 char *malloced_msg;
1548 const char *errmsg;
1549 bool has_ownership;
1551 JIT_LOG_SCOPE (get_logger ());
1553 len = vasprintf (&malloced_msg, fmt, ap);
1554 if (malloced_msg == NULL || len < 0)
1556 errmsg = "out of memory generating error message";
1557 has_ownership = false;
1559 else
1561 errmsg = malloced_msg;
1562 has_ownership = true;
1564 if (get_logger ())
1565 get_logger ()->log ("error %i: %s", m_error_count, errmsg);
1567 const char *ctxt_progname =
1568 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
1569 if (!ctxt_progname)
1570 ctxt_progname = "libgccjit.so";
1572 bool print_errors_to_stderr =
1573 get_inner_bool_option (INNER_BOOL_OPTION_PRINT_ERRORS_TO_STDERR);
1574 if (print_errors_to_stderr)
1576 if (loc)
1577 fprintf (stderr, "%s: %s: error: %s\n",
1578 ctxt_progname,
1579 loc->get_debug_string (),
1580 errmsg);
1581 else
1582 fprintf (stderr, "%s: error: %s\n",
1583 ctxt_progname,
1584 errmsg);
1587 if (!m_error_count)
1589 m_first_error_str = const_cast <char *> (errmsg);
1590 m_owns_first_error_str = has_ownership;
1593 if (m_owns_last_error_str)
1594 if (m_last_error_str != m_first_error_str)
1595 free (m_last_error_str);
1596 m_last_error_str = const_cast <char *> (errmsg);
1597 m_owns_last_error_str = has_ownership;
1599 m_error_count++;
1602 /* Get the message for the first error that occurred on this context, or
1603 NULL if no errors have occurred on it.
1605 Implements the post-error-checking part of
1606 gcc_jit_context_get_first_error. */
1608 const char *
1609 recording::context::get_first_error () const
1611 return m_first_error_str;
1614 /* Get the message for the last error that occurred on this context, or
1615 NULL if no errors have occurred on it.
1617 Implements the post-error-checking part of
1618 gcc_jit_context_get_last_error. */
1620 const char *
1621 recording::context::get_last_error () const
1623 return m_last_error_str;
1626 /* Lazily generate and record a recording::type representing an opaque
1627 struct named "FILE".
1629 For use if client code tries to dereference the result of
1630 get_type (GCC_JIT_TYPE_FILE_PTR). */
1632 recording::type *
1633 recording::context::get_opaque_FILE_type ()
1635 if (!m_FILE_type)
1636 m_FILE_type = new_struct_type (NULL, "FILE");
1637 return m_FILE_type;
1640 /* Dump a C-like representation of the given context to the given path.
1641 If UPDATE_LOCATIONS is true, update the locations within the
1642 context's mementos to point to the dumpfile.
1644 Implements the post-error-checking part of
1645 gcc_jit_context_dump_to_file. */
1647 void
1648 recording::context::dump_to_file (const char *path, bool update_locations)
1650 int i;
1651 dump d (*this, path, update_locations);
1653 /* Forward declaration of structs and unions. */
1654 compound_type *st;
1655 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1657 d.write ("%s;\n\n", st->get_debug_string ());
1660 /* Content of structs, where set. */
1661 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1662 if (st->get_fields ())
1664 st->get_fields ()->write_to_dump (d);
1665 d.write ("\n");
1668 /* Globals. */
1669 global *g;
1670 FOR_EACH_VEC_ELT (m_globals, i, g)
1672 g->write_to_dump (d);
1674 if (!m_globals.is_empty ())
1675 d.write ("\n");
1677 function *fn;
1678 FOR_EACH_VEC_ELT (m_functions, i, fn)
1680 fn->write_to_dump (d);
1683 top_level_asm *tla;
1684 FOR_EACH_VEC_ELT (m_top_level_asms, i, tla)
1685 tla->write_to_dump (d);
1688 static const char * const
1689 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
1690 "GCC_JIT_STR_OPTION_PROGNAME"
1693 static const char * const
1694 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
1695 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1698 static const char * const
1699 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
1700 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1701 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1702 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1703 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1704 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1705 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1706 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1707 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1710 static const char * const
1711 inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = {
1712 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1713 "gcc_jit_context_set_bool_use_external_driver",
1714 "gcc_jit_context_set_bool_print_errors_to_stderr",
1717 /* Write the current value of all options to the log file (if any). */
1719 void
1720 recording::context::log_all_options () const
1722 int opt_idx;
1724 if (!get_logger ())
1725 return;
1727 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1728 log_str_option ((enum gcc_jit_str_option)opt_idx);
1730 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1731 log_int_option ((enum gcc_jit_int_option)opt_idx);
1733 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1734 log_bool_option ((enum gcc_jit_bool_option)opt_idx);
1735 for (opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1736 log_inner_bool_option ((enum inner_bool_option)opt_idx);
1739 /* Write the current value of the given string option to the
1740 log file (if any). */
1742 void
1743 recording::context::log_str_option (enum gcc_jit_str_option opt) const
1745 gcc_assert (opt < GCC_JIT_NUM_STR_OPTIONS);
1746 if (get_logger ())
1748 if (m_str_options[opt])
1749 log ("%s: \"%s\"",
1750 str_option_reproducer_strings[opt],
1751 m_str_options[opt]);
1752 else
1753 log ("%s: NULL",
1754 str_option_reproducer_strings[opt]);
1758 /* Write the current value of the given int option to the
1759 log file (if any). */
1761 void
1762 recording::context::log_int_option (enum gcc_jit_int_option opt) const
1764 gcc_assert (opt < GCC_JIT_NUM_INT_OPTIONS);
1765 if (get_logger ())
1766 log ("%s: %i",
1767 int_option_reproducer_strings[opt],
1768 m_int_options[opt]);
1771 /* Write the current value of the given bool option to the
1772 log file (if any). */
1774 void
1775 recording::context::log_bool_option (enum gcc_jit_bool_option opt) const
1777 gcc_assert (opt < GCC_JIT_NUM_BOOL_OPTIONS);
1778 if (get_logger ())
1779 log ("%s: %s",
1780 bool_option_reproducer_strings[opt],
1781 m_bool_options[opt] ? "true" : "false");
1784 /* Write the current value of the given "inner" bool option to the
1785 log file (if any). */
1787 void
1788 recording::context::log_inner_bool_option (enum inner_bool_option opt) const
1790 gcc_assert (opt < NUM_INNER_BOOL_OPTIONS);
1791 if (get_logger ())
1792 log ("%s: %s",
1793 inner_bool_option_reproducer_strings[opt],
1794 m_inner_bool_options[opt] ? "true" : "false");
1797 /* Write C source code to PATH that attempts to replay the API
1798 calls made to this context (and its parents), for use in
1799 minimizing test cases for libgccjit.
1801 Implements the post-error-checking part of
1802 gcc_jit_context_dump_reproducer_to_file. */
1804 void
1805 recording::context::dump_reproducer_to_file (const char *path)
1807 JIT_LOG_SCOPE (get_logger ());
1808 reproducer r (*this, path);
1810 /* Generate the "ancestry" of this context, as a list. */
1811 auto_vec <context *> ascending_contexts;
1812 for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
1813 ascending_contexts.safe_push (ctxt);
1815 /* Reverse the list, giving a list of contexts from
1816 top-most parent context down through to youngest child context.
1817 We will use this list as the parameters of the functions in
1818 our generated file. */
1819 unsigned num_ctxts = ascending_contexts.length ();
1820 auto_vec <context *> contexts (num_ctxts);
1821 for (unsigned i = 0; i < num_ctxts; i++)
1822 contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
1824 /* contexts[0] should be the top-level context. */
1825 gcc_assert (contexts[0]);
1826 gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
1828 /* The final element in contexts should be "this". */
1829 gcc_assert (contexts[contexts.length () - 1] == this);
1830 gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
1831 == contexts[0]);
1833 r.write ("/* This code was autogenerated by"
1834 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1835 print_version (r.get_file (), " ", false);
1836 r.write ("*/\n");
1837 r.write ("#include <libgccjit.h>\n\n");
1838 r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1839 r.write ("static void\nset_options (");
1840 r.write_params (contexts);
1841 r.write (");\n\n");
1842 r.write ("static void\ncreate_code (");
1843 r.write_params (contexts);
1844 r.write (");\n\n");
1845 r.write ("int\nmain (int argc, const char **argv)\n");
1846 r.write ("{\n");
1847 for (unsigned i = 0; i < num_ctxts; i++)
1848 r.write (" gcc_jit_context *%s;\n",
1849 r.get_identifier (contexts[i]));
1850 r.write (" gcc_jit_result *result;\n"
1851 "\n");
1853 /* Create the contexts.
1854 The top-level context is acquired from a clean slate, the others as
1855 children of the prior context. */
1856 r.write (" %s = gcc_jit_context_acquire ();\n",
1857 r.get_identifier (contexts[0]));
1858 for (unsigned i = 1; i < num_ctxts; i++)
1859 r.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1860 r.get_identifier (contexts[i]),
1861 r.get_identifier (contexts[i - 1]));
1862 r.write (" set_options (");
1863 r.write_args (contexts);
1864 r.write (");\n");
1865 r.write (" create_code (");
1866 r.write_args (contexts);
1867 r.write (");\n");
1869 r.write (" result = gcc_jit_context_compile (%s);\n",
1870 r.get_identifier (this));
1872 for (unsigned i = num_ctxts; i > 0; i--)
1873 r.write (" gcc_jit_context_release (%s);\n",
1874 r.get_identifier (contexts[i - 1]));
1876 r.write (" gcc_jit_result_release (result);\n"
1877 " return 0;\n"
1878 "}\n\n");
1880 /* Define (char *) variables for use in calls to
1881 gcc_jit_context_enable_dump. */
1882 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1884 if (m_requested_dumps.length ())
1886 r.write ("/* Requested dumps for %s. */\n",
1887 r.get_identifier (contexts[ctxt_idx]));
1888 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1889 r.write ("static char *dump_%p;\n",
1890 (void *)&m_requested_dumps[i]);
1891 r.write ("\n");
1895 /* Write out values of options. */
1896 r.write ("static void\nset_options (");
1897 r.write_params (contexts);
1898 r.write (")\n{\n");
1899 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1901 if (ctxt_idx > 0)
1902 r.write ("\n");
1904 r.write (" /* Set options for %s. */\n",
1905 r.get_identifier (contexts[ctxt_idx]));
1907 r.write (" /* String options. */\n");
1908 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1910 r.write (" gcc_jit_context_set_str_option (%s,\n"
1911 " %s,\n",
1912 r.get_identifier (contexts[ctxt_idx]),
1913 str_option_reproducer_strings[opt_idx]);
1914 if (m_str_options[opt_idx])
1915 r.write (" \"%s\");\n",
1916 m_str_options[opt_idx]);
1917 else
1918 r.write (" NULL);\n");
1920 r.write (" /* Int options. */\n");
1921 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1922 r.write (" gcc_jit_context_set_int_option (%s,\n"
1923 " %s,\n"
1924 " %i);\n",
1925 r.get_identifier (contexts[ctxt_idx]),
1926 int_option_reproducer_strings[opt_idx],
1927 m_int_options[opt_idx]);
1928 r.write (" /* Boolean options. */\n");
1929 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1930 r.write (" gcc_jit_context_set_bool_option (%s,\n"
1931 " %s,\n"
1932 " %i);\n",
1933 r.get_identifier (contexts[ctxt_idx]),
1934 bool_option_reproducer_strings[opt_idx],
1935 m_bool_options[opt_idx]);
1936 for (int opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1937 r.write (" %s (%s, %i);\n",
1938 inner_bool_option_reproducer_strings[opt_idx],
1939 r.get_identifier (contexts[ctxt_idx]),
1940 m_inner_bool_options[opt_idx]);
1942 if (!m_command_line_options.is_empty ())
1944 int i;
1945 char *optname;
1946 r.write (" /* User-provided command-line options. */\n");
1947 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1948 r.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1949 r.get_identifier (contexts[ctxt_idx]),
1950 optname);
1953 if (!m_driver_options.is_empty ())
1955 int i;
1956 char *optname;
1957 r.write (" /* User-provided driver options. */\n");
1958 FOR_EACH_VEC_ELT (m_driver_options, i, optname)
1959 r.write (" gcc_jit_context_add_driver_option (%s, \"%s\");\n",
1960 r.get_identifier (contexts[ctxt_idx]),
1961 optname);
1964 if (m_requested_dumps.length ())
1966 r.write (" /* Requested dumps. */\n");
1967 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1968 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1970 r.write (" gcc_jit_context_enable_dump (%s,\n"
1971 " \"%s\",\n"
1972 " &dump_%p);\n",
1973 r.get_identifier (contexts[ctxt_idx]),
1974 m_requested_dumps[i].m_dumpname,
1975 (void *)&m_requested_dumps[i]);
1979 r.write ("}\n\n");
1981 r.write ("static void\ncreate_code (");
1982 r.write_params (contexts);
1983 r.write (")\n"
1984 "{\n");
1985 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1987 memento *m;
1988 int i;
1989 if (ctxt_idx > 0)
1990 r.write ("\n\n");
1992 r.write (" /* Replay of API calls for %s. */\n",
1993 r.get_identifier (contexts[ctxt_idx]));
1994 FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
1995 m->write_reproducer (r);
1997 r.write ("}\n");
2000 /* Copy the requested dumps within this context and all ancestors into
2001 OUT. */
2003 void
2004 recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
2006 if (m_parent_ctxt)
2007 m_parent_ctxt->get_all_requested_dumps (out);
2009 out->reserve (m_requested_dumps.length ());
2010 out->splice (m_requested_dumps);
2013 /* Create a recording::top_level_asm instance and add it to this
2014 context's list of mementos and to m_top_level_asms.
2016 Implements the post-error-checking part of
2017 gcc_jit_context_add_top_level_asm. */
2019 void
2020 recording::context::add_top_level_asm (recording::location *loc,
2021 const char *asm_stmts)
2023 recording::top_level_asm *asm_obj
2024 = new recording::top_level_asm (this, loc, new_string (asm_stmts));
2025 record (asm_obj);
2026 m_top_level_asms.safe_push (asm_obj);
2029 /* This is a pre-compilation check for the context (and any parents).
2031 Detect errors within the context, adding errors if any are found. */
2033 void
2034 recording::context::validate ()
2036 JIT_LOG_SCOPE (get_logger ());
2038 if (m_parent_ctxt)
2039 m_parent_ctxt->validate ();
2041 int i;
2042 function *fn;
2043 FOR_EACH_VEC_ELT (m_functions, i, fn)
2044 fn->validate ();
2047 /* The implementation of class gcc::jit::recording::memento. */
2049 /* Get a (const char *) debug description of the given memento, by
2050 calling the pure-virtual make_debug_string hook, caching the
2051 result.
2053 It is intended that this should only be called in debugging and
2054 error-handling paths, so this doesn't need to be particularly
2055 optimized. */
2057 const char *
2058 recording::memento::get_debug_string ()
2060 if (!m_debug_string)
2061 m_debug_string = make_debug_string ();
2062 return m_debug_string->c_str ();
2065 /* Default implementation of recording::memento::write_to_dump, writing
2066 an indented form of the memento's debug string to the dump. */
2068 void
2069 recording::memento::write_to_dump (dump &d)
2071 d.write(" %s\n", get_debug_string ());
2074 /* The implementation of class gcc::jit::recording::string. */
2076 /* Constructor for gcc::jit::recording::string::string, allocating a
2077 copy of the given text using new char[]. */
2079 recording::string::string (context *ctxt, const char *text, bool escaped)
2080 : memento (ctxt),
2081 m_escaped (escaped)
2083 m_len = strlen (text);
2084 m_buffer = new char[m_len + 1];
2085 strcpy (m_buffer, text);
2088 /* Destructor for gcc::jit::recording::string::string. */
2090 recording::string::~string ()
2092 delete[] m_buffer;
2095 /* Function for making gcc::jit::recording::string instances on a
2096 context via printf-style formatting.
2098 It is intended that this should only be called in debugging and
2099 error-handling paths, so this doesn't need to be particularly
2100 optimized, hence the double-copy of the string is acceptable. */
2102 recording::string *
2103 recording::string::from_printf (context *ctxt, const char *fmt, ...)
2105 int len;
2106 va_list ap;
2107 char *buf;
2108 recording::string *result;
2110 va_start (ap, fmt);
2111 len = vasprintf (&buf, fmt, ap);
2112 va_end (ap);
2114 if (buf == NULL || len < 0)
2116 ctxt->add_error (NULL, "malloc failure");
2117 return NULL;
2120 result = ctxt->new_string (buf);
2121 free (buf);
2122 return result;
2125 /* Implementation of recording::memento::make_debug_string for strings,
2126 wrapping the given string in quotes and escaping as necessary. */
2128 recording::string *
2129 recording::string::make_debug_string ()
2131 /* Avoid infinite recursion into strings when logging all mementos:
2132 don't re-escape strings: */
2133 if (m_escaped)
2134 return this;
2136 /* Wrap in quotes and do escaping etc */
2138 size_t sz = (1 /* opening quote */
2139 + (m_len * 2) /* each char might get escaped */
2140 + 1 /* closing quote */
2141 + 1); /* nil termintator */
2142 char *tmp = new char[sz];
2143 size_t len = 0;
2145 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
2146 APPEND('"'); /* opening quote */
2147 for (size_t i = 0; i < m_len ; i++)
2149 char ch = m_buffer[i];
2150 switch (ch)
2152 default:
2153 APPEND(ch);
2154 break;
2155 case '\t':
2156 APPEND('\\');
2157 APPEND('t');
2158 break;
2159 case '\n':
2160 APPEND('\\');
2161 APPEND('n');
2162 break;
2163 case '\\':
2164 case '"':
2165 APPEND('\\');
2166 APPEND(ch);
2167 break;
2170 APPEND('"'); /* closing quote */
2171 #undef APPEND
2172 tmp[len] = '\0'; /* nil termintator */
2174 string *result = m_ctxt->new_string (tmp, true);
2176 delete[] tmp;
2177 return result;
2180 /* Implementation of recording::memento::write_reproducer for strings. */
2182 void
2183 recording::string::write_reproducer (reproducer &)
2185 /* Empty. */
2188 /* The implementation of class gcc::jit::recording::location. */
2190 /* Implementation of recording::memento::replay_into for locations.
2192 Create a new playback::location and store it into the
2193 recording::location's m_playback_obj field. */
2195 void
2196 recording::location::replay_into (replayer *r)
2198 m_playback_obj = r->new_location (this,
2199 m_filename->c_str (),
2200 m_line,
2201 m_column);
2204 /* Implementation of recording::memento::make_debug_string for locations,
2205 turning them into the usual form:
2206 FILENAME:LINE:COLUMN
2207 like we do when emitting diagnostics. */
2209 recording::string *
2210 recording::location::make_debug_string ()
2212 return string::from_printf (m_ctxt,
2213 "%s:%i:%i",
2214 m_filename->c_str (), m_line, m_column);
2217 /* Implementation of recording::memento::write_reproducer for locations. */
2219 void
2220 recording::location::write_reproducer (reproducer &r)
2222 const char *id = r.make_identifier (this, "loc");
2223 r.write (" gcc_jit_location *%s =\n"
2224 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
2225 " %s, /* const char *filename */\n"
2226 " %i, /* int line */\n"
2227 " %i);/* int column */\n",
2229 r.get_identifier (get_context ()),
2230 m_filename->get_debug_string (),
2231 m_line, m_column);
2234 /* The implementation of class gcc::jit::recording::type. */
2236 /* Given a type T, get the type T*.
2238 If this doesn't already exist, generate a new memento_of_get_pointer
2239 instance and add it to this type's context's list of mementos.
2241 Otherwise, use the cached type.
2243 Implements the post-error-checking part of
2244 gcc_jit_type_get_pointer. */
2246 recording::type *
2247 recording::type::get_pointer ()
2249 if (!m_pointer_to_this_type)
2251 m_pointer_to_this_type = new memento_of_get_pointer (this);
2252 m_ctxt->record (m_pointer_to_this_type);
2254 return m_pointer_to_this_type;
2257 /* Given a type T, get the type const T.
2259 Implements the post-error-checking part of
2260 gcc_jit_type_get_const. */
2262 recording::type *
2263 recording::type::get_const ()
2265 recording::type *result = new memento_of_get_const (this);
2266 m_ctxt->record (result);
2267 return result;
2270 /* Given a type T, get the type restrict T.
2272 Implements the post-error-checking part of
2273 gcc_jit_type_get_restrict. */
2275 recording::type *
2276 recording::type::get_restrict ()
2278 recording::type *result = new memento_of_get_restrict (this);
2279 m_ctxt->record (result);
2280 return result;
2283 /* Given a type T, get the type volatile T.
2285 Implements the post-error-checking part of
2286 gcc_jit_type_get_volatile. */
2288 recording::type *
2289 recording::type::get_volatile ()
2291 recording::type *result = new memento_of_get_volatile (this);
2292 m_ctxt->record (result);
2293 return result;
2296 /* Given a type, get an aligned version of the type.
2298 Implements the post-error-checking part of
2299 gcc_jit_type_get_aligned. */
2301 recording::type *
2302 recording::type::get_aligned (size_t alignment_in_bytes)
2304 recording::type *result
2305 = new memento_of_get_aligned (this, alignment_in_bytes);
2306 m_ctxt->record (result);
2307 return result;
2310 /* Given a type, get a vector version of the type.
2312 Implements the post-error-checking part of
2313 gcc_jit_type_get_vector. */
2315 recording::type *
2316 recording::type::get_vector (size_t num_units)
2318 recording::type *result
2319 = new vector_type (this, num_units);
2320 m_ctxt->record (result);
2321 return result;
2324 const char *
2325 recording::type::access_as_type (reproducer &r)
2327 return r.get_identifier (this);
2330 /* Override of default implementation of
2331 recording::type::get_size.
2333 Return the size in bytes. This is in use for global
2334 initialization. */
2336 size_t
2337 recording::memento_of_get_type::get_size ()
2339 int size;
2340 switch (m_kind)
2342 case GCC_JIT_TYPE_VOID:
2343 return 0;
2344 case GCC_JIT_TYPE_BOOL:
2345 case GCC_JIT_TYPE_CHAR:
2346 case GCC_JIT_TYPE_SIGNED_CHAR:
2347 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2348 return 1;
2349 case GCC_JIT_TYPE_SHORT:
2350 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2351 size = SHORT_TYPE_SIZE;
2352 break;
2353 case GCC_JIT_TYPE_INT:
2354 case GCC_JIT_TYPE_UNSIGNED_INT:
2355 size = INT_TYPE_SIZE;
2356 break;
2357 case GCC_JIT_TYPE_LONG:
2358 case GCC_JIT_TYPE_UNSIGNED_LONG:
2359 size = LONG_TYPE_SIZE;
2360 break;
2361 case GCC_JIT_TYPE_LONG_LONG:
2362 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2363 size = LONG_LONG_TYPE_SIZE;
2364 break;
2365 case GCC_JIT_TYPE_UINT8_T:
2366 case GCC_JIT_TYPE_INT8_T:
2367 size = 8;
2368 break;
2369 case GCC_JIT_TYPE_UINT16_T:
2370 case GCC_JIT_TYPE_INT16_T:
2371 size = 16;
2372 break;
2373 case GCC_JIT_TYPE_UINT32_T:
2374 case GCC_JIT_TYPE_INT32_T:
2375 size = 32;
2376 break;
2377 case GCC_JIT_TYPE_UINT64_T:
2378 case GCC_JIT_TYPE_INT64_T:
2379 size = 64;
2380 break;
2381 case GCC_JIT_TYPE_UINT128_T:
2382 case GCC_JIT_TYPE_INT128_T:
2383 size = 128;
2384 break;
2385 case GCC_JIT_TYPE_FLOAT:
2386 size = FLOAT_TYPE_SIZE;
2387 break;
2388 case GCC_JIT_TYPE_DOUBLE:
2389 size = DOUBLE_TYPE_SIZE;
2390 break;
2391 case GCC_JIT_TYPE_LONG_DOUBLE:
2392 size = LONG_DOUBLE_TYPE_SIZE;
2393 break;
2394 case GCC_JIT_TYPE_SIZE_T:
2395 size = MAX_BITS_PER_WORD;
2396 break;
2397 default:
2398 /* As this function is called by
2399 'gcc_jit_global_set_initializer' and
2400 'recording::global::write_reproducer' possible types are only
2401 integrals and are covered by the previous cases. */
2402 gcc_unreachable ();
2405 return size / BITS_PER_UNIT;
2408 /* Implementation of pure virtual hook recording::type::dereference for
2409 recording::memento_of_get_type. */
2411 recording::type *
2412 recording::memento_of_get_type::dereference ()
2414 switch (m_kind)
2416 default: gcc_unreachable ();
2418 case GCC_JIT_TYPE_VOID:
2419 return NULL;
2421 case GCC_JIT_TYPE_VOID_PTR:
2422 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
2424 case GCC_JIT_TYPE_BOOL:
2425 case GCC_JIT_TYPE_CHAR:
2426 case GCC_JIT_TYPE_SIGNED_CHAR:
2427 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2428 case GCC_JIT_TYPE_SHORT:
2429 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2430 case GCC_JIT_TYPE_INT:
2431 case GCC_JIT_TYPE_UNSIGNED_INT:
2432 case GCC_JIT_TYPE_LONG:
2433 case GCC_JIT_TYPE_UNSIGNED_LONG:
2434 case GCC_JIT_TYPE_LONG_LONG:
2435 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2436 case GCC_JIT_TYPE_UINT8_T:
2437 case GCC_JIT_TYPE_UINT16_T:
2438 case GCC_JIT_TYPE_UINT32_T:
2439 case GCC_JIT_TYPE_UINT64_T:
2440 case GCC_JIT_TYPE_UINT128_T:
2441 case GCC_JIT_TYPE_INT8_T:
2442 case GCC_JIT_TYPE_INT16_T:
2443 case GCC_JIT_TYPE_INT32_T:
2444 case GCC_JIT_TYPE_INT64_T:
2445 case GCC_JIT_TYPE_INT128_T:
2446 case GCC_JIT_TYPE_FLOAT:
2447 case GCC_JIT_TYPE_DOUBLE:
2448 case GCC_JIT_TYPE_LONG_DOUBLE:
2449 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2450 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2451 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2452 /* Not a pointer: */
2453 return NULL;
2455 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2456 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
2458 case GCC_JIT_TYPE_SIZE_T:
2459 /* Not a pointer: */
2460 return NULL;
2462 case GCC_JIT_TYPE_FILE_PTR:
2463 /* Give the client code back an opaque "struct FILE". */
2464 return m_ctxt->get_opaque_FILE_type ();
2468 /* Implementation of pure virtual hook recording::type::is_int for
2469 recording::memento_of_get_type. */
2471 bool
2472 recording::memento_of_get_type::is_int () const
2474 switch (m_kind)
2476 default: gcc_unreachable ();
2478 case GCC_JIT_TYPE_VOID:
2479 return false;
2481 case GCC_JIT_TYPE_VOID_PTR:
2482 return false;
2484 case GCC_JIT_TYPE_BOOL:
2485 return false;
2487 case GCC_JIT_TYPE_CHAR:
2488 case GCC_JIT_TYPE_SIGNED_CHAR:
2489 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2490 case GCC_JIT_TYPE_SHORT:
2491 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2492 case GCC_JIT_TYPE_INT:
2493 case GCC_JIT_TYPE_UNSIGNED_INT:
2494 case GCC_JIT_TYPE_LONG:
2495 case GCC_JIT_TYPE_UNSIGNED_LONG:
2496 case GCC_JIT_TYPE_LONG_LONG:
2497 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2498 case GCC_JIT_TYPE_UINT8_T:
2499 case GCC_JIT_TYPE_UINT16_T:
2500 case GCC_JIT_TYPE_UINT32_T:
2501 case GCC_JIT_TYPE_UINT64_T:
2502 case GCC_JIT_TYPE_UINT128_T:
2503 case GCC_JIT_TYPE_INT8_T:
2504 case GCC_JIT_TYPE_INT16_T:
2505 case GCC_JIT_TYPE_INT32_T:
2506 case GCC_JIT_TYPE_INT64_T:
2507 case GCC_JIT_TYPE_INT128_T:
2508 return true;
2510 case GCC_JIT_TYPE_FLOAT:
2511 case GCC_JIT_TYPE_DOUBLE:
2512 case GCC_JIT_TYPE_LONG_DOUBLE:
2513 return false;
2515 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2516 return false;
2518 case GCC_JIT_TYPE_SIZE_T:
2519 return true;
2521 case GCC_JIT_TYPE_FILE_PTR:
2522 return false;
2524 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2525 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2526 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2527 return false;
2531 /* Implementation of pure virtual hook recording::type::is_signed for
2532 recording::memento_of_get_type. */
2534 bool
2535 recording::memento_of_get_type::is_signed () const
2537 switch (m_kind)
2539 default: gcc_unreachable ();
2541 case GCC_JIT_TYPE_SIGNED_CHAR:
2542 case GCC_JIT_TYPE_CHAR:
2543 case GCC_JIT_TYPE_SHORT:
2544 case GCC_JIT_TYPE_INT:
2545 case GCC_JIT_TYPE_LONG:
2546 case GCC_JIT_TYPE_LONG_LONG:
2547 case GCC_JIT_TYPE_INT8_T:
2548 case GCC_JIT_TYPE_INT16_T:
2549 case GCC_JIT_TYPE_INT32_T:
2550 case GCC_JIT_TYPE_INT64_T:
2551 case GCC_JIT_TYPE_INT128_T:
2552 return true;
2554 case GCC_JIT_TYPE_VOID:
2555 case GCC_JIT_TYPE_VOID_PTR:
2556 case GCC_JIT_TYPE_BOOL:
2557 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2558 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2559 case GCC_JIT_TYPE_UNSIGNED_INT:
2560 case GCC_JIT_TYPE_UNSIGNED_LONG:
2561 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2562 case GCC_JIT_TYPE_UINT8_T:
2563 case GCC_JIT_TYPE_UINT16_T:
2564 case GCC_JIT_TYPE_UINT32_T:
2565 case GCC_JIT_TYPE_UINT64_T:
2566 case GCC_JIT_TYPE_UINT128_T:
2568 case GCC_JIT_TYPE_FLOAT:
2569 case GCC_JIT_TYPE_DOUBLE:
2570 case GCC_JIT_TYPE_LONG_DOUBLE:
2572 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2574 case GCC_JIT_TYPE_SIZE_T:
2576 case GCC_JIT_TYPE_FILE_PTR:
2578 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2579 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2580 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2581 return false;
2585 /* Implementation of pure virtual hook recording::type::is_float for
2586 recording::memento_of_get_type. */
2588 bool
2589 recording::memento_of_get_type::is_float () const
2591 switch (m_kind)
2593 default: gcc_unreachable ();
2595 case GCC_JIT_TYPE_VOID:
2596 return false;
2598 case GCC_JIT_TYPE_VOID_PTR:
2599 return false;
2601 case GCC_JIT_TYPE_BOOL:
2602 return false;
2604 case GCC_JIT_TYPE_CHAR:
2605 case GCC_JIT_TYPE_SIGNED_CHAR:
2606 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2607 case GCC_JIT_TYPE_SHORT:
2608 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2609 case GCC_JIT_TYPE_INT:
2610 case GCC_JIT_TYPE_UNSIGNED_INT:
2611 case GCC_JIT_TYPE_LONG:
2612 case GCC_JIT_TYPE_UNSIGNED_LONG:
2613 case GCC_JIT_TYPE_LONG_LONG:
2614 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2615 case GCC_JIT_TYPE_UINT8_T:
2616 case GCC_JIT_TYPE_UINT16_T:
2617 case GCC_JIT_TYPE_UINT32_T:
2618 case GCC_JIT_TYPE_UINT64_T:
2619 case GCC_JIT_TYPE_UINT128_T:
2620 case GCC_JIT_TYPE_INT8_T:
2621 case GCC_JIT_TYPE_INT16_T:
2622 case GCC_JIT_TYPE_INT32_T:
2623 case GCC_JIT_TYPE_INT64_T:
2624 case GCC_JIT_TYPE_INT128_T:
2625 return false;
2627 case GCC_JIT_TYPE_FLOAT:
2628 case GCC_JIT_TYPE_DOUBLE:
2629 case GCC_JIT_TYPE_LONG_DOUBLE:
2630 return true;
2632 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2633 return false;
2635 case GCC_JIT_TYPE_SIZE_T:
2636 return false;
2638 case GCC_JIT_TYPE_FILE_PTR:
2639 return false;
2641 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2642 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2643 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2644 return true;
2648 /* Implementation of pure virtual hook recording::type::is_bool for
2649 recording::memento_of_get_type. */
2651 bool
2652 recording::memento_of_get_type::is_bool () const
2654 switch (m_kind)
2656 default: gcc_unreachable ();
2658 case GCC_JIT_TYPE_VOID:
2659 return false;
2661 case GCC_JIT_TYPE_VOID_PTR:
2662 return false;
2664 case GCC_JIT_TYPE_BOOL:
2665 return true;
2667 case GCC_JIT_TYPE_CHAR:
2668 case GCC_JIT_TYPE_SIGNED_CHAR:
2669 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2670 case GCC_JIT_TYPE_SHORT:
2671 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2672 case GCC_JIT_TYPE_INT:
2673 case GCC_JIT_TYPE_UNSIGNED_INT:
2674 case GCC_JIT_TYPE_LONG:
2675 case GCC_JIT_TYPE_UNSIGNED_LONG:
2676 case GCC_JIT_TYPE_LONG_LONG:
2677 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2678 case GCC_JIT_TYPE_UINT8_T:
2679 case GCC_JIT_TYPE_UINT16_T:
2680 case GCC_JIT_TYPE_UINT32_T:
2681 case GCC_JIT_TYPE_UINT64_T:
2682 case GCC_JIT_TYPE_UINT128_T:
2683 case GCC_JIT_TYPE_INT8_T:
2684 case GCC_JIT_TYPE_INT16_T:
2685 case GCC_JIT_TYPE_INT32_T:
2686 case GCC_JIT_TYPE_INT64_T:
2687 case GCC_JIT_TYPE_INT128_T:
2688 return false;
2690 case GCC_JIT_TYPE_FLOAT:
2691 case GCC_JIT_TYPE_DOUBLE:
2692 case GCC_JIT_TYPE_LONG_DOUBLE:
2693 return false;
2695 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2696 return false;
2698 case GCC_JIT_TYPE_SIZE_T:
2699 return false;
2701 case GCC_JIT_TYPE_FILE_PTR:
2702 return false;
2704 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2705 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2706 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2707 return false;
2711 /* Implementation of pure virtual hook recording::memento::replay_into
2712 for recording::memento_of_get_type. */
2714 void
2715 recording::memento_of_get_type::replay_into (replayer *r)
2717 set_playback_obj (r->get_type (m_kind));
2720 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2722 /* Descriptive strings for each of enum gcc_jit_types. */
2724 static const char * const get_type_strings[] = {
2725 "void", /* GCC_JIT_TYPE_VOID */
2726 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2728 "bool", /* GCC_JIT_TYPE_BOOL */
2730 "char", /* GCC_JIT_TYPE_CHAR */
2731 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2732 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2734 "short", /* GCC_JIT_TYPE_SHORT */
2735 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2737 "int", /* GCC_JIT_TYPE_INT */
2738 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2740 "long", /* GCC_JIT_TYPE_LONG */
2741 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2743 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2744 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2746 "float", /* GCC_JIT_TYPE_FLOAT */
2747 "double", /* GCC_JIT_TYPE_DOUBLE */
2748 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2750 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2752 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2754 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2756 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2757 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2758 "complex long double", /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2760 "__uint8_t", /* GCC_JIT_TYPE_UINT8_T */
2761 "__uint16_t", /* GCC_JIT_TYPE_UINT16_T */
2762 "__uint32_t", /* GCC_JIT_TYPE_UINT32_T */
2763 "__uint64_t", /* GCC_JIT_TYPE_UINT64_T */
2764 "__uint128_t", /* GCC_JIT_TYPE_UINT128_T */
2765 "__int8_t", /* GCC_JIT_TYPE_INT8_T */
2766 "__int16_t", /* GCC_JIT_TYPE_INT16_T */
2767 "__int32_t", /* GCC_JIT_TYPE_INT32_T */
2768 "__int64_t", /* GCC_JIT_TYPE_INT64_T */
2769 "__int128_t", /* GCC_JIT_TYPE_INT128_T */
2773 /* Implementation of recording::memento::make_debug_string for
2774 results of get_type, using a simple table of type names. */
2776 recording::string *
2777 recording::memento_of_get_type::make_debug_string ()
2779 return m_ctxt->new_string (get_type_strings[m_kind]);
2782 static const char * const get_type_enum_strings[] = {
2783 "GCC_JIT_TYPE_VOID",
2784 "GCC_JIT_TYPE_VOID_PTR",
2785 "GCC_JIT_TYPE_BOOL",
2786 "GCC_JIT_TYPE_CHAR",
2787 "GCC_JIT_TYPE_SIGNED_CHAR",
2788 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2789 "GCC_JIT_TYPE_SHORT",
2790 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2791 "GCC_JIT_TYPE_INT",
2792 "GCC_JIT_TYPE_UNSIGNED_INT",
2793 "GCC_JIT_TYPE_LONG",
2794 "GCC_JIT_TYPE_UNSIGNED_LONG",
2795 "GCC_JIT_TYPE_LONG_LONG",
2796 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2797 "GCC_JIT_TYPE_FLOAT",
2798 "GCC_JIT_TYPE_DOUBLE",
2799 "GCC_JIT_TYPE_LONG_DOUBLE",
2800 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2801 "GCC_JIT_TYPE_SIZE_T",
2802 "GCC_JIT_TYPE_FILE_PTR",
2803 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2804 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2805 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE",
2806 "GCC_JIT_TYPE_UINT8_T",
2807 "GCC_JIT_TYPE_UINT16_T",
2808 "GCC_JIT_TYPE_UINT32_T",
2809 "GCC_JIT_TYPE_UINT64_T",
2810 "GCC_JIT_TYPE_UINT128_T",
2811 "GCC_JIT_TYPE_INT8_T",
2812 "GCC_JIT_TYPE_INT16_T",
2813 "GCC_JIT_TYPE_INT32_T",
2814 "GCC_JIT_TYPE_INT64_T",
2815 "GCC_JIT_TYPE_INT128_T",
2818 void
2819 recording::memento_of_get_type::write_reproducer (reproducer &r)
2821 const char *id = r.make_identifier (this, "type");
2822 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2824 r.get_identifier (get_context ()),
2825 get_type_enum_strings[m_kind]);
2828 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2830 /* Override of default implementation of
2831 recording::type::get_size for get_pointer. */
2833 size_t
2834 recording::memento_of_get_pointer::get_size ()
2836 return POINTER_SIZE / BITS_PER_UNIT;
2839 /* Override of default implementation of
2840 recording::type::accepts_writes_from for get_pointer.
2842 Require a pointer type, and allowing writes to
2843 (const T *) from a (T*), but not the other way around. */
2845 bool
2846 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2848 /* Must be a pointer type: */
2849 type *rtype_points_to = rtype->is_pointer ();
2850 if (!rtype_points_to)
2851 return false;
2853 /* It's OK to assign to a (const T *) from a (T *). */
2854 if (m_other_type->unqualified ()->accepts_writes_from (rtype_points_to))
2856 return true;
2859 /* It's OK to assign to a (volatile const T *) from a (volatile const T *). */
2860 return m_other_type->is_same_type_as (rtype_points_to);
2863 /* Implementation of pure virtual hook recording::memento::replay_into
2864 for recording::memento_of_get_pointer. */
2866 void
2867 recording::memento_of_get_pointer::replay_into (replayer *)
2869 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2872 /* Implementation of recording::memento::make_debug_string for
2873 results of get_pointer, adding " *" to the underlying type,
2874 with special-casing to handle function pointer types. */
2876 recording::string *
2877 recording::memento_of_get_pointer::make_debug_string ()
2879 /* Special-case function pointer types, to put the "*" in parens between
2880 the return type and the params (for one level of dereferencing, at
2881 least). */
2882 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2883 return fn_type->make_debug_string_with_ptr ();
2885 return string::from_printf (m_ctxt,
2886 "%s *", m_other_type->get_debug_string ());
2889 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2891 void
2892 recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2894 /* We need to special-case function pointer types; see the notes in
2895 recording::function_type::write_deferred_reproducer. */
2896 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2898 fn_type->write_deferred_reproducer (r, this);
2899 return;
2902 const char *id = r.make_identifier (this, "type");
2903 r.write (" gcc_jit_type *%s =\n"
2904 " gcc_jit_type_get_pointer (%s);\n",
2906 r.get_identifier_as_type (m_other_type));
2909 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2911 /* Implementation of pure virtual hook recording::memento::replay_into
2912 for recording::memento_of_get_const. */
2914 void
2915 recording::memento_of_get_const::replay_into (replayer *)
2917 set_playback_obj (m_other_type->playback_type ()->get_const ());
2920 /* Implementation of recording::memento::make_debug_string for
2921 results of get_const, prepending "const ". */
2923 recording::string *
2924 recording::memento_of_get_const::make_debug_string ()
2926 return string::from_printf (m_ctxt,
2927 "const %s", m_other_type->get_debug_string ());
2930 /* Implementation of recording::memento::write_reproducer for const types. */
2932 void
2933 recording::memento_of_get_const::write_reproducer (reproducer &r)
2935 const char *id = r.make_identifier (this, "type");
2936 r.write (" gcc_jit_type *%s =\n"
2937 " gcc_jit_type_get_const (%s);\n",
2939 r.get_identifier_as_type (m_other_type));
2942 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2944 /* Implementation of pure virtual hook recording::memento::replay_into
2945 for recording::memento_of_get_volatile. */
2947 void
2948 recording::memento_of_get_volatile::replay_into (replayer *)
2950 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2953 /* Implementation of recording::memento::make_debug_string for
2954 results of get_volatile, prepending "volatile ". */
2956 recording::string *
2957 recording::memento_of_get_volatile::make_debug_string ()
2959 return string::from_printf (m_ctxt,
2960 "volatile %s", m_other_type->get_debug_string ());
2963 /* Implementation of recording::memento::write_reproducer for volatile
2964 types. */
2966 void
2967 recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2969 const char *id = r.make_identifier (this, "type");
2970 r.write (" gcc_jit_type *%s =\n"
2971 " gcc_jit_type_get_volatile (%s);\n",
2973 r.get_identifier_as_type (m_other_type));
2976 /* The implementation of class gcc::jit::recording::memento_of_get_restrict. */
2978 /* Implementation of pure virtual hook recording::memento::replay_into
2979 for recording::memento_of_get_restrict. */
2981 void
2982 recording::memento_of_get_restrict::replay_into (replayer *)
2984 set_playback_obj (m_other_type->playback_type ()->get_restrict ());
2987 /* Implementation of recording::memento::make_debug_string for
2988 results of get_restrict, prepending "restrict ". */
2990 recording::string *
2991 recording::memento_of_get_restrict::make_debug_string ()
2993 return string::from_printf (m_ctxt,
2994 "restrict %s", m_other_type->get_debug_string ());
2997 /* Implementation of recording::memento::write_reproducer for restrict
2998 types. */
3000 void
3001 recording::memento_of_get_restrict::write_reproducer (reproducer &r)
3003 const char *id = r.make_identifier (this, "type");
3004 r.write (" gcc_jit_type *%s =\n"
3005 " gcc_jit_type_get_restrict (%s);\n",
3007 r.get_identifier_as_type (m_other_type));
3010 /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
3012 /* Implementation of pure virtual hook recording::memento::replay_into
3013 for recording::memento_of_get_aligned. */
3015 void
3016 recording::memento_of_get_aligned::replay_into (replayer *)
3018 set_playback_obj
3019 (m_other_type->playback_type ()->get_aligned (m_alignment_in_bytes));
3022 /* Implementation of recording::memento::make_debug_string for
3023 results of get_aligned. */
3025 recording::string *
3026 recording::memento_of_get_aligned::make_debug_string ()
3028 return string::from_printf (m_ctxt,
3029 "%s __attribute__((aligned(%zi)))",
3030 m_other_type->get_debug_string (),
3031 m_alignment_in_bytes);
3034 /* Implementation of recording::memento::write_reproducer for aligned
3035 types. */
3037 void
3038 recording::memento_of_get_aligned::write_reproducer (reproducer &r)
3040 const char *id = r.make_identifier (this, "type");
3041 r.write (" gcc_jit_type *%s =\n"
3042 " gcc_jit_type_get_aligned (%s, %zi);\n",
3044 r.get_identifier_as_type (m_other_type),
3045 m_alignment_in_bytes);
3048 /* The implementation of class gcc::jit::recording::vector_type. */
3050 /* Implementation of pure virtual hook recording::memento::replay_into
3051 for recording::vector_type. */
3053 void
3054 recording::vector_type::replay_into (replayer *)
3056 set_playback_obj
3057 (m_other_type->playback_type ()->get_vector (m_num_units));
3060 /* Implementation of recording::memento::make_debug_string for
3061 results of get_vector. */
3063 recording::string *
3064 recording::vector_type::make_debug_string ()
3066 return string::from_printf
3067 (m_ctxt,
3068 "%s __attribute__((vector_size(sizeof (%s) * %zi)))",
3069 m_other_type->get_debug_string (),
3070 m_other_type->get_debug_string (),
3071 m_num_units);
3074 /* Implementation of recording::memento::write_reproducer for vector types. */
3076 void
3077 recording::vector_type::write_reproducer (reproducer &r)
3079 const char *id = r.make_identifier (this, "type");
3080 r.write (" gcc_jit_type *%s =\n"
3081 " gcc_jit_type_get_vector (%s, %zi);\n",
3083 r.get_identifier_as_type (m_other_type),
3084 m_num_units);
3087 /* The implementation of class gcc::jit::recording::array_type */
3089 /* Implementation of pure virtual hook recording::type::dereference for
3090 recording::array_type. */
3092 recording::type *
3093 recording::array_type::dereference ()
3095 return m_element_type;
3098 /* Implementation of pure virtual hook recording::memento::replay_into
3099 for recording::array_type. */
3101 void
3102 recording::array_type::replay_into (replayer *r)
3104 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
3105 m_element_type->playback_type (),
3106 m_num_elements));
3109 /* Implementation of recording::memento::make_debug_string for
3110 results of new_array_type. */
3112 recording::string *
3113 recording::array_type::make_debug_string ()
3115 return string::from_printf (m_ctxt,
3116 "%s[%d]",
3117 m_element_type->get_debug_string (),
3118 m_num_elements);
3121 /* Implementation of recording::memento::write_reproducer for array
3122 types. */
3124 void
3125 recording::array_type::write_reproducer (reproducer &r)
3127 const char *id = r.make_identifier (this, "array_type");
3128 r.write (" gcc_jit_type *%s =\n"
3129 " gcc_jit_context_new_array_type (%s,\n"
3130 " %s, /* gcc_jit_location *loc */\n"
3131 " %s, /* gcc_jit_type *element_type */\n"
3132 " %i); /* int num_elements */\n",
3134 r.get_identifier (get_context ()),
3135 r.get_identifier (m_loc),
3136 r.get_identifier_as_type (m_element_type),
3137 m_num_elements);
3140 /* The implementation of class gcc::jit::recording::function_type */
3142 /* Constructor for gcc::jit::recording::function_type. */
3144 recording::function_type::function_type (context *ctxt,
3145 type *return_type,
3146 int num_params,
3147 type **param_types,
3148 int is_variadic)
3149 : type (ctxt),
3150 m_return_type (return_type),
3151 m_param_types (),
3152 m_is_variadic (is_variadic)
3154 for (int i = 0; i< num_params; i++)
3155 m_param_types.safe_push (param_types[i]);
3158 /* Implementation of pure virtual hook recording::type::dereference for
3159 recording::function_type. */
3161 recording::type *
3162 recording::function_type::dereference ()
3164 return NULL;
3167 /* Implementation of virtual hook recording::type::is_same_type_as for
3168 recording::function_type.
3170 We override this to avoid requiring identity of function pointer types,
3171 so that if client code has obtained the same signature in
3172 different ways (e.g. via gcc_jit_context_new_function_ptr_type
3173 vs gcc_jit_function_get_address), the different function_type
3174 instances are treated as compatible.
3176 We can't use type::accepts_writes_from for this as we need a stronger
3177 notion of "sameness": if we have a fn_ptr type that has args that are
3178 themselves fn_ptr types, then those args still need to match exactly.
3180 Alternatively, we could consolidate attempts to create identical
3181 function_type instances so that pointer equality works, but that runs
3182 into issues about the lifetimes of the cache (w.r.t. nested contexts). */
3184 bool
3185 recording::function_type::is_same_type_as (type *other)
3187 gcc_assert (other);
3189 function_type *other_fn_type = other->dyn_cast_function_type ();
3190 if (!other_fn_type)
3191 return false;
3193 /* Everything must match. */
3195 if (!m_return_type->is_same_type_as (other_fn_type->m_return_type))
3196 return false;
3198 if (m_param_types.length () != other_fn_type->m_param_types.length ())
3199 return false;
3201 unsigned i;
3202 type *param_type;
3203 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
3204 if (!param_type->is_same_type_as (other_fn_type->m_param_types[i]))
3205 return false;
3207 if (m_is_variadic != other_fn_type->m_is_variadic)
3208 return false;
3210 /* Passed all tests. */
3211 return true;
3214 /* Implementation of pure virtual hook recording::memento::replay_into
3215 for recording::function_type. */
3217 void
3218 recording::function_type::replay_into (replayer *r)
3220 /* Convert m_param_types to a vec of playback type. */
3221 auto_vec <playback::type *> param_types;
3222 int i;
3223 recording::type *type;
3224 param_types.create (m_param_types.length ());
3225 FOR_EACH_VEC_ELT (m_param_types, i, type)
3226 param_types.safe_push (type->playback_type ());
3228 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
3229 &param_types,
3230 m_is_variadic));
3233 /* Special-casing for make_debug_string for get_pointer results for
3234 handling (one level) of pointers to functions. */
3236 recording::string *
3237 recording::function_type::make_debug_string_with_ptr ()
3239 return make_debug_string_with ("(*) ");
3242 /* Implementation of recording::memento::make_debug_string for
3243 results of new_function_type. */
3245 recording::string *
3246 recording::function_type::make_debug_string ()
3248 return make_debug_string_with ("");
3251 /* Build a debug string representation of the form:
3253 RESULT_TYPE INSERT (PARAM_TYPES)
3255 for use when handling 0 and 1 level of indirection to this
3256 function type. */
3258 recording::string *
3259 recording::function_type::make_debug_string_with (const char *insert)
3261 /* First, build a buffer for the arguments. */
3262 /* Calculate length of said buffer. */
3263 size_t sz = 1; /* nil terminator */
3264 for (unsigned i = 0; i< m_param_types.length (); i++)
3266 sz += strlen (m_param_types[i]->get_debug_string ());
3267 sz += 2; /* ", " separator */
3269 if (m_is_variadic)
3270 sz += 5; /* ", ..." separator and ellipsis */
3272 /* Now allocate and populate the buffer. */
3273 char *argbuf = new char[sz];
3274 size_t len = 0;
3276 for (unsigned i = 0; i< m_param_types.length (); i++)
3278 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
3279 len += strlen (m_param_types[i]->get_debug_string ());
3280 if (i + 1 < m_param_types.length ())
3282 strcpy (argbuf + len, ", ");
3283 len += 2;
3286 if (m_is_variadic)
3288 if (m_param_types.length ())
3290 strcpy (argbuf + len, ", ");
3291 len += 2;
3293 strcpy (argbuf + len, "...");
3294 len += 3;
3296 argbuf[len] = '\0';
3298 /* ...and use it to get the string for the call as a whole. */
3299 string *result = string::from_printf (m_ctxt,
3300 "%s %s(%s)",
3301 m_return_type->get_debug_string (),
3302 insert,
3303 argbuf);
3305 delete[] argbuf;
3307 return result;
3310 /* Implementation of recording::memento::write_reproducer for function
3311 types. */
3313 void
3314 recording::function_type::write_reproducer (reproducer &)
3316 /* see notes below. */
3319 /* There's a get_pointer within context::new_function_ptr_type:
3320 the type received by client code isn't the memento for the
3321 function_type, but instead the result of get_pointer on it.
3323 Hence we can't directly write a reproducer that gives function_type.
3324 Instead we special-case things within get_pointer, detecting this
3325 case, calling the following function. */
3327 void
3328 recording::function_type::write_deferred_reproducer (reproducer &r,
3329 memento *ptr_type)
3331 gcc_assert (ptr_type);
3332 r.make_identifier (this, "function_type");
3333 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
3334 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
3335 r.write (" gcc_jit_type *%s[%i] = {\n",
3336 param_types_id,
3337 m_param_types.length ());
3338 int i;
3339 type *param_type;
3340 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
3341 r.write (" %s,\n", r.get_identifier_as_type (param_type));
3342 r.write (" };\n");
3343 r.write (" gcc_jit_type *%s =\n"
3344 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
3345 " %s, /* gcc_jit_location *loc */\n"
3346 " %s, /* gcc_jit_type *return_type */\n"
3347 " %i, /* int num_params */\n"
3348 " %s, /* gcc_jit_type **param_types */\n"
3349 " %i); /* int is_variadic */\n",
3350 ptr_id,
3351 r.get_identifier (get_context ()),
3352 "NULL", /* location is not stored */
3353 r.get_identifier_as_type (m_return_type),
3354 m_param_types.length (),
3355 param_types_id,
3356 m_is_variadic);
3359 /* The implementation of class gcc::jit::recording::field. */
3361 /* Implementation of pure virtual hook recording::memento::replay_into
3362 for recording::field. */
3364 void
3365 recording::field::replay_into (replayer *r)
3367 set_playback_obj (r->new_field (playback_location (r, m_loc),
3368 m_type->playback_type (),
3369 playback_string (m_name)));
3372 /* Override the default implementation of
3373 recording::memento::write_to_dump. Dump each field
3374 by dumping a line of the form:
3375 TYPE NAME;
3376 so that we can build up a struct/union field by field. */
3378 void
3379 recording::field::write_to_dump (dump &d)
3381 d.write (" %s %s;\n",
3382 m_type->get_debug_string (),
3383 m_name->c_str ());
3386 /* Implementation of recording::memento::make_debug_string for
3387 results of new_field. */
3389 recording::string *
3390 recording::field::make_debug_string ()
3392 return m_name;
3395 /* Implementation of recording::memento::write_reproducer for fields. */
3397 void
3398 recording::field::write_reproducer (reproducer &r)
3400 const char *id = r.make_identifier (this, "field");
3401 r.write(" gcc_jit_field *%s =\n"
3402 " gcc_jit_context_new_field (%s,\n"
3403 " %s, /* gcc_jit_location *loc */\n"
3404 " %s, /* gcc_jit_type *type, */\n"
3405 " %s); /* const char *name */\n",
3407 r.get_identifier (get_context ()),
3408 r.get_identifier (m_loc),
3409 r.get_identifier_as_type (m_type),
3410 m_name->get_debug_string ());
3413 /* The implementation of class gcc::jit::recording::bitfield. */
3415 /* Implementation of pure virtual hook recording::memento::replay_into
3416 for recording::bitfield. */
3418 void
3419 recording::bitfield::replay_into (replayer *r)
3421 set_playback_obj (r->new_bitfield (playback_location (r, m_loc),
3422 m_type->playback_type (),
3423 m_width,
3424 playback_string (m_name)));
3427 /* Override the default implementation of
3428 recording::memento::write_to_dump. Dump each bit field
3429 by dumping a line of the form:
3430 TYPE NAME:WIDTH;
3431 so that we can build up a struct/union field by field. */
3433 void
3434 recording::bitfield::write_to_dump (dump &d)
3436 d.write (" %s %s:%d;\n",
3437 m_type->get_debug_string (),
3438 m_name->c_str (),
3439 m_width);
3442 /* Implementation of recording::memento::make_debug_string for
3443 results of new_bitfield. */
3445 recording::string *
3446 recording::bitfield::make_debug_string ()
3448 return string::from_printf (m_ctxt,
3449 "%s:%d",
3450 m_name->c_str (), m_width);
3453 /* Implementation of recording::memento::write_reproducer for bitfields. */
3455 void
3456 recording::bitfield::write_reproducer (reproducer &r)
3458 const char *id = r.make_identifier (this, "bitfield");
3459 r.write (" gcc_jit_field *%s =\n"
3460 " gcc_jit_context_new_bitfield (%s,\n"
3461 " %s, /* gcc_jit_location *loc */\n"
3462 " %s, /* gcc_jit_type *type, */\n"
3463 " %d, /* int width, */\n"
3464 " %s); /* const char *name */\n",
3466 r.get_identifier (get_context ()),
3467 r.get_identifier (m_loc),
3468 r.get_identifier_as_type (m_type),
3469 m_width,
3470 m_name->get_debug_string ());
3473 /* The implementation of class gcc::jit::recording::compound_type */
3475 /* The constructor for gcc::jit::recording::compound_type. */
3477 recording::compound_type::compound_type (context *ctxt,
3478 location *loc,
3479 string *name)
3480 : type (ctxt),
3481 m_loc (loc),
3482 m_name (name),
3483 m_fields (NULL)
3487 /* Set the fields of a compound type.
3489 Implements the post-error-checking part of
3490 gcc_jit_struct_set_fields, and is also used by
3491 gcc_jit_context_new_union_type. */
3493 void
3494 recording::compound_type::set_fields (location *loc,
3495 int num_fields,
3496 field **field_array)
3498 m_loc = loc;
3499 gcc_assert (m_fields == NULL);
3501 m_fields = new fields (this, num_fields, field_array);
3502 m_ctxt->record (m_fields);
3505 /* Implementation of pure virtual hook recording::type::dereference for
3506 recording::compound_type. */
3508 recording::type *
3509 recording::compound_type::dereference ()
3511 return NULL; /* not a pointer */
3514 /* The implementation of class gcc::jit::recording::struct_. */
3516 /* The constructor for gcc::jit::recording::struct_. */
3518 recording::struct_::struct_ (context *ctxt,
3519 location *loc,
3520 string *name)
3521 : compound_type (ctxt, loc, name)
3525 /* Implementation of pure virtual hook recording::memento::replay_into
3526 for recording::struct_. */
3528 void
3529 recording::struct_::replay_into (replayer *r)
3531 set_playback_obj (
3532 r->new_compound_type (playback_location (r, get_loc ()),
3533 get_name ()->c_str (),
3534 true /* is_struct */));
3537 const char *
3538 recording::struct_::access_as_type (reproducer &r)
3540 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
3541 r.get_identifier (this));
3544 /* Implementation of recording::memento::make_debug_string for
3545 structs. */
3547 recording::string *
3548 recording::struct_::make_debug_string ()
3550 return string::from_printf (m_ctxt,
3551 "struct %s", get_name ()->c_str ());
3554 void
3555 recording::struct_::write_reproducer (reproducer &r)
3557 const char *id = r.make_identifier (this, "struct");
3558 r.write (" gcc_jit_struct *%s =\n"
3559 " gcc_jit_context_new_opaque_struct (%s,\n"
3560 " %s, /* gcc_jit_location *loc */\n"
3561 " %s); /* const char *name */\n",
3563 r.get_identifier (get_context ()),
3564 r.get_identifier (get_loc ()),
3565 get_name ()->get_debug_string ());
3568 /* The implementation of class gcc::jit::recording::union_. */
3570 /* The constructor for gcc::jit::recording::union_. */
3572 recording::union_::union_ (context *ctxt,
3573 location *loc,
3574 string *name)
3575 : compound_type (ctxt, loc, name)
3579 /* Implementation of pure virtual hook recording::memento::replay_into
3580 for recording::union_. */
3582 void
3583 recording::union_::replay_into (replayer *r)
3585 set_playback_obj (
3586 r->new_compound_type (playback_location (r, get_loc ()),
3587 get_name ()->c_str (),
3588 false /* is_struct */));
3591 /* Implementation of recording::memento::make_debug_string for
3592 unions. */
3594 recording::string *
3595 recording::union_::make_debug_string ()
3597 return string::from_printf (m_ctxt,
3598 "union %s", get_name ()->c_str ());
3601 /* Implementation of recording::memento::write_reproducer for unions. */
3603 void
3604 recording::union_::write_reproducer (reproducer &r)
3606 const char *id = r.make_identifier (this, "union");
3608 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
3609 r.write (" gcc_jit_field *%s[%i] = {\n",
3610 fields_id,
3611 get_fields ()->length ());
3612 for (int i = 0; i < get_fields ()->length (); i++)
3613 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
3614 r.write (" };\n");
3616 r.write (" gcc_jit_type *%s =\n"
3617 " gcc_jit_context_new_union_type (%s,\n"
3618 " %s, /* gcc_jit_location *loc */\n"
3619 " %s, /* const char *name */\n"
3620 " %i, /* int num_fields */\n"
3621 " %s); /* gcc_jit_field **fields */\n",
3623 r.get_identifier (get_context ()),
3624 r.get_identifier (get_loc ()),
3625 get_name ()->get_debug_string (),
3626 get_fields ()->length (),
3627 fields_id);
3630 /* The implementation of class gcc::jit::recording::fields. */
3632 /* The constructor for gcc::jit::recording::fields. */
3634 recording::fields::fields (compound_type *struct_or_union,
3635 int num_fields,
3636 field **fields)
3637 : memento (struct_or_union->m_ctxt),
3638 m_struct_or_union (struct_or_union),
3639 m_fields ()
3641 for (int i = 0; i < num_fields; i++)
3643 gcc_assert (fields[i]->get_container () == NULL);
3644 fields[i]->set_container (m_struct_or_union);
3645 m_fields.safe_push (fields[i]);
3649 /* Implementation of pure virtual hook recording::memento::replay_into
3650 for recording::fields. */
3652 void
3653 recording::fields::replay_into (replayer *)
3655 auto_vec<playback::field *> playback_fields;
3656 playback_fields.create (m_fields.length ());
3657 for (unsigned i = 0; i < m_fields.length (); i++)
3658 playback_fields.safe_push (m_fields[i]->playback_field ());
3659 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
3662 /* Override the default implementation of
3663 recording::memento::write_to_dump by writing a union/struct
3664 declaration of this form:
3666 struct/union NAME {
3667 TYPE_1 NAME_1;
3668 TYPE_2 NAME_2;
3669 ....
3670 TYPE_N NAME_N;
3673 to the dump. */
3675 void
3676 recording::fields::write_to_dump (dump &d)
3678 int i;
3679 field *f;
3681 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
3682 FOR_EACH_VEC_ELT (m_fields, i, f)
3683 f->write_to_dump (d);
3684 d.write ("};\n");
3687 /* Implementation of recording::memento::write_reproducer for the fields
3688 subclass. */
3690 void
3691 recording::fields::write_reproducer (reproducer &r)
3693 if (m_struct_or_union)
3694 if (m_struct_or_union->dyn_cast_struct () == NULL)
3695 /* We have a union; the fields have already been written by
3696 union::write_reproducer. */
3697 return;
3699 const char *fields_id = r.make_identifier (this, "fields");
3700 r.write (" gcc_jit_field *%s[%i] = {\n",
3701 fields_id,
3702 m_fields.length ());
3703 int i;
3704 field *field;
3705 FOR_EACH_VEC_ELT (m_fields, i, field)
3706 r.write (" %s,\n", r.get_identifier (field));
3707 r.write (" };\n");
3709 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
3710 " %s, /* gcc_jit_location *loc */\n"
3711 " %i, /* int num_fields */\n"
3712 " %s); /* gcc_jit_field **fields */\n",
3713 r.get_identifier (m_struct_or_union),
3714 r.get_identifier ((memento *)NULL),
3715 m_fields.length (),
3716 fields_id);
3719 /* Implementation of recording::memento::make_debug_string for
3720 field tables. */
3722 recording::string *
3723 recording::fields::make_debug_string ()
3725 return string::from_printf (m_ctxt,
3726 "fields");
3729 /* The implementation of class gcc::jit::recording::rvalue. */
3731 /* Create a recording::access_field_rvalue instance and add it to
3732 the rvalue's context's list of mementos.
3734 Implements the post-error-checking part of
3735 gcc_jit_rvalue_access_field. */
3737 recording::rvalue *
3738 recording::rvalue::access_field (recording::location *loc,
3739 field *field)
3741 recording::rvalue *result =
3742 new access_field_rvalue (m_ctxt, loc, this, field);
3743 m_ctxt->record (result);
3744 return result;
3747 /* Create a recording::dereference_field_rvalue instance and add it to
3748 the rvalue's context's list of mementos.
3750 Implements the post-error-checking part of
3751 gcc_jit_rvalue_dereference_field. */
3753 recording::lvalue *
3754 recording::rvalue::dereference_field (recording::location *loc,
3755 field *field)
3757 recording::lvalue *result =
3758 new dereference_field_rvalue (m_ctxt, loc, this, field);
3759 m_ctxt->record (result);
3760 return result;
3763 /* Create a recording::dereference_rvalue instance and add it to the
3764 rvalue's context's list of mementos.
3766 Implements the post-error-checking part of
3767 gcc_jit_rvalue_dereference. */
3769 recording::lvalue *
3770 recording::rvalue::dereference (recording::location *loc)
3772 recording::lvalue *result =
3773 new dereference_rvalue (m_ctxt, loc, this);
3774 m_ctxt->record (result);
3775 return result;
3778 /* An rvalue visitor, for validating that every rvalue within an expression
3779 trees within "STMT" has the correct scope (e.g. no access to locals
3780 of a different function). */
3782 class rvalue_usage_validator : public recording::rvalue_visitor
3784 public:
3785 rvalue_usage_validator (const char *api_funcname,
3786 recording::context *ctxt,
3787 recording::statement *stmt);
3789 void
3790 visit (recording::rvalue *rvalue) final override;
3792 private:
3793 const char *m_api_funcname;
3794 recording::context *m_ctxt;
3795 recording::statement *m_stmt;
3798 /* The trivial constructor for rvalue_usage_validator. */
3800 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
3801 recording::context *ctxt,
3802 recording::statement *stmt)
3803 : m_api_funcname (api_funcname),
3804 m_ctxt (ctxt),
3805 m_stmt (stmt)
3809 /* Verify that the given rvalue is in the correct scope. */
3811 void
3812 rvalue_usage_validator::visit (recording::rvalue *rvalue)
3814 gcc_assert (m_stmt->get_block ());
3815 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
3817 /* Most rvalues don't have a scope (only locals and params). */
3818 if (rvalue->get_scope ())
3820 if (rvalue->get_scope () != stmt_scope)
3821 m_ctxt->add_error
3822 (rvalue->get_loc (),
3823 "%s:"
3824 " rvalue %s (type: %s)"
3825 " has scope limited to function %s"
3826 " but was used within function %s"
3827 " (in statement: %s)",
3828 m_api_funcname,
3829 rvalue->get_debug_string (),
3830 rvalue->get_type ()->get_debug_string (),
3831 rvalue->get_scope ()->get_debug_string (),
3832 stmt_scope->get_debug_string (),
3833 m_stmt->get_debug_string ());
3835 else
3837 if (rvalue->dyn_cast_param ())
3838 m_ctxt->add_error
3839 (rvalue->get_loc (),
3840 "%s:"
3841 " param %s (type: %s)"
3842 " was used within function %s"
3843 " (in statement: %s)"
3844 " but is not associated with any function",
3845 m_api_funcname,
3846 rvalue->get_debug_string (),
3847 rvalue->get_type ()->get_debug_string (),
3848 stmt_scope->get_debug_string (),
3849 m_stmt->get_debug_string ());
3853 /* Verify that it's valid to use this rvalue (and all expressions
3854 in the tree below it) within the given statement.
3856 For example, we must reject attempts to use a local from one
3857 function within a different function here, or we'll get
3858 an ICE deep inside toplev::main. */
3860 void
3861 recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
3863 rvalue_usage_validator v (api_funcname,
3864 s->get_context (),
3867 /* Verify that it's OK to use this rvalue within s. */
3868 v.visit (this);
3870 /* Traverse the expression tree below "this", verifying all rvalues
3871 within it. */
3872 visit_children (&v);
3875 /* Set the scope of this rvalue to be the given function. This can only
3876 be done once on a given rvalue. */
3878 void
3879 recording::rvalue::set_scope (function *scope)
3881 gcc_assert (scope);
3882 gcc_assert (m_scope == NULL);
3883 m_scope = scope;
3887 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3888 themselves.
3889 Instances of rvalue don't need an upcast call. */
3891 const char *
3892 recording::rvalue::access_as_rvalue (reproducer &r)
3894 return r.get_identifier (this);
3897 /* Return a debug string for the given rvalue, wrapping it in parentheses
3898 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3899 stronger precedence that this rvalue's precedence.
3901 For example, given:
3903 MULT
3905 PLUS MINUS
3906 / \ / \
3907 A B C D
3909 we want to emit:
3911 (A + B) * (C - D)
3913 since MULT has strong precedence than PLUS and MINUS, whereas for:
3915 PLUS
3917 MULT DIVIDE
3918 / \ / \
3919 A B C D
3921 we can simply emit:
3923 A * B + C / D
3925 since PLUS has weaker precedence than MULT and DIVIDE. */
3927 const char *
3928 recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
3930 enum precedence this_prec = get_precedence ();
3932 /* If this_prec has stronger precedence than outer_prec, we don't
3933 need to wrap this in parens within the outer debug string.
3934 Stronger precedences occur earlier than weaker within the enum,
3935 so this is a less than test. Equal precedences don't need
3936 parentheses. */
3937 if (this_prec <= outer_prec)
3938 return get_debug_string();
3940 /* Otherwise, we need parentheses. */
3942 /* Lazily-build and cache m_parenthesized_string. */
3943 if (!m_parenthesized_string)
3945 const char *debug_string = get_debug_string ();
3946 m_parenthesized_string = string::from_printf (get_context (),
3947 "(%s)",
3948 debug_string);
3950 gcc_assert (m_parenthesized_string);
3951 return m_parenthesized_string->c_str ();
3955 /* The implementation of class gcc::jit::recording::lvalue. */
3957 /* Create a recording::new_access_field_of_lvalue instance and add it to
3958 the lvalue's context's list of mementos.
3960 Implements the post-error-checking part of
3961 gcc_jit_lvalue_access_field. */
3963 recording::lvalue *
3964 recording::lvalue::access_field (recording::location *loc,
3965 field *field)
3967 recording::lvalue *result =
3968 new access_field_of_lvalue (m_ctxt, loc, this, field);
3969 m_ctxt->record (result);
3970 return result;
3973 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3974 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3975 upcast call. */
3977 const char *
3978 recording::lvalue::access_as_rvalue (reproducer &r)
3980 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3981 r.get_identifier (this));
3984 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3985 Instances of lvalue don't need to be upcast. */
3987 const char *
3988 recording::lvalue::access_as_lvalue (reproducer &r)
3990 return r.get_identifier (this);
3993 /* Create a recording::get_address_of_lvalue instance and add it to
3994 the lvalue's context's list of mementos.
3996 Implements the post-error-checking part of
3997 gcc_jit_lvalue_get_address. */
3999 recording::rvalue *
4000 recording::lvalue::get_address (recording::location *loc)
4002 recording::rvalue *result =
4003 new get_address_of_lvalue (m_ctxt, loc, this);
4004 m_ctxt->record (result);
4005 return result;
4008 void
4009 recording::lvalue::set_tls_model (enum gcc_jit_tls_model model)
4011 m_tls_model = model;
4014 void recording::lvalue::set_link_section (const char *name)
4016 m_link_section = new_string (name);
4019 void recording::lvalue::set_register_name (const char *reg_name)
4021 m_reg_name = new_string (reg_name);
4024 void recording::lvalue::set_alignment (unsigned bytes)
4026 m_alignment = bytes;
4029 /* The implementation of class gcc::jit::recording::param. */
4031 /* Implementation of pure virtual hook recording::memento::replay_into
4032 for recording::param. */
4034 void
4035 recording::param::replay_into (replayer *r)
4037 set_playback_obj (r->new_param (playback_location (r, m_loc),
4038 m_type->playback_type (),
4039 m_name->c_str ()));
4042 /* Implementation of recording::rvalue::access_as_rvalue for params.
4043 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
4044 upcast call. */
4046 const char *
4047 recording::param::access_as_rvalue (reproducer &r)
4049 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
4050 r.get_identifier (this));
4053 /* Implementation of recording::lvalue::access_as_lvalue for params.
4054 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
4055 upcast call. */
4057 const char *
4058 recording::param::access_as_lvalue (reproducer &r)
4060 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
4061 r.get_identifier (this));
4064 /* Implementation of recording::memento::write_reproducer for params. */
4066 void
4067 recording::param::write_reproducer (reproducer &r)
4069 const char *id = r.make_identifier (this, "param");
4070 r.write (" gcc_jit_param *%s =\n"
4071 " gcc_jit_context_new_param (%s,\n"
4072 " %s, /* gcc_jit_location *loc */\n"
4073 " %s, /*gcc_jit_type *type */\n"
4074 " %s); /* const char *name */\n",
4076 r.get_identifier (get_context ()),
4077 r.get_identifier (m_loc),
4078 r.get_identifier_as_type (m_type),
4079 m_name->get_debug_string ());
4082 /* The implementation of class gcc::jit::recording::function. */
4084 /* gcc::jit::recording::function's constructor. */
4086 recording::function::function (context *ctxt,
4087 recording::location *loc,
4088 enum gcc_jit_function_kind kind,
4089 type *return_type,
4090 recording::string *name,
4091 int num_params,
4092 recording::param **params,
4093 int is_variadic,
4094 enum built_in_function builtin_id)
4095 : memento (ctxt),
4096 m_loc (loc),
4097 m_kind (kind),
4098 m_return_type (return_type),
4099 m_name (name),
4100 m_params (),
4101 m_is_variadic (is_variadic),
4102 m_builtin_id (builtin_id),
4103 m_locals (),
4104 m_blocks (),
4105 m_fn_ptr_type (NULL)
4107 for (int i = 0; i< num_params; i++)
4109 param *param = params[i];
4110 gcc_assert (param);
4112 /* Associate each param with this function.
4114 Verify that the param doesn't already have a function. */
4115 if (param->get_scope ())
4117 /* We've already rejected attempts to reuse a param between
4118 different functions (within gcc_jit_context_new_function), so
4119 if the param *does* already have a function, it must be being
4120 reused within the params array for this function. We must
4121 produce an error for this reuse (blocking the compile), since
4122 otherwise we'd have an ICE later on. */
4123 gcc_assert (this == param->get_scope ());
4124 ctxt->add_error
4125 (loc,
4126 "gcc_jit_context_new_function:"
4127 " parameter %s (type: %s)"
4128 " is used more than once when creating function %s",
4129 param->get_debug_string (),
4130 param->get_type ()->get_debug_string (),
4131 name->c_str ());
4133 else
4135 /* The normal, non-error case: associate this function with the
4136 param. */
4137 param->set_scope (this);
4140 m_params.safe_push (param);
4144 /* Implementation of pure virtual hook recording::memento::replay_into
4145 for recording::function. */
4147 void
4148 recording::function::replay_into (replayer *r)
4150 /* Convert m_params to a vec of playback param. */
4151 auto_vec <playback::param *> params;
4152 int i;
4153 recording::param *param;
4154 params.create (m_params.length ());
4155 FOR_EACH_VEC_ELT (m_params, i, param)
4156 params.safe_push (param->playback_param ());
4158 set_playback_obj (r->new_function (playback_location (r, m_loc),
4159 m_kind,
4160 m_return_type->playback_type (),
4161 m_name->c_str (),
4162 &params,
4163 m_is_variadic,
4164 m_builtin_id));
4167 /* Create a recording::local instance and add it to
4168 the functions's context's list of mementos, and to the function's
4169 list of locals.
4171 Implements the post-error-checking part of
4172 gcc_jit_function_new_local. */
4174 recording::lvalue *
4175 recording::function::new_local (recording::location *loc,
4176 type *type,
4177 const char *name)
4179 local *result = new local (this, loc, type, new_string (name));
4180 m_ctxt->record (result);
4181 m_locals.safe_push (result);
4182 return result;
4185 /* Create a recording::block instance and add it to
4186 the functions's context's list of mementos, and to the function's
4187 list of blocks.
4189 Implements the post-error-checking part of
4190 gcc_jit_function_new_block. */
4192 recording::block*
4193 recording::function::new_block (const char *name)
4195 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
4197 recording::block *result =
4198 new recording::block (this, m_blocks.length (), new_string (name));
4199 m_ctxt->record (result);
4200 m_blocks.safe_push (result);
4201 return result;
4204 /* Override the default implementation of
4205 recording::memento::write_to_dump by dumping a C-like
4206 representation of the function; either like a prototype
4207 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
4208 all other kinds of function. */
4210 void
4211 recording::function::write_to_dump (dump &d)
4213 switch (m_kind)
4215 default: gcc_unreachable ();
4216 case GCC_JIT_FUNCTION_EXPORTED:
4217 case GCC_JIT_FUNCTION_IMPORTED:
4218 d.write ("extern ");
4219 break;
4220 case GCC_JIT_FUNCTION_INTERNAL:
4221 d.write ("static ");
4222 break;
4223 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
4224 d.write ("static inline ");
4225 break;
4227 d.write ("%s\n", m_return_type->get_debug_string ());
4229 if (d.update_locations ())
4230 m_loc = d.make_location ();
4232 d.write ("%s (", get_debug_string ());
4234 int i;
4235 recording::param *param;
4236 FOR_EACH_VEC_ELT (m_params, i, param)
4238 if (i > 0)
4239 d.write (", ");
4240 d.write ("%s %s",
4241 param->get_type ()->get_debug_string (),
4242 param->get_debug_string ());
4244 d.write (")");
4245 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
4247 d.write ("; /* (imported) */\n\n");
4249 else
4251 int i;
4252 local *var = NULL;
4253 block *b;
4254 d.write ("\n{\n");
4256 /* Write locals: */
4257 FOR_EACH_VEC_ELT (m_locals, i, var)
4258 var->write_to_dump (d);
4259 if (m_locals.length ())
4260 d.write ("\n");
4262 /* Write each block: */
4263 FOR_EACH_VEC_ELT (m_blocks, i, b)
4265 if (i > 0)
4266 d.write ("\n");
4267 b->write_to_dump (d);
4270 d.write ("}\n\n");
4274 /* Pre-compilation validation of a function, for those things we can't
4275 check until the context is (supposedly) fully-populated. */
4277 void
4278 recording::function::validate ()
4280 /* Complain about empty functions with non-void return type. */
4281 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
4282 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
4283 if (m_blocks.length () == 0)
4284 m_ctxt->add_error (m_loc,
4285 "function %s returns non-void (type: %s)"
4286 " but has no blocks",
4287 get_debug_string (),
4288 m_return_type->get_debug_string ());
4290 /* Check that all blocks are terminated. */
4291 int num_invalid_blocks = 0;
4293 int i;
4294 block *b;
4296 FOR_EACH_VEC_ELT (m_blocks, i, b)
4297 if (!b->validate ())
4298 num_invalid_blocks++;
4301 /* Check that all blocks are reachable. */
4302 if (!m_ctxt->get_inner_bool_option
4303 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
4304 && m_blocks.length () > 0 && num_invalid_blocks == 0)
4306 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
4307 flag, starting at the initial block. */
4308 auto_vec<block *> worklist (m_blocks.length ());
4309 worklist.safe_push (m_blocks[0]);
4310 while (worklist.length () > 0)
4312 block *b = worklist.pop ();
4313 b->m_is_reachable = true;
4315 /* Add successor blocks that aren't yet marked to the worklist. */
4316 /* We checked that each block has a terminating statement above . */
4317 vec <block *> successors = b->get_successor_blocks ();
4318 int i;
4319 block *succ;
4320 FOR_EACH_VEC_ELT (successors, i, succ)
4321 if (!succ->m_is_reachable)
4322 worklist.safe_push (succ);
4323 successors.release ();
4326 /* Now complain about any blocks that haven't been marked. */
4328 int i;
4329 block *b;
4330 FOR_EACH_VEC_ELT (m_blocks, i, b)
4331 if (!b->m_is_reachable)
4332 m_ctxt->add_error (b->get_loc (),
4333 "unreachable block: %s",
4334 b->get_debug_string ());
4339 /* Implements the post-error-checking part of
4340 gcc_jit_function_dump_to_dot. */
4342 void
4343 recording::function::dump_to_dot (const char *path)
4345 FILE *fp = fopen (path, "w");
4346 if (!fp)
4347 return;
4349 pretty_printer the_pp;
4350 the_pp.buffer->stream = fp;
4352 pretty_printer *pp = &the_pp;
4354 pp_printf (pp, "digraph %s", get_debug_string ());
4355 pp_string (pp, " {\n");
4357 /* Blocks: */
4359 int i;
4360 block *b;
4361 FOR_EACH_VEC_ELT (m_blocks, i, b)
4362 b->dump_to_dot (pp);
4365 /* Edges: */
4367 int i;
4368 block *b;
4369 FOR_EACH_VEC_ELT (m_blocks, i, b)
4370 b->dump_edges_to_dot (pp);
4373 pp_string (pp, "}\n");
4374 pp_flush (pp);
4375 fclose (fp);
4378 /* Implements the post-error-checking part of
4379 gcc_jit_function_get_address. */
4381 recording::rvalue *
4382 recording::function::get_address (recording::location *loc)
4384 /* Lazily create and cache the function pointer type. */
4385 if (!m_fn_ptr_type)
4387 /* Make a recording::function_type for this function. */
4388 auto_vec <recording::type *> param_types (m_params.length ());
4389 unsigned i;
4390 recording::param *param;
4391 FOR_EACH_VEC_ELT (m_params, i, param)
4392 param_types.safe_push (param->get_type ());
4393 recording::function_type *fn_type
4394 = m_ctxt->new_function_type (m_return_type,
4395 m_params.length (),
4396 param_types.address (),
4397 m_is_variadic);
4398 m_fn_ptr_type = fn_type->get_pointer ();
4400 gcc_assert (m_fn_ptr_type);
4402 rvalue *result = new function_pointer (get_context (), loc, this, m_fn_ptr_type);
4403 m_ctxt->record (result);
4404 return result;
4407 /* Implementation of recording::memento::make_debug_string for
4408 functions. */
4410 recording::string *
4411 recording::function::make_debug_string ()
4413 return m_name;
4416 /* A table of enum gcc_jit_function_kind values expressed in string
4417 form. */
4419 static const char * const names_of_function_kinds[] = {
4420 "GCC_JIT_FUNCTION_EXPORTED",
4421 "GCC_JIT_FUNCTION_INTERNAL",
4422 "GCC_JIT_FUNCTION_IMPORTED",
4423 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
4426 /* Implementation of recording::memento::write_reproducer for functions. */
4428 void
4429 recording::function::write_reproducer (reproducer &r)
4431 const char *id = r.make_identifier (this, "func");
4433 if (m_builtin_id)
4435 r.write (" gcc_jit_function *%s =\n"
4436 " gcc_jit_context_get_builtin_function (%s,\n"
4437 " %s);\n",
4439 r.get_identifier (get_context ()),
4440 m_name->get_debug_string ());
4441 return;
4443 const char *params_id = r.make_tmp_identifier ("params_for", this);
4444 r.write (" gcc_jit_param *%s[%i] = {\n",
4445 params_id,
4446 m_params.length ());
4447 int i;
4448 param *param;
4449 FOR_EACH_VEC_ELT (m_params, i, param)
4450 r.write (" %s,\n", r.get_identifier (param));
4451 r.write (" };\n");
4452 r.write (" gcc_jit_function *%s =\n"
4453 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
4454 " %s, /* gcc_jit_location *loc */\n"
4455 " %s, /* enum gcc_jit_function_kind kind */\n"
4456 " %s, /* gcc_jit_type *return_type */\n"
4457 " %s, /* const char *name */\n"
4458 " %i, /* int num_params */\n"
4459 " %s, /* gcc_jit_param **params */\n"
4460 " %i); /* int is_variadic */\n",
4462 r.get_identifier (get_context ()),
4463 r.get_identifier (m_loc),
4464 names_of_function_kinds[m_kind],
4465 r.get_identifier_as_type (m_return_type),
4466 m_name->get_debug_string (),
4467 m_params.length (),
4468 params_id,
4469 m_is_variadic);
4473 /* The implementation of class gcc::jit::recording::block. */
4475 /* Create a recording::eval instance and add it to
4476 the block's context's list of mementos, and to the block's
4477 list of statements.
4479 Implements the heart of gcc_jit_block_add_eval. */
4481 recording::statement *
4482 recording::block::add_eval (recording::location *loc,
4483 recording::rvalue *rvalue)
4485 statement *result = new eval (this, loc, rvalue);
4486 m_ctxt->record (result);
4487 m_statements.safe_push (result);
4488 return result;
4491 /* Create a recording::assignment instance and add it to
4492 the block's context's list of mementos, and to the block's
4493 list of statements.
4495 Implements the heart of gcc_jit_block_add_assignment. */
4497 recording::statement *
4498 recording::block::add_assignment (recording::location *loc,
4499 recording::lvalue *lvalue,
4500 recording::rvalue *rvalue)
4502 statement *result = new assignment (this, loc, lvalue, rvalue);
4503 m_ctxt->record (result);
4504 m_statements.safe_push (result);
4505 return result;
4508 /* Create a recording::assignment_op instance and add it to
4509 the block's context's list of mementos, and to the block's
4510 list of statements.
4512 Implements the heart of gcc_jit_block_add_assignment_op. */
4514 recording::statement *
4515 recording::block::add_assignment_op (recording::location *loc,
4516 recording::lvalue *lvalue,
4517 enum gcc_jit_binary_op op,
4518 recording::rvalue *rvalue)
4520 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
4521 m_ctxt->record (result);
4522 m_statements.safe_push (result);
4523 return result;
4526 /* Create a recording::comment instance and add it to
4527 the block's context's list of mementos, and to the block's
4528 list of statements.
4530 Implements the heart of gcc_jit_block_add_comment. */
4532 recording::statement *
4533 recording::block::add_comment (recording::location *loc,
4534 const char *text)
4536 statement *result = new comment (this, loc, new_string (text));
4537 m_ctxt->record (result);
4538 m_statements.safe_push (result);
4539 return result;
4542 /* Create a recording::extended_asm_simple instance and add it to
4543 the block's context's list of mementos, and to the block's
4544 list of statements.
4546 Implements the heart of gcc_jit_block_add_extended_asm. */
4548 recording::extended_asm *
4549 recording::block::add_extended_asm (location *loc,
4550 const char *asm_template)
4552 extended_asm *result
4553 = new extended_asm_simple (this, loc, new_string (asm_template));
4554 m_ctxt->record (result);
4555 m_statements.safe_push (result);
4556 return result;
4559 /* Create a recording::end_with_conditional instance and add it to
4560 the block's context's list of mementos, and to the block's
4561 list of statements.
4563 Implements the heart of gcc_jit_block_end_with_conditional. */
4565 recording::statement *
4566 recording::block::end_with_conditional (recording::location *loc,
4567 recording::rvalue *boolval,
4568 recording::block *on_true,
4569 recording::block *on_false)
4571 statement *result = new conditional (this, loc, boolval, on_true, on_false);
4572 m_ctxt->record (result);
4573 m_statements.safe_push (result);
4574 m_has_been_terminated = true;
4575 return result;
4578 /* Create a recording::end_with_jump instance and add it to
4579 the block's context's list of mementos, and to the block's
4580 list of statements.
4582 Implements the heart of gcc_jit_block_end_with_jump. */
4584 recording::statement *
4585 recording::block::end_with_jump (recording::location *loc,
4586 recording::block *target)
4588 statement *result = new jump (this, loc, target);
4589 m_ctxt->record (result);
4590 m_statements.safe_push (result);
4591 m_has_been_terminated = true;
4592 return result;
4595 /* Create a recording::end_with_return instance and add it to
4596 the block's context's list of mementos, and to the block's
4597 list of statements.
4599 Implements the post-error-checking parts of
4600 gcc_jit_block_end_with_return and
4601 gcc_jit_block_end_with_void_return. */
4603 recording::statement *
4604 recording::block::end_with_return (recording::location *loc,
4605 recording::rvalue *rvalue)
4607 /* This is used by both gcc_jit_function_add_return and
4608 gcc_jit_function_add_void_return; rvalue will be non-NULL for
4609 the former and NULL for the latter. */
4610 statement *result = new return_ (this, loc, rvalue);
4611 m_ctxt->record (result);
4612 m_statements.safe_push (result);
4613 m_has_been_terminated = true;
4614 return result;
4617 /* Create a recording::switch_ instance and add it to
4618 the block's context's list of mementos, and to the block's
4619 list of statements.
4621 Implements the heart of gcc_jit_block_end_with_switch. */
4623 recording::statement *
4624 recording::block::end_with_switch (recording::location *loc,
4625 recording::rvalue *expr,
4626 recording::block *default_block,
4627 int num_cases,
4628 recording::case_ **cases)
4630 statement *result = new switch_ (this, loc,
4631 expr,
4632 default_block,
4633 num_cases,
4634 cases);
4635 m_ctxt->record (result);
4636 m_statements.safe_push (result);
4637 m_has_been_terminated = true;
4638 return result;
4641 /* Create a recording::extended_asm_goto instance and add it to
4642 the block's context's list of mementos, and to the block's
4643 list of statements.
4645 Implements the heart of gcc_jit_block_end_with_extended_asm_goto. */
4648 recording::extended_asm *
4649 recording::block::end_with_extended_asm_goto (location *loc,
4650 const char *asm_template,
4651 int num_goto_blocks,
4652 block **goto_blocks,
4653 block *fallthrough_block)
4655 extended_asm *result
4656 = new extended_asm_goto (this, loc, new_string (asm_template),
4657 num_goto_blocks, goto_blocks,
4658 fallthrough_block);
4659 m_ctxt->record (result);
4660 m_statements.safe_push (result);
4661 m_has_been_terminated = true;
4662 return result;
4665 /* Override the default implementation of
4666 recording::memento::write_to_dump for blocks by writing
4667 an unindented block name as a label, followed by the indented
4668 statements:
4670 BLOCK_NAME:
4671 STATEMENT_1;
4672 STATEMENT_2;
4674 STATEMENT_N; */
4676 void
4677 recording::block::write_to_dump (dump &d)
4679 d.write ("%s:\n", get_debug_string ());
4681 int i;
4682 statement *s;
4683 FOR_EACH_VEC_ELT (m_statements, i, s)
4684 s->write_to_dump (d);
4687 /* Validate a block by ensuring that it has been terminated. */
4689 bool
4690 recording::block::validate ()
4692 /* Check for termination. */
4693 if (!has_been_terminated ())
4695 statement *stmt = get_last_statement ();
4696 location *loc = stmt ? stmt->get_loc () : NULL;
4697 m_func->get_context ()->add_error (loc,
4698 "unterminated block in %s: %s",
4699 m_func->get_debug_string (),
4700 get_debug_string ());
4701 return false;
4704 return true;
4707 /* Get the source-location of a block by using that of the first
4708 statement within it, if any. */
4710 recording::location *
4711 recording::block::get_loc () const
4713 recording::statement *stmt = get_first_statement ();
4714 if (stmt)
4715 return stmt->get_loc ();
4716 else
4717 return NULL;
4720 /* Get the first statement within a block, if any. */
4722 recording::statement *
4723 recording::block::get_first_statement () const
4725 if (m_statements.length ())
4726 return m_statements[0];
4727 else
4728 return NULL;
4731 /* Get the last statement within a block, if any. */
4733 recording::statement *
4734 recording::block::get_last_statement () const
4736 if (m_statements.length ())
4737 return m_statements[m_statements.length () - 1];
4738 else
4739 return NULL;
4742 /* Assuming that this block has been terminated, get the successor blocks
4743 as a vector. Ownership of the vector transfers to the caller, which
4744 must call its release () method.
4746 Used when validating functions, and when dumping dot representations
4747 of them. */
4749 vec <recording::block *>
4750 recording::block::get_successor_blocks () const
4752 gcc_assert (m_has_been_terminated);
4753 statement *last_statement = get_last_statement ();
4754 gcc_assert (last_statement);
4755 return last_statement->get_successor_blocks ();
4758 /* Implementation of pure virtual hook recording::memento::replay_into
4759 for recording::block. */
4761 void
4762 recording::block::replay_into (replayer *)
4764 set_playback_obj (m_func->playback_function ()
4765 ->new_block (playback_string (m_name)));
4768 /* Implementation of recording::memento::make_debug_string for
4769 blocks. */
4771 recording::string *
4772 recording::block::make_debug_string ()
4774 if (m_name)
4775 return m_name;
4776 else
4777 return string::from_printf (m_ctxt,
4778 "<UNNAMED BLOCK %p>",
4779 (void *)this);
4782 /* Implementation of recording::memento::write_reproducer for blocks. */
4784 void
4785 recording::block::write_reproducer (reproducer &r)
4787 const char *id = r.make_identifier (this, "block");
4788 r.write (" gcc_jit_block *%s =\n"
4789 " gcc_jit_function_new_block (%s, %s);\n",
4791 r.get_identifier (m_func),
4792 m_name ? m_name->get_debug_string () : "NULL");
4795 /* Disable warnings about missing quoting in GCC diagnostics for
4796 the pp_printf calls. Their format strings deliberately don't
4797 follow GCC diagnostic conventions. */
4798 #if __GNUC__ >= 10
4799 # pragma GCC diagnostic push
4800 # pragma GCC diagnostic ignored "-Wformat-diag"
4801 #endif
4803 /* Dump a block in graphviz form into PP, capturing the block name (if
4804 any) and the statements. */
4806 void
4807 recording::block::dump_to_dot (pretty_printer *pp)
4809 pp_printf (pp,
4810 ("\tblock_%d "
4811 "[shape=record,style=filled,fillcolor=white,label=\"{"),
4812 m_index);
4813 pp_write_text_to_stream (pp);
4814 if (m_name)
4816 pp_string (pp, m_name->c_str ());
4817 pp_string (pp, ":");
4818 pp_newline (pp);
4819 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4822 int i;
4823 statement *s;
4824 FOR_EACH_VEC_ELT (m_statements, i, s)
4826 pp_string (pp, s->get_debug_string ());
4827 pp_newline (pp);
4828 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4831 pp_string (pp,
4832 "}\"];\n\n");
4833 pp_flush (pp);
4836 /* Dump the out-edges of the block in graphviz form into PP. */
4838 void
4839 recording::block::dump_edges_to_dot (pretty_printer *pp)
4841 vec <block *> successors = get_successor_blocks ();
4842 int i;
4843 block *succ;
4844 FOR_EACH_VEC_ELT (successors, i, succ)
4845 pp_printf (pp,
4846 "\tblock_%d:s -> block_%d:n;\n",
4847 m_index, succ->m_index);
4848 successors.release ();
4851 #if __GNUC__ >= 10
4852 # pragma GCC diagnostic pop
4853 #endif
4855 namespace recording {
4856 static const enum tls_model tls_models[] = {
4857 TLS_MODEL_NONE, /* GCC_JIT_TLS_MODEL_NONE */
4858 TLS_MODEL_GLOBAL_DYNAMIC, /* GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC */
4859 TLS_MODEL_LOCAL_DYNAMIC, /* GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC */
4860 TLS_MODEL_INITIAL_EXEC, /* GCC_JIT_TLS_MODEL_INITIAL_EXEC */
4861 TLS_MODEL_LOCAL_EXEC, /* GCC_JIT_TLS_MODEL_LOCAL_EXEC */
4863 } /* namespace recording */
4865 /* The implementation of class gcc::jit::recording::global. */
4867 /* Implementation of pure virtual hook recording::memento::replay_into
4868 for recording::global. */
4870 void
4871 recording::global::replay_into (replayer *r)
4873 playback::lvalue *global = m_initializer
4874 ? r->new_global_initialized (playback_location (r, m_loc),
4875 m_kind,
4876 m_type->playback_type (),
4877 m_type->dereference ()->get_size (),
4878 m_initializer_num_bytes
4879 / m_type->dereference ()->get_size (),
4880 m_initializer,
4881 playback_string (m_name),
4882 m_flags)
4883 : r->new_global (playback_location (r, m_loc),
4884 m_kind,
4885 m_type->playback_type (),
4886 playback_string (m_name),
4887 m_flags);
4889 if (m_tls_model != GCC_JIT_TLS_MODEL_NONE)
4890 global->set_tls_model (recording::tls_models[m_tls_model]);
4892 if (m_link_section != NULL)
4893 global->set_link_section (m_link_section->c_str ());
4895 if (m_reg_name != NULL)
4896 global->set_register_name (m_reg_name->c_str ());
4898 if (m_alignment != 0)
4899 global->set_alignment (m_alignment);
4901 set_playback_obj (global);
4904 /* Override the default implementation of
4905 recording::memento::write_to_dump for globals.
4906 This will be of the form:
4908 GCC_JIT_GLOBAL_EXPORTED:
4909 "TYPE NAME;"
4910 e.g. "int foo;"
4912 GCC_JIT_GLOBAL_INTERNAL:
4913 "static TYPE NAME;"
4914 e.g. "static int foo;"
4916 GCC_JIT_GLOBAL_IMPORTED:
4917 "extern TYPE NAME;"
4918 e.g. "extern int foo;"
4920 These are written to the top of the dump by
4921 recording::context::dump_to_file. */
4923 void
4924 recording::global::write_to_dump (dump &d)
4926 if (d.update_locations ())
4927 m_loc = d.make_location ();
4929 switch (m_kind)
4931 default:
4932 gcc_unreachable ();
4934 case GCC_JIT_GLOBAL_EXPORTED:
4935 break;
4937 case GCC_JIT_GLOBAL_INTERNAL:
4938 d.write ("static ");
4939 break;
4941 case GCC_JIT_GLOBAL_IMPORTED:
4942 d.write ("extern ");
4943 break;
4946 d.write ("%s %s",
4947 m_type->get_debug_string (),
4948 get_debug_string ());
4950 if (!m_initializer && !m_rvalue_init)
4952 d.write (";\n");
4954 else if (m_initializer)
4956 d.write ("=\n { ");
4957 const unsigned char *p = (const unsigned char *)m_initializer;
4958 for (size_t i = 0; i < m_initializer_num_bytes; i++)
4960 d.write ("0x%x, ", p[i]);
4961 if (i && !(i % 64))
4962 d.write ("\n ");
4964 d.write ("};\n");
4966 else if (m_rvalue_init)
4968 d.write (" = ");
4969 d.write ("%s", m_rvalue_init->get_debug_string ());
4970 d.write (";\n");
4973 return;
4976 /* A table of enum gcc_jit_global_kind values expressed in string
4977 form. */
4979 static const char * const global_kind_reproducer_strings[] = {
4980 "GCC_JIT_GLOBAL_EXPORTED",
4981 "GCC_JIT_GLOBAL_INTERNAL",
4982 "GCC_JIT_GLOBAL_IMPORTED"
4985 template <typename T>
4986 void
4987 recording::global::write_initializer_reproducer (const char *id, reproducer &r)
4989 const char *init_id = r.make_tmp_identifier ("init_for", this);
4990 r.write (" %s %s[] =\n {",
4991 m_type->dereference ()->get_debug_string (),
4992 init_id);
4994 const T *p = (const T *)m_initializer;
4995 for (size_t i = 0; i < m_initializer_num_bytes / sizeof (T); i++)
4997 r.write ("%" PRIu64 ", ", (uint64_t)p[i]);
4998 if (i && !(i % 64))
4999 r.write ("\n ");
5001 r.write ("};\n");
5002 r.write (" gcc_jit_global_set_initializer (%s, %s, sizeof (%s));\n",
5003 id, init_id, init_id);
5006 /* Implementation of recording::memento::write_reproducer for globals. */
5008 static const char * const tls_model_enum_strings[] = {
5009 "GCC_JIT_TLS_MODEL_NONE",
5010 "GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC",
5011 "GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC",
5012 "GCC_JIT_TLS_MODEL_INITIAL_EXEC",
5013 "GCC_JIT_TLS_MODEL_LOCAL_EXEC",
5016 void
5017 recording::global::write_reproducer (reproducer &r)
5019 const char *id = r.make_identifier (this, "block");
5020 r.write (" gcc_jit_lvalue *%s =\n"
5021 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
5022 " %s, /* gcc_jit_location *loc */\n"
5023 " %s, /* enum gcc_jit_global_kind kind */\n"
5024 " %s, /* gcc_jit_type *type */\n"
5025 " %s); /* const char *name */\n",
5027 r.get_identifier (get_context ()),
5028 r.get_identifier (m_loc),
5029 global_kind_reproducer_strings[m_kind],
5030 r.get_identifier_as_type (get_type ()),
5031 m_name->get_debug_string ());
5033 if (m_tls_model != GCC_JIT_TLS_MODEL_NONE)
5034 r.write (" gcc_jit_lvalue_set_tls_model (%s, /* gcc_jit_lvalue *lvalue */\n"
5035 " %s); /* enum gcc_jit_tls_model model */\n",
5037 tls_model_enum_strings[m_tls_model]);
5039 if (m_link_section != NULL)
5040 r.write (" gcc_jit_lvalue_set_link_section (%s, /* gcc_jit_lvalue *lvalue */\n"
5041 " \"%s\"); /* */\n",
5043 m_link_section->c_str ());
5045 if (m_initializer)
5046 switch (m_type->dereference ()->get_size ())
5048 case 1:
5049 write_initializer_reproducer<uint8_t> (id, r);
5050 break;
5051 case 2:
5052 write_initializer_reproducer<uint16_t> (id, r);
5053 break;
5054 case 4:
5055 write_initializer_reproducer<uint32_t> (id, r);
5056 break;
5057 case 8:
5058 write_initializer_reproducer<uint64_t> (id, r);
5059 break;
5060 default:
5061 /* This function is serving on sizes returned by 'get_size',
5062 these are all covered by the previous cases. */
5063 gcc_unreachable ();
5067 /* The implementation of the various const-handling classes:
5068 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
5070 /* Explicit specialization of the various mementos we're interested in. */
5071 template class recording::memento_of_new_rvalue_from_const <int>;
5072 template class recording::memento_of_new_rvalue_from_const <long>;
5073 template class recording::memento_of_new_rvalue_from_const <double>;
5074 template class recording::memento_of_new_rvalue_from_const <void *>;
5076 /* Implementation of the pure virtual hook recording::memento::replay_into
5077 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
5079 template <typename HOST_TYPE>
5080 void
5081 recording::
5082 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
5084 set_playback_obj
5085 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
5086 m_value));
5089 /* The make_debug_string and write_reproducer methods vary between the
5090 various
5091 memento_of_new_rvalue_from_const <HOST_TYPE>
5092 classes, so we explicitly write specializations of them.
5094 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
5095 namespaces are written out explicitly, which is why most of this file
5096 doesn't abbreviate things by entering the "recording" namespace.
5098 However, these specializations are required to be in the same namespace
5099 as the template, hence we now have to enter the gcc::jit::recording
5100 namespace. */
5102 namespace recording
5105 /* The make_debug_string specialization for <int>, which renders it as
5106 (TARGET_TYPE)LITERAL
5107 e.g.
5108 "(int)42". */
5110 template <>
5111 string *
5112 memento_of_new_rvalue_from_const <int>::make_debug_string ()
5114 return string::from_printf (m_ctxt,
5115 "(%s)%i",
5116 m_type->get_debug_string (),
5117 m_value);
5120 /* The get_wide_int specialization for <int>. */
5122 template <>
5123 bool
5124 memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const
5126 *out = wi::shwi (m_value, sizeof (m_value) * 8);
5127 return true;
5130 /* The write_reproducer specialization for <int>. */
5132 template <>
5133 void
5134 memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
5136 const char *id = r.make_identifier (this, "rvalue");
5137 r.write (" gcc_jit_rvalue *%s =\n"
5138 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
5139 " %s, /* gcc_jit_type *numeric_type */\n"
5140 " %i); /* int value */\n",
5142 r.get_identifier (get_context ()),
5143 r.get_identifier_as_type (m_type),
5144 m_value);
5147 /* The make_debug_string specialization for <long>, rendering it as
5148 (TARGET_TYPE)LITERAL
5149 e.g.
5150 "(long)42". */
5152 template <>
5153 string *
5154 memento_of_new_rvalue_from_const <long>::make_debug_string ()
5156 return string::from_printf (m_ctxt,
5157 "(%s)%li",
5158 m_type->get_debug_string (),
5159 m_value);
5162 /* The get_wide_int specialization for <long>. */
5164 template <>
5165 bool
5166 memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const
5168 *out = wi::shwi (m_value, sizeof (m_value) * 8);
5169 return true;
5172 /* The write_reproducer specialization for <long>. */
5174 template <>
5175 void
5176 recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
5178 const char *id = r.make_identifier (this, "rvalue");
5180 /* We have to special-case LONG_MIN, since e.g.
5181 -9223372036854775808L
5182 is parsed as
5183 -(9223372036854775808L)
5184 and hence we'd get:
5185 error: integer constant is so large that it is unsigned [-Werror]
5186 Workaround this by writing (LONG_MIN + 1) - 1. */
5187 if (m_value == LONG_MIN)
5189 r.write (" gcc_jit_rvalue *%s =\n"
5190 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
5191 " %s, /* gcc_jit_type *numeric_type */\n"
5192 " %ldL - 1); /* long value */\n",
5194 r.get_identifier (get_context ()),
5195 r.get_identifier_as_type (m_type),
5196 m_value + 1);
5197 return;
5200 r.write (" gcc_jit_rvalue *%s =\n"
5201 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
5202 " %s, /* gcc_jit_type *numeric_type */\n"
5203 " %ldL); /* long value */\n",
5205 r.get_identifier (get_context ()),
5206 r.get_identifier_as_type (m_type),
5207 m_value);
5210 /* The make_debug_string specialization for <double>, rendering it as
5211 (TARGET_TYPE)LITERAL
5212 e.g.
5213 "(float)42.0". */
5215 template <>
5216 string *
5217 memento_of_new_rvalue_from_const <double>::make_debug_string ()
5219 return string::from_printf (m_ctxt,
5220 "(%s)%f",
5221 m_type->get_debug_string (),
5222 m_value);
5225 /* The get_wide_int specialization for <double>. */
5227 template <>
5228 bool
5229 memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
5231 return false;
5234 /* The write_reproducer specialization for <double>. */
5236 template <>
5237 void
5238 recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
5240 const char *id = r.make_identifier (this, "rvalue");
5241 r.write (" gcc_jit_rvalue *%s =\n"
5242 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
5243 " %s, /* gcc_jit_type *numeric_type */\n"
5244 " %f); /* double value */\n",
5246 r.get_identifier (get_context ()),
5247 r.get_identifier_as_type (m_type),
5248 m_value);
5251 /* The make_debug_string specialization for <void *>, rendering it as
5252 (TARGET_TYPE)HEX
5253 e.g.
5254 "(int *)0xdeadbeef"
5256 Zero is rendered as NULL e.g.
5257 "(int *)NULL". */
5259 template <>
5260 string *
5261 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
5263 if (m_value != NULL)
5264 return string::from_printf (m_ctxt,
5265 "(%s)%p",
5266 m_type->get_debug_string (), m_value);
5267 else
5268 return string::from_printf (m_ctxt,
5269 "(%s)NULL",
5270 m_type->get_debug_string ());
5273 /* The get_wide_int specialization for <void *>. */
5275 template <>
5276 bool
5277 memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const
5279 return false;
5282 /* Implementation of recording::memento::write_reproducer for <void *>
5283 values. */
5285 template <>
5286 void
5287 memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
5289 const char *id = r.make_identifier (this, "rvalue");
5290 if (m_value)
5291 r.write (" gcc_jit_rvalue *%s =\n"
5292 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
5293 " %s, /* gcc_jit_type *pointer_type */\n"
5294 " (void *)%p); /* void *value */\n",
5296 r.get_identifier (get_context ()),
5297 r.get_identifier_as_type (m_type),
5298 m_value);
5299 else
5300 r.write (" gcc_jit_rvalue *%s =\n"
5301 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
5302 " %s); /* gcc_jit_type *pointer_type */\n",
5304 r.get_identifier (get_context ()),
5305 r.get_identifier_as_type (m_type));
5308 /* We're done specializing make_debug_string and write_reproducer, so we
5309 can exit the gcc::jit::recording namespace. */
5311 } // namespace recording
5313 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
5315 /* Implementation of pure virtual hook recording::memento::replay_into
5316 for recording::memento_of_new_string_literal. */
5318 void
5319 recording::memento_of_new_string_literal::replay_into (replayer *r)
5321 set_playback_obj (r->new_string_literal (m_value->c_str ()));
5324 /* Implementation of recording::memento::make_debug_string for
5325 string literals. */
5327 recording::string *
5328 recording::memento_of_new_string_literal::make_debug_string ()
5330 return string::from_printf (m_ctxt,
5331 "%s",
5332 m_value->get_debug_string ());
5335 /* Implementation of recording::memento::write_reproducer for string literal
5336 values. */
5338 void
5339 recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
5341 const char *id = r.make_identifier (this, "rvalue");
5342 r.write (" gcc_jit_rvalue *%s =\n"
5343 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
5344 " %s); /* const char *value */\n",
5346 r.get_identifier (get_context ()),
5347 m_value->get_debug_string ());
5350 /* The implementation of class
5351 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
5353 /* The constructor for
5354 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
5356 recording::memento_of_new_rvalue_from_vector::
5357 memento_of_new_rvalue_from_vector (context *ctxt,
5358 location *loc,
5359 vector_type *type,
5360 rvalue **elements)
5361 : rvalue (ctxt, loc, type),
5362 m_vector_type (type),
5363 m_elements ()
5365 for (unsigned i = 0; i < type->get_num_units (); i++)
5366 m_elements.safe_push (elements[i]);
5369 /* Implementation of pure virtual hook recording::memento::replay_into
5370 for recording::memento_of_new_rvalue_from_vector. */
5372 void
5373 recording::memento_of_new_rvalue_from_vector::replay_into (replayer *r)
5375 auto_vec<playback::rvalue *> playback_elements;
5376 playback_elements.create (m_elements.length ());
5377 for (unsigned i = 0; i< m_elements.length (); i++)
5378 playback_elements.safe_push (m_elements[i]->playback_rvalue ());
5380 set_playback_obj (r->new_rvalue_from_vector (playback_location (r, m_loc),
5381 m_type->playback_type (),
5382 playback_elements));
5385 /* Implementation of pure virtual hook recording::rvalue::visit_children
5386 for recording::memento_of_new_rvalue_from_vector. */
5388 void
5389 recording::memento_of_new_rvalue_from_vector::visit_children (rvalue_visitor *v)
5391 for (unsigned i = 0; i< m_elements.length (); i++)
5392 v->visit (m_elements[i]);
5395 /* Implementation of recording::memento::make_debug_string for
5396 vectors. */
5398 recording::string *
5399 recording::memento_of_new_rvalue_from_vector::make_debug_string ()
5401 comma_separated_string elements (m_elements, get_precedence ());
5403 /* Now build a string. */
5404 string *result = string::from_printf (m_ctxt,
5405 "{%s}",
5406 elements.as_char_ptr ());
5408 return result;
5412 /* Implementation of recording::memento::write_reproducer for
5413 vectors. */
5415 void
5416 recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer &r)
5418 const char *id = r.make_identifier (this, "vector");
5419 const char *elements_id = r.make_tmp_identifier ("elements_for_", this);
5420 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
5421 elements_id,
5422 m_elements.length ());
5423 for (unsigned i = 0; i< m_elements.length (); i++)
5424 r.write (" %s,\n", r.get_identifier_as_rvalue (m_elements[i]));
5425 r.write (" };\n");
5426 r.write (" gcc_jit_rvalue *%s =\n"
5427 " gcc_jit_context_new_rvalue_from_vector (%s, /* gcc_jit_context *ctxt */\n"
5428 " %s, /* gcc_jit_location *loc */\n"
5429 " %s, /* gcc_jit_type *vec_type */\n"
5430 " %i, /* size_t num_elements */ \n"
5431 " %s); /* gcc_jit_rvalue **elements*/\n",
5433 r.get_identifier (get_context ()),
5434 r.get_identifier (m_loc),
5435 r.get_identifier (m_vector_type),
5436 m_elements.length (),
5437 elements_id);
5440 void
5441 recording::ctor::visit_children (rvalue_visitor *v)
5443 for (unsigned int i = 0; i < m_values.length (); i++)
5444 v->visit (m_values[i]);
5447 recording::string *
5448 recording::ctor::make_debug_string ()
5450 //Make a compound literal-ish
5451 pretty_printer pp;
5453 pp_string (&pp, "(");
5454 pp_string (&pp, m_type->get_debug_string ());
5455 pp_string (&pp, ") {");
5457 size_t field_n = m_fields.length ();
5458 size_t values_n = m_values.length ();
5460 if (!field_n && !values_n)
5462 else if (!field_n && values_n)
5464 for (size_t i = 0; i < values_n; i++)
5466 if (m_values[i])
5467 pp_string (&pp, m_values[i]->get_debug_string ());
5468 else
5469 pp_string (&pp, "0");
5470 if (i + 1 != values_n)
5471 pp_string (&pp, ", ");
5474 else if (field_n && values_n)
5476 for (size_t i = 0; i < values_n; i++)
5478 pp_string (&pp, ".");
5479 pp_string (&pp, m_fields[i]->get_debug_string ());
5480 pp_string (&pp, "=");
5481 if (m_values[i])
5482 pp_string (&pp, m_values[i]->get_debug_string ());
5483 else
5484 pp_string (&pp, "0");
5485 if (i + 1 != values_n)
5486 pp_string (&pp, ", ");
5489 /* m_fields are never populated with m_values empty. */
5491 pp_string (&pp, "}");
5493 return new_string (pp_formatted_text (&pp));
5496 void
5497 recording::ctor::write_reproducer (reproducer &r)
5499 const char *id = r.make_identifier (this, "rvalue");
5500 type *type = get_type ();
5502 r.write (" gcc_jit_rvalue *%s;\n", id);
5503 r.write (" {\n"); /* Open scope for locals. */
5505 if (type->is_union ())
5507 if (m_values.length () == 0)
5508 r.write (" gcc_jit_rvalue *value = NULL;\n");
5509 else
5510 r.write (" gcc_jit_rvalue *value = %s;\n",
5511 r.get_identifier (m_values[0]));
5513 if (m_fields.length () == 0)
5514 r.write (" gcc_jit_field *field = NULL;\n");
5515 else
5516 r.write (" gcc_jit_field *field = %s;\n",
5517 r.get_identifier (m_fields[0]));
5519 else
5521 /* Write the array of values. */
5522 if (m_values.length () == 0)
5523 r.write (" gcc_jit_rvalue **values = NULL;\n");
5524 else
5526 r.write (" gcc_jit_rvalue *values[] = {\n");
5527 for (size_t i = 0; i < m_values.length (); i++)
5528 r.write (" %s,\n", r.get_identifier (m_values[i]));
5529 r.write (" };\n");
5531 /* Write the array of fields. */
5532 if (m_fields.length () == 0)
5533 r.write (" gcc_jit_field **fields = NULL;\n");
5534 else
5536 r.write (" gcc_jit_field *fields[] = {\n");
5537 for (size_t i = 0; i < m_fields.length (); i++)
5538 r.write (" %s,\n", r.get_identifier (m_fields[i]));
5539 r.write (" };\n");
5542 if (type->is_array ())
5543 r.write (
5544 " %s =\n"
5545 " gcc_jit_context_new_array_constructor (%s,\n"
5546 " %s, /* gcc_jit_location *loc */\n"
5547 " %s, /* gcc_jit_type *type */\n"
5548 " %i, /* int num_values */\n"
5549 " values);\n",
5551 r.get_identifier (get_context ()),
5552 r.get_identifier (m_loc),
5553 r.get_identifier_as_type (get_type ()),
5554 m_values.length ());
5555 else if (type->is_struct ())
5556 r.write (
5557 " %s =\n"
5558 " gcc_jit_context_new_struct_constructor (%s,\n"
5559 " %s, /* loc */\n"
5560 " %s, /* gcc_jit_type *type */\n"
5561 " %i, /* int num_values */\n"
5562 " fields,\n"
5563 " values);\n",
5565 r.get_identifier (get_context ()),
5566 r.get_identifier (m_loc),
5567 r.get_identifier_as_type (get_type ()),
5568 m_values.length ());
5569 else if (type->is_union ())
5570 r.write (
5571 " %s =\n"
5572 " gcc_jit_context_new_union_constructor (%s,\n"
5573 " %s, /* loc */\n"
5574 " %s, /* gcc_jit_type *type */\n"
5575 " field,\n"
5576 " value);\n",
5578 r.get_identifier (get_context ()),
5579 r.get_identifier (m_loc),
5580 r.get_identifier_as_type (get_type ()));
5581 else
5582 gcc_unreachable ();
5584 r.write (" }\n"); /* Close scope for locals. */
5587 void
5588 recording::ctor::replay_into (replayer *r)
5590 auto_vec<playback::rvalue *> playback_values;
5591 auto_vec<playback::field *> playback_fields;
5593 int n = m_values.length ();
5595 type *type = get_type ();
5597 /* Handle arrays, and return. */
5598 if (type->is_array ())
5600 playback_values.reserve (n, false);
5602 for (int i = 0; i < n; i++)
5604 /* null m_values element indicates zero ctor. */
5605 playback_values.quick_push (m_values[i] ?
5606 m_values[i]->playback_rvalue () :
5607 NULL);
5609 set_playback_obj (r->new_ctor (playback_location (r, m_loc),
5610 get_type ()->playback_type (),
5611 NULL,
5612 &playback_values));
5613 return;
5615 /* ... else handle unions and structs. */
5617 playback_values.reserve (n, false);
5618 playback_fields.reserve (n, false);
5620 for (int i = 0; i < n; i++)
5622 /* null m_values element indicates zero ctor. */
5623 playback_values.quick_push (m_values[i] ?
5624 m_values[i]->playback_rvalue () :
5625 NULL);
5626 playback_fields.quick_push (m_fields[i]->playback_field ());
5629 set_playback_obj (r->new_ctor (playback_location (r, m_loc),
5630 get_type ()->playback_type (),
5631 &playback_fields,
5632 &playback_values));
5635 /* The implementation of class gcc::jit::recording::unary_op. */
5637 /* Implementation of pure virtual hook recording::memento::replay_into
5638 for recording::unary_op. */
5640 void
5641 recording::unary_op::replay_into (replayer *r)
5643 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
5644 m_op,
5645 get_type ()->playback_type (),
5646 m_a->playback_rvalue ()));
5649 /* Implementation of pure virtual hook recording::rvalue::visit_children
5650 for recording::unary_op. */
5651 void
5652 recording::unary_op::visit_children (rvalue_visitor *v)
5654 v->visit (m_a);
5657 /* Implementation of recording::memento::make_debug_string for
5658 unary ops. */
5660 static const char * const unary_op_strings[] = {
5661 "-", /* GCC_JIT_UNARY_OP_MINUS */
5662 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
5663 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
5664 "abs ", /* GCC_JIT_UNARY_OP_ABS */
5667 recording::string *
5668 recording::unary_op::make_debug_string ()
5670 return string::from_printf (m_ctxt,
5671 "%s(%s)",
5672 unary_op_strings[m_op],
5673 m_a->get_debug_string ());
5676 const char * const unary_op_reproducer_strings[] = {
5677 "GCC_JIT_UNARY_OP_MINUS",
5678 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
5679 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
5680 "GCC_JIT_UNARY_OP_ABS"
5683 /* Implementation of recording::memento::write_reproducer for unary ops. */
5685 void
5686 recording::unary_op::write_reproducer (reproducer &r)
5688 const char *id = r.make_identifier (this, "rvalue");
5689 r.write (" gcc_jit_rvalue *%s =\n"
5690 " gcc_jit_context_new_unary_op (%s,\n"
5691 " %s, /* gcc_jit_location *loc */\n"
5692 " %s, /* enum gcc_jit_unary_op op */\n"
5693 " %s, /* gcc_jit_type *result_type */\n"
5694 " %s); /* gcc_jit_rvalue *a */\n",
5696 r.get_identifier (get_context ()),
5697 r.get_identifier (m_loc),
5698 unary_op_reproducer_strings[m_op],
5699 r.get_identifier_as_type (get_type ()),
5700 r.get_identifier_as_rvalue (m_a));
5703 /* The implementation of class gcc::jit::recording::binary_op. */
5705 /* Implementation of pure virtual hook recording::memento::replay_into
5706 for recording::binary_op. */
5708 void
5709 recording::binary_op::replay_into (replayer *r)
5711 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
5712 m_op,
5713 get_type ()->playback_type (),
5714 m_a->playback_rvalue (),
5715 m_b->playback_rvalue ()));
5718 /* Implementation of pure virtual hook recording::rvalue::visit_children
5719 for recording::binary_op. */
5720 void
5721 recording::binary_op::visit_children (rvalue_visitor *v)
5723 v->visit (m_a);
5724 v->visit (m_b);
5727 /* Implementation of recording::memento::make_debug_string for
5728 binary ops. */
5730 static const char * const binary_op_strings[] = {
5731 "+", /* GCC_JIT_BINARY_OP_PLUS */
5732 "-", /* GCC_JIT_BINARY_OP_MINUS */
5733 "*", /* GCC_JIT_BINARY_OP_MULT */
5734 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
5735 "%", /* GCC_JIT_BINARY_OP_MODULO */
5736 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
5737 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
5738 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
5739 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
5740 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
5741 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
5742 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
5745 recording::string *
5746 recording::binary_op::make_debug_string ()
5748 enum precedence prec = get_precedence ();
5749 return string::from_printf (m_ctxt,
5750 "%s %s %s",
5751 m_a->get_debug_string_parens (prec),
5752 binary_op_strings[m_op],
5753 m_b->get_debug_string_parens (prec));
5756 const char * const binary_op_reproducer_strings[] = {
5757 "GCC_JIT_BINARY_OP_PLUS",
5758 "GCC_JIT_BINARY_OP_MINUS",
5759 "GCC_JIT_BINARY_OP_MULT",
5760 "GCC_JIT_BINARY_OP_DIVIDE",
5761 "GCC_JIT_BINARY_OP_MODULO",
5762 "GCC_JIT_BINARY_OP_BITWISE_AND",
5763 "GCC_JIT_BINARY_OP_BITWISE_XOR",
5764 "GCC_JIT_BINARY_OP_BITWISE_OR",
5765 "GCC_JIT_BINARY_OP_LOGICAL_AND",
5766 "GCC_JIT_BINARY_OP_LOGICAL_OR",
5767 "GCC_JIT_BINARY_OP_LSHIFT",
5768 "GCC_JIT_BINARY_OP_RSHIFT"
5771 /* Implementation of recording::memento::write_reproducer for binary ops. */
5773 void
5774 recording::binary_op::write_reproducer (reproducer &r)
5776 const char *id = r.make_identifier (this, "rvalue");
5777 r.write (" gcc_jit_rvalue *%s =\n"
5778 " gcc_jit_context_new_binary_op (%s,\n"
5779 " %s, /* gcc_jit_location *loc */\n"
5780 " %s, /* enum gcc_jit_binary_op op */\n"
5781 " %s, /* gcc_jit_type *result_type */\n"
5782 " %s, /* gcc_jit_rvalue *a */\n"
5783 " %s); /* gcc_jit_rvalue *b */\n",
5785 r.get_identifier (get_context ()),
5786 r.get_identifier (m_loc),
5787 binary_op_reproducer_strings[m_op],
5788 r.get_identifier_as_type (get_type ()),
5789 r.get_identifier_as_rvalue (m_a),
5790 r.get_identifier_as_rvalue (m_b));
5793 namespace recording {
5794 static const enum precedence binary_op_precedence[] = {
5795 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
5796 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
5798 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
5799 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
5800 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
5802 PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
5803 PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
5804 PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
5805 PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
5806 PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
5807 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
5808 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
5810 } /* namespace recording */
5812 enum recording::precedence
5813 recording::binary_op::get_precedence () const
5815 return binary_op_precedence[m_op];
5818 /* The implementation of class gcc::jit::recording::comparison. */
5820 /* Implementation of recording::memento::make_debug_string for
5821 comparisons. */
5823 static const char * const comparison_strings[] =
5825 "==", /* GCC_JIT_COMPARISON_EQ */
5826 "!=", /* GCC_JIT_COMPARISON_NE */
5827 "<", /* GCC_JIT_COMPARISON_LT */
5828 "<=", /* GCC_JIT_COMPARISON_LE */
5829 ">", /* GCC_JIT_COMPARISON_GT */
5830 ">=", /* GCC_JIT_COMPARISON_GE */
5833 recording::string *
5834 recording::comparison::make_debug_string ()
5836 enum precedence prec = get_precedence ();
5837 return string::from_printf (m_ctxt,
5838 "%s %s %s",
5839 m_a->get_debug_string_parens (prec),
5840 comparison_strings[m_op],
5841 m_b->get_debug_string_parens (prec));
5844 /* A table of enum gcc_jit_comparison values expressed in string
5845 form. */
5847 static const char * const comparison_reproducer_strings[] =
5849 "GCC_JIT_COMPARISON_EQ",
5850 "GCC_JIT_COMPARISON_NE",
5851 "GCC_JIT_COMPARISON_LT",
5852 "GCC_JIT_COMPARISON_LE",
5853 "GCC_JIT_COMPARISON_GT",
5854 "GCC_JIT_COMPARISON_GE"
5857 /* Implementation of recording::memento::write_reproducer for comparisons. */
5859 void
5860 recording::comparison::write_reproducer (reproducer &r)
5862 const char *id = r.make_identifier (this, "rvalue");
5863 r.write (" gcc_jit_rvalue *%s =\n"
5864 " gcc_jit_context_new_comparison (%s,\n"
5865 " %s, /* gcc_jit_location *loc */\n"
5866 " %s, /* enum gcc_jit_comparison op */\n"
5867 " %s, /* gcc_jit_rvalue *a */\n"
5868 " %s); /* gcc_jit_rvalue *b */\n",
5870 r.get_identifier (get_context ()),
5871 r.get_identifier (m_loc),
5872 comparison_reproducer_strings[m_op],
5873 r.get_identifier_as_rvalue (m_a),
5874 r.get_identifier_as_rvalue (m_b));
5877 /* Implementation of pure virtual hook recording::memento::replay_into
5878 for recording::comparison. */
5880 void
5881 recording::comparison::replay_into (replayer *r)
5883 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
5884 m_op,
5885 m_a->playback_rvalue (),
5886 m_b->playback_rvalue (),
5887 m_type->playback_type ()));
5890 /* Implementation of pure virtual hook recording::rvalue::visit_children
5891 for recording::comparison. */
5893 void
5894 recording::comparison::visit_children (rvalue_visitor *v)
5896 v->visit (m_a);
5897 v->visit (m_b);
5900 namespace recording {
5901 static const enum precedence comparison_precedence[] =
5903 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
5904 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
5906 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LT */
5907 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
5908 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GT */
5909 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
5911 } /* namespace recording */
5913 enum recording::precedence
5914 recording::comparison::get_precedence () const
5916 return comparison_precedence[m_op];
5919 /* Implementation of pure virtual hook recording::memento::replay_into
5920 for recording::cast. */
5922 void
5923 recording::cast::replay_into (replayer *r)
5925 set_playback_obj (r->new_cast (playback_location (r, m_loc),
5926 m_rvalue->playback_rvalue (),
5927 get_type ()->playback_type ()));
5930 /* Implementation of pure virtual hook recording::rvalue::visit_children
5931 for recording::cast. */
5932 void
5933 recording::cast::visit_children (rvalue_visitor *v)
5935 v->visit (m_rvalue);
5938 /* Implementation of recording::memento::make_debug_string for
5939 casts. */
5941 recording::string *
5942 recording::cast::make_debug_string ()
5944 enum precedence prec = get_precedence ();
5945 return string::from_printf (m_ctxt,
5946 "(%s)%s",
5947 get_type ()->get_debug_string (),
5948 m_rvalue->get_debug_string_parens (prec));
5951 /* Implementation of recording::memento::write_reproducer for casts. */
5953 void
5954 recording::cast::write_reproducer (reproducer &r)
5956 const char *id = r.make_identifier (this, "rvalue");
5957 r.write (" gcc_jit_rvalue *%s =\n"
5958 " gcc_jit_context_new_cast (%s,\n"
5959 " %s, /* gcc_jit_location *loc */\n"
5960 " %s, /* gcc_jit_rvalue *rvalue */\n"
5961 " %s); /* gcc_jit_type *type */\n",
5963 r.get_identifier (get_context ()),
5964 r.get_identifier (m_loc),
5965 r.get_identifier_as_rvalue (m_rvalue),
5966 r.get_identifier_as_type (get_type ()));
5969 /* Implementation of pure virtual hook recording::memento::replay_into
5970 for recording::bitcast. */
5972 void
5973 recording::bitcast::replay_into (replayer *r)
5975 set_playback_obj (r->new_bitcast (playback_location (r, m_loc),
5976 m_rvalue->playback_rvalue (),
5977 get_type ()->playback_type ()));
5980 /* Implementation of pure virtual hook recording::rvalue::visit_children
5981 for recording::bitcast. */
5982 void
5983 recording::bitcast::visit_children (rvalue_visitor *v)
5985 v->visit (m_rvalue);
5988 /* Implementation of recording::memento::make_debug_string for
5989 casts. */
5991 recording::string *
5992 recording::bitcast::make_debug_string ()
5994 enum precedence prec = get_precedence ();
5995 return string::from_printf (m_ctxt,
5996 "bitcast(%s, %s)",
5997 m_rvalue->get_debug_string_parens (prec),
5998 get_type ()->get_debug_string ());
6001 /* Implementation of recording::memento::write_reproducer for casts. */
6003 void
6004 recording::bitcast::write_reproducer (reproducer &r)
6006 const char *id = r.make_identifier (this, "rvalue");
6007 r.write (" gcc_jit_rvalue *%s =\n"
6008 " gcc_jit_context_new_bitcast (%s,\n"
6009 " %s, /* gcc_jit_location *loc */\n"
6010 " %s, /* gcc_jit_rvalue *rvalue */\n"
6011 " %s); /* gcc_jit_type *type */\n",
6013 r.get_identifier (get_context ()),
6014 r.get_identifier (m_loc),
6015 r.get_identifier_as_rvalue (m_rvalue),
6016 r.get_identifier_as_type (get_type ()));
6019 /* The implementation of class gcc::jit::recording::base_call. */
6021 /* The constructor for gcc::jit::recording::base_call. */
6023 recording::base_call::base_call (context *ctxt,
6024 location *loc,
6025 type *type_,
6026 int numargs,
6027 rvalue **args)
6028 : rvalue (ctxt, loc, type_),
6029 m_args (),
6030 m_require_tail_call (0)
6032 for (int i = 0; i< numargs; i++)
6033 m_args.safe_push (args[i]);
6036 /* Subroutine for use by call and call_though_ptr's write_reproducer
6037 methods. */
6039 void
6040 recording::base_call::write_reproducer_tail_call (reproducer &r,
6041 const char *id)
6043 if (m_require_tail_call)
6045 r.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
6046 " %i); /* int require_tail_call*/\n",
6052 /* The implementation of class gcc::jit::recording::call. */
6054 /* The constructor for gcc::jit::recording::call. */
6056 recording::call::call (recording::context *ctxt,
6057 recording::location *loc,
6058 recording::function *func,
6059 int numargs,
6060 rvalue **args)
6061 : base_call (ctxt, loc, func->get_return_type (), numargs, args),
6062 m_func (func)
6066 /* Implementation of pure virtual hook recording::memento::replay_into
6067 for recording::call. */
6069 void
6070 recording::call::replay_into (replayer *r)
6072 auto_vec<playback::rvalue *> playback_args;
6073 playback_args.create (m_args.length ());
6074 for (unsigned i = 0; i< m_args.length (); i++)
6075 playback_args.safe_push (m_args[i]->playback_rvalue ());
6077 set_playback_obj (r->new_call (playback_location (r, m_loc),
6078 m_func->playback_function (),
6079 &playback_args,
6080 m_require_tail_call));
6083 /* Implementation of pure virtual hook recording::rvalue::visit_children
6084 for recording::call. */
6086 void
6087 recording::call::visit_children (rvalue_visitor *v)
6089 for (unsigned i = 0; i< m_args.length (); i++)
6090 v->visit (m_args[i]);
6093 /* Implementation of recording::memento::make_debug_string for
6094 function calls. */
6096 recording::string *
6097 recording::call::make_debug_string ()
6099 /* First, build a buffer for the arguments. */
6100 comma_separated_string args (m_args, get_precedence ());
6102 /* ...and use it to get the string for the call as a whole. */
6103 string *result = string::from_printf (m_ctxt,
6104 "%s (%s)",
6105 m_func->get_debug_string (),
6106 args.as_char_ptr ());
6108 return result;
6111 void
6112 recording::call::write_reproducer (reproducer &r)
6114 const char *id = r.make_identifier (this, "call");
6115 const char *args_id = r.make_tmp_identifier ("args_for_", this);
6116 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
6117 args_id,
6118 m_args.length ());
6119 for (unsigned i = 0; i< m_args.length (); i++)
6120 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
6121 r.write (" };\n");
6122 r.write (" gcc_jit_rvalue *%s =\n"
6123 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
6124 " %s, /* gcc_jit_location *loc */\n"
6125 " %s, /* gcc_jit_function *func */\n"
6126 " %i, /* int numargs */ \n"
6127 " %s); /* gcc_jit_rvalue **args*/\n",
6129 r.get_identifier (get_context ()),
6130 r.get_identifier (m_loc),
6131 r.get_identifier (m_func),
6132 m_args.length (),
6133 args_id);
6134 write_reproducer_tail_call (r, id);
6137 /* The implementation of class gcc::jit::recording::call_through_ptr. */
6139 /* The constructor for recording::call_through_ptr. */
6141 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
6142 recording::location *loc,
6143 recording::rvalue *fn_ptr,
6144 int numargs,
6145 rvalue **args)
6146 : base_call (ctxt, loc,
6147 fn_ptr->get_type ()->dereference ()
6148 ->as_a_function_type ()->get_return_type (),
6149 numargs, args),
6150 m_fn_ptr (fn_ptr)
6154 /* Implementation of pure virtual hook recording::memento::replay_into
6155 for recording::call_through_ptr. */
6157 void
6158 recording::call_through_ptr::replay_into (replayer *r)
6160 auto_vec<playback::rvalue *> playback_args;
6161 playback_args.create (m_args.length ());
6162 for (unsigned i = 0; i< m_args.length (); i++)
6163 playback_args.safe_push (m_args[i]->playback_rvalue ());
6165 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
6166 m_fn_ptr->playback_rvalue (),
6167 &playback_args,
6168 m_require_tail_call));
6171 /* Implementation of pure virtual hook recording::rvalue::visit_children
6172 for recording::call_through_ptr. */
6174 void
6175 recording::call_through_ptr::visit_children (rvalue_visitor *v)
6177 v->visit (m_fn_ptr);
6178 for (unsigned i = 0; i< m_args.length (); i++)
6179 v->visit (m_args[i]);
6182 /* Implementation of recording::memento::make_debug_string for
6183 calls through function ptrs. */
6185 recording::string *
6186 recording::call_through_ptr::make_debug_string ()
6188 enum precedence prec = get_precedence ();
6189 /* First, build a buffer for the arguments. */
6190 /* Calculate length of said buffer. */
6191 size_t sz = 1; /* nil terminator */
6192 for (unsigned i = 0; i< m_args.length (); i++)
6194 sz += strlen (m_args[i]->get_debug_string_parens (prec));
6195 sz += 2; /* ", " separator */
6198 /* Now allocate and populate the buffer. */
6199 char *argbuf = new char[sz];
6200 size_t len = 0;
6202 for (unsigned i = 0; i< m_args.length (); i++)
6204 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
6205 len += strlen (m_args[i]->get_debug_string_parens (prec));
6206 if (i + 1 < m_args.length ())
6208 strcpy (argbuf + len, ", ");
6209 len += 2;
6212 argbuf[len] = '\0';
6214 /* ...and use it to get the string for the call as a whole. */
6215 string *result = string::from_printf (m_ctxt,
6216 "%s (%s)",
6217 m_fn_ptr->get_debug_string_parens (prec),
6218 argbuf);
6220 delete[] argbuf;
6222 return result;
6225 /* Implementation of recording::memento::write_reproducer for
6226 call_through_ptr. */
6228 void
6229 recording::call_through_ptr::write_reproducer (reproducer &r)
6231 const char *id = r.make_identifier (this, "call");
6232 const char *args_id = r.make_tmp_identifier ("args_for_", this);
6233 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
6234 args_id,
6235 m_args.length ());
6236 for (unsigned i = 0; i< m_args.length (); i++)
6237 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
6238 r.write (" };\n");
6239 r.write (" gcc_jit_rvalue *%s =\n"
6240 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
6241 " %s, /* gcc_jit_location *loc */\n"
6242 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
6243 " %i, /* int numargs */ \n"
6244 " %s); /* gcc_jit_rvalue **args*/\n",
6246 r.get_identifier (get_context ()),
6247 r.get_identifier (m_loc),
6248 r.get_identifier_as_rvalue (m_fn_ptr),
6249 m_args.length (),
6250 args_id);
6251 write_reproducer_tail_call (r, id);
6254 /* The implementation of class gcc::jit::recording::array_access. */
6256 /* Implementation of pure virtual hook recording::memento::replay_into
6257 for recording::array_access. */
6259 void
6260 recording::array_access::replay_into (replayer *r)
6262 set_playback_obj (
6263 r->new_array_access (playback_location (r, m_loc),
6264 m_ptr->playback_rvalue (),
6265 m_index->playback_rvalue ()));
6268 /* Implementation of pure virtual hook recording::rvalue::visit_children
6269 for recording::array_access. */
6271 void
6272 recording::array_access::visit_children (rvalue_visitor *v)
6274 v->visit (m_ptr);
6275 v->visit (m_index);
6278 /* Implementation of recording::memento::make_debug_string for
6279 array accesses. */
6281 recording::string *
6282 recording::array_access::make_debug_string ()
6284 enum precedence prec = get_precedence ();
6285 return string::from_printf (m_ctxt,
6286 "%s[%s]",
6287 m_ptr->get_debug_string_parens (prec),
6288 m_index->get_debug_string_parens (prec));
6291 /* Implementation of recording::memento::write_reproducer for
6292 array_access. */
6294 void
6295 recording::array_access::write_reproducer (reproducer &r)
6297 const char *id = r.make_identifier (this, "lvalue");
6298 r.write (" gcc_jit_lvalue *%s = \n"
6299 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
6300 " %s, /*gcc_jit_location *loc */\n"
6301 " %s, /* gcc_jit_rvalue *ptr */\n"
6302 " %s); /* gcc_jit_rvalue *index */\n",
6304 r.get_identifier (get_context ()),
6305 r.get_identifier (m_loc),
6306 r.get_identifier_as_rvalue (m_ptr),
6307 r.get_identifier_as_rvalue (m_index));
6310 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
6312 /* Implementation of pure virtual hook recording::memento::replay_into
6313 for recording::access_field_of_lvalue. */
6315 void
6316 recording::access_field_of_lvalue::replay_into (replayer *r)
6318 set_playback_obj (
6319 m_lvalue->playback_lvalue ()
6320 ->access_field (playback_location (r, m_loc),
6321 m_field->playback_field ()));
6325 /* Implementation of pure virtual hook recording::rvalue::visit_children
6326 for recording::access_field_of_lvalue. */
6328 void
6329 recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
6331 v->visit (m_lvalue);
6334 /* Implementation of recording::memento::make_debug_string for
6335 accessing a field of an lvalue. */
6337 recording::string *
6338 recording::access_field_of_lvalue::make_debug_string ()
6340 enum precedence prec = get_precedence ();
6341 return string::from_printf (m_ctxt,
6342 "%s.%s",
6343 m_lvalue->get_debug_string_parens (prec),
6344 m_field->get_debug_string ());
6347 /* Implementation of recording::memento::write_reproducer for
6348 access_field_of_lvalue. */
6350 void
6351 recording::access_field_of_lvalue::write_reproducer (reproducer &r)
6353 const char *id = r.make_identifier (this, "lvalue");
6354 r.write (" gcc_jit_lvalue *%s = \n"
6355 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
6356 " %s, /*gcc_jit_location *loc */\n"
6357 " %s);\n",
6359 r.get_identifier_as_lvalue (m_lvalue),
6360 r.get_identifier (m_loc),
6361 r.get_identifier (m_field));
6364 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
6366 /* Implementation of pure virtual hook recording::memento::replay_into
6367 for recording::access_field_rvalue. */
6369 void
6370 recording::access_field_rvalue::replay_into (replayer *r)
6372 set_playback_obj (
6373 m_rvalue->playback_rvalue ()
6374 ->access_field (playback_location (r, m_loc),
6375 m_field->playback_field ()));
6378 /* Implementation of pure virtual hook recording::rvalue::visit_children
6379 for recording::access_field_rvalue. */
6381 void
6382 recording::access_field_rvalue::visit_children (rvalue_visitor *v)
6384 v->visit (m_rvalue);
6387 /* Implementation of recording::memento::make_debug_string for
6388 accessing a field of an rvalue. */
6390 recording::string *
6391 recording::access_field_rvalue::make_debug_string ()
6393 enum precedence prec = get_precedence ();
6394 return string::from_printf (m_ctxt,
6395 "%s.%s",
6396 m_rvalue->get_debug_string_parens (prec),
6397 m_field->get_debug_string ());
6400 /* Implementation of recording::memento::write_reproducer for
6401 access_field_rvalue. */
6403 void
6404 recording::access_field_rvalue::write_reproducer (reproducer &r)
6406 const char *id = r.make_identifier (this, "rvalue");
6407 r.write (" gcc_jit_rvalue *%s = \n"
6408 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
6409 " %s, /*gcc_jit_location *loc */\n"
6410 " %s);\n",
6412 r.get_identifier_as_rvalue (m_rvalue),
6413 r.get_identifier (m_loc),
6414 r.get_identifier (m_field));
6417 /* The implementation of class
6418 gcc::jit::recording::dereference_field_rvalue. */
6420 /* Implementation of pure virtual hook recording::memento::replay_into
6421 for recording::dereference_field_rvalue. */
6423 void
6424 recording::dereference_field_rvalue::replay_into (replayer *r)
6426 set_playback_obj (
6427 m_rvalue->playback_rvalue ()->
6428 dereference_field (playback_location (r, m_loc),
6429 m_field->playback_field ()));
6432 /* Implementation of pure virtual hook recording::rvalue::visit_children
6433 for recording::dereference_field_rvalue. */
6435 void
6436 recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
6438 v->visit (m_rvalue);
6441 /* Implementation of recording::memento::make_debug_string for
6442 dereferencing a field of an rvalue. */
6444 recording::string *
6445 recording::dereference_field_rvalue::make_debug_string ()
6447 enum precedence prec = get_precedence ();
6448 return string::from_printf (m_ctxt,
6449 "%s->%s",
6450 m_rvalue->get_debug_string_parens (prec),
6451 m_field->get_debug_string ());
6454 /* Implementation of recording::memento::write_reproducer for
6455 dereference_field_rvalue. */
6457 void
6458 recording::dereference_field_rvalue::write_reproducer (reproducer &r)
6460 const char *id = r.make_identifier (this, "lvalue");
6461 r.write (" gcc_jit_lvalue *%s=\n"
6462 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
6463 " %s, /* gcc_jit_location *loc */\n"
6464 " %s); /* gcc_jit_field *field */\n",
6466 r.get_identifier_as_rvalue (m_rvalue),
6467 r.get_identifier (m_loc),
6468 r.get_identifier (m_field));
6471 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
6473 /* Implementation of pure virtual hook recording::memento::replay_into
6474 for recording::dereference_rvalue. */
6476 void
6477 recording::dereference_rvalue::replay_into (replayer *r)
6479 set_playback_obj (
6480 m_rvalue->playback_rvalue ()->
6481 dereference (playback_location (r, m_loc)));
6484 /* Implementation of pure virtual hook recording::rvalue::visit_children
6485 for recording::dereference_rvalue. */
6487 void
6488 recording::dereference_rvalue::visit_children (rvalue_visitor *v)
6490 v->visit (m_rvalue);
6493 /* Implementation of recording::memento::make_debug_string for
6494 dereferencing an rvalue. */
6496 recording::string *
6497 recording::dereference_rvalue::make_debug_string ()
6499 enum precedence prec = get_precedence ();
6500 return string::from_printf (m_ctxt,
6501 "*%s",
6502 m_rvalue->get_debug_string_parens (prec));
6505 /* Implementation of recording::memento::write_reproducer for
6506 dereference_rvalue. */
6508 void
6509 recording::dereference_rvalue::write_reproducer (reproducer &r)
6511 const char *id = r.make_identifier (this, "dereference");
6512 r.write (" gcc_jit_lvalue *%s =\n"
6513 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
6514 " %s); /* gcc_jit_location *loc */\n",
6516 r.get_identifier_as_rvalue (m_rvalue),
6517 r.get_identifier (m_loc));
6520 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
6522 /* Implementation of pure virtual hook recording::memento::replay_into
6523 for recording::get_address_of_lvalue. */
6525 void
6526 recording::get_address_of_lvalue::replay_into (replayer *r)
6528 set_playback_obj (
6529 m_lvalue->playback_lvalue ()->
6530 get_address (playback_location (r, m_loc)));
6533 /* Implementation of pure virtual hook recording::rvalue::visit_children
6534 for recording::get_address_of_lvalue. */
6536 void
6537 recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
6539 v->visit (m_lvalue);
6542 /* Implementation of recording::memento::make_debug_string for
6543 getting the address of an lvalue. */
6545 recording::string *
6546 recording::get_address_of_lvalue::make_debug_string ()
6548 enum precedence prec = get_precedence ();
6549 return string::from_printf (m_ctxt,
6550 "&%s",
6551 m_lvalue->get_debug_string_parens (prec));
6554 /* Implementation of recording::memento::write_reproducer for
6555 get_address_of_lvalue. */
6557 void
6558 recording::get_address_of_lvalue::write_reproducer (reproducer &r)
6560 const char *id = r.make_identifier (this, "address_of");
6561 r.write (" gcc_jit_rvalue *%s =\n"
6562 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
6563 " %s); /* gcc_jit_location *loc */\n",
6565 r.get_identifier_as_lvalue (m_lvalue),
6566 r.get_identifier (m_loc));
6569 /* The implementation of class gcc::jit::recording::function_pointer. */
6571 /* Implementation of pure virtual hook recording::memento::replay_into
6572 for recording::function_pointer. */
6574 void
6575 recording::function_pointer::replay_into (replayer *r)
6577 set_playback_obj (
6578 m_fn->playback_function ()->
6579 get_address (playback_location (r, m_loc)));
6582 void
6583 recording::function_pointer::visit_children (rvalue_visitor *)
6585 /* Empty. */
6588 /* Implementation of recording::memento::make_debug_string for
6589 getting the address of an lvalue. */
6591 recording::string *
6592 recording::function_pointer::make_debug_string ()
6594 return string::from_printf (m_ctxt,
6595 "%s",
6596 m_fn->get_debug_string ());
6599 /* Implementation of recording::memento::write_reproducer for
6600 function_pointer. */
6602 void
6603 recording::function_pointer::write_reproducer (reproducer &r)
6605 const char *id = r.make_identifier (this, "address_of");
6606 r.write (" gcc_jit_rvalue *%s =\n"
6607 " gcc_jit_function_get_address (%s, /* gcc_jit_function *fn */\n"
6608 " %s); /* gcc_jit_location *loc */\n",
6610 r.get_identifier (m_fn),
6611 r.get_identifier (m_loc));
6614 /* The implementation of class gcc::jit::recording::local. */
6616 /* Implementation of pure virtual hook recording::memento::replay_into
6617 for recording::local. */
6619 void
6620 recording::local::replay_into (replayer *r)
6622 playback::lvalue *obj = m_func->playback_function ()
6623 ->new_local (playback_location (r, m_loc),
6624 m_type->playback_type (),
6625 playback_string (m_name));
6627 if (m_reg_name != NULL)
6628 obj->set_register_name (m_reg_name->c_str ());
6630 if (m_alignment != 0)
6631 obj->set_alignment (m_alignment);
6633 set_playback_obj (obj);
6636 /* Override the default implementation of
6637 recording::memento::write_to_dump for locals by writing
6638 TYPE NAME;
6639 for use at the top of the function body as if it were a
6640 declaration. */
6642 void
6643 recording::local::write_to_dump (dump &d)
6645 if (d.update_locations ())
6646 m_loc = d.make_location ();
6647 d.write(" %s %s;\n",
6648 m_type->get_debug_string (),
6649 get_debug_string ());
6652 void
6653 recording::local::write_reproducer (reproducer &r)
6655 const char *id = r.make_identifier (this, "local");
6656 r.write (" gcc_jit_lvalue *%s =\n"
6657 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
6658 " %s, /* gcc_jit_location *loc */\n"
6659 " %s, /* gcc_jit_type *type */\n"
6660 " %s); /* const char *name */\n",
6662 r.get_identifier (m_func),
6663 r.get_identifier (m_loc),
6664 r.get_identifier_as_type (m_type),
6665 m_name->get_debug_string ());
6668 /* The implementation of class gcc::jit::recording::statement. */
6670 /* We poison the default implementation of
6671 gcc::jit::recording::statement::get_successor_blocks
6672 since this vfunc must only ever be called on terminator
6673 statements. */
6675 vec <recording::block *>
6676 recording::statement::get_successor_blocks () const
6678 /* The base class implementation is for non-terminating statements,
6679 and thus should never be called. */
6680 gcc_unreachable ();
6681 vec <block *> result;
6682 result.create (0);
6683 return result;
6686 /* Extend the default implementation of
6687 recording::memento::write_to_dump for statements by (if requested)
6688 updating the location of the statement to the current location in
6689 the dumpfile. */
6691 void
6692 recording::statement::write_to_dump (dump &d)
6694 memento::write_to_dump (d);
6695 if (d.update_locations ())
6696 m_loc = d.make_location ();
6699 /* The implementation of class gcc::jit::recording::eval. */
6701 /* Implementation of pure virtual hook recording::memento::replay_into
6702 for recording::eval. */
6704 void
6705 recording::eval::replay_into (replayer *r)
6707 playback_block (get_block ())
6708 ->add_eval (playback_location (r),
6709 m_rvalue->playback_rvalue ());
6712 /* Implementation of recording::memento::make_debug_string for
6713 an eval statement. */
6715 recording::string *
6716 recording::eval::make_debug_string ()
6718 return string::from_printf (m_ctxt,
6719 "(void)%s;",
6720 m_rvalue->get_debug_string ());
6723 /* Implementation of recording::memento::write_reproducer for
6724 eval statements. */
6726 void
6727 recording::eval::write_reproducer (reproducer &r)
6729 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
6730 " %s, /* gcc_jit_location *loc */\n"
6731 " %s); /* gcc_jit_rvalue *rvalue */\n",
6732 r.get_identifier (get_block ()),
6733 r.get_identifier (get_loc ()),
6734 r.get_identifier_as_rvalue (m_rvalue));
6737 /* The implementation of class gcc::jit::recording::assignment. */
6739 /* Implementation of pure virtual hook recording::memento::replay_into
6740 for recording::assignment. */
6742 void
6743 recording::assignment::replay_into (replayer *r)
6745 playback_block (get_block ())
6746 ->add_assignment (playback_location (r),
6747 m_lvalue->playback_lvalue (),
6748 m_rvalue->playback_rvalue ());
6751 /* Implementation of recording::memento::make_debug_string for
6752 an assignment statement. */
6754 recording::string *
6755 recording::assignment::make_debug_string ()
6757 return string::from_printf (m_ctxt,
6758 "%s = %s;",
6759 m_lvalue->get_debug_string (),
6760 m_rvalue->get_debug_string ());
6763 /* Implementation of recording::memento::write_reproducer for
6764 assignment statements. */
6766 void
6767 recording::assignment::write_reproducer (reproducer &r)
6769 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
6770 " %s, /* gcc_jit_location *loc */\n"
6771 " %s, /* gcc_jit_lvalue *lvalue */\n"
6772 " %s); /* gcc_jit_rvalue *rvalue */\n",
6773 r.get_identifier (get_block ()),
6774 r.get_identifier (get_loc ()),
6775 r.get_identifier_as_lvalue (m_lvalue),
6776 r.get_identifier_as_rvalue (m_rvalue));
6779 /* The implementation of class gcc::jit::recording::assignment_op. */
6781 /* Implementation of pure virtual hook recording::memento::replay_into
6782 for recording::assignment_op. */
6784 void
6785 recording::assignment_op::replay_into (replayer *r)
6787 playback::type *result_type =
6788 m_lvalue->playback_lvalue ()->get_type ();
6790 playback::rvalue *binary_op =
6791 r->new_binary_op (playback_location (r),
6792 m_op,
6793 result_type,
6794 m_lvalue->playback_rvalue (),
6795 m_rvalue->playback_rvalue ());
6797 playback_block (get_block ())
6798 ->add_assignment (playback_location (r),
6799 m_lvalue->playback_lvalue (),
6800 binary_op);
6803 /* Implementation of recording::memento::make_debug_string for
6804 an assignment_op statement. */
6806 recording::string *
6807 recording::assignment_op::make_debug_string ()
6809 return string::from_printf (m_ctxt,
6810 "%s %s= %s;",
6811 m_lvalue->get_debug_string (),
6812 binary_op_strings[m_op],
6813 m_rvalue->get_debug_string ());
6816 /* Implementation of recording::memento::write_reproducer for
6817 assignment_op statements. */
6819 void
6820 recording::assignment_op::write_reproducer (reproducer &r)
6822 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
6823 " %s, /* gcc_jit_location *loc */\n"
6824 " %s, /* gcc_jit_lvalue *lvalue */\n"
6825 " %s, /* enum gcc_jit_binary_op op */\n"
6826 " %s); /* gcc_jit_rvalue *rvalue */\n",
6827 r.get_identifier (get_block ()),
6828 r.get_identifier (get_loc ()),
6829 r.get_identifier_as_lvalue (m_lvalue),
6830 binary_op_reproducer_strings[m_op],
6831 r.get_identifier_as_rvalue (m_rvalue));
6834 /* The implementation of class gcc::jit::recording::comment. */
6836 /* Implementation of pure virtual hook recording::memento::replay_into
6837 for recording::comment. */
6839 void
6840 recording::comment::replay_into (replayer *r)
6842 playback_block (get_block ())
6843 ->add_comment (playback_location (r),
6844 m_text->c_str ());
6847 /* Implementation of recording::memento::make_debug_string for
6848 a comment "statement". */
6850 recording::string *
6851 recording::comment::make_debug_string ()
6853 return string::from_printf (m_ctxt,
6854 "/* %s */",
6855 m_text->c_str ());
6858 /* Implementation of recording::memento::write_reproducer for
6859 comments. */
6861 void
6862 recording::comment::write_reproducer (reproducer &r)
6864 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
6865 " %s, /* gcc_jit_location *loc */\n"
6866 " %s); /* const char *text */\n",
6867 r.get_identifier (get_block ()),
6868 r.get_identifier (get_loc ()),
6869 m_text->get_debug_string ());
6872 /* The implementation of class gcc::jit::recording::conditional. */
6874 /* Implementation of pure virtual hook recording::memento::replay_into
6875 for recording::conditional. */
6877 void
6878 recording::conditional::replay_into (replayer *r)
6880 playback_block (get_block ())
6881 ->add_conditional (playback_location (r),
6882 m_boolval->playback_rvalue (),
6883 playback_block (m_on_true),
6884 playback_block (m_on_false));
6887 /* Override the poisoned default implementation of
6888 gcc::jit::recording::statement::get_successor_blocks
6890 A conditional jump has 2 successor blocks. */
6892 vec <recording::block *>
6893 recording::conditional::get_successor_blocks () const
6895 vec <block *> result;
6896 result.create (2);
6897 result.quick_push (m_on_true);
6898 result.quick_push (m_on_false);
6899 return result;
6902 /* Implementation of recording::memento::make_debug_string for
6903 a conditional jump statement. */
6905 recording::string *
6906 recording::conditional::make_debug_string ()
6908 if (m_on_false)
6909 return string::from_printf (m_ctxt,
6910 "if (%s) goto %s; else goto %s;",
6911 m_boolval->get_debug_string (),
6912 m_on_true->get_debug_string (),
6913 m_on_false->get_debug_string ());
6914 else
6915 return string::from_printf (m_ctxt,
6916 "if (%s) goto %s;",
6917 m_boolval->get_debug_string (),
6918 m_on_true->get_debug_string ());
6921 /* Implementation of recording::memento::write_reproducer for
6922 conditional statements. */
6924 void
6925 recording::conditional::write_reproducer (reproducer &r)
6927 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
6928 " %s, /* gcc_jit_location *loc */\n"
6929 " %s, /* gcc_jit_rvalue *boolval */\n"
6930 " %s, /* gcc_jit_block *on_true */\n"
6931 " %s); /* gcc_jit_block *on_false */\n",
6932 r.get_identifier (get_block ()),
6933 r.get_identifier (get_loc ()),
6934 r.get_identifier_as_rvalue (m_boolval),
6935 r.get_identifier (m_on_true),
6936 r.get_identifier (m_on_false));
6939 /* The implementation of class gcc::jit::recording::jump. */
6941 /* Implementation of pure virtual hook recording::memento::replay_into
6942 for recording::jump. */
6944 void
6945 recording::jump::replay_into (replayer *r)
6947 playback_block (get_block ())
6948 ->add_jump (playback_location (r),
6949 m_target->playback_block ());
6952 /* Override the poisoned default implementation of
6953 gcc::jit::recording::statement::get_successor_blocks
6955 An unconditional jump has 1 successor block. */
6957 vec <recording::block *>
6958 recording::jump::get_successor_blocks () const
6960 vec <block *> result;
6961 result.create (1);
6962 result.quick_push (m_target);
6963 return result;
6966 /* Implementation of recording::memento::make_debug_string for
6967 a unconditional jump statement. */
6969 recording::string *
6970 recording::jump::make_debug_string ()
6972 return string::from_printf (m_ctxt,
6973 "goto %s;",
6974 m_target->get_debug_string ());
6977 /* Implementation of recording::memento::write_reproducer for
6978 jump statements. */
6980 void
6981 recording::jump::write_reproducer (reproducer &r)
6983 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
6984 " %s, /* gcc_jit_location *loc */\n"
6985 " %s); /* gcc_jit_block *target */\n",
6986 r.get_identifier (get_block ()),
6987 r.get_identifier (get_loc ()),
6988 r.get_identifier (m_target));
6991 /* The implementation of class gcc::jit::recording::return_. */
6993 /* Implementation of pure virtual hook recording::memento::replay_into
6994 for recording::return_. */
6996 void
6997 recording::return_::replay_into (replayer *r)
6999 playback_block (get_block ())
7000 ->add_return (playback_location (r),
7001 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
7004 /* Override the poisoned default implementation of
7005 gcc::jit::recording::statement::get_successor_blocks
7007 A return statement has no successor block. */
7009 vec <recording::block *>
7010 recording::return_::get_successor_blocks () const
7012 vec <block *> result;
7013 result.create (0);
7014 return result;
7017 /* Implementation of recording::memento::make_debug_string for
7018 a return statement (covers both those with and without rvalues). */
7020 recording::string *
7021 recording::return_::make_debug_string ()
7023 if (m_rvalue)
7024 return string::from_printf (m_ctxt,
7025 "return %s;",
7026 m_rvalue->get_debug_string ());
7027 else
7028 return string::from_printf (m_ctxt,
7029 "return;");
7032 /* Implementation of recording::memento::write_reproducer for
7033 return statements. */
7035 void
7036 recording::return_::write_reproducer (reproducer &r)
7038 if (m_rvalue)
7039 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
7040 " %s, /* gcc_jit_location *loc */\n"
7041 " %s); /* gcc_jit_rvalue *rvalue */\n",
7042 r.get_identifier (get_block ()),
7043 r.get_identifier (get_loc ()),
7044 r.get_identifier_as_rvalue (m_rvalue));
7045 else
7046 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
7047 " %s); /* gcc_jit_location *loc */\n",
7048 r.get_identifier (get_block ()),
7049 r.get_identifier (get_loc ()));
7052 /* The implementation of class gcc::jit::recording::case_. */
7054 void
7055 recording::case_::write_reproducer (reproducer &r)
7057 const char *id = r.make_identifier (this, "case");
7058 const char *fmt =
7059 " gcc_jit_case *%s = \n"
7060 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
7061 " %s, /* gcc_jit_rvalue *min_value */\n"
7062 " %s, /* gcc_jit_rvalue *max_value */\n"
7063 " %s); /* gcc_jit_block *dest_block */\n";
7064 r.write (fmt,
7066 r.get_identifier (get_context ()),
7067 r.get_identifier_as_rvalue (m_min_value),
7068 r.get_identifier_as_rvalue (m_max_value),
7069 r.get_identifier (m_dest_block));
7072 recording::string *
7073 recording::case_::make_debug_string ()
7075 return string::from_printf (get_context (),
7076 "case %s ... %s: goto %s;",
7077 m_min_value->get_debug_string (),
7078 m_max_value->get_debug_string (),
7079 m_dest_block->get_debug_string ());
7082 /* The implementation of class gcc::jit::recording::switch_. */
7084 /* gcc::jit::recording::switch_'s constructor. */
7086 recording::switch_::switch_ (block *b,
7087 location *loc,
7088 rvalue *expr,
7089 block *default_block,
7090 int num_cases,
7091 case_ **cases)
7092 : statement (b, loc),
7093 m_expr (expr),
7094 m_default_block (default_block)
7096 m_cases.reserve_exact (num_cases);
7097 for (int i = 0; i< num_cases; i++)
7098 m_cases.quick_push (cases[i]);
7101 /* Implementation of pure virtual hook recording::memento::replay_into
7102 for recording::switch_. */
7104 void
7105 recording::switch_::replay_into (replayer *r)
7107 auto_vec <playback::case_> pcases;
7108 int i;
7109 recording::case_ *rcase;
7110 pcases.reserve_exact (m_cases.length ());
7111 FOR_EACH_VEC_ELT (m_cases, i, rcase)
7113 playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (),
7114 rcase->get_max_value ()->playback_rvalue (),
7115 rcase->get_dest_block ()->playback_block ());
7116 pcases.safe_push (pcase);
7118 playback_block (get_block ())
7119 ->add_switch (playback_location (r),
7120 m_expr->playback_rvalue (),
7121 m_default_block->playback_block (),
7122 &pcases);
7125 /* Override the poisoned default implementation of
7126 gcc::jit::recording::statement::get_successor_blocks
7128 A switch statement has (NUM_CASES + 1) successor blocks. */
7130 vec <recording::block *>
7131 recording::switch_::get_successor_blocks () const
7133 vec <block *> result;
7134 result.create (m_cases.length () + 1);
7135 result.quick_push (m_default_block);
7136 int i;
7137 case_ *c;
7138 FOR_EACH_VEC_ELT (m_cases, i, c)
7139 result.quick_push (c->get_dest_block ());
7140 return result;
7143 /* Implementation of recording::memento::make_debug_string for
7144 a switch statement. */
7146 recording::string *
7147 recording::switch_::make_debug_string ()
7149 auto_vec <char> cases_str;
7150 int i;
7151 case_ *c;
7152 FOR_EACH_VEC_ELT (m_cases, i, c)
7154 size_t len = strlen (c->get_debug_string ());
7155 unsigned idx = cases_str.length ();
7156 cases_str.safe_grow (idx + 1 + len, true);
7157 cases_str[idx] = ' ';
7158 memcpy (&(cases_str[idx + 1]),
7159 c->get_debug_string (),
7160 len);
7162 cases_str.safe_push ('\0');
7164 return string::from_printf (m_ctxt,
7165 "switch (%s) {default: goto %s;%s}",
7166 m_expr->get_debug_string (),
7167 m_default_block->get_debug_string (),
7168 &cases_str[0]);
7171 /* Implementation of recording::memento::write_reproducer for
7172 switch statements. */
7174 void
7175 recording::switch_::write_reproducer (reproducer &r)
7177 r.make_identifier (this, "switch");
7178 int i;
7179 case_ *c;
7180 const char *cases_id =
7181 r.make_tmp_identifier ("cases_for", this);
7182 r.write (" gcc_jit_case *%s[%i] = {\n",
7183 cases_id,
7184 m_cases.length ());
7185 FOR_EACH_VEC_ELT (m_cases, i, c)
7186 r.write (" %s,\n", r.get_identifier (c));
7187 r.write (" };\n");
7188 const char *fmt =
7189 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
7190 " %s, /* gcc_jit_location *loc */\n"
7191 " %s, /* gcc_jit_rvalue *expr */\n"
7192 " %s, /* gcc_jit_block *default_block */\n"
7193 " %i, /* int num_cases */\n"
7194 " %s); /* gcc_jit_case **cases */\n";
7195 r.write (fmt,
7196 r.get_identifier (get_block ()),
7197 r.get_identifier (get_loc ()),
7198 r.get_identifier_as_rvalue (m_expr),
7199 r.get_identifier (m_default_block),
7200 m_cases.length (),
7201 cases_id);
7204 /* class asm_operand : public memento. */
7206 recording::asm_operand::asm_operand (extended_asm *ext_asm,
7207 string *asm_symbolic_name,
7208 string *constraint)
7209 : memento (ext_asm->get_context ()),
7210 m_ext_asm (ext_asm),
7211 m_asm_symbolic_name (asm_symbolic_name),
7212 m_constraint (constraint)
7216 void
7217 recording::asm_operand::print (pretty_printer *pp) const
7219 if (m_asm_symbolic_name)
7221 pp_character (pp, '[');
7222 pp_string (pp, m_asm_symbolic_name->c_str ());
7223 pp_character (pp, ']');
7224 pp_space (pp);
7226 pp_string (pp, m_constraint->get_debug_string ());
7227 /* Subclass will add lvalue/rvalue. */
7230 recording::string *
7231 recording::asm_operand::make_debug_string ()
7233 pretty_printer pp;
7234 print (&pp);
7235 return m_ctxt->new_string (pp_formatted_text (&pp), false);
7238 /* class output_asm_operand : public asm_operand. */
7240 void
7241 recording::output_asm_operand::write_reproducer (reproducer &r)
7243 const char *fmt =
7244 " gcc_jit_extended_asm_add_output_operand (%s, /* gcc_jit_extended_asm *ext_asm */\n"
7245 " %s, /* const char *asm_symbolic_name */\n"
7246 " %s, /* const char *constraint */\n"
7247 " %s); /* gcc_jit_lvalue *dest */\n";
7248 r.write (fmt,
7249 r.get_identifier (m_ext_asm),
7250 (m_asm_symbolic_name
7251 ? m_asm_symbolic_name->get_debug_string () : "NULL"),
7252 m_constraint->get_debug_string (),
7253 r.get_identifier (m_dest));
7256 void
7257 recording::output_asm_operand::print (pretty_printer *pp) const
7259 asm_operand::print (pp);
7260 pp_string (pp, " (");
7261 pp_string (pp, m_dest->get_debug_string ());
7262 pp_string (pp, ")");
7265 /* class input_asm_operand : public asm_operand. */
7267 void
7268 recording::input_asm_operand::write_reproducer (reproducer &r)
7270 const char *fmt =
7271 " gcc_jit_extended_asm_add_input_operand (%s, /* gcc_jit_extended_asm *ext_asm */\n"
7272 " %s, /* const char *asm_symbolic_name */\n"
7273 " %s, /* const char *constraint */\n"
7274 " %s); /* gcc_jit_rvalue *src */\n";
7275 r.write (fmt,
7276 r.get_identifier (m_ext_asm),
7277 (m_asm_symbolic_name
7278 ? m_asm_symbolic_name->get_debug_string () : "NULL"),
7279 m_constraint->get_debug_string (),
7280 r.get_identifier_as_rvalue (m_src));
7283 void
7284 recording::input_asm_operand::print (pretty_printer *pp) const
7286 asm_operand::print (pp);
7287 pp_string (pp, " (");
7288 pp_string (pp, m_src->get_debug_string ());
7289 pp_string (pp, ")");
7292 /* The implementation of class gcc::jit::recording::extended_asm. */
7294 void
7295 recording::extended_asm::add_output_operand (const char *asm_symbolic_name,
7296 const char *constraint,
7297 lvalue *dest)
7299 output_asm_operand *op
7300 = new output_asm_operand (this,
7301 new_string (asm_symbolic_name),
7302 new_string (constraint),
7303 dest);
7304 m_ctxt->record (op);
7305 m_output_ops.safe_push (op);
7308 void
7309 recording::extended_asm::add_input_operand (const char *asm_symbolic_name,
7310 const char *constraint,
7311 rvalue *src)
7313 input_asm_operand *op
7314 = new input_asm_operand (this,
7315 new_string (asm_symbolic_name),
7316 new_string (constraint),
7317 src);
7318 m_ctxt->record (op);
7319 m_input_ops.safe_push (op);
7322 void
7323 recording::extended_asm::add_clobber (const char *victim)
7325 m_clobbers.safe_push (new_string (victim));
7328 /* Implementation of recording::memento::replay_into
7329 for recording::extended_asm. */
7331 void
7332 recording::extended_asm::replay_into (replayer *r)
7334 auto_vec<playback::asm_operand> playback_output_ops;
7335 auto_vec<playback::asm_operand> playback_input_ops;
7336 auto_vec<const char *> playback_clobbers;
7337 auto_vec<playback::block *> playback_goto_blocks;
7339 /* Populate outputs. */
7341 output_asm_operand *rec_asm_op;
7342 unsigned i;
7343 FOR_EACH_VEC_ELT (m_output_ops, i, rec_asm_op)
7345 playback::asm_operand playback_asm_op
7346 (rec_asm_op->get_symbolic_name (),
7347 rec_asm_op->get_constraint (),
7348 rec_asm_op->get_lvalue ()->playback_lvalue ()->as_tree ());
7349 playback_output_ops.safe_push (playback_asm_op);
7353 /* Populate inputs. */
7355 input_asm_operand *rec_asm_op;
7356 unsigned i;
7357 FOR_EACH_VEC_ELT (m_input_ops, i, rec_asm_op)
7359 playback::asm_operand playback_asm_op
7360 (rec_asm_op->get_symbolic_name (),
7361 rec_asm_op->get_constraint (),
7362 rec_asm_op->get_rvalue ()->playback_rvalue ()->as_tree ());
7363 playback_input_ops.safe_push (playback_asm_op);
7367 /* Populate clobbers. */
7369 string *rec_clobber;
7370 unsigned i;
7371 FOR_EACH_VEC_ELT (m_clobbers, i, rec_clobber)
7372 playback_clobbers.safe_push (rec_clobber->c_str ());
7375 /* Populate playback blocks if an "asm goto". */
7376 maybe_populate_playback_blocks (&playback_goto_blocks);
7378 playback_block (get_block ())
7379 ->add_extended_asm (playback_location (r),
7380 m_asm_template->c_str (),
7381 m_is_volatile, m_is_inline,
7382 &playback_output_ops,
7383 &playback_input_ops,
7384 &playback_clobbers,
7385 &playback_goto_blocks);
7388 /* Implementation of recording::memento::make_debug_string for
7389 an extended_asm "statement". */
7391 recording::string *
7392 recording::extended_asm::make_debug_string ()
7394 pretty_printer pp;
7395 pp_string (&pp, "asm ");
7396 if (m_is_volatile)
7397 pp_string (&pp, "volatile ");
7398 if (m_is_inline)
7399 pp_string (&pp, "inline ");
7400 if (is_goto ())
7401 pp_string (&pp, "goto ");
7402 pp_character (&pp, '(');
7403 pp_string (&pp, m_asm_template->get_debug_string ());
7404 pp_string (&pp, " : ");
7405 unsigned i;
7407 output_asm_operand *asm_op;
7408 FOR_EACH_VEC_ELT (m_output_ops, i, asm_op)
7410 if (i > 0)
7411 pp_string (&pp, ", ");
7412 asm_op->print (&pp);
7415 pp_string (&pp, " : ");
7417 input_asm_operand *asm_op;
7418 FOR_EACH_VEC_ELT (m_input_ops, i, asm_op)
7420 if (i > 0)
7421 pp_string (&pp, ", ");
7422 asm_op->print (&pp);
7425 pp_string (&pp, " : ");
7426 string *rec_clobber;
7427 FOR_EACH_VEC_ELT (m_clobbers, i, rec_clobber)
7429 if (i > 0)
7430 pp_string (&pp, ", ");
7431 pp_string (&pp, rec_clobber->get_debug_string ());
7433 maybe_print_gotos (&pp);
7434 pp_character (&pp, ')');
7435 return new_string (pp_formatted_text (&pp));
7438 void
7439 recording::extended_asm::write_flags (reproducer &r)
7441 if (m_is_volatile)
7442 r.write (" gcc_jit_extended_asm_set_volatile_flag (%s, 1);\n",
7443 r.get_identifier (this));
7444 if (m_is_inline)
7445 r.write (" gcc_jit_extended_asm_set_inline_flag (%s, 1);\n",
7446 r.get_identifier (this));
7449 void
7450 recording::extended_asm::write_clobbers (reproducer &r)
7452 string *clobber;
7453 unsigned i;
7454 FOR_EACH_VEC_ELT (m_clobbers, i, clobber)
7455 r.write (" gcc_jit_extended_asm_add_clobber (%s, %s);\n",
7456 r.get_identifier (this),
7457 clobber->get_debug_string ());
7460 /* Implementation of recording::memento::write_reproducer for
7461 extended_asm_simple. */
7463 void
7464 recording::extended_asm_simple::write_reproducer (reproducer &r)
7466 const char *id = r.make_identifier (this, "extended_asm");
7467 r.write (" gcc_jit_extended_asm *%s =\n"
7468 " gcc_jit_block_add_extended_asm (%s, /*gcc_jit_block *block */\n"
7469 " %s, /* gcc_jit_location *loc */\n"
7470 " %s); /* const char *asm_template */\n",
7472 r.get_identifier (get_block ()),
7473 r.get_identifier (get_loc ()),
7474 m_asm_template->get_debug_string ());
7475 write_flags (r);
7476 write_clobbers (r);
7479 void
7480 recording::extended_asm::
7481 maybe_populate_playback_blocks (auto_vec <playback::block *> *)
7483 /* Do nothing; not an "asm goto". */
7486 /* The implementation of class gcc::jit::recording::extended_asm_goto. */
7488 /* recording::extended_asm_goto's ctor. */
7490 recording::extended_asm_goto::extended_asm_goto (block *b,
7491 location *loc,
7492 string *asm_template,
7493 int num_goto_blocks,
7494 block **goto_blocks,
7495 block *fallthrough_block)
7496 : extended_asm (b, loc, asm_template),
7497 m_goto_blocks (num_goto_blocks),
7498 m_fallthrough_block (fallthrough_block)
7500 for (int i = 0; i < num_goto_blocks; i++)
7501 m_goto_blocks.quick_push (goto_blocks[i]);
7504 /* Implementation of recording::memento::replay_into
7505 for recording::extended_asm_goto. */
7507 void
7508 recording::extended_asm_goto::replay_into (replayer *r)
7510 /* Chain up to base class impl. */
7511 recording::extended_asm::replay_into (r);
7513 /* ...and potentially add a goto for the fallthrough. */
7514 if (m_fallthrough_block)
7515 playback_block (get_block ())
7516 ->add_jump (playback_location (r),
7517 m_fallthrough_block->playback_block ());
7520 /* Implementation of recording::memento::write_reproducer for
7521 extended_asm_goto. */
7523 void
7524 recording::extended_asm_goto::write_reproducer (reproducer &r)
7526 const char *id = r.make_identifier (this, "extended_asm");
7527 const char *blocks_id = r.make_tmp_identifier ("blocks_for", this);
7528 r.write (" gcc_jit_block *%s[%i] = {\n",
7529 blocks_id,
7530 m_goto_blocks.length ());
7531 int i;
7532 block *b;
7533 FOR_EACH_VEC_ELT (m_goto_blocks, i, b)
7534 r.write (" %s,\n", r.get_identifier (b));
7535 r.write (" };\n");
7536 r.write (" gcc_jit_extended_asm *%s =\n"
7537 " gcc_jit_block_end_with_extended_asm_goto (%s, /*gcc_jit_block *block */\n"
7538 " %s, /* gcc_jit_location *loc */\n"
7539 " %s, /* const char *asm_template */\n"
7540 " %i, /* int num_goto_blocks */\n"
7541 " %s, /* gcc_jit_block **goto_blocks */\n"
7542 " %s); /* gcc_jit_block *fallthrough_block */\n",
7544 r.get_identifier (get_block ()),
7545 r.get_identifier (get_loc ()),
7546 m_asm_template->get_debug_string (),
7547 m_goto_blocks.length (),
7548 blocks_id,
7549 (m_fallthrough_block
7550 ? r.get_identifier (m_fallthrough_block)
7551 : "NULL"));
7552 write_flags (r);
7553 write_clobbers (r);
7556 /* Override the poisoned default implementation of
7557 gcc::jit::recording::statement::get_successor_blocks
7559 An extended_asm_goto can jump to the m_goto_blocks, and to
7560 the (optional) m_fallthrough_block. */
7562 vec <recording::block *>
7563 recording::extended_asm_goto::get_successor_blocks () const
7565 vec <block *> result;
7566 result.create (m_goto_blocks.length () + 1);
7567 if (m_fallthrough_block)
7568 result.quick_push (m_fallthrough_block);
7569 result.splice (m_goto_blocks);
7570 return result;
7573 /* Vfunc for use by recording::extended_asm::make_debug_string. */
7575 void
7576 recording::extended_asm_goto::maybe_print_gotos (pretty_printer *pp) const
7578 pp_string (pp, " : ");
7579 unsigned i;
7580 block *b;
7581 FOR_EACH_VEC_ELT (m_goto_blocks, i, b)
7583 if (i > 0)
7584 pp_string (pp, ", ");
7585 pp_string (pp, b->get_debug_string ());
7587 /* Non-C syntax here. */
7588 if (m_fallthrough_block)
7589 pp_printf (pp, " [fallthrough: %s]",
7590 m_fallthrough_block->get_debug_string ());
7593 /* Vfunc for use by recording::extended_asm::replay_into. */
7595 void
7596 recording::extended_asm_goto::
7597 maybe_populate_playback_blocks (auto_vec <playback::block *> *out)
7599 unsigned i;
7600 block *b;
7601 FOR_EACH_VEC_ELT (m_goto_blocks, i, b)
7602 out->safe_push (b->playback_block ());
7605 /* class top_level_asm : public memento. */
7607 recording::top_level_asm::top_level_asm (context *ctxt,
7608 location *loc,
7609 string *asm_stmts)
7610 : memento (ctxt),
7611 m_loc (loc),
7612 m_asm_stmts (asm_stmts)
7616 /* Implementation of recording::memento::replay_into for top-level asm. */
7618 void
7619 recording::top_level_asm::replay_into (replayer *r)
7621 r->add_top_level_asm (m_asm_stmts->c_str ());
7624 /* Implementation of recording::memento::make_debug_string for
7625 top-level asm. */
7627 recording::string *
7628 recording::top_level_asm::make_debug_string ()
7630 return string::from_printf (m_ctxt, "asm (%s)",
7631 m_asm_stmts->get_debug_string ());
7634 /* Override the default implementation of
7635 recording::memento::write_to_dump.
7636 Don't indent the string. */
7638 void
7639 recording::top_level_asm::write_to_dump (dump &d)
7641 d.write ("%s;\n", get_debug_string ());
7644 /* Implementation of recording::memento::write_reproducer for top-level asm. */
7646 void
7647 recording::top_level_asm::write_reproducer (reproducer &r)
7649 r.write (" gcc_jit_context_add_top_level_asm (%s, /* gcc_jit_context *ctxt */\n"
7650 " %s, /* gcc_jit_location *loc */\n"
7651 " %s); /* const char *asm_stmts */\n",
7652 r.get_identifier (get_context ()),
7653 r.get_identifier (m_loc),
7654 m_asm_stmts->get_debug_string ());
7657 void
7658 recording::global_init_rvalue::replay_into (replayer *r)
7660 r->global_set_init_rvalue (m_variable->playback_lvalue (),
7661 m_init->playback_rvalue ());
7664 void
7665 recording::global_init_rvalue::write_reproducer (reproducer &r)
7667 r.write (
7668 " gcc_jit_global_set_initializer_rvalue (%s, /* lvalue *global */\n"
7669 " %s);/* rvalue *init */\n",
7670 r.get_identifier (m_variable),
7671 r.get_identifier_as_rvalue (m_init));
7674 void
7675 recording::global_init_rvalue::write_to_dump (dump &d)
7677 d.write ("%s;\n", get_debug_string ());
7680 recording::string *
7681 recording::global_init_rvalue::make_debug_string ()
7683 return string::from_printf (m_ctxt, "%s = %s",
7684 m_variable->get_debug_string (),
7685 m_init->get_debug_string ());
7688 enum strip_flags {
7689 STRIP_FLAG_NONE,
7690 STRIP_FLAG_ARR,
7691 STRIP_FLAG_VEC
7694 /* Strips type down to array, vector or base type (whichever comes first)
7696 Also saves 'ptr_depth' and sets 'flags' for array or vector types. */
7697 static
7698 recording::type *
7699 strip_and_count (recording::type *type_to_strip,
7700 int &ptr_depth,
7701 strip_flags &flags)
7703 recording::type *t = type_to_strip;
7705 while (true)
7707 if (!t)
7708 gcc_unreachable (); /* Should only happen on corrupt input. */
7710 recording::type *pointed_to_type = t->is_pointer ();
7711 if (pointed_to_type != NULL)
7713 ptr_depth++;
7714 t = pointed_to_type;
7715 continue;
7718 recording::type *array_el = t->is_array ();
7719 if (array_el != NULL)
7721 flags = STRIP_FLAG_ARR;
7722 break;
7725 recording::type *vec = t->dyn_cast_vector_type ();
7726 if (vec != NULL)
7728 flags = STRIP_FLAG_VEC;
7729 break;
7732 /* unqualified () returns 'this' on base types. */
7733 recording::type *next = t->unqualified ();
7734 if (next == t)
7736 break;
7738 t = next;
7741 return t;
7744 /* Strip qualifiers and count pointer depth, returning true
7745 if the types' base type and pointer depth are
7746 the same, otherwise false.
7748 For array and vector types the number of element also
7749 has to match.
7751 Do not call this directly. Call 'types_kinda_same'. */
7752 bool
7753 types_kinda_same_internal (recording::type *a, recording::type *b)
7755 int ptr_depth_a = 0;
7756 int ptr_depth_b = 0;
7757 recording::type *base_a;
7758 recording::type *base_b;
7760 strip_flags flags_a = STRIP_FLAG_NONE;
7761 strip_flags flags_b = STRIP_FLAG_NONE;
7763 base_a = strip_and_count (a, ptr_depth_a, flags_a);
7764 base_b = strip_and_count (b, ptr_depth_b, flags_b);
7766 if (ptr_depth_a != ptr_depth_b)
7767 return false;
7769 if (base_a == base_b)
7770 return true;
7772 if (flags_a != flags_b)
7773 return false;
7775 /* If the "base type" is an array or vector we might need to
7776 check deeper. */
7777 if (flags_a == STRIP_FLAG_ARR)
7779 recording::array_type *arr_a =
7780 static_cast<recording::array_type*> (base_a);
7781 recording::array_type *arr_b =
7782 static_cast<recording::array_type*> (base_b);
7784 if (arr_a->num_elements () != arr_b->num_elements ())
7785 return false;
7787 /* is_array returns element type. */
7788 recording::type *el_a = arr_a->is_array ();
7789 recording::type *el_b = arr_b->is_array ();
7791 if (el_a == el_b)
7792 return true;
7794 return types_kinda_same_internal (el_a, el_b);
7796 if (flags_a == STRIP_FLAG_VEC)
7798 recording::vector_type *arr_a =
7799 static_cast<recording::vector_type*> (base_a);
7800 recording::vector_type *arr_b =
7801 static_cast<recording::vector_type*> (base_b);
7803 if (arr_a->get_num_units () != arr_b->get_num_units ())
7804 return false;
7806 recording::type *el_a = arr_a->get_element_type ();
7807 recording::type *el_b = arr_b->get_element_type ();
7809 if (el_a == el_b)
7810 return true;
7812 return types_kinda_same_internal (el_a, el_b);
7815 return false;
7818 } // namespace gcc::jit
7820 } // namespace gcc