Add initial version of C++17 <memory_resource> header
[official-gcc.git] / gcc / jit / jit-recording.c
blob95bcaa01d442ee915971d6e8748a126c339f6224
1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2018 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "pretty-print.h"
26 #include "toplev.h"
28 #include <pthread.h>
30 #include "jit-builtins.h"
31 #include "jit-recording.h"
32 #include "jit-playback.h"
34 namespace gcc {
35 namespace jit {
37 // class dump
39 dump::dump (recording::context &ctxt,
40 const char *filename,
41 bool update_locations)
42 : m_ctxt (ctxt),
43 m_filename (filename),
44 m_update_locations (update_locations),
45 m_line (0),
46 m_column (0)
48 m_file = fopen (filename, "w");
49 if (!m_file)
50 ctxt.add_error (NULL,
51 "error opening dump file %s for writing: %s",
52 filename,
53 xstrerror (errno));
56 dump::~dump ()
58 if (m_file)
60 int err = fclose (m_file);
61 if (err)
62 m_ctxt.add_error (NULL,
63 "error closing dump file %s: %s",
64 m_filename,
65 xstrerror (errno));
69 /* Write the given message to the dump, using printf-formatting
70 conventions, updating the line/column within the dump.
72 Emit an error on the context if a failure occurs. */
74 void
75 dump::write (const char *fmt, ...)
77 int len;
78 va_list ap;
79 char *buf;
81 /* If there was an error opening the file, we've already reported it.
82 Don't attempt further work. */
83 if (!m_file)
84 return;
86 va_start (ap, fmt);
87 len = vasprintf (&buf, fmt, ap);
88 va_end (ap);
90 if (buf == NULL || len < 0)
92 m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
93 m_filename);
94 return;
97 if (fwrite (buf, strlen (buf), 1, m_file) != 1)
98 m_ctxt.add_error (NULL, "error writing to dump file %s",
99 m_filename);
101 /* Flush after each line, to ease debugging crashes. */
102 fflush (m_file);
104 /* Update line/column: */
105 for (const char *ptr = buf; *ptr; ptr++)
107 if ('\n' == *ptr)
109 m_line++;
110 m_column = 0;
112 else
113 m_column++;
116 free (buf);
119 /* Construct a gcc::jit::recording::location instance for the current
120 location within the dump. */
122 recording::location *
123 dump::make_location () const
125 return m_ctxt.new_location (m_filename, m_line, m_column,
126 /* We need to flag such locations as *not*
127 created by the user, so that
128 reproducer::get_identifier can cope with
129 them appearing *after* the memento that
130 refers to them. */
131 false);
134 /* A collection of allocations, all of which can be released together, to
135 avoid needing to track and release them individually. */
137 class allocator
139 public:
140 ~allocator ();
142 char *
143 xstrdup_printf (const char *, ...)
144 ATTRIBUTE_RETURNS_NONNULL
145 GNU_PRINTF(2, 3);
147 char *
148 xstrdup_printf_va (const char *, va_list ap)
149 ATTRIBUTE_RETURNS_NONNULL
150 GNU_PRINTF(2, 0);
152 private:
153 auto_vec <void *> m_buffers;
156 /* allocator's destructor. Call "free" on all of the allocations. */
158 allocator::~allocator ()
160 unsigned i;
161 void *buffer;
162 FOR_EACH_VEC_ELT (m_buffers, i, buffer)
163 free (buffer);
166 /* Formatted printing, allocating to a buffer (or exiting the process if
167 the allocation fails).
169 The buffer exists until the allocator is cleaned up, and is freed at
170 that point, so the caller doesn't need to track the result. */
172 char *
173 allocator::xstrdup_printf (const char *fmt, ...)
175 char *result;
176 va_list ap;
177 va_start (ap, fmt);
178 result = xstrdup_printf_va (fmt, ap);
179 va_end (ap);
180 return result;
183 /* Formatted printing, allocating to a buffer (or exiting the process if
184 the allocation fails).
186 The buffer exists until the allocator is cleaned up, and is freed at
187 that point, so the caller doesn't need to track the result. */
189 char *
190 allocator::xstrdup_printf_va (const char *fmt, va_list ap)
192 char *result = xvasprintf (fmt, ap);
193 m_buffers.safe_push (result);
194 return result;
197 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
198 implementing gcc_jit_context_dump_reproducer_to_file. */
200 class reproducer : public dump
202 public:
203 reproducer (recording::context &ctxt,
204 const char *filename);
206 void
207 write_params (const vec <recording::context *> &contexts);
209 void
210 write_args (const vec <recording::context *> &contexts);
212 const char *
213 make_identifier (recording::memento *m, const char *prefix);
215 const char *
216 make_tmp_identifier (const char *prefix, recording::memento *m);
218 const char *
219 get_identifier (recording::context *ctxt);
221 const char *
222 get_identifier (recording::memento *m);
224 const char *
225 get_identifier_as_rvalue (recording::rvalue *m);
227 const char *
228 get_identifier_as_lvalue (recording::lvalue *m);
230 const char *
231 get_identifier_as_type (recording::type *m);
233 char *
234 xstrdup_printf (const char *, ...)
235 ATTRIBUTE_RETURNS_NONNULL
236 GNU_PRINTF(2, 3);
238 private:
239 const char * ensure_identifier_is_unique (const char *candidate, void *ptr);
241 private:
242 hash_map<recording::memento *, const char *> m_map_memento_to_identifier;
244 struct hash_traits : public string_hash
246 static void remove (const char *) {}
248 hash_set<const char *, hash_traits> m_set_identifiers;
249 allocator m_allocator;
252 /* gcc::jit::reproducer's constructor. */
254 reproducer::reproducer (recording::context &ctxt,
255 const char *filename) :
256 dump (ctxt, filename, 0),
257 m_map_memento_to_identifier (),
258 m_set_identifiers (),
259 m_allocator ()
263 /* Write out a list of contexts as a set of parameters within a
264 C function declaration. */
266 void
267 reproducer::write_params (const vec <recording::context *> &contexts)
269 unsigned i;
270 recording::context *ctxt;
271 FOR_EACH_VEC_ELT (contexts, i, ctxt)
273 write ("gcc_jit_context *%s",
274 get_identifier (ctxt));
275 if (i < contexts.length () - 1)
276 write (",\n"
277 " ");
281 /* Write out a list of contexts as a set of arguments within a call
282 to a C function. */
284 void
285 reproducer::write_args (const vec <recording::context *> &contexts)
287 unsigned i;
288 recording::context *ctxt;
289 FOR_EACH_VEC_ELT (contexts, i, ctxt)
291 write ("%s",
292 get_identifier (ctxt));
293 if (i < contexts.length () - 1)
294 write (",\n"
295 " ");
299 /* Ensure that STR is a valid C identifier by overwriting
300 any invalid chars in-place with underscores.
302 This doesn't special-case the first character. */
304 static void
305 convert_to_identifier (char *str)
307 for (char *p = str; *p; p++)
308 if (!ISALNUM (*p))
309 *p = '_';
312 /* Given CANDIDATE, a possible C identifier for use in a reproducer,
313 ensure that it is unique within the generated source file by
314 appending PTR to it if necessary. Return the resulting string.
316 The reproducer will eventually clean up the buffer in its dtor. */
318 const char *
319 reproducer::ensure_identifier_is_unique (const char *candidate, void *ptr)
321 if (m_set_identifiers.contains (candidate))
322 candidate = m_allocator.xstrdup_printf ("%s_%p", candidate, ptr);
323 gcc_assert (!m_set_identifiers.contains (candidate));
324 m_set_identifiers.add (candidate);
325 return candidate;
328 /* Generate a C identifier for the given memento, associating the generated
329 buffer with the memento (for future calls to get_identifier et al).
331 The reproducer will eventually clean up the buffer in its dtor. */
332 const char *
333 reproducer::make_identifier (recording::memento *m, const char *prefix)
335 const char *result;
336 if (strlen (m->get_debug_string ()) < 100)
338 char *buf = m_allocator.xstrdup_printf ("%s_%s",
339 prefix,
340 m->get_debug_string ());
341 convert_to_identifier (buf);
342 result = buf;
344 else
345 result = m_allocator.xstrdup_printf ("%s_%p",
346 prefix, (void *) m);
347 result = ensure_identifier_is_unique (result, m);
348 m_map_memento_to_identifier.put (m, result);
349 return result;
352 /* Generate a C identifier for a temporary variable.
353 The reproducer will eventually clean up the buffer in its dtor. */
355 const char *
356 reproducer::make_tmp_identifier (const char *prefix, recording::memento *m)
358 return m_allocator.xstrdup_printf ("%s_%s",
359 prefix, get_identifier (m));
362 /* Generate a C identifier for the given context.
363 The reproducer will eventually clean up the buffer in its dtor. */
365 const char *
366 reproducer::get_identifier (recording::context *ctxt)
368 return m_allocator.xstrdup_printf ("ctxt_%p",
369 (void *)ctxt);
372 /* Locate the C identifier for the given memento, which is assumed to
373 have already been created via make_identifier. */
375 const char *
376 reproducer::get_identifier (recording::memento *m)
378 if (!m)
379 return "NULL";
381 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
382 and hence these locations appear in the context's memento list
383 out-of-order: they appear in the context's memento list *after*
384 the memento that refers to them. For this case, it's simplest to
385 pretend that they're NULL when writing out the code to recreate the
386 memento that uses them. */
387 if (recording::location *loc = m->dyn_cast_location ())
388 if (!loc->created_by_user ())
389 return "NULL";
391 const char **slot = m_map_memento_to_identifier.get (m);
392 if (!slot)
394 get_context ().add_error (NULL,
395 "unable to find identifier for %p: %s",
396 (void *)m,
397 m->get_debug_string ());
398 gcc_unreachable ();
400 return *slot;
403 /* Locate the C identifier for the given rvalue, wrapping it within
404 a gcc_*_as_rvalue upcast if necessary. */
406 const char *
407 reproducer::get_identifier_as_rvalue (recording::rvalue *m)
409 return m->access_as_rvalue (*this);
412 /* Locate the C identifier for the given lvalue, wrapping it within
413 a gcc_*_as_lvalue upcast if necessary. */
415 const char *
416 reproducer::get_identifier_as_lvalue (recording::lvalue *m)
418 return m->access_as_lvalue (*this);
421 /* Locate the C identifier for the given type, wrapping it within
422 a gcc_*_as_type upcast if necessary. */
424 const char *
425 reproducer::get_identifier_as_type (recording::type *m)
427 return m->access_as_type (*this);
430 /* Formatted printing, allocating to a buffer (or exiting the process if
431 the allocation fails).
433 The buffer exists until the allocator is cleaned up, and is freed at
434 that point, so the caller doesn't need to track the result.
436 Note that we can't use ggc_printf since we're not within the compiler
437 proper (when within gcc_jit_context_dump_reproducer_to_file). */
439 char *
440 reproducer::xstrdup_printf (const char *fmt, ...)
442 char *result;
443 va_list ap;
444 va_start (ap, fmt);
445 result = m_allocator.xstrdup_printf_va (fmt, ap);
446 va_end (ap);
447 return result;
450 /* A helper class for implementing make_debug_string, for building
451 a temporary string from a vec of rvalues. */
453 class comma_separated_string
455 public:
456 comma_separated_string (const auto_vec<recording::rvalue *> &rvalues,
457 enum recording::precedence prec);
458 ~comma_separated_string ();
460 const char *as_char_ptr () const { return m_buf; }
462 private:
463 char *m_buf;
466 /* comma_separated_string's ctor
467 Build m_buf. */
469 comma_separated_string::comma_separated_string
470 (const auto_vec<recording::rvalue *> &rvalues,
471 enum recording::precedence prec)
472 : m_buf (NULL)
474 /* Calculate length of said buffer. */
475 size_t sz = 1; /* nil terminator */
476 for (unsigned i = 0; i< rvalues.length (); i++)
478 sz += strlen (rvalues[i]->get_debug_string_parens (prec));
479 sz += 2; /* ", " separator */
482 /* Now allocate and populate the buffer. */
483 m_buf = new char[sz];
484 size_t len = 0;
486 for (unsigned i = 0; i< rvalues.length (); i++)
488 strcpy (m_buf + len, rvalues[i]->get_debug_string_parens (prec));
489 len += strlen (rvalues[i]->get_debug_string_parens (prec));
490 if (i + 1 < rvalues.length ())
492 strcpy (m_buf + len, ", ");
493 len += 2;
496 m_buf[len] = '\0';
499 /* comma_separated_string's dtor. */
501 comma_separated_string::~comma_separated_string ()
503 delete[] m_buf;
506 /**********************************************************************
507 Recording.
508 **********************************************************************/
510 /* Get the playback::location for the given recording::location,
511 handling a NULL input with a NULL output. */
513 playback::location *
514 recording::playback_location (replayer *r, recording::location *loc)
516 if (loc)
517 return loc->playback_location (r);
518 else
519 return NULL;
522 /* Get a const char * for the given recording::string
523 handling a NULL input with a NULL output. */
525 const char *
526 recording::playback_string (recording::string *str)
528 if (str)
529 return str->c_str ();
530 else
531 return NULL;
534 /* Get the playback::block for the given recording::block,
535 handling a NULL input with a NULL output. */
537 playback::block *
538 recording::playback_block (recording::block *b)
540 if (b)
541 return b->playback_block ();
542 else
543 return NULL;
546 /* Methods of cc::jit::recording::context. */
548 /* The constructor for gcc::jit::recording::context, used by
549 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
551 recording::context::context (context *parent_ctxt)
552 : log_user (NULL),
553 m_parent_ctxt (parent_ctxt),
554 m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this),
555 m_timer (NULL),
556 m_error_count (0),
557 m_first_error_str (NULL),
558 m_owns_first_error_str (false),
559 m_last_error_str (NULL),
560 m_owns_last_error_str (false),
561 m_mementos (),
562 m_compound_types (),
563 m_globals (),
564 m_functions (),
565 m_FILE_type (NULL),
566 m_builtins_manager(NULL)
568 if (parent_ctxt)
570 /* Inherit options from parent. */
571 for (unsigned i = 0;
572 i < sizeof (m_str_options) / sizeof (m_str_options[0]);
573 i++)
575 const char *parent_opt = parent_ctxt->m_str_options[i];
576 m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
578 memcpy (m_int_options,
579 parent_ctxt->m_int_options,
580 sizeof (m_int_options));
581 memcpy (m_bool_options,
582 parent_ctxt->m_bool_options,
583 sizeof (m_bool_options));
584 memcpy (m_inner_bool_options,
585 parent_ctxt->m_inner_bool_options,
586 sizeof (m_inner_bool_options));
587 set_logger (parent_ctxt->get_logger ());
589 else
591 memset (m_str_options, 0, sizeof (m_str_options));
592 memset (m_int_options, 0, sizeof (m_int_options));
593 memset (m_bool_options, 0, sizeof (m_bool_options));
594 memset (m_inner_bool_options, 0, sizeof (m_inner_bool_options));
597 memset (m_basic_types, 0, sizeof (m_basic_types));
600 /* The destructor for gcc::jit::recording::context, implicitly used by
601 gcc_jit_context_release. */
603 recording::context::~context ()
605 JIT_LOG_SCOPE (get_logger ());
606 int i;
607 memento *m;
608 FOR_EACH_VEC_ELT (m_mementos, i, m)
610 delete m;
613 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
614 free (m_str_options[i]);
616 char *optname;
617 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
618 free (optname);
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)
727 if (!text)
728 return NULL;
730 recording::string *result = new string (this, text);
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.c'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);
824 /* Some other size, not corresponding to the C int types. */
825 /* To be written: support arbitrary other sizes, sharing by
826 memoizing at the recording::context level? */
827 gcc_unreachable ();
830 /* Create a recording::type instance and add it to this context's list
831 of mementos.
833 Implements the post-error-checking part of
834 gcc_jit_context_new_array_type. */
836 recording::type *
837 recording::context::new_array_type (recording::location *loc,
838 recording::type *element_type,
839 int num_elements)
841 if (struct_ *s = element_type->dyn_cast_struct ())
842 if (!s->get_fields ())
844 add_error (NULL,
845 "cannot create an array of type %s"
846 " until the fields have been set",
847 s->get_name ()->c_str ());
848 return NULL;
850 recording::type *result =
851 new recording::array_type (this, loc, element_type, num_elements);
852 record (result);
853 return result;
856 /* Create a recording::field instance and add it to this context's list
857 of mementos.
859 Implements the post-error-checking part of
860 gcc_jit_context_new_field. */
862 recording::field *
863 recording::context::new_field (recording::location *loc,
864 recording::type *type,
865 const char *name)
867 recording::field *result =
868 new recording::field (this, loc, type, new_string (name));
869 record (result);
870 return result;
873 /* Create a recording::struct_ instance and add it to this context's
874 list of mementos and list of compound types.
876 Implements the post-error-checking part of
877 gcc_jit_context_new_struct_type. */
879 recording::struct_ *
880 recording::context::new_struct_type (recording::location *loc,
881 const char *name)
883 recording::struct_ *result = new struct_ (this, loc, new_string (name));
884 record (result);
885 m_compound_types.safe_push (result);
886 return result;
889 /* Create a recording::union_ instance and add it to this context's
890 list of mementos and list of compound types.
892 Implements the first post-error-checking part of
893 gcc_jit_context_new_union_type. */
895 recording::union_ *
896 recording::context::new_union_type (recording::location *loc,
897 const char *name)
899 recording::union_ *result = new union_ (this, loc, new_string (name));
900 record (result);
901 m_compound_types.safe_push (result);
902 return result;
905 /* Create a recording::function_type instance and add it to this context's
906 list of mementos.
908 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
910 recording::function_type *
911 recording::context::new_function_type (recording::type *return_type,
912 int num_params,
913 recording::type **param_types,
914 int is_variadic)
916 recording::function_type *fn_type
917 = new function_type (this,
918 return_type,
919 num_params,
920 param_types,
921 is_variadic);
922 record (fn_type);
923 return fn_type;
926 /* Create a recording::type instance and add it to this context's list
927 of mementos.
929 Implements the post-error-checking part of
930 gcc_jit_context_new_function_ptr_type. */
932 recording::type *
933 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
934 recording::type *return_type,
935 int num_params,
936 recording::type **param_types,
937 int is_variadic)
939 recording::function_type *fn_type
940 = new_function_type (return_type,
941 num_params,
942 param_types,
943 is_variadic);
945 /* Return a pointer-type to the function type. */
946 return fn_type->get_pointer ();
949 /* Create a recording::param instance and add it to this context's list
950 of mementos.
952 Implements the post-error-checking part of
953 gcc_jit_context_new_param. */
955 recording::param *
956 recording::context::new_param (recording::location *loc,
957 recording::type *type,
958 const char *name)
960 recording::param *result = new recording::param (this, loc, type, new_string (name));
961 record (result);
962 return result;
965 /* Create a recording::function instance and add it to this context's list
966 of mementos and list of functions.
968 Implements the post-error-checking part of
969 gcc_jit_context_new_function. */
971 recording::function *
972 recording::context::new_function (recording::location *loc,
973 enum gcc_jit_function_kind kind,
974 recording::type *return_type,
975 const char *name,
976 int num_params,
977 recording::param **params,
978 int is_variadic,
979 enum built_in_function builtin_id)
981 recording::function *result =
982 new recording::function (this,
983 loc, kind, return_type,
984 new_string (name),
985 num_params, params, is_variadic,
986 builtin_id);
987 record (result);
988 m_functions.safe_push (result);
990 return result;
993 /* Locate the builtins_manager (if any) for this family of contexts,
994 creating it if it doesn't exist already.
996 All of the recording contexts in a family share one builtins_manager:
997 if we have a child context, follow the parent links to get the
998 ultimate ancestor context, and look for it/store it there. */
1000 builtins_manager *
1001 recording::context::get_builtins_manager ()
1003 if (m_parent_ctxt)
1004 return m_parent_ctxt->get_builtins_manager ();
1006 if (!m_builtins_manager)
1007 m_builtins_manager = new builtins_manager (this);
1009 return m_builtins_manager;
1012 /* Get a recording::function instance, which is lazily-created and added
1013 to the context's lists of mementos.
1015 Implements the post-error-checking part of
1016 gcc_jit_context_get_builtin_function. */
1018 recording::function *
1019 recording::context::get_builtin_function (const char *name)
1021 builtins_manager *bm = get_builtins_manager ();
1022 return bm->get_builtin_function (name);
1025 /* Create a recording::global instance and add it to this context's list
1026 of mementos.
1028 Implements the post-error-checking part of
1029 gcc_jit_context_new_global. */
1031 recording::lvalue *
1032 recording::context::new_global (recording::location *loc,
1033 enum gcc_jit_global_kind kind,
1034 recording::type *type,
1035 const char *name)
1037 recording::global *result =
1038 new recording::global (this, loc, kind, type, new_string (name));
1039 record (result);
1040 m_globals.safe_push (result);
1042 return result;
1045 /* Create a recording::memento_of_new_string_literal instance and add it
1046 to this context's list of mementos.
1048 Implements the post-error-checking part of
1049 gcc_jit_context_new_string_literal. */
1051 recording::rvalue *
1052 recording::context::new_string_literal (const char *value)
1054 recording::rvalue *result =
1055 new memento_of_new_string_literal (this, NULL, new_string (value));
1056 record (result);
1057 return result;
1060 /* Create a recording::memento_of_new_rvalue_from_vector instance and add it
1061 to this context's list of mementos.
1063 Implements the post-error-checking part of
1064 gcc_jit_context_new_rvalue_from_vector. */
1066 recording::rvalue *
1067 recording::context::new_rvalue_from_vector (location *loc,
1068 vector_type *type,
1069 rvalue **elements)
1071 recording::rvalue *result
1072 = new memento_of_new_rvalue_from_vector (this, loc, type, elements);
1073 record (result);
1074 return result;
1077 /* Create a recording::unary_op instance and add it to this context's
1078 list of mementos.
1080 Implements the post-error-checking part of
1081 gcc_jit_context_new_unary_op. */
1083 recording::rvalue *
1084 recording::context::new_unary_op (recording::location *loc,
1085 enum gcc_jit_unary_op op,
1086 recording::type *result_type,
1087 recording::rvalue *a)
1089 recording::rvalue *result =
1090 new unary_op (this, loc, op, result_type, a);
1091 record (result);
1092 return result;
1095 /* Create a recording::binary_op instance and add it to this context's
1096 list of mementos.
1098 Implements the post-error-checking part of
1099 gcc_jit_context_new_binary_op. */
1101 recording::rvalue *
1102 recording::context::new_binary_op (recording::location *loc,
1103 enum gcc_jit_binary_op op,
1104 recording::type *result_type,
1105 recording::rvalue *a,
1106 recording::rvalue *b)
1108 recording::rvalue *result =
1109 new binary_op (this, loc, op, result_type, a, b);
1110 record (result);
1111 return result;
1114 /* Create a recording::comparison instance and add it to this context's
1115 list of mementos.
1117 Implements the post-error-checking part of
1118 gcc_jit_context_new_comparison. */
1120 recording::rvalue *
1121 recording::context::new_comparison (recording::location *loc,
1122 enum gcc_jit_comparison op,
1123 recording::rvalue *a,
1124 recording::rvalue *b)
1126 recording::rvalue *result = new comparison (this, loc, op, a, b);
1127 record (result);
1128 return result;
1131 /* Create a recording::cast instance and add it to this context's list
1132 of mementos.
1134 Implements the post-error-checking part of
1135 gcc_jit_context_new_cast. */
1137 recording::rvalue *
1138 recording::context::new_cast (recording::location *loc,
1139 recording::rvalue *expr,
1140 recording::type *type_)
1142 recording::rvalue *result = new cast (this, loc, expr, type_);
1143 record (result);
1144 return result;
1147 /* Create a recording::call instance and add it to this context's list
1148 of mementos.
1150 Implements the post-error-checking part of
1151 gcc_jit_context_new_call. */
1153 recording::rvalue *
1154 recording::context::new_call (recording::location *loc,
1155 function *func,
1156 int numargs , recording::rvalue **args)
1158 recording::rvalue *result = new call (this, loc, func, numargs, args);
1159 record (result);
1160 return result;
1163 /* Create a recording::call_through_ptr instance and add it to this
1164 context's list of mementos.
1166 Implements the post-error-checking part of
1167 gcc_jit_context_new_call_through_ptr. */
1169 recording::rvalue *
1170 recording::context::new_call_through_ptr (recording::location *loc,
1171 recording::rvalue *fn_ptr,
1172 int numargs,
1173 recording::rvalue **args)
1175 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
1176 record (result);
1177 return result;
1180 /* Create a recording::array_access instance and add it to this context's list
1181 of mementos.
1183 Implements the post-error-checking part of
1184 gcc_jit_context_new_array_access. */
1186 recording::lvalue *
1187 recording::context::new_array_access (recording::location *loc,
1188 recording::rvalue *ptr,
1189 recording::rvalue *index)
1191 recording::lvalue *result = new array_access (this, loc, ptr, index);
1192 record (result);
1193 return result;
1196 /* Create a recording::case_ instance and add it to this context's list
1197 of mementos.
1199 Implements the post-error-checking part of
1200 gcc_jit_context_new_case. */
1202 recording::case_ *
1203 recording::context::new_case (recording::rvalue *min_value,
1204 recording::rvalue *max_value,
1205 recording::block *block)
1207 recording::case_ *result = new case_ (this, min_value, max_value, block);
1208 record (result);
1209 return result;
1212 /* Set the given string option for this context, or add an error if
1213 it's not recognized.
1215 Implements the post-error-checking part of
1216 gcc_jit_context_set_str_option. */
1218 void
1219 recording::context::set_str_option (enum gcc_jit_str_option opt,
1220 const char *value)
1222 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
1224 add_error (NULL,
1225 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
1226 return;
1228 free (m_str_options[opt]);
1229 m_str_options[opt] = value ? xstrdup (value) : NULL;
1230 log_str_option (opt);
1233 /* Set the given integer option for this context, or add an error if
1234 it's not recognized.
1236 Implements the post-error-checking part of
1237 gcc_jit_context_set_int_option. */
1239 void
1240 recording::context::set_int_option (enum gcc_jit_int_option opt,
1241 int value)
1243 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
1245 add_error (NULL,
1246 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
1247 return;
1249 m_int_options[opt] = value;
1250 log_int_option (opt);
1253 /* Set the given boolean option for this context, or add an error if
1254 it's not recognized.
1256 Implements the post-error-checking part of
1257 gcc_jit_context_set_bool_option. */
1259 void
1260 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
1261 int value)
1263 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
1265 add_error (NULL,
1266 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
1267 return;
1269 m_bool_options[opt] = value ? true : false;
1270 log_bool_option (opt);
1273 void
1274 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt,
1275 int value)
1277 gcc_assert (inner_opt >= 0 && inner_opt < NUM_INNER_BOOL_OPTIONS);
1278 m_inner_bool_options[inner_opt] = value ? true : false;
1279 log_inner_bool_option (inner_opt);
1283 /* Add the given optname to this context's list of extra options.
1285 Implements the post-error-checking part of
1286 gcc_jit_context_add_command_line_option. */
1288 void
1289 recording::context::add_command_line_option (const char *optname)
1291 m_command_line_options.safe_push (xstrdup (optname));
1294 /* Add any user-provided extra options, starting with any from
1295 parent contexts.
1296 Called by playback::context::make_fake_args. */
1298 void
1299 recording::context::append_command_line_options (vec <char *> *argvec)
1301 if (m_parent_ctxt)
1302 m_parent_ctxt->append_command_line_options (argvec);
1304 int i;
1305 char *optname;
1306 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1307 argvec->safe_push (xstrdup (optname));
1310 /* Add the given dumpname/out_ptr pair to this context's list of requested
1311 dumps.
1313 Implements the post-error-checking part of
1314 gcc_jit_context_enable_dump. */
1316 void
1317 recording::context::enable_dump (const char *dumpname,
1318 char **out_ptr)
1320 requested_dump d;
1321 gcc_assert (dumpname);
1322 gcc_assert (out_ptr);
1324 d.m_dumpname = dumpname;
1325 d.m_out_ptr = out_ptr;
1326 *out_ptr = NULL;
1327 m_requested_dumps.safe_push (d);
1330 /* Validate this context, and if it passes, compile it to memory
1331 (within a mutex).
1333 Implements the post-error-checking part of
1334 gcc_jit_context_compile. */
1336 result *
1337 recording::context::compile ()
1339 JIT_LOG_SCOPE (get_logger ());
1341 log_all_options ();
1343 validate ();
1345 if (errors_occurred ())
1346 return NULL;
1348 /* Set up a compile_to_memory playback context. */
1349 ::gcc::jit::playback::compile_to_memory replayer (this);
1351 /* Use it. */
1352 replayer.compile ();
1354 /* Get the jit::result (or NULL) from the
1355 compile_to_memory playback context. */
1356 return replayer.get_result_obj ();
1359 /* Validate this context, and if it passes, compile it to a file
1360 (within a mutex).
1362 Implements the post-error-checking part of
1363 gcc_jit_context_compile_to_file. */
1365 void
1366 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
1367 const char *output_path)
1369 JIT_LOG_SCOPE (get_logger ());
1371 log_all_options ();
1373 validate ();
1375 if (errors_occurred ())
1376 return;
1378 /* Set up a compile_to_file playback context. */
1379 ::gcc::jit::playback::compile_to_file replayer (this,
1380 output_kind,
1381 output_path);
1383 /* Use it. */
1384 replayer.compile ();
1387 /* Format the given error using printf's conventions, print
1388 it to stderr, and add it to the context. */
1390 void
1391 recording::context::add_error (location *loc, const char *fmt, ...)
1393 va_list ap;
1394 va_start (ap, fmt);
1395 add_error_va (loc, fmt, ap);
1396 va_end (ap);
1399 /* Format the given error using printf's conventions, print
1400 it to stderr, and add it to the context. */
1402 void
1403 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
1405 int len;
1406 char *malloced_msg;
1407 const char *errmsg;
1408 bool has_ownership;
1410 JIT_LOG_SCOPE (get_logger ());
1412 len = vasprintf (&malloced_msg, fmt, ap);
1413 if (malloced_msg == NULL || len < 0)
1415 errmsg = "out of memory generating error message";
1416 has_ownership = false;
1418 else
1420 errmsg = malloced_msg;
1421 has_ownership = true;
1423 if (get_logger ())
1424 get_logger ()->log ("error %i: %s", m_error_count, errmsg);
1426 const char *ctxt_progname =
1427 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
1428 if (!ctxt_progname)
1429 ctxt_progname = "libgccjit.so";
1431 if (loc)
1432 fprintf (stderr, "%s: %s: error: %s\n",
1433 ctxt_progname,
1434 loc->get_debug_string (),
1435 errmsg);
1436 else
1437 fprintf (stderr, "%s: error: %s\n",
1438 ctxt_progname,
1439 errmsg);
1441 if (!m_error_count)
1443 m_first_error_str = const_cast <char *> (errmsg);
1444 m_owns_first_error_str = has_ownership;
1447 if (m_owns_last_error_str)
1448 if (m_last_error_str != m_first_error_str)
1449 free (m_last_error_str);
1450 m_last_error_str = const_cast <char *> (errmsg);
1451 m_owns_last_error_str = has_ownership;
1453 m_error_count++;
1456 /* Get the message for the first error that occurred on this context, or
1457 NULL if no errors have occurred on it.
1459 Implements the post-error-checking part of
1460 gcc_jit_context_get_first_error. */
1462 const char *
1463 recording::context::get_first_error () const
1465 return m_first_error_str;
1468 /* Get the message for the last error that occurred on this context, or
1469 NULL if no errors have occurred on it.
1471 Implements the post-error-checking part of
1472 gcc_jit_context_get_last_error. */
1474 const char *
1475 recording::context::get_last_error () const
1477 return m_last_error_str;
1480 /* Lazily generate and record a recording::type representing an opaque
1481 struct named "FILE".
1483 For use if client code tries to dereference the result of
1484 get_type (GCC_JIT_TYPE_FILE_PTR). */
1486 recording::type *
1487 recording::context::get_opaque_FILE_type ()
1489 if (!m_FILE_type)
1490 m_FILE_type = new_struct_type (NULL, "FILE");
1491 return m_FILE_type;
1494 /* Dump a C-like representation of the given context to the given path.
1495 If UPDATE_LOCATIONS is true, update the locations within the
1496 context's mementos to point to the dumpfile.
1498 Implements the post-error-checking part of
1499 gcc_jit_context_dump_to_file. */
1501 void
1502 recording::context::dump_to_file (const char *path, bool update_locations)
1504 int i;
1505 dump d (*this, path, update_locations);
1507 /* Forward declaration of structs and unions. */
1508 compound_type *st;
1509 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1511 d.write ("%s;\n\n", st->get_debug_string ());
1514 /* Content of structs, where set. */
1515 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1516 if (st->get_fields ())
1518 st->get_fields ()->write_to_dump (d);
1519 d.write ("\n");
1522 /* Globals. */
1523 global *g;
1524 FOR_EACH_VEC_ELT (m_globals, i, g)
1526 g->write_to_dump (d);
1528 if (!m_globals.is_empty ())
1529 d.write ("\n");
1531 function *fn;
1532 FOR_EACH_VEC_ELT (m_functions, i, fn)
1534 fn->write_to_dump (d);
1538 static const char * const
1539 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
1540 "GCC_JIT_STR_OPTION_PROGNAME"
1543 static const char * const
1544 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
1545 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1548 static const char * const
1549 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
1550 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1551 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1552 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1553 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1554 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1555 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1556 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1557 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1560 static const char * const
1561 inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = {
1562 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1563 "gcc_jit_context_set_bool_use_external_driver"
1566 /* Write the current value of all options to the log file (if any). */
1568 void
1569 recording::context::log_all_options () const
1571 int opt_idx;
1573 if (!get_logger ())
1574 return;
1576 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1577 log_str_option ((enum gcc_jit_str_option)opt_idx);
1579 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1580 log_int_option ((enum gcc_jit_int_option)opt_idx);
1582 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1583 log_bool_option ((enum gcc_jit_bool_option)opt_idx);
1584 for (opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1585 log_inner_bool_option ((enum inner_bool_option)opt_idx);
1588 /* Write the current value of the given string option to the
1589 log file (if any). */
1591 void
1592 recording::context::log_str_option (enum gcc_jit_str_option opt) const
1594 gcc_assert (opt < GCC_JIT_NUM_STR_OPTIONS);
1595 if (get_logger ())
1597 if (m_str_options[opt])
1598 log ("%s: \"%s\"",
1599 str_option_reproducer_strings[opt],
1600 m_str_options[opt]);
1601 else
1602 log ("%s: NULL",
1603 str_option_reproducer_strings[opt]);
1607 /* Write the current value of the given int option to the
1608 log file (if any). */
1610 void
1611 recording::context::log_int_option (enum gcc_jit_int_option opt) const
1613 gcc_assert (opt < GCC_JIT_NUM_INT_OPTIONS);
1614 if (get_logger ())
1615 log ("%s: %i",
1616 int_option_reproducer_strings[opt],
1617 m_int_options[opt]);
1620 /* Write the current value of the given bool option to the
1621 log file (if any). */
1623 void
1624 recording::context::log_bool_option (enum gcc_jit_bool_option opt) const
1626 gcc_assert (opt < GCC_JIT_NUM_BOOL_OPTIONS);
1627 if (get_logger ())
1628 log ("%s: %s",
1629 bool_option_reproducer_strings[opt],
1630 m_bool_options[opt] ? "true" : "false");
1633 /* Write the current value of the given "inner" bool option to the
1634 log file (if any). */
1636 void
1637 recording::context::log_inner_bool_option (enum inner_bool_option opt) const
1639 gcc_assert (opt < NUM_INNER_BOOL_OPTIONS);
1640 if (get_logger ())
1641 log ("%s: %s",
1642 inner_bool_option_reproducer_strings[opt],
1643 m_inner_bool_options[opt] ? "true" : "false");
1646 /* Write C source code to PATH that attempts to replay the API
1647 calls made to this context (and its parents), for use in
1648 minimizing test cases for libgccjit.
1650 Implements the post-error-checking part of
1651 gcc_jit_context_dump_reproducer_to_file. */
1653 void
1654 recording::context::dump_reproducer_to_file (const char *path)
1656 JIT_LOG_SCOPE (get_logger ());
1657 reproducer r (*this, path);
1659 /* Generate the "ancestry" of this context, as a list. */
1660 auto_vec <context *> ascending_contexts;
1661 for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
1662 ascending_contexts.safe_push (ctxt);
1664 /* Reverse the list, giving a list of contexts from
1665 top-most parent context down through to youngest child context.
1666 We will use this list as the parameters of the functions in
1667 our generated file. */
1668 unsigned num_ctxts = ascending_contexts.length ();
1669 auto_vec <context *> contexts (num_ctxts);
1670 for (unsigned i = 0; i < num_ctxts; i++)
1671 contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
1673 /* contexts[0] should be the top-level context. */
1674 gcc_assert (contexts[0]);
1675 gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
1677 /* The final element in contexts should be "this". */
1678 gcc_assert (contexts[contexts.length () - 1] == this);
1679 gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
1680 == contexts[0]);
1682 r.write ("/* This code was autogenerated by"
1683 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1684 print_version (r.get_file (), " ", false);
1685 r.write ("*/\n");
1686 r.write ("#include <libgccjit.h>\n\n");
1687 r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1688 r.write ("static void\nset_options (");
1689 r.write_params (contexts);
1690 r.write (");\n\n");
1691 r.write ("static void\ncreate_code (");
1692 r.write_params (contexts);
1693 r.write (");\n\n");
1694 r.write ("int\nmain (int argc, const char **argv)\n");
1695 r.write ("{\n");
1696 for (unsigned i = 0; i < num_ctxts; i++)
1697 r.write (" gcc_jit_context *%s;\n",
1698 r.get_identifier (contexts[i]));
1699 r.write (" gcc_jit_result *result;\n"
1700 "\n");
1702 /* Create the contexts.
1703 The top-level context is acquired from a clean slate, the others as
1704 children of the prior context. */
1705 r.write (" %s = gcc_jit_context_acquire ();\n",
1706 r.get_identifier (contexts[0]));
1707 for (unsigned i = 1; i < num_ctxts; i++)
1708 r.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1709 r.get_identifier (contexts[i]),
1710 r.get_identifier (contexts[i - 1]));
1711 r.write (" set_options (");
1712 r.write_args (contexts);
1713 r.write (");\n");
1714 r.write (" create_code (");
1715 r.write_args (contexts);
1716 r.write (");\n");
1718 r.write (" result = gcc_jit_context_compile (%s);\n",
1719 r.get_identifier (this));
1721 for (unsigned i = num_ctxts; i > 0; i--)
1722 r.write (" gcc_jit_context_release (%s);\n",
1723 r.get_identifier (contexts[i - 1]));
1725 r.write (" gcc_jit_result_release (result);\n"
1726 " return 0;\n"
1727 "}\n\n");
1729 /* Define (char *) variables for use in calls to
1730 gcc_jit_context_enable_dump. */
1731 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1733 if (m_requested_dumps.length ())
1735 r.write ("/* Requested dumps for %s. */\n",
1736 r.get_identifier (contexts[ctxt_idx]));
1737 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1738 r.write ("static char *dump_%p;\n",
1739 (void *)&m_requested_dumps[i]);
1740 r.write ("\n");
1744 /* Write out values of options. */
1745 r.write ("static void\nset_options (");
1746 r.write_params (contexts);
1747 r.write (")\n{\n");
1748 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1750 if (ctxt_idx > 0)
1751 r.write ("\n");
1753 r.write (" /* Set options for %s. */\n",
1754 r.get_identifier (contexts[ctxt_idx]));
1756 r.write (" /* String options. */\n");
1757 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1759 r.write (" gcc_jit_context_set_str_option (%s,\n"
1760 " %s,\n",
1761 r.get_identifier (contexts[ctxt_idx]),
1762 str_option_reproducer_strings[opt_idx]);
1763 if (m_str_options[opt_idx])
1764 r.write (" \"%s\");\n",
1765 m_str_options[opt_idx]);
1766 else
1767 r.write (" NULL);\n");
1769 r.write (" /* Int options. */\n");
1770 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1771 r.write (" gcc_jit_context_set_int_option (%s,\n"
1772 " %s,\n"
1773 " %i);\n",
1774 r.get_identifier (contexts[ctxt_idx]),
1775 int_option_reproducer_strings[opt_idx],
1776 m_int_options[opt_idx]);
1777 r.write (" /* Boolean options. */\n");
1778 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1779 r.write (" gcc_jit_context_set_bool_option (%s,\n"
1780 " %s,\n"
1781 " %i);\n",
1782 r.get_identifier (contexts[ctxt_idx]),
1783 bool_option_reproducer_strings[opt_idx],
1784 m_bool_options[opt_idx]);
1785 for (int opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++)
1786 r.write (" %s (%s, %i);\n",
1787 inner_bool_option_reproducer_strings[opt_idx],
1788 r.get_identifier (contexts[ctxt_idx]),
1789 m_inner_bool_options[opt_idx]);
1791 if (!m_command_line_options.is_empty ())
1793 int i;
1794 char *optname;
1795 r.write (" /* User-provided command-line options. */\n");
1796 FOR_EACH_VEC_ELT (m_command_line_options, i, optname)
1797 r.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1798 r.get_identifier (contexts[ctxt_idx]),
1799 optname);
1802 if (m_requested_dumps.length ())
1804 r.write (" /* Requested dumps. */\n");
1805 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1806 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1808 r.write (" gcc_jit_context_enable_dump (%s,\n"
1809 " \"%s\",\n"
1810 " &dump_%p);\n",
1811 r.get_identifier (contexts[ctxt_idx]),
1812 m_requested_dumps[i].m_dumpname,
1813 (void *)&m_requested_dumps[i]);
1817 r.write ("}\n\n");
1819 r.write ("static void\ncreate_code (");
1820 r.write_params (contexts);
1821 r.write (")\n"
1822 "{\n");
1823 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1825 memento *m;
1826 int i;
1827 if (ctxt_idx > 0)
1828 r.write ("\n\n");
1830 r.write (" /* Replay of API calls for %s. */\n",
1831 r.get_identifier (contexts[ctxt_idx]));
1832 FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
1833 m->write_reproducer (r);
1835 r.write ("}\n");
1838 /* Copy the requested dumps within this context and all ancestors into
1839 OUT. */
1841 void
1842 recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
1844 if (m_parent_ctxt)
1845 m_parent_ctxt->get_all_requested_dumps (out);
1847 out->reserve (m_requested_dumps.length ());
1848 out->splice (m_requested_dumps);
1851 /* This is a pre-compilation check for the context (and any parents).
1853 Detect errors within the context, adding errors if any are found. */
1855 void
1856 recording::context::validate ()
1858 JIT_LOG_SCOPE (get_logger ());
1860 if (m_parent_ctxt)
1861 m_parent_ctxt->validate ();
1863 int i;
1864 function *fn;
1865 FOR_EACH_VEC_ELT (m_functions, i, fn)
1866 fn->validate ();
1869 /* The implementation of class gcc::jit::recording::memento. */
1871 /* Get a (const char *) debug description of the given memento, by
1872 calling the pure-virtual make_debug_string hook, caching the
1873 result.
1875 It is intended that this should only be called in debugging and
1876 error-handling paths, so this doesn't need to be particularly
1877 optimized. */
1879 const char *
1880 recording::memento::get_debug_string ()
1882 if (!m_debug_string)
1883 m_debug_string = make_debug_string ();
1884 return m_debug_string->c_str ();
1887 /* Default implementation of recording::memento::write_to_dump, writing
1888 an indented form of the memento's debug string to the dump. */
1890 void
1891 recording::memento::write_to_dump (dump &d)
1893 d.write(" %s\n", get_debug_string ());
1896 /* The implementation of class gcc::jit::recording::string. */
1898 /* Constructor for gcc::jit::recording::string::string, allocating a
1899 copy of the given text using new char[]. */
1901 recording::string::string (context *ctxt, const char *text)
1902 : memento (ctxt)
1904 m_len = strlen (text);
1905 m_buffer = new char[m_len + 1];
1906 strcpy (m_buffer, text);
1909 /* Destructor for gcc::jit::recording::string::string. */
1911 recording::string::~string ()
1913 delete[] m_buffer;
1916 /* Function for making gcc::jit::recording::string instances on a
1917 context via printf-style formatting.
1919 It is intended that this should only be called in debugging and
1920 error-handling paths, so this doesn't need to be particularly
1921 optimized, hence the double-copy of the string is acceptable. */
1923 recording::string *
1924 recording::string::from_printf (context *ctxt, const char *fmt, ...)
1926 int len;
1927 va_list ap;
1928 char *buf;
1929 recording::string *result;
1931 va_start (ap, fmt);
1932 len = vasprintf (&buf, fmt, ap);
1933 va_end (ap);
1935 if (buf == NULL || len < 0)
1937 ctxt->add_error (NULL, "malloc failure");
1938 return NULL;
1941 result = ctxt->new_string (buf);
1942 free (buf);
1943 return result;
1946 /* Implementation of recording::memento::make_debug_string for strings,
1947 wrapping the given string in quotes and escaping as necessary. */
1949 recording::string *
1950 recording::string::make_debug_string ()
1952 /* Hack to avoid infinite recursion into strings when logging all
1953 mementos: don't re-escape strings: */
1954 if (m_buffer[0] == '"')
1955 return this;
1957 /* Wrap in quotes and do escaping etc */
1959 size_t sz = (1 /* opening quote */
1960 + (m_len * 2) /* each char might get escaped */
1961 + 1 /* closing quote */
1962 + 1); /* nil termintator */
1963 char *tmp = new char[sz];
1964 size_t len = 0;
1966 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1967 APPEND('"'); /* opening quote */
1968 for (size_t i = 0; i < m_len ; i++)
1970 char ch = m_buffer[i];
1971 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
1972 APPEND('\\');
1973 APPEND(ch);
1975 APPEND('"'); /* closing quote */
1976 #undef APPEND
1977 tmp[len] = '\0'; /* nil termintator */
1979 string *result = m_ctxt->new_string (tmp);
1981 delete[] tmp;
1982 return result;
1985 /* Implementation of recording::memento::write_reproducer for strings. */
1987 void
1988 recording::string::write_reproducer (reproducer &)
1990 /* Empty. */
1993 /* The implementation of class gcc::jit::recording::location. */
1995 /* Implementation of recording::memento::replay_into for locations.
1997 Create a new playback::location and store it into the
1998 recording::location's m_playback_obj field. */
2000 void
2001 recording::location::replay_into (replayer *r)
2003 m_playback_obj = r->new_location (this,
2004 m_filename->c_str (),
2005 m_line,
2006 m_column);
2009 /* Implementation of recording::memento::make_debug_string for locations,
2010 turning them into the usual form:
2011 FILENAME:LINE:COLUMN
2012 like we do when emitting diagnostics. */
2014 recording::string *
2015 recording::location::make_debug_string ()
2017 return string::from_printf (m_ctxt,
2018 "%s:%i:%i",
2019 m_filename->c_str (), m_line, m_column);
2022 /* Implementation of recording::memento::write_reproducer for locations. */
2024 void
2025 recording::location::write_reproducer (reproducer &r)
2027 const char *id = r.make_identifier (this, "loc");
2028 r.write (" gcc_jit_location *%s =\n"
2029 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
2030 " %s, /* const char *filename */\n"
2031 " %i, /* int line */\n"
2032 " %i);/* int column */\n",
2034 r.get_identifier (get_context ()),
2035 m_filename->get_debug_string (),
2036 m_line, m_column);
2039 /* The implementation of class gcc::jit::recording::type. */
2041 /* Given a type T, get the type T*.
2043 If this doesn't already exist, generate a new memento_of_get_pointer
2044 instance and add it to this type's context's list of mementos.
2046 Otherwise, use the cached type.
2048 Implements the post-error-checking part of
2049 gcc_jit_type_get_pointer. */
2051 recording::type *
2052 recording::type::get_pointer ()
2054 if (!m_pointer_to_this_type)
2056 m_pointer_to_this_type = new memento_of_get_pointer (this);
2057 m_ctxt->record (m_pointer_to_this_type);
2059 return m_pointer_to_this_type;
2062 /* Given a type T, get the type const T.
2064 Implements the post-error-checking part of
2065 gcc_jit_type_get_const. */
2067 recording::type *
2068 recording::type::get_const ()
2070 recording::type *result = new memento_of_get_const (this);
2071 m_ctxt->record (result);
2072 return result;
2075 /* Given a type T, get the type volatile T.
2077 Implements the post-error-checking part of
2078 gcc_jit_type_get_volatile. */
2080 recording::type *
2081 recording::type::get_volatile ()
2083 recording::type *result = new memento_of_get_volatile (this);
2084 m_ctxt->record (result);
2085 return result;
2088 /* Given a type, get an aligned version of the type.
2090 Implements the post-error-checking part of
2091 gcc_jit_type_get_aligned. */
2093 recording::type *
2094 recording::type::get_aligned (size_t alignment_in_bytes)
2096 recording::type *result
2097 = new memento_of_get_aligned (this, alignment_in_bytes);
2098 m_ctxt->record (result);
2099 return result;
2102 /* Given a type, get a vector version of the type.
2104 Implements the post-error-checking part of
2105 gcc_jit_type_get_vector. */
2107 recording::type *
2108 recording::type::get_vector (size_t num_units)
2110 recording::type *result
2111 = new vector_type (this, num_units);
2112 m_ctxt->record (result);
2113 return result;
2116 const char *
2117 recording::type::access_as_type (reproducer &r)
2119 return r.get_identifier (this);
2122 /* Implementation of pure virtual hook recording::type::dereference for
2123 recording::memento_of_get_type. */
2125 recording::type *
2126 recording::memento_of_get_type::dereference ()
2128 switch (m_kind)
2130 default: gcc_unreachable ();
2132 case GCC_JIT_TYPE_VOID:
2133 return NULL;
2135 case GCC_JIT_TYPE_VOID_PTR:
2136 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
2138 case GCC_JIT_TYPE_BOOL:
2139 case GCC_JIT_TYPE_CHAR:
2140 case GCC_JIT_TYPE_SIGNED_CHAR:
2141 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2142 case GCC_JIT_TYPE_SHORT:
2143 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2144 case GCC_JIT_TYPE_INT:
2145 case GCC_JIT_TYPE_UNSIGNED_INT:
2146 case GCC_JIT_TYPE_LONG:
2147 case GCC_JIT_TYPE_UNSIGNED_LONG:
2148 case GCC_JIT_TYPE_LONG_LONG:
2149 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2150 case GCC_JIT_TYPE_FLOAT:
2151 case GCC_JIT_TYPE_DOUBLE:
2152 case GCC_JIT_TYPE_LONG_DOUBLE:
2153 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2154 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2155 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2156 /* Not a pointer: */
2157 return NULL;
2159 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2160 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
2162 case GCC_JIT_TYPE_SIZE_T:
2163 /* Not a pointer: */
2164 return NULL;
2166 case GCC_JIT_TYPE_FILE_PTR:
2167 /* Give the client code back an opaque "struct FILE". */
2168 return m_ctxt->get_opaque_FILE_type ();
2172 /* Implementation of pure virtual hook recording::type::is_int for
2173 recording::memento_of_get_type. */
2175 bool
2176 recording::memento_of_get_type::is_int () const
2178 switch (m_kind)
2180 default: gcc_unreachable ();
2182 case GCC_JIT_TYPE_VOID:
2183 return false;
2185 case GCC_JIT_TYPE_VOID_PTR:
2186 return false;
2188 case GCC_JIT_TYPE_BOOL:
2189 return false;
2191 case GCC_JIT_TYPE_CHAR:
2192 case GCC_JIT_TYPE_SIGNED_CHAR:
2193 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2194 case GCC_JIT_TYPE_SHORT:
2195 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2196 case GCC_JIT_TYPE_INT:
2197 case GCC_JIT_TYPE_UNSIGNED_INT:
2198 case GCC_JIT_TYPE_LONG:
2199 case GCC_JIT_TYPE_UNSIGNED_LONG:
2200 case GCC_JIT_TYPE_LONG_LONG:
2201 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2202 return true;
2204 case GCC_JIT_TYPE_FLOAT:
2205 case GCC_JIT_TYPE_DOUBLE:
2206 case GCC_JIT_TYPE_LONG_DOUBLE:
2207 return false;
2209 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2210 return false;
2212 case GCC_JIT_TYPE_SIZE_T:
2213 return true;
2215 case GCC_JIT_TYPE_FILE_PTR:
2216 return false;
2218 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2219 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2220 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2221 return false;
2225 /* Implementation of pure virtual hook recording::type::is_float for
2226 recording::memento_of_get_type. */
2228 bool
2229 recording::memento_of_get_type::is_float () const
2231 switch (m_kind)
2233 default: gcc_unreachable ();
2235 case GCC_JIT_TYPE_VOID:
2236 return false;
2238 case GCC_JIT_TYPE_VOID_PTR:
2239 return false;
2241 case GCC_JIT_TYPE_BOOL:
2242 return false;
2244 case GCC_JIT_TYPE_CHAR:
2245 case GCC_JIT_TYPE_SIGNED_CHAR:
2246 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2247 case GCC_JIT_TYPE_SHORT:
2248 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2249 case GCC_JIT_TYPE_INT:
2250 case GCC_JIT_TYPE_UNSIGNED_INT:
2251 case GCC_JIT_TYPE_LONG:
2252 case GCC_JIT_TYPE_UNSIGNED_LONG:
2253 case GCC_JIT_TYPE_LONG_LONG:
2254 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2255 return false;
2257 case GCC_JIT_TYPE_FLOAT:
2258 case GCC_JIT_TYPE_DOUBLE:
2259 case GCC_JIT_TYPE_LONG_DOUBLE:
2260 return true;
2262 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2263 return false;
2265 case GCC_JIT_TYPE_SIZE_T:
2266 return false;
2268 case GCC_JIT_TYPE_FILE_PTR:
2269 return false;
2271 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2272 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2273 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2274 return true;
2278 /* Implementation of pure virtual hook recording::type::is_bool for
2279 recording::memento_of_get_type. */
2281 bool
2282 recording::memento_of_get_type::is_bool () const
2284 switch (m_kind)
2286 default: gcc_unreachable ();
2288 case GCC_JIT_TYPE_VOID:
2289 return false;
2291 case GCC_JIT_TYPE_VOID_PTR:
2292 return false;
2294 case GCC_JIT_TYPE_BOOL:
2295 return true;
2297 case GCC_JIT_TYPE_CHAR:
2298 case GCC_JIT_TYPE_SIGNED_CHAR:
2299 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2300 case GCC_JIT_TYPE_SHORT:
2301 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2302 case GCC_JIT_TYPE_INT:
2303 case GCC_JIT_TYPE_UNSIGNED_INT:
2304 case GCC_JIT_TYPE_LONG:
2305 case GCC_JIT_TYPE_UNSIGNED_LONG:
2306 case GCC_JIT_TYPE_LONG_LONG:
2307 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2308 return false;
2310 case GCC_JIT_TYPE_FLOAT:
2311 case GCC_JIT_TYPE_DOUBLE:
2312 case GCC_JIT_TYPE_LONG_DOUBLE:
2313 return false;
2315 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2316 return false;
2318 case GCC_JIT_TYPE_SIZE_T:
2319 return false;
2321 case GCC_JIT_TYPE_FILE_PTR:
2322 return false;
2324 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2325 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2326 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2327 return false;
2331 /* Implementation of pure virtual hook recording::memento::replay_into
2332 for recording::memento_of_get_type. */
2334 void
2335 recording::memento_of_get_type::replay_into (replayer *r)
2337 set_playback_obj (r->get_type (m_kind));
2340 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2342 /* Descriptive strings for each of enum gcc_jit_types. */
2344 static const char * const get_type_strings[] = {
2345 "void", /* GCC_JIT_TYPE_VOID */
2346 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2348 "bool", /* GCC_JIT_TYPE_BOOL */
2350 "char", /* GCC_JIT_TYPE_CHAR */
2351 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2352 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2354 "short", /* GCC_JIT_TYPE_SHORT */
2355 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2357 "int", /* GCC_JIT_TYPE_INT */
2358 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2360 "long", /* GCC_JIT_TYPE_LONG */
2361 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2363 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2364 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2366 "float", /* GCC_JIT_TYPE_FLOAT */
2367 "double", /* GCC_JIT_TYPE_DOUBLE */
2368 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2370 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2372 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2374 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2376 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2377 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2378 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2382 /* Implementation of recording::memento::make_debug_string for
2383 results of get_type, using a simple table of type names. */
2385 recording::string *
2386 recording::memento_of_get_type::make_debug_string ()
2388 return m_ctxt->new_string (get_type_strings[m_kind]);
2391 static const char * const get_type_enum_strings[] = {
2392 "GCC_JIT_TYPE_VOID",
2393 "GCC_JIT_TYPE_VOID_PTR",
2394 "GCC_JIT_TYPE_BOOL",
2395 "GCC_JIT_TYPE_CHAR",
2396 "GCC_JIT_TYPE_SIGNED_CHAR",
2397 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2398 "GCC_JIT_TYPE_SHORT",
2399 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2400 "GCC_JIT_TYPE_INT",
2401 "GCC_JIT_TYPE_UNSIGNED_INT",
2402 "GCC_JIT_TYPE_LONG",
2403 "GCC_JIT_TYPE_UNSIGNED_LONG",
2404 "GCC_JIT_TYPE_LONG_LONG",
2405 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2406 "GCC_JIT_TYPE_FLOAT",
2407 "GCC_JIT_TYPE_DOUBLE",
2408 "GCC_JIT_TYPE_LONG_DOUBLE",
2409 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2410 "GCC_JIT_TYPE_SIZE_T",
2411 "GCC_JIT_TYPE_FILE_PTR",
2412 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2413 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2414 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2417 void
2418 recording::memento_of_get_type::write_reproducer (reproducer &r)
2420 const char *id = r.make_identifier (this, "type");
2421 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2423 r.get_identifier (get_context ()),
2424 get_type_enum_strings[m_kind]);
2427 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2429 /* Override of default implementation of
2430 recording::type::accepts_writes_from for get_pointer.
2432 Require a pointer type, and allowing writes to
2433 (const T *) from a (T*), but not the other way around. */
2435 bool
2436 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2438 /* Must be a pointer type: */
2439 type *rtype_points_to = rtype->is_pointer ();
2440 if (!rtype_points_to)
2441 return false;
2443 /* It's OK to assign to a (const T *) from a (T *). */
2444 return m_other_type->unqualified ()
2445 ->accepts_writes_from (rtype_points_to);
2448 /* Implementation of pure virtual hook recording::memento::replay_into
2449 for recording::memento_of_get_pointer. */
2451 void
2452 recording::memento_of_get_pointer::replay_into (replayer *)
2454 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2457 /* Implementation of recording::memento::make_debug_string for
2458 results of get_pointer, adding " *" to the underlying type,
2459 with special-casing to handle function pointer types. */
2461 recording::string *
2462 recording::memento_of_get_pointer::make_debug_string ()
2464 /* Special-case function pointer types, to put the "*" in parens between
2465 the return type and the params (for one level of dereferencing, at
2466 least). */
2467 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2468 return fn_type->make_debug_string_with_ptr ();
2470 return string::from_printf (m_ctxt,
2471 "%s *", m_other_type->get_debug_string ());
2474 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2476 void
2477 recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2479 /* We need to special-case function pointer types; see the notes in
2480 recording::function_type::write_deferred_reproducer. */
2481 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2483 fn_type->write_deferred_reproducer (r, this);
2484 return;
2487 const char *id = r.make_identifier (this, "type");
2488 r.write (" gcc_jit_type *%s =\n"
2489 " gcc_jit_type_get_pointer (%s);\n",
2491 r.get_identifier_as_type (m_other_type));
2494 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2496 /* Implementation of pure virtual hook recording::memento::replay_into
2497 for recording::memento_of_get_const. */
2499 void
2500 recording::memento_of_get_const::replay_into (replayer *)
2502 set_playback_obj (m_other_type->playback_type ()->get_const ());
2505 /* Implementation of recording::memento::make_debug_string for
2506 results of get_const, prepending "const ". */
2508 recording::string *
2509 recording::memento_of_get_const::make_debug_string ()
2511 return string::from_printf (m_ctxt,
2512 "const %s", m_other_type->get_debug_string ());
2515 /* Implementation of recording::memento::write_reproducer for const types. */
2517 void
2518 recording::memento_of_get_const::write_reproducer (reproducer &r)
2520 const char *id = r.make_identifier (this, "type");
2521 r.write (" gcc_jit_type *%s =\n"
2522 " gcc_jit_type_get_const (%s);\n",
2524 r.get_identifier_as_type (m_other_type));
2527 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2529 /* Implementation of pure virtual hook recording::memento::replay_into
2530 for recording::memento_of_get_volatile. */
2532 void
2533 recording::memento_of_get_volatile::replay_into (replayer *)
2535 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2538 /* Implementation of recording::memento::make_debug_string for
2539 results of get_volatile, prepending "volatile ". */
2541 recording::string *
2542 recording::memento_of_get_volatile::make_debug_string ()
2544 return string::from_printf (m_ctxt,
2545 "volatile %s", m_other_type->get_debug_string ());
2548 /* Implementation of recording::memento::write_reproducer for volatile
2549 types. */
2551 void
2552 recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2554 const char *id = r.make_identifier (this, "type");
2555 r.write (" gcc_jit_type *%s =\n"
2556 " gcc_jit_type_get_volatile (%s);\n",
2558 r.get_identifier_as_type (m_other_type));
2561 /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
2563 /* Implementation of pure virtual hook recording::memento::replay_into
2564 for recording::memento_of_get_aligned. */
2566 void
2567 recording::memento_of_get_aligned::replay_into (replayer *)
2569 set_playback_obj
2570 (m_other_type->playback_type ()->get_aligned (m_alignment_in_bytes));
2573 /* Implementation of recording::memento::make_debug_string for
2574 results of get_aligned. */
2576 recording::string *
2577 recording::memento_of_get_aligned::make_debug_string ()
2579 return string::from_printf (m_ctxt,
2580 "%s __attribute__((aligned(%zi)))",
2581 m_other_type->get_debug_string (),
2582 m_alignment_in_bytes);
2585 /* Implementation of recording::memento::write_reproducer for aligned
2586 types. */
2588 void
2589 recording::memento_of_get_aligned::write_reproducer (reproducer &r)
2591 const char *id = r.make_identifier (this, "type");
2592 r.write (" gcc_jit_type *%s =\n"
2593 " gcc_jit_type_get_aligned (%s, %zi);\n",
2595 r.get_identifier_as_type (m_other_type),
2596 m_alignment_in_bytes);
2599 /* The implementation of class gcc::jit::recording::vector_type. */
2601 /* Implementation of pure virtual hook recording::memento::replay_into
2602 for recording::vector_type. */
2604 void
2605 recording::vector_type::replay_into (replayer *)
2607 set_playback_obj
2608 (m_other_type->playback_type ()->get_vector (m_num_units));
2611 /* Implementation of recording::memento::make_debug_string for
2612 results of get_vector. */
2614 recording::string *
2615 recording::vector_type::make_debug_string ()
2617 return string::from_printf
2618 (m_ctxt,
2619 "%s __attribute__((vector_size(sizeof (%s) * %zi)))",
2620 m_other_type->get_debug_string (),
2621 m_other_type->get_debug_string (),
2622 m_num_units);
2625 /* Implementation of recording::memento::write_reproducer for vector types. */
2627 void
2628 recording::vector_type::write_reproducer (reproducer &r)
2630 const char *id = r.make_identifier (this, "type");
2631 r.write (" gcc_jit_type *%s =\n"
2632 " gcc_jit_type_get_vector (%s, %zi);\n",
2634 r.get_identifier_as_type (m_other_type),
2635 m_num_units);
2638 /* The implementation of class gcc::jit::recording::array_type */
2640 /* Implementation of pure virtual hook recording::type::dereference for
2641 recording::array_type. */
2643 recording::type *
2644 recording::array_type::dereference ()
2646 return m_element_type;
2649 /* Implementation of pure virtual hook recording::memento::replay_into
2650 for recording::array_type. */
2652 void
2653 recording::array_type::replay_into (replayer *r)
2655 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
2656 m_element_type->playback_type (),
2657 m_num_elements));
2660 /* Implementation of recording::memento::make_debug_string for
2661 results of new_array_type. */
2663 recording::string *
2664 recording::array_type::make_debug_string ()
2666 return string::from_printf (m_ctxt,
2667 "%s[%d]",
2668 m_element_type->get_debug_string (),
2669 m_num_elements);
2672 /* Implementation of recording::memento::write_reproducer for array
2673 types. */
2675 void
2676 recording::array_type::write_reproducer (reproducer &r)
2678 const char *id = r.make_identifier (this, "array_type");
2679 r.write (" gcc_jit_type *%s =\n"
2680 " gcc_jit_context_new_array_type (%s,\n"
2681 " %s, /* gcc_jit_location *loc */\n"
2682 " %s, /* gcc_jit_type *element_type */\n"
2683 " %i); /* int num_elements */\n",
2685 r.get_identifier (get_context ()),
2686 r.get_identifier (m_loc),
2687 r.get_identifier_as_type (m_element_type),
2688 m_num_elements);
2691 /* The implementation of class gcc::jit::recording::function_type */
2693 /* Constructor for gcc::jit::recording::function_type. */
2695 recording::function_type::function_type (context *ctxt,
2696 type *return_type,
2697 int num_params,
2698 type **param_types,
2699 int is_variadic)
2700 : type (ctxt),
2701 m_return_type (return_type),
2702 m_param_types (),
2703 m_is_variadic (is_variadic)
2705 for (int i = 0; i< num_params; i++)
2706 m_param_types.safe_push (param_types[i]);
2709 /* Implementation of pure virtual hook recording::type::dereference for
2710 recording::function_type. */
2712 recording::type *
2713 recording::function_type::dereference ()
2715 return NULL;
2718 /* Implementation of virtual hook recording::type::is_same_type_as for
2719 recording::function_type.
2721 We override this to avoid requiring identity of function pointer types,
2722 so that if client code has obtained the same signature in
2723 different ways (e.g. via gcc_jit_context_new_function_ptr_type
2724 vs gcc_jit_function_get_address), the different function_type
2725 instances are treated as compatible.
2727 We can't use type::accepts_writes_from for this as we need a stronger
2728 notion of "sameness": if we have a fn_ptr type that has args that are
2729 themselves fn_ptr types, then those args still need to match exactly.
2731 Alternatively, we could consolidate attempts to create identical
2732 function_type instances so that pointer equality works, but that runs
2733 into issues about the lifetimes of the cache (w.r.t. nested contexts). */
2735 bool
2736 recording::function_type::is_same_type_as (type *other)
2738 gcc_assert (other);
2740 function_type *other_fn_type = other->dyn_cast_function_type ();
2741 if (!other_fn_type)
2742 return false;
2744 /* Everything must match. */
2746 if (!m_return_type->is_same_type_as (other_fn_type->m_return_type))
2747 return false;
2749 if (m_param_types.length () != other_fn_type->m_param_types.length ())
2750 return false;
2752 unsigned i;
2753 type *param_type;
2754 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2755 if (!param_type->is_same_type_as (other_fn_type->m_param_types[i]))
2756 return false;
2758 if (m_is_variadic != other_fn_type->m_is_variadic)
2759 return false;
2761 /* Passed all tests. */
2762 return true;
2765 /* Implementation of pure virtual hook recording::memento::replay_into
2766 for recording::function_type. */
2768 void
2769 recording::function_type::replay_into (replayer *r)
2771 /* Convert m_param_types to a vec of playback type. */
2772 auto_vec <playback::type *> param_types;
2773 int i;
2774 recording::type *type;
2775 param_types.create (m_param_types.length ());
2776 FOR_EACH_VEC_ELT (m_param_types, i, type)
2777 param_types.safe_push (type->playback_type ());
2779 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
2780 &param_types,
2781 m_is_variadic));
2784 /* Special-casing for make_debug_string for get_pointer results for
2785 handling (one level) of pointers to functions. */
2787 recording::string *
2788 recording::function_type::make_debug_string_with_ptr ()
2790 return make_debug_string_with ("(*) ");
2793 /* Implementation of recording::memento::make_debug_string for
2794 results of new_function_type. */
2796 recording::string *
2797 recording::function_type::make_debug_string ()
2799 return make_debug_string_with ("");
2802 /* Build a debug string representation of the form:
2804 RESULT_TYPE INSERT (PARAM_TYPES)
2806 for use when handling 0 and 1 level of indirection to this
2807 function type. */
2809 recording::string *
2810 recording::function_type::make_debug_string_with (const char *insert)
2812 /* First, build a buffer for the arguments. */
2813 /* Calculate length of said buffer. */
2814 size_t sz = 1; /* nil terminator */
2815 for (unsigned i = 0; i< m_param_types.length (); i++)
2817 sz += strlen (m_param_types[i]->get_debug_string ());
2818 sz += 2; /* ", " separator */
2820 if (m_is_variadic)
2821 sz += 5; /* ", ..." separator and ellipsis */
2823 /* Now allocate and populate the buffer. */
2824 char *argbuf = new char[sz];
2825 size_t len = 0;
2827 for (unsigned i = 0; i< m_param_types.length (); i++)
2829 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
2830 len += strlen (m_param_types[i]->get_debug_string ());
2831 if (i + 1 < m_param_types.length ())
2833 strcpy (argbuf + len, ", ");
2834 len += 2;
2837 if (m_is_variadic)
2839 if (m_param_types.length ())
2841 strcpy (argbuf + len, ", ");
2842 len += 2;
2844 strcpy (argbuf + len, "...");
2845 len += 3;
2847 argbuf[len] = '\0';
2849 /* ...and use it to get the string for the call as a whole. */
2850 string *result = string::from_printf (m_ctxt,
2851 "%s %s(%s)",
2852 m_return_type->get_debug_string (),
2853 insert,
2854 argbuf);
2856 delete[] argbuf;
2858 return result;
2861 /* Implementation of recording::memento::write_reproducer for function
2862 types. */
2864 void
2865 recording::function_type::write_reproducer (reproducer &)
2867 /* see notes below. */
2870 /* There's a get_pointer within context::new_function_ptr_type:
2871 the type received by client code isn't the memento for the
2872 function_type, but instead the result of get_pointer on it.
2874 Hence we can't directly write a reproducer that gives function_type.
2875 Instead we special-case things within get_pointer, detecting this
2876 case, calling the following function. */
2878 void
2879 recording::function_type::write_deferred_reproducer (reproducer &r,
2880 memento *ptr_type)
2882 gcc_assert (ptr_type);
2883 r.make_identifier (this, "function_type");
2884 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
2885 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
2886 r.write (" gcc_jit_type *%s[%i] = {\n",
2887 param_types_id,
2888 m_param_types.length ());
2889 int i;
2890 type *param_type;
2891 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2892 r.write (" %s,\n", r.get_identifier_as_type (param_type));
2893 r.write (" };\n");
2894 r.write (" gcc_jit_type *%s =\n"
2895 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2896 " %s, /* gcc_jit_location *loc */\n"
2897 " %s, /* gcc_jit_type *return_type */\n"
2898 " %i, /* int num_params */\n"
2899 " %s, /* gcc_jit_type **param_types */\n"
2900 " %i); /* int is_variadic */\n",
2901 ptr_id,
2902 r.get_identifier (get_context ()),
2903 "NULL", /* location is not stored */
2904 r.get_identifier_as_type (m_return_type),
2905 m_param_types.length (),
2906 param_types_id,
2907 m_is_variadic);
2910 /* The implementation of class gcc::jit::recording::field. */
2912 /* Implementation of pure virtual hook recording::memento::replay_into
2913 for recording::field. */
2915 void
2916 recording::field::replay_into (replayer *r)
2918 set_playback_obj (r->new_field (playback_location (r, m_loc),
2919 m_type->playback_type (),
2920 playback_string (m_name)));
2923 /* Override the default implementation of
2924 recording::memento::write_to_dump. Dump each field
2925 by dumping a line of the form:
2926 TYPE NAME;
2927 so that we can build up a struct/union field-byfield. */
2929 void
2930 recording::field::write_to_dump (dump &d)
2932 d.write (" %s %s;\n",
2933 m_type->get_debug_string (),
2934 m_name->c_str ());
2937 /* Implementation of recording::memento::make_debug_string for
2938 results of new_field. */
2940 recording::string *
2941 recording::field::make_debug_string ()
2943 return m_name;
2946 /* Implementation of recording::memento::write_reproducer for fields. */
2948 void
2949 recording::field::write_reproducer (reproducer &r)
2951 const char *id = r.make_identifier (this, "field");
2952 r.write(" gcc_jit_field *%s =\n"
2953 " gcc_jit_context_new_field (%s,\n"
2954 " %s, /* gcc_jit_location *loc */\n"
2955 " %s, /* gcc_jit_type *type, */\n"
2956 " %s); /* const char *name */\n",
2958 r.get_identifier (get_context ()),
2959 r.get_identifier (m_loc),
2960 r.get_identifier_as_type (m_type),
2961 m_name->get_debug_string ());
2964 /* The implementation of class gcc::jit::recording::compound_type */
2966 /* The constructor for gcc::jit::recording::compound_type. */
2968 recording::compound_type::compound_type (context *ctxt,
2969 location *loc,
2970 string *name)
2971 : type (ctxt),
2972 m_loc (loc),
2973 m_name (name),
2974 m_fields (NULL)
2978 /* Set the fields of a compound type.
2980 Implements the post-error-checking part of
2981 gcc_jit_struct_set_fields, and is also used by
2982 gcc_jit_context_new_union_type. */
2984 void
2985 recording::compound_type::set_fields (location *loc,
2986 int num_fields,
2987 field **field_array)
2989 m_loc = loc;
2990 gcc_assert (m_fields == NULL);
2992 m_fields = new fields (this, num_fields, field_array);
2993 m_ctxt->record (m_fields);
2996 /* Implementation of pure virtual hook recording::type::dereference for
2997 recording::compound_type. */
2999 recording::type *
3000 recording::compound_type::dereference ()
3002 return NULL; /* not a pointer */
3005 /* The implementation of class gcc::jit::recording::struct_. */
3007 /* The constructor for gcc::jit::recording::struct_. */
3009 recording::struct_::struct_ (context *ctxt,
3010 location *loc,
3011 string *name)
3012 : compound_type (ctxt, loc, name)
3016 /* Implementation of pure virtual hook recording::memento::replay_into
3017 for recording::struct_. */
3019 void
3020 recording::struct_::replay_into (replayer *r)
3022 set_playback_obj (
3023 r->new_compound_type (playback_location (r, get_loc ()),
3024 get_name ()->c_str (),
3025 true /* is_struct */));
3028 const char *
3029 recording::struct_::access_as_type (reproducer &r)
3031 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
3032 r.get_identifier (this));
3035 /* Implementation of recording::memento::make_debug_string for
3036 structs. */
3038 recording::string *
3039 recording::struct_::make_debug_string ()
3041 return string::from_printf (m_ctxt,
3042 "struct %s", get_name ()->c_str ());
3045 void
3046 recording::struct_::write_reproducer (reproducer &r)
3048 const char *id = r.make_identifier (this, "struct");
3049 r.write (" gcc_jit_struct *%s =\n"
3050 " gcc_jit_context_new_opaque_struct (%s,\n"
3051 " %s, /* gcc_jit_location *loc */\n"
3052 " %s); /* const char *name */\n",
3054 r.get_identifier (get_context ()),
3055 r.get_identifier (get_loc ()),
3056 get_name ()->get_debug_string ());
3059 /* The implementation of class gcc::jit::recording::union_. */
3061 /* The constructor for gcc::jit::recording::union_. */
3063 recording::union_::union_ (context *ctxt,
3064 location *loc,
3065 string *name)
3066 : compound_type (ctxt, loc, name)
3070 /* Implementation of pure virtual hook recording::memento::replay_into
3071 for recording::union_. */
3073 void
3074 recording::union_::replay_into (replayer *r)
3076 set_playback_obj (
3077 r->new_compound_type (playback_location (r, get_loc ()),
3078 get_name ()->c_str (),
3079 false /* is_struct */));
3082 /* Implementation of recording::memento::make_debug_string for
3083 unions. */
3085 recording::string *
3086 recording::union_::make_debug_string ()
3088 return string::from_printf (m_ctxt,
3089 "union %s", get_name ()->c_str ());
3092 /* Implementation of recording::memento::write_reproducer for unions. */
3094 void
3095 recording::union_::write_reproducer (reproducer &r)
3097 const char *id = r.make_identifier (this, "union");
3099 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
3100 r.write (" gcc_jit_field *%s[%i] = {\n",
3101 fields_id,
3102 get_fields ()->length ());
3103 for (int i = 0; i < get_fields ()->length (); i++)
3104 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
3105 r.write (" };\n");
3107 r.write (" gcc_jit_type *%s =\n"
3108 " gcc_jit_context_new_union_type (%s,\n"
3109 " %s, /* gcc_jit_location *loc */\n"
3110 " %s, /* const char *name */\n"
3111 " %i, /* int num_fields */\n"
3112 " %s); /* gcc_jit_field **fields */\n",
3114 r.get_identifier (get_context ()),
3115 r.get_identifier (get_loc ()),
3116 get_name ()->get_debug_string (),
3117 get_fields ()->length (),
3118 fields_id);
3121 /* The implementation of class gcc::jit::recording::fields. */
3123 /* The constructor for gcc::jit::recording::fields. */
3125 recording::fields::fields (compound_type *struct_or_union,
3126 int num_fields,
3127 field **fields)
3128 : memento (struct_or_union->m_ctxt),
3129 m_struct_or_union (struct_or_union),
3130 m_fields ()
3132 for (int i = 0; i < num_fields; i++)
3134 gcc_assert (fields[i]->get_container () == NULL);
3135 fields[i]->set_container (m_struct_or_union);
3136 m_fields.safe_push (fields[i]);
3140 /* Implementation of pure virtual hook recording::memento::replay_into
3141 for recording::fields. */
3143 void
3144 recording::fields::replay_into (replayer *)
3146 auto_vec<playback::field *> playback_fields;
3147 playback_fields.create (m_fields.length ());
3148 for (unsigned i = 0; i < m_fields.length (); i++)
3149 playback_fields.safe_push (m_fields[i]->playback_field ());
3150 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
3153 /* Override the default implementation of
3154 recording::memento::write_to_dump by writing a union/struct
3155 declaration of this form:
3157 struct/union NAME {
3158 TYPE_1 NAME_1;
3159 TYPE_2 NAME_2;
3160 ....
3161 TYPE_N NAME_N;
3164 to the dump. */
3166 void
3167 recording::fields::write_to_dump (dump &d)
3169 int i;
3170 field *f;
3172 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
3173 FOR_EACH_VEC_ELT (m_fields, i, f)
3174 f->write_to_dump (d);
3175 d.write ("};\n");
3178 /* Implementation of recording::memento::write_reproducer for the fields
3179 subclass. */
3181 void
3182 recording::fields::write_reproducer (reproducer &r)
3184 if (m_struct_or_union)
3185 if (m_struct_or_union->dyn_cast_struct () == NULL)
3186 /* We have a union; the fields have already been written by
3187 union::write_reproducer. */
3188 return;
3190 const char *fields_id = r.make_identifier (this, "fields");
3191 r.write (" gcc_jit_field *%s[%i] = {\n",
3192 fields_id,
3193 m_fields.length ());
3194 int i;
3195 field *field;
3196 FOR_EACH_VEC_ELT (m_fields, i, field)
3197 r.write (" %s,\n", r.get_identifier (field));
3198 r.write (" };\n");
3200 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
3201 " %s, /* gcc_jit_location *loc */\n"
3202 " %i, /* int num_fields */\n"
3203 " %s); /* gcc_jit_field **fields */\n",
3204 r.get_identifier (m_struct_or_union),
3205 r.get_identifier ((memento *)NULL),
3206 m_fields.length (),
3207 fields_id);
3210 /* Implementation of recording::memento::make_debug_string for
3211 field tables. */
3213 recording::string *
3214 recording::fields::make_debug_string ()
3216 return string::from_printf (m_ctxt,
3217 "fields");
3220 /* The implementation of class gcc::jit::recording::rvalue. */
3222 /* Create a recording::access_field_rvalue instance and add it to
3223 the rvalue's context's list of mementos.
3225 Implements the post-error-checking part of
3226 gcc_jit_rvalue_access_field. */
3228 recording::rvalue *
3229 recording::rvalue::access_field (recording::location *loc,
3230 field *field)
3232 recording::rvalue *result =
3233 new access_field_rvalue (m_ctxt, loc, this, field);
3234 m_ctxt->record (result);
3235 return result;
3238 /* Create a recording::dereference_field_rvalue instance and add it to
3239 the rvalue's context's list of mementos.
3241 Implements the post-error-checking part of
3242 gcc_jit_rvalue_dereference_field. */
3244 recording::lvalue *
3245 recording::rvalue::dereference_field (recording::location *loc,
3246 field *field)
3248 recording::lvalue *result =
3249 new dereference_field_rvalue (m_ctxt, loc, this, field);
3250 m_ctxt->record (result);
3251 return result;
3254 /* Create a recording::dereference_rvalue instance and add it to the
3255 rvalue's context's list of mementos.
3257 Implements the post-error-checking part of
3258 gcc_jit_rvalue_dereference. */
3260 recording::lvalue *
3261 recording::rvalue::dereference (recording::location *loc)
3263 recording::lvalue *result =
3264 new dereference_rvalue (m_ctxt, loc, this);
3265 m_ctxt->record (result);
3266 return result;
3269 /* An rvalue visitor, for validating that every rvalue within an expression
3270 trees within "STMT" has the correct scope (e.g. no access to locals
3271 of a different function). */
3273 class rvalue_usage_validator : public recording::rvalue_visitor
3275 public:
3276 rvalue_usage_validator (const char *api_funcname,
3277 recording::context *ctxt,
3278 recording::statement *stmt);
3280 void
3281 visit (recording::rvalue *rvalue) FINAL OVERRIDE;
3283 private:
3284 const char *m_api_funcname;
3285 recording::context *m_ctxt;
3286 recording::statement *m_stmt;
3289 /* The trivial constructor for rvalue_usage_validator. */
3291 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
3292 recording::context *ctxt,
3293 recording::statement *stmt)
3294 : m_api_funcname (api_funcname),
3295 m_ctxt (ctxt),
3296 m_stmt (stmt)
3300 /* Verify that the given rvalue is in the correct scope. */
3302 void
3303 rvalue_usage_validator::visit (recording::rvalue *rvalue)
3305 gcc_assert (m_stmt->get_block ());
3306 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
3308 /* Most rvalues don't have a scope (only locals and params). */
3309 if (rvalue->get_scope ())
3311 if (rvalue->get_scope () != stmt_scope)
3312 m_ctxt->add_error
3313 (rvalue->get_loc (),
3314 "%s:"
3315 " rvalue %s (type: %s)"
3316 " has scope limited to function %s"
3317 " but was used within function %s"
3318 " (in statement: %s)",
3319 m_api_funcname,
3320 rvalue->get_debug_string (),
3321 rvalue->get_type ()->get_debug_string (),
3322 rvalue->get_scope ()->get_debug_string (),
3323 stmt_scope->get_debug_string (),
3324 m_stmt->get_debug_string ());
3326 else
3328 if (rvalue->dyn_cast_param ())
3329 m_ctxt->add_error
3330 (rvalue->get_loc (),
3331 "%s:"
3332 " param %s (type: %s)"
3333 " was used within function %s"
3334 " (in statement: %s)"
3335 " but is not associated with any function",
3336 m_api_funcname,
3337 rvalue->get_debug_string (),
3338 rvalue->get_type ()->get_debug_string (),
3339 stmt_scope->get_debug_string (),
3340 m_stmt->get_debug_string ());
3344 /* Verify that it's valid to use this rvalue (and all expressions
3345 in the tree below it) within the given statement.
3347 For example, we must reject attempts to use a local from one
3348 function within a different function here, or we'll get
3349 an ICE deep inside toplev::main. */
3351 void
3352 recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
3354 rvalue_usage_validator v (api_funcname,
3355 s->get_context (),
3358 /* Verify that it's OK to use this rvalue within s. */
3359 v.visit (this);
3361 /* Traverse the expression tree below "this", verifying all rvalues
3362 within it. */
3363 visit_children (&v);
3366 /* Set the scope of this rvalue to be the given function. This can only
3367 be done once on a given rvalue. */
3369 void
3370 recording::rvalue::set_scope (function *scope)
3372 gcc_assert (scope);
3373 gcc_assert (m_scope == NULL);
3374 m_scope = scope;
3378 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3379 themselves.
3380 Instances of rvalue don't need an upcast call. */
3382 const char *
3383 recording::rvalue::access_as_rvalue (reproducer &r)
3385 return r.get_identifier (this);
3388 /* Return a debug string for the given rvalue, wrapping it in parentheses
3389 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3390 stronger precedence that this rvalue's precedence.
3392 For example, given:
3394 MULT
3396 PLUS MINUS
3397 / \ / \
3398 A B C D
3400 we want to emit:
3402 (A + B) * (C - D)
3404 since MULT has strong precedence than PLUS and MINUS, whereas for:
3406 PLUS
3408 MULT DIVIDE
3409 / \ / \
3410 A B C D
3412 we can simply emit:
3414 A * B + C / D
3416 since PLUS has weaker precedence than MULT and DIVIDE. */
3418 const char *
3419 recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
3421 enum precedence this_prec = get_precedence ();
3423 /* If this_prec has stronger precedence than outer_prec, we don't
3424 need to wrap this in parens within the outer debug string.
3425 Stronger precedences occur earlier than weaker within the enum,
3426 so this is a less than test. Equal precedences don't need
3427 parentheses. */
3428 if (this_prec <= outer_prec)
3429 return get_debug_string();
3431 /* Otherwise, we need parentheses. */
3433 /* Lazily-build and cache m_parenthesized_string. */
3434 if (!m_parenthesized_string)
3436 const char *debug_string = get_debug_string ();
3437 m_parenthesized_string = string::from_printf (get_context (),
3438 "(%s)",
3439 debug_string);
3441 gcc_assert (m_parenthesized_string);
3442 return m_parenthesized_string->c_str ();
3446 /* The implementation of class gcc::jit::recording::lvalue. */
3448 /* Create a recording::new_access_field_of_lvalue instance and add it to
3449 the lvalue's context's list of mementos.
3451 Implements the post-error-checking part of
3452 gcc_jit_lvalue_access_field. */
3454 recording::lvalue *
3455 recording::lvalue::access_field (recording::location *loc,
3456 field *field)
3458 recording::lvalue *result =
3459 new access_field_of_lvalue (m_ctxt, loc, this, field);
3460 m_ctxt->record (result);
3461 return result;
3464 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3465 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3466 upcast call. */
3468 const char *
3469 recording::lvalue::access_as_rvalue (reproducer &r)
3471 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3472 r.get_identifier (this));
3475 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3476 Instances of lvalue don't need to be upcast. */
3478 const char *
3479 recording::lvalue::access_as_lvalue (reproducer &r)
3481 return r.get_identifier (this);
3484 /* Create a recording::get_address_of_lvalue instance and add it to
3485 the lvalue's context's list of mementos.
3487 Implements the post-error-checking part of
3488 gcc_jit_lvalue_get_address. */
3490 recording::rvalue *
3491 recording::lvalue::get_address (recording::location *loc)
3493 recording::rvalue *result =
3494 new get_address_of_lvalue (m_ctxt, loc, this);
3495 m_ctxt->record (result);
3496 return result;
3499 /* The implementation of class gcc::jit::recording::param. */
3501 /* Implementation of pure virtual hook recording::memento::replay_into
3502 for recording::param. */
3504 void
3505 recording::param::replay_into (replayer *r)
3507 set_playback_obj (r->new_param (playback_location (r, m_loc),
3508 m_type->playback_type (),
3509 m_name->c_str ()));
3512 /* Implementation of recording::rvalue::access_as_rvalue for params.
3513 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3514 upcast call. */
3516 const char *
3517 recording::param::access_as_rvalue (reproducer &r)
3519 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3520 r.get_identifier (this));
3523 /* Implementation of recording::lvalue::access_as_lvalue for params.
3524 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3525 upcast call. */
3527 const char *
3528 recording::param::access_as_lvalue (reproducer &r)
3530 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3531 r.get_identifier (this));
3534 /* Implementation of recording::memento::write_reproducer for params. */
3536 void
3537 recording::param::write_reproducer (reproducer &r)
3539 const char *id = r.make_identifier (this, "param");
3540 r.write (" gcc_jit_param *%s =\n"
3541 " gcc_jit_context_new_param (%s,\n"
3542 " %s, /* gcc_jit_location *loc */\n"
3543 " %s, /*gcc_jit_type *type */\n"
3544 " %s); /* const char *name */\n",
3546 r.get_identifier (get_context ()),
3547 r.get_identifier (m_loc),
3548 r.get_identifier_as_type (m_type),
3549 m_name->get_debug_string ());
3552 /* The implementation of class gcc::jit::recording::function. */
3554 /* gcc::jit::recording::function's constructor. */
3556 recording::function::function (context *ctxt,
3557 recording::location *loc,
3558 enum gcc_jit_function_kind kind,
3559 type *return_type,
3560 recording::string *name,
3561 int num_params,
3562 recording::param **params,
3563 int is_variadic,
3564 enum built_in_function builtin_id)
3565 : memento (ctxt),
3566 m_loc (loc),
3567 m_kind (kind),
3568 m_return_type (return_type),
3569 m_name (name),
3570 m_params (),
3571 m_is_variadic (is_variadic),
3572 m_builtin_id (builtin_id),
3573 m_locals (),
3574 m_blocks (),
3575 m_fn_ptr_type (NULL)
3577 for (int i = 0; i< num_params; i++)
3579 param *param = params[i];
3580 gcc_assert (param);
3582 /* Associate each param with this function.
3584 Verify that the param doesn't already have a function. */
3585 if (param->get_scope ())
3587 /* We've already rejected attempts to reuse a param between
3588 different functions (within gcc_jit_context_new_function), so
3589 if the param *does* already have a function, it must be being
3590 reused within the params array for this function. We must
3591 produce an error for this reuse (blocking the compile), since
3592 otherwise we'd have an ICE later on. */
3593 gcc_assert (this == param->get_scope ());
3594 ctxt->add_error
3595 (loc,
3596 "gcc_jit_context_new_function:"
3597 " parameter %s (type: %s)"
3598 " is used more than once when creating function %s",
3599 param->get_debug_string (),
3600 param->get_type ()->get_debug_string (),
3601 name->c_str ());
3603 else
3605 /* The normal, non-error case: associate this function with the
3606 param. */
3607 param->set_scope (this);
3610 m_params.safe_push (param);
3614 /* Implementation of pure virtual hook recording::memento::replay_into
3615 for recording::function. */
3617 void
3618 recording::function::replay_into (replayer *r)
3620 /* Convert m_params to a vec of playback param. */
3621 auto_vec <playback::param *> params;
3622 int i;
3623 recording::param *param;
3624 params.create (m_params.length ());
3625 FOR_EACH_VEC_ELT (m_params, i, param)
3626 params.safe_push (param->playback_param ());
3628 set_playback_obj (r->new_function (playback_location (r, m_loc),
3629 m_kind,
3630 m_return_type->playback_type (),
3631 m_name->c_str (),
3632 &params,
3633 m_is_variadic,
3634 m_builtin_id));
3637 /* Create a recording::local instance and add it to
3638 the functions's context's list of mementos, and to the function's
3639 list of locals.
3641 Implements the post-error-checking part of
3642 gcc_jit_function_new_local. */
3644 recording::lvalue *
3645 recording::function::new_local (recording::location *loc,
3646 type *type,
3647 const char *name)
3649 local *result = new local (this, loc, type, new_string (name));
3650 m_ctxt->record (result);
3651 m_locals.safe_push (result);
3652 return result;
3655 /* Create a recording::block instance and add it to
3656 the functions's context's list of mementos, and to the function's
3657 list of blocks.
3659 Implements the post-error-checking part of
3660 gcc_jit_function_new_block. */
3662 recording::block*
3663 recording::function::new_block (const char *name)
3665 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
3667 recording::block *result =
3668 new recording::block (this, m_blocks.length (), new_string (name));
3669 m_ctxt->record (result);
3670 m_blocks.safe_push (result);
3671 return result;
3674 /* Override the default implementation of
3675 recording::memento::write_to_dump by dumping a C-like
3676 representation of the function; either like a prototype
3677 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3678 all other kinds of function. */
3680 void
3681 recording::function::write_to_dump (dump &d)
3683 switch (m_kind)
3685 default: gcc_unreachable ();
3686 case GCC_JIT_FUNCTION_EXPORTED:
3687 case GCC_JIT_FUNCTION_IMPORTED:
3688 d.write ("extern ");
3689 break;
3690 case GCC_JIT_FUNCTION_INTERNAL:
3691 d.write ("static ");
3692 break;
3693 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
3694 d.write ("static inline ");
3695 break;
3697 d.write ("%s\n", m_return_type->get_debug_string ());
3699 if (d.update_locations ())
3700 m_loc = d.make_location ();
3702 d.write ("%s (", get_debug_string ());
3704 int i;
3705 recording::param *param;
3706 FOR_EACH_VEC_ELT (m_params, i, param)
3708 if (i > 0)
3709 d.write (", ");
3710 d.write ("%s %s",
3711 param->get_type ()->get_debug_string (),
3712 param->get_debug_string ());
3714 d.write (")");
3715 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
3717 d.write ("; /* (imported) */\n\n");
3719 else
3721 int i;
3722 local *var = NULL;
3723 block *b;
3724 d.write ("\n{\n");
3726 /* Write locals: */
3727 FOR_EACH_VEC_ELT (m_locals, i, var)
3728 var->write_to_dump (d);
3729 if (m_locals.length ())
3730 d.write ("\n");
3732 /* Write each block: */
3733 FOR_EACH_VEC_ELT (m_blocks, i, b)
3735 if (i > 0)
3736 d.write ("\n");
3737 b->write_to_dump (d);
3740 d.write ("}\n\n");
3744 /* Pre-compilation validation of a function, for those things we can't
3745 check until the context is (supposedly) fully-populated. */
3747 void
3748 recording::function::validate ()
3750 /* Complain about empty functions with non-void return type. */
3751 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
3752 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
3753 if (m_blocks.length () == 0)
3754 m_ctxt->add_error (m_loc,
3755 "function %s returns non-void (type: %s)"
3756 " but has no blocks",
3757 get_debug_string (),
3758 m_return_type->get_debug_string ());
3760 /* Check that all blocks are terminated. */
3761 int num_invalid_blocks = 0;
3763 int i;
3764 block *b;
3766 FOR_EACH_VEC_ELT (m_blocks, i, b)
3767 if (!b->validate ())
3768 num_invalid_blocks++;
3771 /* Check that all blocks are reachable. */
3772 if (!m_ctxt->get_inner_bool_option
3773 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
3774 && m_blocks.length () > 0 && num_invalid_blocks == 0)
3776 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3777 flag, starting at the initial block. */
3778 auto_vec<block *> worklist (m_blocks.length ());
3779 worklist.safe_push (m_blocks[0]);
3780 while (worklist.length () > 0)
3782 block *b = worklist.pop ();
3783 b->m_is_reachable = true;
3785 /* Add successor blocks that aren't yet marked to the worklist. */
3786 /* We checked that each block has a terminating statement above . */
3787 vec <block *> successors = b->get_successor_blocks ();
3788 int i;
3789 block *succ;
3790 FOR_EACH_VEC_ELT (successors, i, succ)
3791 if (!succ->m_is_reachable)
3792 worklist.safe_push (succ);
3793 successors.release ();
3796 /* Now complain about any blocks that haven't been marked. */
3798 int i;
3799 block *b;
3800 FOR_EACH_VEC_ELT (m_blocks, i, b)
3801 if (!b->m_is_reachable)
3802 m_ctxt->add_error (b->get_loc (),
3803 "unreachable block: %s",
3804 b->get_debug_string ());
3809 /* Implements the post-error-checking part of
3810 gcc_jit_function_dump_to_dot. */
3812 void
3813 recording::function::dump_to_dot (const char *path)
3815 FILE *fp = fopen (path, "w");
3816 if (!fp)
3817 return;
3819 pretty_printer the_pp;
3820 the_pp.buffer->stream = fp;
3822 pretty_printer *pp = &the_pp;
3824 pp_printf (pp,
3825 "digraph %s {\n", get_debug_string ());
3827 /* Blocks: */
3829 int i;
3830 block *b;
3831 FOR_EACH_VEC_ELT (m_blocks, i, b)
3832 b->dump_to_dot (pp);
3835 /* Edges: */
3837 int i;
3838 block *b;
3839 FOR_EACH_VEC_ELT (m_blocks, i, b)
3840 b->dump_edges_to_dot (pp);
3843 pp_printf (pp, "}\n");
3844 pp_flush (pp);
3845 fclose (fp);
3848 /* Implements the post-error-checking part of
3849 gcc_jit_function_get_address. */
3851 recording::rvalue *
3852 recording::function::get_address (recording::location *loc)
3854 /* Lazily create and cache the function pointer type. */
3855 if (!m_fn_ptr_type)
3857 /* Make a recording::function_type for this function. */
3858 auto_vec <recording::type *> param_types (m_params.length ());
3859 unsigned i;
3860 recording::param *param;
3861 FOR_EACH_VEC_ELT (m_params, i, param)
3862 param_types.safe_push (param->get_type ());
3863 recording::function_type *fn_type
3864 = m_ctxt->new_function_type (m_return_type,
3865 m_params.length (),
3866 param_types.address (),
3867 m_is_variadic);
3868 m_fn_ptr_type = fn_type->get_pointer ();
3870 gcc_assert (m_fn_ptr_type);
3872 rvalue *result = new function_pointer (get_context (), loc, this, m_fn_ptr_type);
3873 m_ctxt->record (result);
3874 return result;
3877 /* Implementation of recording::memento::make_debug_string for
3878 functions. */
3880 recording::string *
3881 recording::function::make_debug_string ()
3883 return m_name;
3886 /* A table of enum gcc_jit_function_kind values expressed in string
3887 form. */
3889 static const char * const names_of_function_kinds[] = {
3890 "GCC_JIT_FUNCTION_EXPORTED",
3891 "GCC_JIT_FUNCTION_INTERNAL",
3892 "GCC_JIT_FUNCTION_IMPORTED",
3893 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3896 /* Implementation of recording::memento::write_reproducer for functions. */
3898 void
3899 recording::function::write_reproducer (reproducer &r)
3901 const char *id = r.make_identifier (this, "func");
3903 if (m_builtin_id)
3905 r.write (" gcc_jit_function *%s =\n"
3906 " gcc_jit_context_get_builtin_function (%s,\n"
3907 " %s);\n",
3909 r.get_identifier (get_context ()),
3910 m_name->get_debug_string ());
3911 return;
3913 const char *params_id = r.make_tmp_identifier ("params_for", this);
3914 r.write (" gcc_jit_param *%s[%i] = {\n",
3915 params_id,
3916 m_params.length ());
3917 int i;
3918 param *param;
3919 FOR_EACH_VEC_ELT (m_params, i, param)
3920 r.write (" %s,\n", r.get_identifier (param));
3921 r.write (" };\n");
3922 r.write (" gcc_jit_function *%s =\n"
3923 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3924 " %s, /* gcc_jit_location *loc */\n"
3925 " %s, /* enum gcc_jit_function_kind kind */\n"
3926 " %s, /* gcc_jit_type *return_type */\n"
3927 " %s, /* const char *name */\n"
3928 " %i, /* int num_params */\n"
3929 " %s, /* gcc_jit_param **params */\n"
3930 " %i); /* int is_variadic */\n",
3932 r.get_identifier (get_context ()),
3933 r.get_identifier (m_loc),
3934 names_of_function_kinds[m_kind],
3935 r.get_identifier_as_type (m_return_type),
3936 m_name->get_debug_string (),
3937 m_params.length (),
3938 params_id,
3939 m_is_variadic);
3943 /* The implementation of class gcc::jit::recording::block. */
3945 /* Create a recording::eval instance and add it to
3946 the block's context's list of mementos, and to the block's
3947 list of statements.
3949 Implements the heart of gcc_jit_block_add_eval. */
3951 recording::statement *
3952 recording::block::add_eval (recording::location *loc,
3953 recording::rvalue *rvalue)
3955 statement *result = new eval (this, loc, rvalue);
3956 m_ctxt->record (result);
3957 m_statements.safe_push (result);
3958 return result;
3961 /* Create a recording::assignment instance and add it to
3962 the block's context's list of mementos, and to the block's
3963 list of statements.
3965 Implements the heart of gcc_jit_block_add_assignment. */
3967 recording::statement *
3968 recording::block::add_assignment (recording::location *loc,
3969 recording::lvalue *lvalue,
3970 recording::rvalue *rvalue)
3972 statement *result = new assignment (this, loc, lvalue, rvalue);
3973 m_ctxt->record (result);
3974 m_statements.safe_push (result);
3975 return result;
3978 /* Create a recording::assignment_op instance and add it to
3979 the block's context's list of mementos, and to the block's
3980 list of statements.
3982 Implements the heart of gcc_jit_block_add_assignment_op. */
3984 recording::statement *
3985 recording::block::add_assignment_op (recording::location *loc,
3986 recording::lvalue *lvalue,
3987 enum gcc_jit_binary_op op,
3988 recording::rvalue *rvalue)
3990 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
3991 m_ctxt->record (result);
3992 m_statements.safe_push (result);
3993 return result;
3996 /* Create a recording::comment instance and add it to
3997 the block's context's list of mementos, and to the block's
3998 list of statements.
4000 Implements the heart of gcc_jit_block_add_comment. */
4002 recording::statement *
4003 recording::block::add_comment (recording::location *loc,
4004 const char *text)
4006 statement *result = new comment (this, loc, new_string (text));
4007 m_ctxt->record (result);
4008 m_statements.safe_push (result);
4009 return result;
4012 /* Create a recording::end_with_conditional instance and add it to
4013 the block's context's list of mementos, and to the block's
4014 list of statements.
4016 Implements the heart of gcc_jit_block_end_with_conditional. */
4018 recording::statement *
4019 recording::block::end_with_conditional (recording::location *loc,
4020 recording::rvalue *boolval,
4021 recording::block *on_true,
4022 recording::block *on_false)
4024 statement *result = new conditional (this, loc, boolval, on_true, on_false);
4025 m_ctxt->record (result);
4026 m_statements.safe_push (result);
4027 m_has_been_terminated = true;
4028 return result;
4031 /* Create a recording::end_with_jump instance and add it to
4032 the block's context's list of mementos, and to the block's
4033 list of statements.
4035 Implements the heart of gcc_jit_block_end_with_jump. */
4037 recording::statement *
4038 recording::block::end_with_jump (recording::location *loc,
4039 recording::block *target)
4041 statement *result = new jump (this, loc, target);
4042 m_ctxt->record (result);
4043 m_statements.safe_push (result);
4044 m_has_been_terminated = true;
4045 return result;
4048 /* Create a recording::end_with_return instance and add it to
4049 the block's context's list of mementos, and to the block's
4050 list of statements.
4052 Implements the post-error-checking parts of
4053 gcc_jit_block_end_with_return and
4054 gcc_jit_block_end_with_void_return. */
4056 recording::statement *
4057 recording::block::end_with_return (recording::location *loc,
4058 recording::rvalue *rvalue)
4060 /* This is used by both gcc_jit_function_add_return and
4061 gcc_jit_function_add_void_return; rvalue will be non-NULL for
4062 the former and NULL for the latter. */
4063 statement *result = new return_ (this, loc, rvalue);
4064 m_ctxt->record (result);
4065 m_statements.safe_push (result);
4066 m_has_been_terminated = true;
4067 return result;
4070 /* Create a recording::switch_ instance and add it to
4071 the block's context's list of mementos, and to the block's
4072 list of statements.
4074 Implements the heart of gcc_jit_block_end_with_switch. */
4076 recording::statement *
4077 recording::block::end_with_switch (recording::location *loc,
4078 recording::rvalue *expr,
4079 recording::block *default_block,
4080 int num_cases,
4081 recording::case_ **cases)
4083 statement *result = new switch_ (this, loc,
4084 expr,
4085 default_block,
4086 num_cases,
4087 cases);
4088 m_ctxt->record (result);
4089 m_statements.safe_push (result);
4090 m_has_been_terminated = true;
4091 return result;
4094 /* Override the default implementation of
4095 recording::memento::write_to_dump for blocks by writing
4096 an unindented block name as a label, followed by the indented
4097 statements:
4099 BLOCK_NAME:
4100 STATEMENT_1;
4101 STATEMENT_2;
4103 STATEMENT_N; */
4105 void
4106 recording::block::write_to_dump (dump &d)
4108 d.write ("%s:\n", get_debug_string ());
4110 int i;
4111 statement *s;
4112 FOR_EACH_VEC_ELT (m_statements, i, s)
4113 s->write_to_dump (d);
4116 /* Validate a block by ensuring that it has been terminated. */
4118 bool
4119 recording::block::validate ()
4121 /* Check for termination. */
4122 if (!has_been_terminated ())
4124 statement *stmt = get_last_statement ();
4125 location *loc = stmt ? stmt->get_loc () : NULL;
4126 m_func->get_context ()->add_error (loc,
4127 "unterminated block in %s: %s",
4128 m_func->get_debug_string (),
4129 get_debug_string ());
4130 return false;
4133 return true;
4136 /* Get the source-location of a block by using that of the first
4137 statement within it, if any. */
4139 recording::location *
4140 recording::block::get_loc () const
4142 recording::statement *stmt = get_first_statement ();
4143 if (stmt)
4144 return stmt->get_loc ();
4145 else
4146 return NULL;
4149 /* Get the first statement within a block, if any. */
4151 recording::statement *
4152 recording::block::get_first_statement () const
4154 if (m_statements.length ())
4155 return m_statements[0];
4156 else
4157 return NULL;
4160 /* Get the last statement within a block, if any. */
4162 recording::statement *
4163 recording::block::get_last_statement () const
4165 if (m_statements.length ())
4166 return m_statements[m_statements.length () - 1];
4167 else
4168 return NULL;
4171 /* Assuming that this block has been terminated, get the successor blocks
4172 as a vector. Ownership of the vector transfers to the caller, which
4173 must call its release () method.
4175 Used when validating functions, and when dumping dot representations
4176 of them. */
4178 vec <recording::block *>
4179 recording::block::get_successor_blocks () const
4181 gcc_assert (m_has_been_terminated);
4182 statement *last_statement = get_last_statement ();
4183 gcc_assert (last_statement);
4184 return last_statement->get_successor_blocks ();
4187 /* Implementation of pure virtual hook recording::memento::replay_into
4188 for recording::block. */
4190 void
4191 recording::block::replay_into (replayer *)
4193 set_playback_obj (m_func->playback_function ()
4194 ->new_block (playback_string (m_name)));
4197 /* Implementation of recording::memento::make_debug_string for
4198 blocks. */
4200 recording::string *
4201 recording::block::make_debug_string ()
4203 if (m_name)
4204 return m_name;
4205 else
4206 return string::from_printf (m_ctxt,
4207 "<UNNAMED BLOCK %p>",
4208 (void *)this);
4211 /* Implementation of recording::memento::write_reproducer for blocks. */
4213 void
4214 recording::block::write_reproducer (reproducer &r)
4216 const char *id = r.make_identifier (this, "block");
4217 r.write (" gcc_jit_block *%s =\n"
4218 " gcc_jit_function_new_block (%s, %s);\n",
4220 r.get_identifier (m_func),
4221 m_name ? m_name->get_debug_string () : "NULL");
4224 /* Dump a block in graphviz form into PP, capturing the block name (if
4225 any) and the statements. */
4227 void
4228 recording::block::dump_to_dot (pretty_printer *pp)
4230 pp_printf (pp,
4231 ("\tblock_%d "
4232 "[shape=record,style=filled,fillcolor=white,label=\"{"),
4233 m_index);
4234 pp_write_text_to_stream (pp);
4235 if (m_name)
4237 pp_string (pp, m_name->c_str ());
4238 pp_string (pp, ":");
4239 pp_newline (pp);
4240 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4243 int i;
4244 statement *s;
4245 FOR_EACH_VEC_ELT (m_statements, i, s)
4247 pp_string (pp, s->get_debug_string ());
4248 pp_newline (pp);
4249 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4252 pp_printf (pp,
4253 "}\"];\n\n");
4254 pp_flush (pp);
4257 /* Dump the out-edges of the block in graphviz form into PP. */
4259 void
4260 recording::block::dump_edges_to_dot (pretty_printer *pp)
4262 vec <block *> successors = get_successor_blocks ();
4263 int i;
4264 block *succ;
4265 FOR_EACH_VEC_ELT (successors, i, succ)
4266 pp_printf (pp,
4267 "\tblock_%d:s -> block_%d:n;\n",
4268 m_index, succ->m_index);
4269 successors.release ();
4272 /* The implementation of class gcc::jit::recording::global. */
4274 /* Implementation of pure virtual hook recording::memento::replay_into
4275 for recording::global. */
4277 void
4278 recording::global::replay_into (replayer *r)
4280 set_playback_obj (r->new_global (playback_location (r, m_loc),
4281 m_kind,
4282 m_type->playback_type (),
4283 playback_string (m_name)));
4286 /* Override the default implementation of
4287 recording::memento::write_to_dump for globals.
4288 This will be of the form:
4290 GCC_JIT_GLOBAL_EXPORTED:
4291 "TYPE NAME;"
4292 e.g. "int foo;"
4294 GCC_JIT_GLOBAL_INTERNAL:
4295 "static TYPE NAME;"
4296 e.g. "static int foo;"
4298 GCC_JIT_GLOBAL_IMPORTED:
4299 "extern TYPE NAME;"
4300 e.g. "extern int foo;"
4302 These are written to the top of the dump by
4303 recording::context::dump_to_file. */
4305 void
4306 recording::global::write_to_dump (dump &d)
4308 if (d.update_locations ())
4309 m_loc = d.make_location ();
4311 switch (m_kind)
4313 default:
4314 gcc_unreachable ();
4316 case GCC_JIT_GLOBAL_EXPORTED:
4317 break;
4319 case GCC_JIT_GLOBAL_INTERNAL:
4320 d.write ("static ");
4321 break;
4323 case GCC_JIT_GLOBAL_IMPORTED:
4324 d.write ("extern ");
4325 break;
4327 d.write ("%s %s;\n",
4328 m_type->get_debug_string (),
4329 get_debug_string ());
4332 /* A table of enum gcc_jit_global_kind values expressed in string
4333 form. */
4335 static const char * const global_kind_reproducer_strings[] = {
4336 "GCC_JIT_GLOBAL_EXPORTED",
4337 "GCC_JIT_GLOBAL_INTERNAL",
4338 "GCC_JIT_GLOBAL_IMPORTED"
4341 /* Implementation of recording::memento::write_reproducer for globals. */
4343 void
4344 recording::global::write_reproducer (reproducer &r)
4346 const char *id = r.make_identifier (this, "block");
4347 r.write (" gcc_jit_lvalue *%s =\n"
4348 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4349 " %s, /* gcc_jit_location *loc */\n"
4350 " %s, /* enum gcc_jit_global_kind kind */\n"
4351 " %s, /* gcc_jit_type *type */\n"
4352 " %s); /* const char *name */\n",
4354 r.get_identifier (get_context ()),
4355 r.get_identifier (m_loc),
4356 global_kind_reproducer_strings[m_kind],
4357 r.get_identifier_as_type (get_type ()),
4358 m_name->get_debug_string ());
4361 /* The implementation of the various const-handling classes:
4362 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4364 /* Explicit specialization of the various mementos we're interested in. */
4365 template class recording::memento_of_new_rvalue_from_const <int>;
4366 template class recording::memento_of_new_rvalue_from_const <long>;
4367 template class recording::memento_of_new_rvalue_from_const <double>;
4368 template class recording::memento_of_new_rvalue_from_const <void *>;
4370 /* Implementation of the pure virtual hook recording::memento::replay_into
4371 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4373 template <typename HOST_TYPE>
4374 void
4375 recording::
4376 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
4378 set_playback_obj
4379 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
4380 m_value));
4383 /* The make_debug_string and write_reproducer methods vary between the
4384 various
4385 memento_of_new_rvalue_from_const <HOST_TYPE>
4386 classes, so we explicitly write specializations of them.
4388 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4389 namespaces are written out explicitly, which is why most of this file
4390 doesn't abbreviate things by entering the "recording" namespace.
4392 However, these specializations are required to be in the same namespace
4393 as the template, hence we now have to enter the gcc::jit::recording
4394 namespace. */
4396 namespace recording
4399 /* The make_debug_string specialization for <int>, which renders it as
4400 (TARGET_TYPE)LITERAL
4401 e.g.
4402 "(int)42". */
4404 template <>
4405 string *
4406 memento_of_new_rvalue_from_const <int>::make_debug_string ()
4408 return string::from_printf (m_ctxt,
4409 "(%s)%i",
4410 m_type->get_debug_string (),
4411 m_value);
4414 /* The get_wide_int specialization for <int>. */
4416 template <>
4417 bool
4418 memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const
4420 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4421 return true;
4424 /* The write_reproducer specialization for <int>. */
4426 template <>
4427 void
4428 memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
4430 const char *id = r.make_identifier (this, "rvalue");
4431 r.write (" gcc_jit_rvalue *%s =\n"
4432 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4433 " %s, /* gcc_jit_type *numeric_type */\n"
4434 " %i); /* int value */\n",
4436 r.get_identifier (get_context ()),
4437 r.get_identifier_as_type (m_type),
4438 m_value);
4441 /* The make_debug_string specialization for <long>, rendering it as
4442 (TARGET_TYPE)LITERAL
4443 e.g.
4444 "(long)42". */
4446 template <>
4447 string *
4448 memento_of_new_rvalue_from_const <long>::make_debug_string ()
4450 return string::from_printf (m_ctxt,
4451 "(%s)%li",
4452 m_type->get_debug_string (),
4453 m_value);
4456 /* The get_wide_int specialization for <long>. */
4458 template <>
4459 bool
4460 memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const
4462 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4463 return true;
4466 /* The write_reproducer specialization for <long>. */
4468 template <>
4469 void
4470 recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
4472 const char *id = r.make_identifier (this, "rvalue");
4474 /* We have to special-case LONG_MIN, since e.g.
4475 -9223372036854775808L
4476 is parsed as
4477 -(9223372036854775808L)
4478 and hence we'd get:
4479 error: integer constant is so large that it is unsigned [-Werror]
4480 Workaround this by writing (LONG_MIN + 1) - 1. */
4481 if (m_value == LONG_MIN)
4483 r.write (" gcc_jit_rvalue *%s =\n"
4484 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4485 " %s, /* gcc_jit_type *numeric_type */\n"
4486 " %ldL - 1); /* long value */\n",
4488 r.get_identifier (get_context ()),
4489 r.get_identifier_as_type (m_type),
4490 m_value + 1);
4491 return;
4494 r.write (" gcc_jit_rvalue *%s =\n"
4495 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4496 " %s, /* gcc_jit_type *numeric_type */\n"
4497 " %ldL); /* long value */\n",
4499 r.get_identifier (get_context ()),
4500 r.get_identifier_as_type (m_type),
4501 m_value);
4504 /* The make_debug_string specialization for <double>, rendering it as
4505 (TARGET_TYPE)LITERAL
4506 e.g.
4507 "(float)42.0". */
4509 template <>
4510 string *
4511 memento_of_new_rvalue_from_const <double>::make_debug_string ()
4513 return string::from_printf (m_ctxt,
4514 "(%s)%f",
4515 m_type->get_debug_string (),
4516 m_value);
4519 /* The get_wide_int specialization for <double>. */
4521 template <>
4522 bool
4523 memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
4525 return false;
4528 /* The write_reproducer specialization for <double>. */
4530 template <>
4531 void
4532 recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
4534 const char *id = r.make_identifier (this, "rvalue");
4535 r.write (" gcc_jit_rvalue *%s =\n"
4536 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4537 " %s, /* gcc_jit_type *numeric_type */\n"
4538 " %f); /* double value */\n",
4540 r.get_identifier (get_context ()),
4541 r.get_identifier_as_type (m_type),
4542 m_value);
4545 /* The make_debug_string specialization for <void *>, rendering it as
4546 (TARGET_TYPE)HEX
4547 e.g.
4548 "(int *)0xdeadbeef"
4550 Zero is rendered as NULL e.g.
4551 "(int *)NULL". */
4553 template <>
4554 string *
4555 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
4557 if (m_value != NULL)
4558 return string::from_printf (m_ctxt,
4559 "(%s)%p",
4560 m_type->get_debug_string (), m_value);
4561 else
4562 return string::from_printf (m_ctxt,
4563 "(%s)NULL",
4564 m_type->get_debug_string ());
4567 /* The get_wide_int specialization for <void *>. */
4569 template <>
4570 bool
4571 memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const
4573 return false;
4576 /* Implementation of recording::memento::write_reproducer for <void *>
4577 values. */
4579 template <>
4580 void
4581 memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
4583 const char *id = r.make_identifier (this, "rvalue");
4584 if (m_value)
4585 r.write (" gcc_jit_rvalue *%s =\n"
4586 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4587 " %s, /* gcc_jit_type *pointer_type */\n"
4588 " (void *)%p); /* void *value */\n",
4590 r.get_identifier (get_context ()),
4591 r.get_identifier_as_type (m_type),
4592 m_value);
4593 else
4594 r.write (" gcc_jit_rvalue *%s =\n"
4595 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4596 " %s); /* gcc_jit_type *pointer_type */\n",
4598 r.get_identifier (get_context ()),
4599 r.get_identifier_as_type (m_type));
4602 /* We're done specializing make_debug_string and write_reproducer, so we
4603 can exit the gcc::jit::recording namespace. */
4605 } // namespace recording
4607 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4609 /* Implementation of pure virtual hook recording::memento::replay_into
4610 for recording::memento_of_new_string_literal. */
4612 void
4613 recording::memento_of_new_string_literal::replay_into (replayer *r)
4615 set_playback_obj (r->new_string_literal (m_value->c_str ()));
4618 /* Implementation of recording::memento::make_debug_string for
4619 string literals. */
4621 recording::string *
4622 recording::memento_of_new_string_literal::make_debug_string ()
4624 return string::from_printf (m_ctxt,
4625 "%s",
4626 m_value->get_debug_string ());
4629 /* Implementation of recording::memento::write_reproducer for string literal
4630 values. */
4632 void
4633 recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
4635 const char *id = r.make_identifier (this, "rvalue");
4636 r.write (" gcc_jit_rvalue *%s =\n"
4637 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4638 " %s); /* const char *value */\n",
4640 r.get_identifier (get_context ()),
4641 m_value->get_debug_string ());
4644 /* The implementation of class
4645 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
4647 /* The constructor for
4648 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
4650 recording::memento_of_new_rvalue_from_vector::
4651 memento_of_new_rvalue_from_vector (context *ctxt,
4652 location *loc,
4653 vector_type *type,
4654 rvalue **elements)
4655 : rvalue (ctxt, loc, type),
4656 m_vector_type (type),
4657 m_elements ()
4659 for (unsigned i = 0; i < type->get_num_units (); i++)
4660 m_elements.safe_push (elements[i]);
4663 /* Implementation of pure virtual hook recording::memento::replay_into
4664 for recording::memento_of_new_rvalue_from_vector. */
4666 void
4667 recording::memento_of_new_rvalue_from_vector::replay_into (replayer *r)
4669 auto_vec<playback::rvalue *> playback_elements;
4670 playback_elements.create (m_elements.length ());
4671 for (unsigned i = 0; i< m_elements.length (); i++)
4672 playback_elements.safe_push (m_elements[i]->playback_rvalue ());
4674 set_playback_obj (r->new_rvalue_from_vector (playback_location (r, m_loc),
4675 m_type->playback_type (),
4676 playback_elements));
4679 /* Implementation of pure virtual hook recording::rvalue::visit_children
4680 for recording::memento_of_new_rvalue_from_vector. */
4682 void
4683 recording::memento_of_new_rvalue_from_vector::visit_children (rvalue_visitor *v)
4685 for (unsigned i = 0; i< m_elements.length (); i++)
4686 v->visit (m_elements[i]);
4689 /* Implementation of recording::memento::make_debug_string for
4690 vectors. */
4692 recording::string *
4693 recording::memento_of_new_rvalue_from_vector::make_debug_string ()
4695 comma_separated_string elements (m_elements, get_precedence ());
4697 /* Now build a string. */
4698 string *result = string::from_printf (m_ctxt,
4699 "{%s}",
4700 elements.as_char_ptr ());
4702 return result;
4706 /* Implementation of recording::memento::write_reproducer for
4707 vectors. */
4709 void
4710 recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer &r)
4712 const char *id = r.make_identifier (this, "vector");
4713 const char *elements_id = r.make_tmp_identifier ("elements_for_", this);
4714 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4715 elements_id,
4716 m_elements.length ());
4717 for (unsigned i = 0; i< m_elements.length (); i++)
4718 r.write (" %s,\n", r.get_identifier_as_rvalue (m_elements[i]));
4719 r.write (" };\n");
4720 r.write (" gcc_jit_rvalue *%s =\n"
4721 " gcc_jit_context_new_rvalue_from_vector (%s, /* gcc_jit_context *ctxt */\n"
4722 " %s, /* gcc_jit_location *loc */\n"
4723 " %s, /* gcc_jit_type *vec_type */\n"
4724 " %i, /* size_t num_elements */ \n"
4725 " %s); /* gcc_jit_rvalue **elements*/\n",
4727 r.get_identifier (get_context ()),
4728 r.get_identifier (m_loc),
4729 r.get_identifier (m_vector_type),
4730 m_elements.length (),
4731 elements_id);
4734 /* The implementation of class gcc::jit::recording::unary_op. */
4736 /* Implementation of pure virtual hook recording::memento::replay_into
4737 for recording::unary_op. */
4739 void
4740 recording::unary_op::replay_into (replayer *r)
4742 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
4743 m_op,
4744 get_type ()->playback_type (),
4745 m_a->playback_rvalue ()));
4748 /* Implementation of pure virtual hook recording::rvalue::visit_children
4749 for recording::unary_op. */
4750 void
4751 recording::unary_op::visit_children (rvalue_visitor *v)
4753 v->visit (m_a);
4756 /* Implementation of recording::memento::make_debug_string for
4757 unary ops. */
4759 static const char * const unary_op_strings[] = {
4760 "-", /* GCC_JIT_UNARY_OP_MINUS */
4761 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4762 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4763 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4766 recording::string *
4767 recording::unary_op::make_debug_string ()
4769 return string::from_printf (m_ctxt,
4770 "%s(%s)",
4771 unary_op_strings[m_op],
4772 m_a->get_debug_string ());
4775 static const char * const unary_op_reproducer_strings[] = {
4776 "GCC_JIT_UNARY_OP_MINUS",
4777 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4778 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4779 "GCC_JIT_UNARY_OP_ABS"
4782 /* Implementation of recording::memento::write_reproducer for unary ops. */
4784 void
4785 recording::unary_op::write_reproducer (reproducer &r)
4787 const char *id = r.make_identifier (this, "rvalue");
4788 r.write (" gcc_jit_rvalue *%s =\n"
4789 " gcc_jit_context_new_unary_op (%s,\n"
4790 " %s, /* gcc_jit_location *loc */\n"
4791 " %s, /* enum gcc_jit_unary_op op */\n"
4792 " %s, /* gcc_jit_type *result_type */\n"
4793 " %s); /* gcc_jit_rvalue *a */\n",
4795 r.get_identifier (get_context ()),
4796 r.get_identifier (m_loc),
4797 unary_op_reproducer_strings[m_op],
4798 r.get_identifier_as_type (get_type ()),
4799 r.get_identifier_as_rvalue (m_a));
4802 /* The implementation of class gcc::jit::recording::binary_op. */
4804 /* Implementation of pure virtual hook recording::memento::replay_into
4805 for recording::binary_op. */
4807 void
4808 recording::binary_op::replay_into (replayer *r)
4810 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
4811 m_op,
4812 get_type ()->playback_type (),
4813 m_a->playback_rvalue (),
4814 m_b->playback_rvalue ()));
4817 /* Implementation of pure virtual hook recording::rvalue::visit_children
4818 for recording::binary_op. */
4819 void
4820 recording::binary_op::visit_children (rvalue_visitor *v)
4822 v->visit (m_a);
4823 v->visit (m_b);
4826 /* Implementation of recording::memento::make_debug_string for
4827 binary ops. */
4829 static const char * const binary_op_strings[] = {
4830 "+", /* GCC_JIT_BINARY_OP_PLUS */
4831 "-", /* GCC_JIT_BINARY_OP_MINUS */
4832 "*", /* GCC_JIT_BINARY_OP_MULT */
4833 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4834 "%", /* GCC_JIT_BINARY_OP_MODULO */
4835 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4836 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4837 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4838 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4839 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4840 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4841 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4844 recording::string *
4845 recording::binary_op::make_debug_string ()
4847 enum precedence prec = get_precedence ();
4848 return string::from_printf (m_ctxt,
4849 "%s %s %s",
4850 m_a->get_debug_string_parens (prec),
4851 binary_op_strings[m_op],
4852 m_b->get_debug_string_parens (prec));
4855 static const char * const binary_op_reproducer_strings[] = {
4856 "GCC_JIT_BINARY_OP_PLUS",
4857 "GCC_JIT_BINARY_OP_MINUS",
4858 "GCC_JIT_BINARY_OP_MULT",
4859 "GCC_JIT_BINARY_OP_DIVIDE",
4860 "GCC_JIT_BINARY_OP_MODULO",
4861 "GCC_JIT_BINARY_OP_BITWISE_AND",
4862 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4863 "GCC_JIT_BINARY_OP_BITWISE_OR",
4864 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4865 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4866 "GCC_JIT_BINARY_OP_LSHIFT",
4867 "GCC_JIT_BINARY_OP_RSHIFT"
4870 /* Implementation of recording::memento::write_reproducer for binary ops. */
4872 void
4873 recording::binary_op::write_reproducer (reproducer &r)
4875 const char *id = r.make_identifier (this, "rvalue");
4876 r.write (" gcc_jit_rvalue *%s =\n"
4877 " gcc_jit_context_new_binary_op (%s,\n"
4878 " %s, /* gcc_jit_location *loc */\n"
4879 " %s, /* enum gcc_jit_binary_op op */\n"
4880 " %s, /* gcc_jit_type *result_type */\n"
4881 " %s, /* gcc_jit_rvalue *a */\n"
4882 " %s); /* gcc_jit_rvalue *b */\n",
4884 r.get_identifier (get_context ()),
4885 r.get_identifier (m_loc),
4886 binary_op_reproducer_strings[m_op],
4887 r.get_identifier_as_type (get_type ()),
4888 r.get_identifier_as_rvalue (m_a),
4889 r.get_identifier_as_rvalue (m_b));
4892 namespace recording {
4893 static const enum precedence binary_op_precedence[] = {
4894 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
4895 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
4897 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
4898 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
4899 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
4901 PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4902 PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4903 PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4904 PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4905 PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4906 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
4907 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
4909 } /* namespace recording */
4911 enum recording::precedence
4912 recording::binary_op::get_precedence () const
4914 return binary_op_precedence[m_op];
4917 /* The implementation of class gcc::jit::recording::comparison. */
4919 /* Implementation of recording::memento::make_debug_string for
4920 comparisons. */
4922 static const char * const comparison_strings[] =
4924 "==", /* GCC_JIT_COMPARISON_EQ */
4925 "!=", /* GCC_JIT_COMPARISON_NE */
4926 "<", /* GCC_JIT_COMPARISON_LT */
4927 "<=", /* GCC_JIT_COMPARISON_LE */
4928 ">", /* GCC_JIT_COMPARISON_GT */
4929 ">=", /* GCC_JIT_COMPARISON_GE */
4932 recording::string *
4933 recording::comparison::make_debug_string ()
4935 enum precedence prec = get_precedence ();
4936 return string::from_printf (m_ctxt,
4937 "%s %s %s",
4938 m_a->get_debug_string_parens (prec),
4939 comparison_strings[m_op],
4940 m_b->get_debug_string_parens (prec));
4943 /* A table of enum gcc_jit_comparison values expressed in string
4944 form. */
4946 static const char * const comparison_reproducer_strings[] =
4948 "GCC_JIT_COMPARISON_EQ",
4949 "GCC_JIT_COMPARISON_NE",
4950 "GCC_JIT_COMPARISON_LT",
4951 "GCC_JIT_COMPARISON_LE",
4952 "GCC_JIT_COMPARISON_GT",
4953 "GCC_JIT_COMPARISON_GE"
4956 /* Implementation of recording::memento::write_reproducer for comparisons. */
4958 void
4959 recording::comparison::write_reproducer (reproducer &r)
4961 const char *id = r.make_identifier (this, "rvalue");
4962 r.write (" gcc_jit_rvalue *%s =\n"
4963 " gcc_jit_context_new_comparison (%s,\n"
4964 " %s, /* gcc_jit_location *loc */\n"
4965 " %s, /* enum gcc_jit_comparison op */\n"
4966 " %s, /* gcc_jit_rvalue *a */\n"
4967 " %s); /* gcc_jit_rvalue *b */\n",
4969 r.get_identifier (get_context ()),
4970 r.get_identifier (m_loc),
4971 comparison_reproducer_strings[m_op],
4972 r.get_identifier_as_rvalue (m_a),
4973 r.get_identifier_as_rvalue (m_b));
4976 /* Implementation of pure virtual hook recording::memento::replay_into
4977 for recording::comparison. */
4979 void
4980 recording::comparison::replay_into (replayer *r)
4982 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
4983 m_op,
4984 m_a->playback_rvalue (),
4985 m_b->playback_rvalue ()));
4988 /* Implementation of pure virtual hook recording::rvalue::visit_children
4989 for recording::comparison. */
4991 void
4992 recording::comparison::visit_children (rvalue_visitor *v)
4994 v->visit (m_a);
4995 v->visit (m_b);
4998 namespace recording {
4999 static const enum precedence comparison_precedence[] =
5001 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
5002 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
5004 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LT */
5005 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
5006 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GT */
5007 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
5009 } /* namespace recording */
5011 enum recording::precedence
5012 recording::comparison::get_precedence () const
5014 return comparison_precedence[m_op];
5017 /* Implementation of pure virtual hook recording::memento::replay_into
5018 for recording::cast. */
5020 void
5021 recording::cast::replay_into (replayer *r)
5023 set_playback_obj (r->new_cast (playback_location (r, m_loc),
5024 m_rvalue->playback_rvalue (),
5025 get_type ()->playback_type ()));
5028 /* Implementation of pure virtual hook recording::rvalue::visit_children
5029 for recording::cast. */
5030 void
5031 recording::cast::visit_children (rvalue_visitor *v)
5033 v->visit (m_rvalue);
5036 /* Implementation of recording::memento::make_debug_string for
5037 casts. */
5039 recording::string *
5040 recording::cast::make_debug_string ()
5042 enum precedence prec = get_precedence ();
5043 return string::from_printf (m_ctxt,
5044 "(%s)%s",
5045 get_type ()->get_debug_string (),
5046 m_rvalue->get_debug_string_parens (prec));
5049 /* Implementation of recording::memento::write_reproducer for casts. */
5051 void
5052 recording::cast::write_reproducer (reproducer &r)
5054 const char *id = r.make_identifier (this, "rvalue");
5055 r.write (" gcc_jit_rvalue *%s =\n"
5056 " gcc_jit_context_new_cast (%s,\n"
5057 " %s, /* gcc_jit_location *loc */\n"
5058 " %s, /* gcc_jit_rvalue *rvalue */\n"
5059 " %s); /* gcc_jit_type *type */\n",
5061 r.get_identifier (get_context ()),
5062 r.get_identifier (m_loc),
5063 r.get_identifier_as_rvalue (m_rvalue),
5064 r.get_identifier_as_type (get_type ()));
5067 /* The implementation of class gcc::jit::recording::base_call. */
5069 /* The constructor for gcc::jit::recording::base_call. */
5071 recording::base_call::base_call (context *ctxt,
5072 location *loc,
5073 type *type_,
5074 int numargs,
5075 rvalue **args)
5076 : rvalue (ctxt, loc, type_),
5077 m_args (),
5078 m_require_tail_call (0)
5080 for (int i = 0; i< numargs; i++)
5081 m_args.safe_push (args[i]);
5084 /* Subroutine for use by call and call_though_ptr's write_reproducer
5085 methods. */
5087 void
5088 recording::base_call::write_reproducer_tail_call (reproducer &r,
5089 const char *id)
5091 if (m_require_tail_call)
5093 r.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
5094 " %i); /* int require_tail_call*/\n",
5100 /* The implementation of class gcc::jit::recording::call. */
5102 /* The constructor for gcc::jit::recording::call. */
5104 recording::call::call (recording::context *ctxt,
5105 recording::location *loc,
5106 recording::function *func,
5107 int numargs,
5108 rvalue **args)
5109 : base_call (ctxt, loc, func->get_return_type (), numargs, args),
5110 m_func (func)
5114 /* Implementation of pure virtual hook recording::memento::replay_into
5115 for recording::call. */
5117 void
5118 recording::call::replay_into (replayer *r)
5120 auto_vec<playback::rvalue *> playback_args;
5121 playback_args.create (m_args.length ());
5122 for (unsigned i = 0; i< m_args.length (); i++)
5123 playback_args.safe_push (m_args[i]->playback_rvalue ());
5125 set_playback_obj (r->new_call (playback_location (r, m_loc),
5126 m_func->playback_function (),
5127 &playback_args,
5128 m_require_tail_call));
5131 /* Implementation of pure virtual hook recording::rvalue::visit_children
5132 for recording::call. */
5134 void
5135 recording::call::visit_children (rvalue_visitor *v)
5137 for (unsigned i = 0; i< m_args.length (); i++)
5138 v->visit (m_args[i]);
5141 /* Implementation of recording::memento::make_debug_string for
5142 function calls. */
5144 recording::string *
5145 recording::call::make_debug_string ()
5147 /* First, build a buffer for the arguments. */
5148 comma_separated_string args (m_args, get_precedence ());
5150 /* ...and use it to get the string for the call as a whole. */
5151 string *result = string::from_printf (m_ctxt,
5152 "%s (%s)",
5153 m_func->get_debug_string (),
5154 args.as_char_ptr ());
5156 return result;
5159 void
5160 recording::call::write_reproducer (reproducer &r)
5162 const char *id = r.make_identifier (this, "call");
5163 const char *args_id = r.make_tmp_identifier ("args_for_", this);
5164 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
5165 args_id,
5166 m_args.length ());
5167 for (unsigned i = 0; i< m_args.length (); i++)
5168 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
5169 r.write (" };\n");
5170 r.write (" gcc_jit_rvalue *%s =\n"
5171 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
5172 " %s, /* gcc_jit_location *loc */\n"
5173 " %s, /* gcc_jit_function *func */\n"
5174 " %i, /* int numargs */ \n"
5175 " %s); /* gcc_jit_rvalue **args*/\n",
5177 r.get_identifier (get_context ()),
5178 r.get_identifier (m_loc),
5179 r.get_identifier (m_func),
5180 m_args.length (),
5181 args_id);
5182 write_reproducer_tail_call (r, id);
5185 /* The implementation of class gcc::jit::recording::call_through_ptr. */
5187 /* The constructor for recording::call_through_ptr. */
5189 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
5190 recording::location *loc,
5191 recording::rvalue *fn_ptr,
5192 int numargs,
5193 rvalue **args)
5194 : base_call (ctxt, loc,
5195 fn_ptr->get_type ()->dereference ()
5196 ->as_a_function_type ()->get_return_type (),
5197 numargs, args),
5198 m_fn_ptr (fn_ptr)
5202 /* Implementation of pure virtual hook recording::memento::replay_into
5203 for recording::call_through_ptr. */
5205 void
5206 recording::call_through_ptr::replay_into (replayer *r)
5208 auto_vec<playback::rvalue *> playback_args;
5209 playback_args.create (m_args.length ());
5210 for (unsigned i = 0; i< m_args.length (); i++)
5211 playback_args.safe_push (m_args[i]->playback_rvalue ());
5213 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
5214 m_fn_ptr->playback_rvalue (),
5215 &playback_args,
5216 m_require_tail_call));
5219 /* Implementation of pure virtual hook recording::rvalue::visit_children
5220 for recording::call_through_ptr. */
5222 void
5223 recording::call_through_ptr::visit_children (rvalue_visitor *v)
5225 v->visit (m_fn_ptr);
5226 for (unsigned i = 0; i< m_args.length (); i++)
5227 v->visit (m_args[i]);
5230 /* Implementation of recording::memento::make_debug_string for
5231 calls through function ptrs. */
5233 recording::string *
5234 recording::call_through_ptr::make_debug_string ()
5236 enum precedence prec = get_precedence ();
5237 /* First, build a buffer for the arguments. */
5238 /* Calculate length of said buffer. */
5239 size_t sz = 1; /* nil terminator */
5240 for (unsigned i = 0; i< m_args.length (); i++)
5242 sz += strlen (m_args[i]->get_debug_string_parens (prec));
5243 sz += 2; /* ", " separator */
5246 /* Now allocate and populate the buffer. */
5247 char *argbuf = new char[sz];
5248 size_t len = 0;
5250 for (unsigned i = 0; i< m_args.length (); i++)
5252 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
5253 len += strlen (m_args[i]->get_debug_string_parens (prec));
5254 if (i + 1 < m_args.length ())
5256 strcpy (argbuf + len, ", ");
5257 len += 2;
5260 argbuf[len] = '\0';
5262 /* ...and use it to get the string for the call as a whole. */
5263 string *result = string::from_printf (m_ctxt,
5264 "%s (%s)",
5265 m_fn_ptr->get_debug_string_parens (prec),
5266 argbuf);
5268 delete[] argbuf;
5270 return result;
5273 /* Implementation of recording::memento::write_reproducer for
5274 call_through_ptr. */
5276 void
5277 recording::call_through_ptr::write_reproducer (reproducer &r)
5279 const char *id = r.make_identifier (this, "call");
5280 const char *args_id = r.make_tmp_identifier ("args_for_", this);
5281 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
5282 args_id,
5283 m_args.length ());
5284 for (unsigned i = 0; i< m_args.length (); i++)
5285 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
5286 r.write (" };\n");
5287 r.write (" gcc_jit_rvalue *%s =\n"
5288 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
5289 " %s, /* gcc_jit_location *loc */\n"
5290 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
5291 " %i, /* int numargs */ \n"
5292 " %s); /* gcc_jit_rvalue **args*/\n",
5294 r.get_identifier (get_context ()),
5295 r.get_identifier (m_loc),
5296 r.get_identifier_as_rvalue (m_fn_ptr),
5297 m_args.length (),
5298 args_id);
5299 write_reproducer_tail_call (r, id);
5302 /* The implementation of class gcc::jit::recording::array_access. */
5304 /* Implementation of pure virtual hook recording::memento::replay_into
5305 for recording::array_access. */
5307 void
5308 recording::array_access::replay_into (replayer *r)
5310 set_playback_obj (
5311 r->new_array_access (playback_location (r, m_loc),
5312 m_ptr->playback_rvalue (),
5313 m_index->playback_rvalue ()));
5316 /* Implementation of pure virtual hook recording::rvalue::visit_children
5317 for recording::array_access. */
5319 void
5320 recording::array_access::visit_children (rvalue_visitor *v)
5322 v->visit (m_ptr);
5323 v->visit (m_index);
5326 /* Implementation of recording::memento::make_debug_string for
5327 array accesses. */
5329 recording::string *
5330 recording::array_access::make_debug_string ()
5332 enum precedence prec = get_precedence ();
5333 return string::from_printf (m_ctxt,
5334 "%s[%s]",
5335 m_ptr->get_debug_string_parens (prec),
5336 m_index->get_debug_string_parens (prec));
5339 /* Implementation of recording::memento::write_reproducer for
5340 array_access. */
5342 void
5343 recording::array_access::write_reproducer (reproducer &r)
5345 const char *id = r.make_identifier (this, "lvalue");
5346 r.write (" gcc_jit_lvalue *%s = \n"
5347 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
5348 " %s, /*gcc_jit_location *loc */\n"
5349 " %s, /* gcc_jit_rvalue *ptr */\n"
5350 " %s); /* gcc_jit_rvalue *index */\n",
5352 r.get_identifier (get_context ()),
5353 r.get_identifier (m_loc),
5354 r.get_identifier_as_rvalue (m_ptr),
5355 r.get_identifier_as_rvalue (m_index));
5358 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
5360 /* Implementation of pure virtual hook recording::memento::replay_into
5361 for recording::access_field_of_lvalue. */
5363 void
5364 recording::access_field_of_lvalue::replay_into (replayer *r)
5366 set_playback_obj (
5367 m_lvalue->playback_lvalue ()
5368 ->access_field (playback_location (r, m_loc),
5369 m_field->playback_field ()));
5373 /* Implementation of pure virtual hook recording::rvalue::visit_children
5374 for recording::access_field_of_lvalue. */
5376 void
5377 recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
5379 v->visit (m_lvalue);
5382 /* Implementation of recording::memento::make_debug_string for
5383 accessing a field of an lvalue. */
5385 recording::string *
5386 recording::access_field_of_lvalue::make_debug_string ()
5388 enum precedence prec = get_precedence ();
5389 return string::from_printf (m_ctxt,
5390 "%s.%s",
5391 m_lvalue->get_debug_string_parens (prec),
5392 m_field->get_debug_string ());
5395 /* Implementation of recording::memento::write_reproducer for
5396 access_field_of_lvalue. */
5398 void
5399 recording::access_field_of_lvalue::write_reproducer (reproducer &r)
5401 const char *id = r.make_identifier (this, "lvalue");
5402 r.write (" gcc_jit_lvalue *%s = \n"
5403 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5404 " %s, /*gcc_jit_location *loc */\n"
5405 " %s);\n",
5407 r.get_identifier_as_lvalue (m_lvalue),
5408 r.get_identifier (m_loc),
5409 r.get_identifier (m_field));
5412 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
5414 /* Implementation of pure virtual hook recording::memento::replay_into
5415 for recording::access_field_rvalue. */
5417 void
5418 recording::access_field_rvalue::replay_into (replayer *r)
5420 set_playback_obj (
5421 m_rvalue->playback_rvalue ()
5422 ->access_field (playback_location (r, m_loc),
5423 m_field->playback_field ()));
5426 /* Implementation of pure virtual hook recording::rvalue::visit_children
5427 for recording::access_field_rvalue. */
5429 void
5430 recording::access_field_rvalue::visit_children (rvalue_visitor *v)
5432 v->visit (m_rvalue);
5435 /* Implementation of recording::memento::make_debug_string for
5436 accessing a field of an rvalue. */
5438 recording::string *
5439 recording::access_field_rvalue::make_debug_string ()
5441 enum precedence prec = get_precedence ();
5442 return string::from_printf (m_ctxt,
5443 "%s.%s",
5444 m_rvalue->get_debug_string_parens (prec),
5445 m_field->get_debug_string ());
5448 /* Implementation of recording::memento::write_reproducer for
5449 access_field_rvalue. */
5451 void
5452 recording::access_field_rvalue::write_reproducer (reproducer &r)
5454 const char *id = r.make_identifier (this, "rvalue");
5455 r.write (" gcc_jit_rvalue *%s = \n"
5456 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5457 " %s, /*gcc_jit_location *loc */\n"
5458 " %s);\n",
5460 r.get_identifier_as_rvalue (m_rvalue),
5461 r.get_identifier (m_loc),
5462 r.get_identifier (m_field));
5465 /* The implementation of class
5466 gcc::jit::recording::dereference_field_rvalue. */
5468 /* Implementation of pure virtual hook recording::memento::replay_into
5469 for recording::dereference_field_rvalue. */
5471 void
5472 recording::dereference_field_rvalue::replay_into (replayer *r)
5474 set_playback_obj (
5475 m_rvalue->playback_rvalue ()->
5476 dereference_field (playback_location (r, m_loc),
5477 m_field->playback_field ()));
5480 /* Implementation of pure virtual hook recording::rvalue::visit_children
5481 for recording::dereference_field_rvalue. */
5483 void
5484 recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
5486 v->visit (m_rvalue);
5489 /* Implementation of recording::memento::make_debug_string for
5490 dereferencing a field of an rvalue. */
5492 recording::string *
5493 recording::dereference_field_rvalue::make_debug_string ()
5495 enum precedence prec = get_precedence ();
5496 return string::from_printf (m_ctxt,
5497 "%s->%s",
5498 m_rvalue->get_debug_string_parens (prec),
5499 m_field->get_debug_string ());
5502 /* Implementation of recording::memento::write_reproducer for
5503 dereference_field_rvalue. */
5505 void
5506 recording::dereference_field_rvalue::write_reproducer (reproducer &r)
5508 const char *id = r.make_identifier (this, "lvalue");
5509 r.write (" gcc_jit_lvalue *%s=\n"
5510 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5511 " %s, /* gcc_jit_location *loc */\n"
5512 " %s); /* gcc_jit_field *field */\n",
5514 r.get_identifier_as_rvalue (m_rvalue),
5515 r.get_identifier (m_loc),
5516 r.get_identifier (m_field));
5519 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5521 /* Implementation of pure virtual hook recording::memento::replay_into
5522 for recording::dereference_rvalue. */
5524 void
5525 recording::dereference_rvalue::replay_into (replayer *r)
5527 set_playback_obj (
5528 m_rvalue->playback_rvalue ()->
5529 dereference (playback_location (r, m_loc)));
5532 /* Implementation of pure virtual hook recording::rvalue::visit_children
5533 for recording::dereference_rvalue. */
5535 void
5536 recording::dereference_rvalue::visit_children (rvalue_visitor *v)
5538 v->visit (m_rvalue);
5541 /* Implementation of recording::memento::make_debug_string for
5542 dereferencing an rvalue. */
5544 recording::string *
5545 recording::dereference_rvalue::make_debug_string ()
5547 enum precedence prec = get_precedence ();
5548 return string::from_printf (m_ctxt,
5549 "*%s",
5550 m_rvalue->get_debug_string_parens (prec));
5553 /* Implementation of recording::memento::write_reproducer for
5554 dereference_rvalue. */
5556 void
5557 recording::dereference_rvalue::write_reproducer (reproducer &r)
5559 const char *id = r.make_identifier (this, "dereference");
5560 r.write (" gcc_jit_lvalue *%s =\n"
5561 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5562 " %s); /* gcc_jit_location *loc */\n",
5564 r.get_identifier_as_rvalue (m_rvalue),
5565 r.get_identifier (m_loc));
5568 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5570 /* Implementation of pure virtual hook recording::memento::replay_into
5571 for recording::get_address_of_lvalue. */
5573 void
5574 recording::get_address_of_lvalue::replay_into (replayer *r)
5576 set_playback_obj (
5577 m_lvalue->playback_lvalue ()->
5578 get_address (playback_location (r, m_loc)));
5581 /* Implementation of pure virtual hook recording::rvalue::visit_children
5582 for recording::get_address_of_lvalue. */
5584 void
5585 recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
5587 v->visit (m_lvalue);
5590 /* Implementation of recording::memento::make_debug_string for
5591 getting the address of an lvalue. */
5593 recording::string *
5594 recording::get_address_of_lvalue::make_debug_string ()
5596 enum precedence prec = get_precedence ();
5597 return string::from_printf (m_ctxt,
5598 "&%s",
5599 m_lvalue->get_debug_string_parens (prec));
5602 /* Implementation of recording::memento::write_reproducer for
5603 get_address_of_lvalue. */
5605 void
5606 recording::get_address_of_lvalue::write_reproducer (reproducer &r)
5608 const char *id = r.make_identifier (this, "address_of");
5609 r.write (" gcc_jit_rvalue *%s =\n"
5610 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5611 " %s); /* gcc_jit_location *loc */\n",
5613 r.get_identifier_as_lvalue (m_lvalue),
5614 r.get_identifier (m_loc));
5617 /* The implementation of class gcc::jit::recording::function_pointer. */
5619 /* Implementation of pure virtual hook recording::memento::replay_into
5620 for recording::function_pointer. */
5622 void
5623 recording::function_pointer::replay_into (replayer *r)
5625 set_playback_obj (
5626 m_fn->playback_function ()->
5627 get_address (playback_location (r, m_loc)));
5630 void
5631 recording::function_pointer::visit_children (rvalue_visitor *)
5633 /* Empty. */
5636 /* Implementation of recording::memento::make_debug_string for
5637 getting the address of an lvalue. */
5639 recording::string *
5640 recording::function_pointer::make_debug_string ()
5642 return string::from_printf (m_ctxt,
5643 "%s",
5644 m_fn->get_debug_string ());
5647 /* Implementation of recording::memento::write_reproducer for
5648 function_pointer. */
5650 void
5651 recording::function_pointer::write_reproducer (reproducer &r)
5653 const char *id = r.make_identifier (this, "address_of");
5654 r.write (" gcc_jit_rvalue *%s =\n"
5655 " gcc_jit_function_get_address (%s, /* gcc_jit_function *fn */\n"
5656 " %s); /* gcc_jit_location *loc */\n",
5658 r.get_identifier (m_fn),
5659 r.get_identifier (m_loc));
5662 /* The implementation of class gcc::jit::recording::local. */
5664 /* Implementation of pure virtual hook recording::memento::replay_into
5665 for recording::local. */
5667 void
5668 recording::local::replay_into (replayer *r)
5670 set_playback_obj (
5671 m_func->playback_function ()
5672 ->new_local (playback_location (r, m_loc),
5673 m_type->playback_type (),
5674 playback_string (m_name)));
5677 /* Override the default implementation of
5678 recording::memento::write_to_dump for locals by writing
5679 TYPE NAME;
5680 for use at the top of the function body as if it were a
5681 declaration. */
5683 void
5684 recording::local::write_to_dump (dump &d)
5686 if (d.update_locations ())
5687 m_loc = d.make_location ();
5688 d.write(" %s %s;\n",
5689 m_type->get_debug_string (),
5690 get_debug_string ());
5693 void
5694 recording::local::write_reproducer (reproducer &r)
5696 const char *id = r.make_identifier (this, "local");
5697 r.write (" gcc_jit_lvalue *%s =\n"
5698 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5699 " %s, /* gcc_jit_location *loc */\n"
5700 " %s, /* gcc_jit_type *type */\n"
5701 " %s); /* const char *name */\n",
5703 r.get_identifier (m_func),
5704 r.get_identifier (m_loc),
5705 r.get_identifier_as_type (m_type),
5706 m_name->get_debug_string ());
5709 /* The implementation of class gcc::jit::recording::statement. */
5711 /* We poison the default implementation of
5712 gcc::jit::recording::statement::get_successor_blocks
5713 since this vfunc must only ever be called on terminator
5714 statements. */
5716 vec <recording::block *>
5717 recording::statement::get_successor_blocks () const
5719 /* The base class implementation is for non-terminating statements,
5720 and thus should never be called. */
5721 gcc_unreachable ();
5722 vec <block *> result;
5723 result.create (0);
5724 return result;
5727 /* Extend the default implementation of
5728 recording::memento::write_to_dump for statements by (if requested)
5729 updating the location of the statement to the current location in
5730 the dumpfile. */
5732 void
5733 recording::statement::write_to_dump (dump &d)
5735 memento::write_to_dump (d);
5736 if (d.update_locations ())
5737 m_loc = d.make_location ();
5740 /* The implementation of class gcc::jit::recording::eval. */
5742 /* Implementation of pure virtual hook recording::memento::replay_into
5743 for recording::eval. */
5745 void
5746 recording::eval::replay_into (replayer *r)
5748 playback_block (get_block ())
5749 ->add_eval (playback_location (r),
5750 m_rvalue->playback_rvalue ());
5753 /* Implementation of recording::memento::make_debug_string for
5754 an eval statement. */
5756 recording::string *
5757 recording::eval::make_debug_string ()
5759 return string::from_printf (m_ctxt,
5760 "(void)%s;",
5761 m_rvalue->get_debug_string ());
5764 /* Implementation of recording::memento::write_reproducer for
5765 eval statements. */
5767 void
5768 recording::eval::write_reproducer (reproducer &r)
5770 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5771 " %s, /* gcc_jit_location *loc */\n"
5772 " %s); /* gcc_jit_rvalue *rvalue */\n",
5773 r.get_identifier (get_block ()),
5774 r.get_identifier (get_loc ()),
5775 r.get_identifier_as_rvalue (m_rvalue));
5778 /* The implementation of class gcc::jit::recording::assignment. */
5780 /* Implementation of pure virtual hook recording::memento::replay_into
5781 for recording::assignment. */
5783 void
5784 recording::assignment::replay_into (replayer *r)
5786 playback_block (get_block ())
5787 ->add_assignment (playback_location (r),
5788 m_lvalue->playback_lvalue (),
5789 m_rvalue->playback_rvalue ());
5792 /* Implementation of recording::memento::make_debug_string for
5793 an assignment statement. */
5795 recording::string *
5796 recording::assignment::make_debug_string ()
5798 return string::from_printf (m_ctxt,
5799 "%s = %s;",
5800 m_lvalue->get_debug_string (),
5801 m_rvalue->get_debug_string ());
5804 /* Implementation of recording::memento::write_reproducer for
5805 assignment statements. */
5807 void
5808 recording::assignment::write_reproducer (reproducer &r)
5810 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5811 " %s, /* gcc_jit_location *loc */\n"
5812 " %s, /* gcc_jit_lvalue *lvalue */\n"
5813 " %s); /* gcc_jit_rvalue *rvalue */\n",
5814 r.get_identifier (get_block ()),
5815 r.get_identifier (get_loc ()),
5816 r.get_identifier_as_lvalue (m_lvalue),
5817 r.get_identifier_as_rvalue (m_rvalue));
5820 /* The implementation of class gcc::jit::recording::assignment_op. */
5822 /* Implementation of pure virtual hook recording::memento::replay_into
5823 for recording::assignment_op. */
5825 void
5826 recording::assignment_op::replay_into (replayer *r)
5828 playback::type *result_type =
5829 m_lvalue->playback_lvalue ()->get_type ();
5831 playback::rvalue *binary_op =
5832 r->new_binary_op (playback_location (r),
5833 m_op,
5834 result_type,
5835 m_lvalue->playback_rvalue (),
5836 m_rvalue->playback_rvalue ());
5838 playback_block (get_block ())
5839 ->add_assignment (playback_location (r),
5840 m_lvalue->playback_lvalue (),
5841 binary_op);
5844 /* Implementation of recording::memento::make_debug_string for
5845 an assignment_op statement. */
5847 recording::string *
5848 recording::assignment_op::make_debug_string ()
5850 return string::from_printf (m_ctxt,
5851 "%s %s= %s;",
5852 m_lvalue->get_debug_string (),
5853 binary_op_strings[m_op],
5854 m_rvalue->get_debug_string ());
5857 /* Implementation of recording::memento::write_reproducer for
5858 assignment_op statements. */
5860 void
5861 recording::assignment_op::write_reproducer (reproducer &r)
5863 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5864 " %s, /* gcc_jit_location *loc */\n"
5865 " %s, /* gcc_jit_lvalue *lvalue */\n"
5866 " %s, /* enum gcc_jit_binary_op op */\n"
5867 " %s); /* gcc_jit_rvalue *rvalue */\n",
5868 r.get_identifier (get_block ()),
5869 r.get_identifier (get_loc ()),
5870 r.get_identifier_as_lvalue (m_lvalue),
5871 binary_op_reproducer_strings[m_op],
5872 r.get_identifier_as_rvalue (m_rvalue));
5875 /* The implementation of class gcc::jit::recording::comment. */
5877 /* Implementation of pure virtual hook recording::memento::replay_into
5878 for recording::comment. */
5880 void
5881 recording::comment::replay_into (replayer *r)
5883 playback_block (get_block ())
5884 ->add_comment (playback_location (r),
5885 m_text->c_str ());
5888 /* Implementation of recording::memento::make_debug_string for
5889 a comment "statement". */
5891 recording::string *
5892 recording::comment::make_debug_string ()
5894 return string::from_printf (m_ctxt,
5895 "/* %s */",
5896 m_text->c_str ());
5899 /* Implementation of recording::memento::write_reproducer for
5900 comments. */
5902 void
5903 recording::comment::write_reproducer (reproducer &r)
5905 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5906 " %s, /* gcc_jit_location *loc */\n"
5907 " %s); /* const char *text */\n",
5908 r.get_identifier (get_block ()),
5909 r.get_identifier (get_loc ()),
5910 m_text->get_debug_string ());
5913 /* The implementation of class gcc::jit::recording::conditional. */
5915 /* Implementation of pure virtual hook recording::memento::replay_into
5916 for recording::conditional. */
5918 void
5919 recording::conditional::replay_into (replayer *r)
5921 playback_block (get_block ())
5922 ->add_conditional (playback_location (r),
5923 m_boolval->playback_rvalue (),
5924 playback_block (m_on_true),
5925 playback_block (m_on_false));
5928 /* Override the poisoned default implementation of
5929 gcc::jit::recording::statement::get_successor_blocks
5931 A conditional jump has 2 successor blocks. */
5933 vec <recording::block *>
5934 recording::conditional::get_successor_blocks () const
5936 vec <block *> result;
5937 result.create (2);
5938 result.quick_push (m_on_true);
5939 result.quick_push (m_on_false);
5940 return result;
5943 /* Implementation of recording::memento::make_debug_string for
5944 a conditional jump statement. */
5946 recording::string *
5947 recording::conditional::make_debug_string ()
5949 if (m_on_false)
5950 return string::from_printf (m_ctxt,
5951 "if (%s) goto %s; else goto %s;",
5952 m_boolval->get_debug_string (),
5953 m_on_true->get_debug_string (),
5954 m_on_false->get_debug_string ());
5955 else
5956 return string::from_printf (m_ctxt,
5957 "if (%s) goto %s;",
5958 m_boolval->get_debug_string (),
5959 m_on_true->get_debug_string ());
5962 /* Implementation of recording::memento::write_reproducer for
5963 conditional statements. */
5965 void
5966 recording::conditional::write_reproducer (reproducer &r)
5968 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5969 " %s, /* gcc_jit_location *loc */\n"
5970 " %s, /* gcc_jit_rvalue *boolval */\n"
5971 " %s, /* gcc_jit_block *on_true */\n"
5972 " %s); /* gcc_jit_block *on_false */\n",
5973 r.get_identifier (get_block ()),
5974 r.get_identifier (get_loc ()),
5975 r.get_identifier_as_rvalue (m_boolval),
5976 r.get_identifier (m_on_true),
5977 r.get_identifier (m_on_false));
5980 /* The implementation of class gcc::jit::recording::jump. */
5982 /* Implementation of pure virtual hook recording::memento::replay_into
5983 for recording::jump. */
5985 void
5986 recording::jump::replay_into (replayer *r)
5988 playback_block (get_block ())
5989 ->add_jump (playback_location (r),
5990 m_target->playback_block ());
5993 /* Override the poisoned default implementation of
5994 gcc::jit::recording::statement::get_successor_blocks
5996 An unconditional jump has 1 successor block. */
5998 vec <recording::block *>
5999 recording::jump::get_successor_blocks () const
6001 vec <block *> result;
6002 result.create (1);
6003 result.quick_push (m_target);
6004 return result;
6007 /* Implementation of recording::memento::make_debug_string for
6008 a unconditional jump statement. */
6010 recording::string *
6011 recording::jump::make_debug_string ()
6013 return string::from_printf (m_ctxt,
6014 "goto %s;",
6015 m_target->get_debug_string ());
6018 /* Implementation of recording::memento::write_reproducer for
6019 jump statements. */
6021 void
6022 recording::jump::write_reproducer (reproducer &r)
6024 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
6025 " %s, /* gcc_jit_location *loc */\n"
6026 " %s); /* gcc_jit_block *target */\n",
6027 r.get_identifier (get_block ()),
6028 r.get_identifier (get_loc ()),
6029 r.get_identifier (m_target));
6032 /* The implementation of class gcc::jit::recording::return_. */
6034 /* Implementation of pure virtual hook recording::memento::replay_into
6035 for recording::return_. */
6037 void
6038 recording::return_::replay_into (replayer *r)
6040 playback_block (get_block ())
6041 ->add_return (playback_location (r),
6042 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
6045 /* Override the poisoned default implementation of
6046 gcc::jit::recording::statement::get_successor_blocks
6048 A return statement has no successor block. */
6050 vec <recording::block *>
6051 recording::return_::get_successor_blocks () const
6053 vec <block *> result;
6054 result.create (0);
6055 return result;
6058 /* Implementation of recording::memento::make_debug_string for
6059 a return statement (covers both those with and without rvalues). */
6061 recording::string *
6062 recording::return_::make_debug_string ()
6064 if (m_rvalue)
6065 return string::from_printf (m_ctxt,
6066 "return %s;",
6067 m_rvalue->get_debug_string ());
6068 else
6069 return string::from_printf (m_ctxt,
6070 "return;");
6073 /* Implementation of recording::memento::write_reproducer for
6074 return statements. */
6076 void
6077 recording::return_::write_reproducer (reproducer &r)
6079 if (m_rvalue)
6080 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
6081 " %s, /* gcc_jit_location *loc */\n"
6082 " %s); /* gcc_jit_rvalue *rvalue */\n",
6083 r.get_identifier (get_block ()),
6084 r.get_identifier (get_loc ()),
6085 r.get_identifier_as_rvalue (m_rvalue));
6086 else
6087 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
6088 " %s); /* gcc_jit_location *loc */\n",
6089 r.get_identifier (get_block ()),
6090 r.get_identifier (get_loc ()));
6093 /* The implementation of class gcc::jit::recording::case_. */
6095 void
6096 recording::case_::write_reproducer (reproducer &r)
6098 const char *id = r.make_identifier (this, "case");
6099 const char *fmt =
6100 " gcc_jit_case *%s = \n"
6101 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
6102 " %s, /* gcc_jit_rvalue *min_value */\n"
6103 " %s, /* gcc_jit_rvalue *max_value */\n"
6104 " %s); /* gcc_jit_block *dest_block */\n";
6105 r.write (fmt,
6107 r.get_identifier (get_context ()),
6108 r.get_identifier_as_rvalue (m_min_value),
6109 r.get_identifier_as_rvalue (m_max_value),
6110 r.get_identifier (m_dest_block));
6113 recording::string *
6114 recording::case_::make_debug_string ()
6116 return string::from_printf (get_context (),
6117 "case %s ... %s: goto %s;",
6118 m_min_value->get_debug_string (),
6119 m_max_value->get_debug_string (),
6120 m_dest_block->get_debug_string ());
6123 /* The implementation of class gcc::jit::recording::switch_. */
6125 /* gcc::jit::recording::switch_'s constructor. */
6127 recording::switch_::switch_ (block *b,
6128 location *loc,
6129 rvalue *expr,
6130 block *default_block,
6131 int num_cases,
6132 case_ **cases)
6133 : statement (b, loc),
6134 m_expr (expr),
6135 m_default_block (default_block)
6137 m_cases.reserve_exact (num_cases);
6138 for (int i = 0; i< num_cases; i++)
6139 m_cases.quick_push (cases[i]);
6142 /* Implementation of pure virtual hook recording::memento::replay_into
6143 for recording::switch_. */
6145 void
6146 recording::switch_::replay_into (replayer *r)
6148 auto_vec <playback::case_> pcases;
6149 int i;
6150 recording::case_ *rcase;
6151 pcases.reserve_exact (m_cases.length ());
6152 FOR_EACH_VEC_ELT (m_cases, i, rcase)
6154 playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (),
6155 rcase->get_max_value ()->playback_rvalue (),
6156 rcase->get_dest_block ()->playback_block ());
6157 pcases.safe_push (pcase);
6159 playback_block (get_block ())
6160 ->add_switch (playback_location (r),
6161 m_expr->playback_rvalue (),
6162 m_default_block->playback_block (),
6163 &pcases);
6166 /* Override the poisoned default implementation of
6167 gcc::jit::recording::statement::get_successor_blocks
6169 A switch statement has (NUM_CASES + 1) successor blocks. */
6171 vec <recording::block *>
6172 recording::switch_::get_successor_blocks () const
6174 vec <block *> result;
6175 result.create (m_cases.length () + 1);
6176 result.quick_push (m_default_block);
6177 int i;
6178 case_ *c;
6179 FOR_EACH_VEC_ELT (m_cases, i, c)
6180 result.quick_push (c->get_dest_block ());
6181 return result;
6184 /* Implementation of recording::memento::make_debug_string for
6185 a switch statement. */
6187 recording::string *
6188 recording::switch_::make_debug_string ()
6190 auto_vec <char> cases_str;
6191 int i;
6192 case_ *c;
6193 FOR_EACH_VEC_ELT (m_cases, i, c)
6195 size_t len = strlen (c->get_debug_string ());
6196 unsigned idx = cases_str.length ();
6197 cases_str.safe_grow (idx + 1 + len);
6198 cases_str[idx] = ' ';
6199 memcpy (&(cases_str[idx + 1]),
6200 c->get_debug_string (),
6201 len);
6203 cases_str.safe_push ('\0');
6205 return string::from_printf (m_ctxt,
6206 "switch (%s) {default: goto %s;%s}",
6207 m_expr->get_debug_string (),
6208 m_default_block->get_debug_string (),
6209 &cases_str[0]);
6212 /* Implementation of recording::memento::write_reproducer for
6213 switch statements. */
6215 void
6216 recording::switch_::write_reproducer (reproducer &r)
6218 r.make_identifier (this, "switch");
6219 int i;
6220 case_ *c;
6221 const char *cases_id =
6222 r.make_tmp_identifier ("cases_for", this);
6223 r.write (" gcc_jit_case *%s[%i] = {\n",
6224 cases_id,
6225 m_cases.length ());
6226 FOR_EACH_VEC_ELT (m_cases, i, c)
6227 r.write (" %s,\n", r.get_identifier (c));
6228 r.write (" };\n");
6229 const char *fmt =
6230 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
6231 " %s, /* gcc_jit_location *loc */\n"
6232 " %s, /* gcc_jit_rvalue *expr */\n"
6233 " %s, /* gcc_jit_block *default_block */\n"
6234 " %i, /* int num_cases */\n"
6235 " %s); /* gcc_jit_case **cases */\n";
6236 r.write (fmt,
6237 r.get_identifier (get_block ()),
6238 r.get_identifier (get_loc ()),
6239 r.get_identifier_as_rvalue (m_expr),
6240 r.get_identifier (m_default_block),
6241 m_cases.length (),
6242 cases_id);
6245 } // namespace gcc::jit
6247 } // namespace gcc