2015-01-30 Gary Dismukes <dismukes@adacore.com>
[official-gcc.git] / gcc / jit / jit-recording.c
blob9f6e5fdeef8f6ec838d10639631077a12aaa24a6
1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2015 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 "hash-map.h"
27 #include "toplev.h"
29 #include <pthread.h>
31 #include "jit-common.h"
32 #include "jit-builtins.h"
33 #include "jit-logging.h"
34 #include "jit-recording.h"
35 #include "jit-playback.h"
37 namespace gcc {
38 namespace jit {
40 // class dump
42 dump::dump (recording::context &ctxt,
43 const char *filename,
44 bool update_locations)
45 : m_ctxt (ctxt),
46 m_filename (filename),
47 m_update_locations (update_locations),
48 m_line (0),
49 m_column (0)
51 m_file = fopen (filename, "w");
52 if (!m_file)
53 ctxt.add_error (NULL,
54 "error opening dump file %s for writing: %s",
55 filename,
56 xstrerror (errno));
59 dump::~dump ()
61 if (m_file)
63 int err = fclose (m_file);
64 if (err)
65 m_ctxt.add_error (NULL,
66 "error closing dump file %s: %s",
67 m_filename,
68 xstrerror (errno));
72 /* Write the given message to the dump, using printf-formatting
73 conventions, updating the line/column within the dump.
75 Emit an error on the context if a failure occurs. */
77 void
78 dump::write (const char *fmt, ...)
80 va_list ap;
81 char *buf = NULL;
83 /* If there was an error opening the file, we've already reported it.
84 Don't attempt further work. */
85 if (!m_file)
86 return;
88 va_start (ap, fmt);
89 vasprintf (&buf, fmt, ap);
90 va_end (ap);
92 if (!buf)
94 m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
95 m_filename);
96 return;
99 if (fwrite (buf, strlen (buf), 1, m_file) != 1)
100 m_ctxt.add_error (NULL, "error writing to dump file %s",
101 m_filename);
103 /* Flush after each line, to ease debugging crashes. */
104 fflush (m_file);
106 /* Update line/column: */
107 for (const char *ptr = buf; *ptr; ptr++)
109 if ('\n' == *ptr)
111 m_line++;
112 m_column = 0;
114 else
115 m_column++;
118 free (buf);
121 /* Construct a gcc::jit::recording::location instance for the current
122 location within the dump. */
124 recording::location *
125 dump::make_location () const
127 return m_ctxt.new_location (m_filename, m_line, m_column,
128 /* We need to flag such locations as *not*
129 created by the user, so that
130 reproducer::get_identifier can cope with
131 them appearing *after* the memento that
132 refers to them. */
133 false);
136 /* A collection of allocations, all of which can be released together, to
137 avoid needing to track and release them individually. */
139 class allocator
141 public:
142 ~allocator ();
144 char *
145 xstrdup_printf (const char *, ...)
146 ATTRIBUTE_RETURNS_NONNULL
147 GNU_PRINTF(2, 3);
149 char *
150 xstrdup_printf_va (const char *, va_list ap)
151 ATTRIBUTE_RETURNS_NONNULL
152 GNU_PRINTF(2, 0);
154 private:
155 auto_vec <void *> m_buffers;
158 /* allocator's destructor. Call "free" on all of the allocations. */
160 allocator::~allocator ()
162 unsigned i;
163 void *buffer;
164 FOR_EACH_VEC_ELT (m_buffers, i, buffer)
165 free (buffer);
168 /* Formatted printing, allocating to a buffer (or exiting the process if
169 the allocation fails).
171 The buffer exists until the allocator is cleaned up, and is freed at
172 that point, so the caller doesn't need to track the result. */
174 char *
175 allocator::xstrdup_printf (const char *fmt, ...)
177 char *result;
178 va_list ap;
179 va_start (ap, fmt);
180 result = xstrdup_printf_va (fmt, ap);
181 va_end (ap);
182 return result;
185 /* Formatted printing, allocating to a buffer (or exiting the process if
186 the allocation fails).
188 The buffer exists until the allocator is cleaned up, and is freed at
189 that point, so the caller doesn't need to track the result. */
191 char *
192 allocator::xstrdup_printf_va (const char *fmt, va_list ap)
194 char *result = xvasprintf (fmt, ap);
195 m_buffers.safe_push (result);
196 return result;
199 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
200 implementing gcc_jit_context_dump_reproducer_to_file. */
202 class reproducer : public dump
204 public:
205 reproducer (recording::context &ctxt,
206 const char *filename);
208 void
209 write_params (const vec <recording::context *> &contexts);
211 void
212 write_args (const vec <recording::context *> &contexts);
214 const char *
215 make_identifier (recording::memento *m, const char *prefix);
217 const char *
218 make_tmp_identifier (const char *prefix, recording::memento *m);
220 const char *
221 get_identifier (recording::context *ctxt);
223 const char *
224 get_identifier (recording::memento *m);
226 const char *
227 get_identifier_as_rvalue (recording::rvalue *m);
229 const char *
230 get_identifier_as_lvalue (recording::lvalue *m);
232 const char *
233 get_identifier_as_type (recording::type *m);
235 char *
236 xstrdup_printf (const char *, ...)
237 ATTRIBUTE_RETURNS_NONNULL
238 GNU_PRINTF(2, 3);
240 private:
241 hash_map<recording::memento *, const char *> m_identifiers;
242 allocator m_allocator;
245 /* gcc::jit::reproducer's constructor. */
247 reproducer::reproducer (recording::context &ctxt,
248 const char *filename) :
249 dump (ctxt, filename, 0),
250 m_identifiers (),
251 m_allocator ()
255 /* Write out a list of contexts as a set of parameters within a
256 C function declaration. */
258 void
259 reproducer::write_params (const vec <recording::context *> &contexts)
261 unsigned i;
262 recording::context *ctxt;
263 FOR_EACH_VEC_ELT (contexts, i, ctxt)
265 write ("gcc_jit_context *%s",
266 get_identifier (ctxt));
267 if (i < contexts.length () - 1)
268 write (",\n"
269 " ");
273 /* Write out a list of contexts as a set of arguments within a call
274 to a C function. */
276 void
277 reproducer::write_args (const vec <recording::context *> &contexts)
279 unsigned i;
280 recording::context *ctxt;
281 FOR_EACH_VEC_ELT (contexts, i, ctxt)
283 write ("%s",
284 get_identifier (ctxt));
285 if (i < contexts.length () - 1)
286 write (",\n"
287 " ");
291 /* Generate a C identifier for the given memento, associating the generated
292 buffer with the memento (for future calls to get_identifier et al).
294 The reproducer will eventually clean up the buffer in its dtor. */
295 const char *
296 reproducer::make_identifier (recording::memento *m, const char *prefix)
298 char *result;
299 if (strlen (m->get_debug_string ()) < 100)
301 result = m_allocator.xstrdup_printf ("%s_%s_%p",
302 prefix,
303 m->get_debug_string (),
304 (void *) m);
305 for (char *p = result; *p; p++)
306 if (!ISALNUM (*p))
307 *p = '_';
309 else
310 result = m_allocator.xstrdup_printf ("%s_%p",
311 prefix, (void *) m);
312 m_identifiers.put (m, result);
313 return result;
316 /* Generate a C identifier for a temporary variable.
317 The reproducer will eventually clean up the buffer in its dtor. */
319 const char *
320 reproducer::make_tmp_identifier (const char *prefix, recording::memento *m)
322 return m_allocator.xstrdup_printf ("%s_%s",
323 prefix, get_identifier (m));
326 /* Generate a C identifier for the given context.
327 The reproducer will eventually clean up the buffer in its dtor. */
329 const char *
330 reproducer::get_identifier (recording::context *ctxt)
332 return m_allocator.xstrdup_printf ("ctxt_%p",
333 (void *)ctxt);
336 /* Locate the C identifier for the given memento, which is assumed to
337 have already been created via make_identifier. */
339 const char *
340 reproducer::get_identifier (recording::memento *m)
342 if (!m)
343 return "NULL";
345 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
346 and hence these locations appear in the context's memento list
347 out-of-order: they appear in the context's memento list *after*
348 the memento that refers to them. For this case, it's simplest to
349 pretend that they're NULL when writing out the code to recreate the
350 memento that uses them. */
351 if (recording::location *loc = m->dyn_cast_location ())
352 if (!loc->created_by_user ())
353 return "NULL";
355 const char **slot = m_identifiers.get (m);
356 if (!slot)
358 get_context ().add_error (NULL,
359 "unable to find identifier for %p: %s",
360 (void *)m,
361 m->get_debug_string ());
362 gcc_unreachable ();
364 return *slot;
367 /* Locate the C identifier for the given rvalue, wrapping it within
368 a gcc_*_as_rvalue upcast if necessary. */
370 const char *
371 reproducer::get_identifier_as_rvalue (recording::rvalue *m)
373 return m->access_as_rvalue (*this);
376 /* Locate the C identifier for the given lvalue, wrapping it within
377 a gcc_*_as_lvalue upcast if necessary. */
379 const char *
380 reproducer::get_identifier_as_lvalue (recording::lvalue *m)
382 return m->access_as_lvalue (*this);
385 /* Locate the C identifier for the given type, wrapping it within
386 a gcc_*_as_type upcast if necessary. */
388 const char *
389 reproducer::get_identifier_as_type (recording::type *m)
391 return m->access_as_type (*this);
394 /* Formatted printing, allocating to a buffer (or exiting the process if
395 the allocation fails).
397 The buffer exists until the allocator is cleaned up, and is freed at
398 that point, so the caller doesn't need to track the result.
400 Note that we can't use ggc_printf since we're not within the compiler
401 proper (when within gcc_jit_context_dump_reproducer_to_file). */
403 char *
404 reproducer::xstrdup_printf (const char *fmt, ...)
406 char *result;
407 va_list ap;
408 va_start (ap, fmt);
409 result = m_allocator.xstrdup_printf_va (fmt, ap);
410 va_end (ap);
411 return result;
414 /**********************************************************************
415 Recording.
416 **********************************************************************/
418 /* Get the playback::location for the given recording::location,
419 handling a NULL input with a NULL output. */
421 playback::location *
422 recording::playback_location (replayer *r, recording::location *loc)
424 if (loc)
425 return loc->playback_location (r);
426 else
427 return NULL;
430 /* Get a const char * for the given recording::string
431 handling a NULL input with a NULL output. */
433 const char *
434 recording::playback_string (recording::string *str)
436 if (str)
437 return str->c_str ();
438 else
439 return NULL;
442 /* Get the playback::block for the given recording::block,
443 handling a NULL input with a NULL output. */
445 playback::block *
446 recording::playback_block (recording::block *b)
448 if (b)
449 return b->playback_block ();
450 else
451 return NULL;
454 /* Methods of cc::jit::recording::context. */
456 /* The constructor for gcc::jit::recording::context, used by
457 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
459 recording::context::context (context *parent_ctxt)
460 : log_user (NULL),
461 m_parent_ctxt (parent_ctxt),
462 m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this),
463 m_error_count (0),
464 m_first_error_str (NULL),
465 m_owns_first_error_str (false),
466 m_last_error_str (NULL),
467 m_owns_last_error_str (false),
468 m_mementos (),
469 m_compound_types (),
470 m_globals (),
471 m_functions (),
472 m_FILE_type (NULL),
473 m_builtins_manager(NULL)
475 if (parent_ctxt)
477 /* Inherit options from parent. */
478 for (unsigned i = 0;
479 i < sizeof (m_str_options) / sizeof (m_str_options[0]);
480 i++)
482 const char *parent_opt = parent_ctxt->m_str_options[i];
483 m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
485 memcpy (m_int_options,
486 parent_ctxt->m_int_options,
487 sizeof (m_int_options));
488 memcpy (m_bool_options,
489 parent_ctxt->m_bool_options,
490 sizeof (m_bool_options));
491 set_logger (parent_ctxt->get_logger ());
493 else
495 memset (m_str_options, 0, sizeof (m_str_options));
496 memset (m_int_options, 0, sizeof (m_int_options));
497 memset (m_bool_options, 0, sizeof (m_bool_options));
500 memset (m_basic_types, 0, sizeof (m_basic_types));
503 /* The destructor for gcc::jit::recording::context, implicitly used by
504 gcc_jit_context_release. */
506 recording::context::~context ()
508 JIT_LOG_SCOPE (get_logger ());
509 int i;
510 memento *m;
511 FOR_EACH_VEC_ELT (m_mementos, i, m)
513 delete m;
516 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
517 free (m_str_options[i]);
519 if (m_builtins_manager)
520 delete m_builtins_manager;
522 if (m_owns_first_error_str)
523 free (m_first_error_str);
525 if (m_owns_last_error_str)
526 if (m_last_error_str != m_first_error_str)
527 free (m_last_error_str);
530 /* Add the given mememto to the list of those tracked by this
531 gcc::jit::recording::context, so that e.g. it can be deleted
532 when this context is released. */
534 void
535 recording::context::record (memento *m)
537 gcc_assert (m);
539 m_mementos.safe_push (m);
542 /* Replay this context (and any parents) into the given replayer. */
544 void
545 recording::context::replay_into (replayer *r)
547 JIT_LOG_SCOPE (get_logger ());
548 int i;
549 memento *m;
551 /* If we have a parent context, we must replay it. This will
552 recursively walk backwards up the historical tree, then replay things
553 forwards "in historical order", starting with the ultimate parent
554 context, until we reach the "this" context.
556 Note that we fully replay the parent, then fully replay the child,
557 which means that inter-context references can only exist from child
558 to parent, not the other way around.
560 All of this replaying is suboptimal - it would be better to do the
561 work for the parent context *once*, rather than replaying the parent
562 every time we replay each child. However, fixing this requires deep
563 surgery to lifetime-management: we'd need every context family tree
564 to have its own GC heap, and to initialize the GCC code to use that
565 heap (with a mutex on such a heap). */
566 if (m_parent_ctxt)
567 m_parent_ctxt->replay_into (r);
569 if (r->errors_occurred ())
570 return;
572 /* Replay this context's saved operations into r. */
573 FOR_EACH_VEC_ELT (m_mementos, i, m)
575 /* Disabled low-level debugging, here if we need it: print what
576 we're replaying.
577 Note that the calls to get_debug_string might lead to more
578 mementos being created for the strings.
579 This can also be used to exercise the debug_string
580 machinery. */
581 if (0)
582 printf ("context %p replaying (%p): %s\n",
583 (void *)this, (void *)m, m->get_debug_string ());
585 m->replay_into (r);
587 if (r->errors_occurred ())
588 return;
592 /* During a playback, we associate objects from the recording with
593 their counterparts during this playback.
595 For simplicity, we store this within the recording objects.
597 The following method cleans away these associations, to ensure that
598 we never have out-of-date associations lingering on subsequent
599 playbacks (the objects pointed to are GC-managed, but the
600 recording objects don't own refs to them). */
602 void
603 recording::context::disassociate_from_playback ()
605 JIT_LOG_SCOPE (get_logger ());
606 int i;
607 memento *m;
609 if (m_parent_ctxt)
610 m_parent_ctxt->disassociate_from_playback ();
612 FOR_EACH_VEC_ELT (m_mementos, i, m)
614 m->set_playback_obj (NULL);
618 /* Create a recording::string instance and add it to this context's list
619 of mementos.
621 This creates a fresh copy of the given 0-terminated buffer. */
623 recording::string *
624 recording::context::new_string (const char *text)
626 if (!text)
627 return NULL;
629 recording::string *result = new string (this, text);
630 record (result);
631 return result;
634 /* Create a recording::location instance and add it to this context's
635 list of mementos.
637 Implements the post-error-checking part of
638 gcc_jit_context_new_location. */
640 recording::location *
641 recording::context::new_location (const char *filename,
642 int line,
643 int column,
644 bool created_by_user)
646 recording::location *result =
647 new recording::location (this,
648 new_string (filename),
649 line, column,
650 created_by_user);
651 record (result);
652 return result;
655 /* If we haven't seen this enum value yet, create a recording::type
656 instance and add it to this context's list of mementos.
658 If we have seen it before, reuse our cached value, so that repeated
659 calls on the context give the same object.
661 If we have a parent context, the cache is within the ultimate
662 ancestor context.
664 Implements the post-error-checking part of
665 gcc_jit_context_get_type. */
667 recording::type *
668 recording::context::get_type (enum gcc_jit_types kind)
670 if (!m_basic_types[kind])
672 if (m_parent_ctxt)
673 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
674 else
676 recording::type *result = new memento_of_get_type (this, kind);
677 record (result);
678 m_basic_types[kind] = result;
682 return m_basic_types[kind];
685 /* Get a recording::type instance for the given size and signedness.
686 This is implemented in terms of recording::context::get_type
687 above.
689 Implements the post-error-checking part of
690 gcc_jit_context_get_int_type. */
692 recording::type *
693 recording::context::get_int_type (int num_bytes, int is_signed)
695 /* We can't use a switch here since some of the values are macros affected
696 by options; e.g. i386.h has
697 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
698 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
699 are in bits, rather than bytes.
701 const int num_bits = num_bytes * 8;
702 if (num_bits == INT_TYPE_SIZE)
703 return get_type (is_signed
704 ? GCC_JIT_TYPE_INT
705 : GCC_JIT_TYPE_UNSIGNED_INT);
706 if (num_bits == CHAR_TYPE_SIZE)
707 return get_type (is_signed
708 ? GCC_JIT_TYPE_SIGNED_CHAR
709 : GCC_JIT_TYPE_UNSIGNED_CHAR);
710 if (num_bits == SHORT_TYPE_SIZE)
711 return get_type (is_signed
712 ? GCC_JIT_TYPE_SHORT
713 : GCC_JIT_TYPE_UNSIGNED_SHORT);
714 if (num_bits == LONG_TYPE_SIZE)
715 return get_type (is_signed
716 ? GCC_JIT_TYPE_LONG
717 : GCC_JIT_TYPE_UNSIGNED_LONG);
718 if (num_bits == LONG_LONG_TYPE_SIZE)
719 return get_type (is_signed
720 ? GCC_JIT_TYPE_LONG_LONG
721 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
723 /* Some other size, not corresponding to the C int types. */
724 /* To be written: support arbitrary other sizes, sharing by
725 memoizing at the recording::context level? */
726 gcc_unreachable ();
729 /* Create a recording::type instance and add it to this context's list
730 of mementos.
732 Implements the post-error-checking part of
733 gcc_jit_context_new_array_type. */
735 recording::type *
736 recording::context::new_array_type (recording::location *loc,
737 recording::type *element_type,
738 int num_elements)
740 if (struct_ *s = element_type->dyn_cast_struct ())
741 if (!s->get_fields ())
743 add_error (NULL,
744 "cannot create an array of type %s"
745 " until the fields have been set",
746 s->get_name ()->c_str ());
747 return NULL;
749 recording::type *result =
750 new recording::array_type (this, loc, element_type, num_elements);
751 record (result);
752 return result;
755 /* Create a recording::field instance and add it to this context's list
756 of mementos.
758 Implements the post-error-checking part of
759 gcc_jit_context_new_field. */
761 recording::field *
762 recording::context::new_field (recording::location *loc,
763 recording::type *type,
764 const char *name)
766 recording::field *result =
767 new recording::field (this, loc, type, new_string (name));
768 record (result);
769 return result;
772 /* Create a recording::struct_ instance and add it to this context's
773 list of mementos and list of compound types.
775 Implements the post-error-checking part of
776 gcc_jit_context_new_struct_type. */
778 recording::struct_ *
779 recording::context::new_struct_type (recording::location *loc,
780 const char *name)
782 recording::struct_ *result = new struct_ (this, loc, new_string (name));
783 record (result);
784 m_compound_types.safe_push (result);
785 return result;
788 /* Create a recording::union_ instance and add it to this context's
789 list of mementos and list of compound types.
791 Implements the first post-error-checking part of
792 gcc_jit_context_new_union_type. */
794 recording::union_ *
795 recording::context::new_union_type (recording::location *loc,
796 const char *name)
798 recording::union_ *result = new union_ (this, loc, new_string (name));
799 record (result);
800 m_compound_types.safe_push (result);
801 return result;
804 /* Create a recording::function_type instance and add it to this context's
805 list of mementos.
807 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
809 recording::function_type *
810 recording::context::new_function_type (recording::type *return_type,
811 int num_params,
812 recording::type **param_types,
813 int is_variadic)
815 recording::function_type *fn_type
816 = new function_type (this,
817 return_type,
818 num_params,
819 param_types,
820 is_variadic);
821 record (fn_type);
822 return fn_type;
825 /* Create a recording::type instance and add it to this context's list
826 of mementos.
828 Implements the post-error-checking part of
829 gcc_jit_context_new_function_ptr_type. */
831 recording::type *
832 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
833 recording::type *return_type,
834 int num_params,
835 recording::type **param_types,
836 int is_variadic)
838 recording::function_type *fn_type
839 = new_function_type (return_type,
840 num_params,
841 param_types,
842 is_variadic);
844 /* Return a pointer-type to the the function type. */
845 return fn_type->get_pointer ();
848 /* Create a recording::param instance and add it to this context's list
849 of mementos.
851 Implements the post-error-checking part of
852 gcc_jit_context_new_param. */
854 recording::param *
855 recording::context::new_param (recording::location *loc,
856 recording::type *type,
857 const char *name)
859 recording::param *result = new recording::param (this, loc, type, new_string (name));
860 record (result);
861 return result;
864 /* Create a recording::function instance and add it to this context's list
865 of mementos and list of functions.
867 Implements the post-error-checking part of
868 gcc_jit_context_new_function. */
870 recording::function *
871 recording::context::new_function (recording::location *loc,
872 enum gcc_jit_function_kind kind,
873 recording::type *return_type,
874 const char *name,
875 int num_params,
876 recording::param **params,
877 int is_variadic,
878 enum built_in_function builtin_id)
880 recording::function *result =
881 new recording::function (this,
882 loc, kind, return_type,
883 new_string (name),
884 num_params, params, is_variadic,
885 builtin_id);
886 record (result);
887 m_functions.safe_push (result);
889 return result;
892 /* Locate the builtins_manager (if any) for this family of contexts,
893 creating it if it doesn't exist already.
895 All of the recording contexts in a family share one builtins_manager:
896 if we have a child context, follow the parent links to get the
897 ultimate ancestor context, and look for it/store it there. */
899 builtins_manager *
900 recording::context::get_builtins_manager ()
902 if (m_parent_ctxt)
903 return m_parent_ctxt->get_builtins_manager ();
905 if (!m_builtins_manager)
906 m_builtins_manager = new builtins_manager (this);
908 return m_builtins_manager;
911 /* Get a recording::function instance, which is lazily-created and added
912 to the context's lists of mementos.
914 Implements the post-error-checking part of
915 gcc_jit_context_get_builtin_function. */
917 recording::function *
918 recording::context::get_builtin_function (const char *name)
920 builtins_manager *bm = get_builtins_manager ();
921 return bm->get_builtin_function (name);
924 /* Create a recording::global instance and add it to this context's list
925 of mementos.
927 Implements the post-error-checking part of
928 gcc_jit_context_new_global. */
930 recording::lvalue *
931 recording::context::new_global (recording::location *loc,
932 enum gcc_jit_global_kind kind,
933 recording::type *type,
934 const char *name)
936 recording::global *result =
937 new recording::global (this, loc, kind, type, new_string (name));
938 record (result);
939 m_globals.safe_push (result);
941 return result;
944 /* Create a recording::memento_of_new_string_literal instance and add it
945 to this context's list of mementos.
947 Implements the post-error-checking part of
948 gcc_jit_context_new_string_literal. */
950 recording::rvalue *
951 recording::context::new_string_literal (const char *value)
953 recording::rvalue *result =
954 new memento_of_new_string_literal (this, NULL, new_string (value));
955 record (result);
956 return result;
959 /* Create a recording::unary_op instance and add it to this context's
960 list of mementos.
962 Implements the post-error-checking part of
963 gcc_jit_context_new_unary_op. */
965 recording::rvalue *
966 recording::context::new_unary_op (recording::location *loc,
967 enum gcc_jit_unary_op op,
968 recording::type *result_type,
969 recording::rvalue *a)
971 recording::rvalue *result =
972 new unary_op (this, loc, op, result_type, a);
973 record (result);
974 return result;
977 /* Create a recording::binary_op instance and add it to this context's
978 list of mementos.
980 Implements the post-error-checking part of
981 gcc_jit_context_new_binary_op. */
983 recording::rvalue *
984 recording::context::new_binary_op (recording::location *loc,
985 enum gcc_jit_binary_op op,
986 recording::type *result_type,
987 recording::rvalue *a,
988 recording::rvalue *b)
990 recording::rvalue *result =
991 new binary_op (this, loc, op, result_type, a, b);
992 record (result);
993 return result;
996 /* Create a recording::comparison instance and add it to this context's
997 list of mementos.
999 Implements the post-error-checking part of
1000 gcc_jit_context_new_comparison. */
1002 recording::rvalue *
1003 recording::context::new_comparison (recording::location *loc,
1004 enum gcc_jit_comparison op,
1005 recording::rvalue *a,
1006 recording::rvalue *b)
1008 recording::rvalue *result = new comparison (this, loc, op, a, b);
1009 record (result);
1010 return result;
1013 /* Create a recording::cast instance and add it to this context's list
1014 of mementos.
1016 Implements the post-error-checking part of
1017 gcc_jit_context_new_cast. */
1019 recording::rvalue *
1020 recording::context::new_cast (recording::location *loc,
1021 recording::rvalue *expr,
1022 recording::type *type_)
1024 recording::rvalue *result = new cast (this, loc, expr, type_);
1025 record (result);
1026 return result;
1029 /* Create a recording::call instance and add it to this context's list
1030 of mementos.
1032 Implements the post-error-checking part of
1033 gcc_jit_context_new_call. */
1035 recording::rvalue *
1036 recording::context::new_call (recording::location *loc,
1037 function *func,
1038 int numargs , recording::rvalue **args)
1040 recording::rvalue *result = new call (this, loc, func, numargs, args);
1041 record (result);
1042 return result;
1045 /* Create a recording::call_through_ptr instance and add it to this
1046 context's list of mementos.
1048 Implements the post-error-checking part of
1049 gcc_jit_context_new_call_through_ptr. */
1051 recording::rvalue *
1052 recording::context::new_call_through_ptr (recording::location *loc,
1053 recording::rvalue *fn_ptr,
1054 int numargs,
1055 recording::rvalue **args)
1057 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
1058 record (result);
1059 return result;
1062 /* Create a recording::array_access instance and add it to this context's list
1063 of mementos.
1065 Implements the post-error-checking part of
1066 gcc_jit_context_new_array_access. */
1068 recording::lvalue *
1069 recording::context::new_array_access (recording::location *loc,
1070 recording::rvalue *ptr,
1071 recording::rvalue *index)
1073 recording::lvalue *result = new array_access (this, loc, ptr, index);
1074 record (result);
1075 return result;
1078 /* Set the given string option for this context, or add an error if
1079 it's not recognized.
1081 Implements the post-error-checking part of
1082 gcc_jit_context_set_str_option. */
1084 void
1085 recording::context::set_str_option (enum gcc_jit_str_option opt,
1086 const char *value)
1088 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
1090 add_error (NULL,
1091 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
1092 return;
1094 free (m_str_options[opt]);
1095 m_str_options[opt] = value ? xstrdup (value) : NULL;
1098 /* Set the given integer option for this context, or add an error if
1099 it's not recognized.
1101 Implements the post-error-checking part of
1102 gcc_jit_context_set_int_option. */
1104 void
1105 recording::context::set_int_option (enum gcc_jit_int_option opt,
1106 int value)
1108 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
1110 add_error (NULL,
1111 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
1112 return;
1114 m_int_options[opt] = value;
1117 /* Set the given boolean option for this context, or add an error if
1118 it's not recognized.
1120 Implements the post-error-checking part of
1121 gcc_jit_context_set_bool_option. */
1123 void
1124 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
1125 int value)
1127 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
1129 add_error (NULL,
1130 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
1131 return;
1133 m_bool_options[opt] = value ? true : false;
1136 /* Add the given dumpname/out_ptr pair to this context's list of requested
1137 dumps.
1139 Implements the post-error-checking part of
1140 gcc_jit_context_enable_dump. */
1142 void
1143 recording::context::enable_dump (const char *dumpname,
1144 char **out_ptr)
1146 requested_dump d;
1147 gcc_assert (dumpname);
1148 gcc_assert (out_ptr);
1150 d.m_dumpname = dumpname;
1151 d.m_out_ptr = out_ptr;
1152 *out_ptr = NULL;
1153 m_requested_dumps.safe_push (d);
1156 /* Validate this context, and if it passes, compile it to memory
1157 (within a mutex).
1159 Implements the post-error-checking part of
1160 gcc_jit_context_compile. */
1162 result *
1163 recording::context::compile ()
1165 JIT_LOG_SCOPE (get_logger ());
1167 validate ();
1169 if (errors_occurred ())
1170 return NULL;
1172 /* Set up a compile_to_memory playback context. */
1173 ::gcc::jit::playback::compile_to_memory replayer (this);
1175 /* Use it. */
1176 replayer.compile ();
1178 /* Get the jit::result (or NULL) from the
1179 compile_to_memory playback context. */
1180 return replayer.get_result_obj ();
1183 /* Validate this context, and if it passes, compile it to a file
1184 (within a mutex).
1186 Implements the post-error-checking part of
1187 gcc_jit_context_compile_to_file. */
1189 void
1190 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
1191 const char *output_path)
1193 JIT_LOG_SCOPE (get_logger ());
1195 validate ();
1197 if (errors_occurred ())
1198 return;
1200 /* Set up a compile_to_file playback context. */
1201 ::gcc::jit::playback::compile_to_file replayer (this,
1202 output_kind,
1203 output_path);
1205 /* Use it. */
1206 replayer.compile ();
1209 /* Format the given error using printf's conventions, print
1210 it to stderr, and add it to the context. */
1212 void
1213 recording::context::add_error (location *loc, const char *fmt, ...)
1215 va_list ap;
1216 va_start (ap, fmt);
1217 add_error_va (loc, fmt, ap);
1218 va_end (ap);
1221 /* Format the given error using printf's conventions, print
1222 it to stderr, and add it to the context. */
1224 void
1225 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
1227 char *malloced_msg;
1228 const char *errmsg;
1229 bool has_ownership;
1231 JIT_LOG_SCOPE (get_logger ());
1233 vasprintf (&malloced_msg, fmt, ap);
1234 if (malloced_msg)
1236 errmsg = malloced_msg;
1237 has_ownership = true;
1239 else
1241 errmsg = "out of memory generating error message";
1242 has_ownership = false;
1244 if (get_logger ())
1245 get_logger ()->log ("error %i: %s", m_error_count, errmsg);
1247 const char *ctxt_progname =
1248 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
1249 if (!ctxt_progname)
1250 ctxt_progname = "libgccjit.so";
1252 if (loc)
1253 fprintf (stderr, "%s: %s: error: %s\n",
1254 ctxt_progname,
1255 loc->get_debug_string (),
1256 errmsg);
1257 else
1258 fprintf (stderr, "%s: error: %s\n",
1259 ctxt_progname,
1260 errmsg);
1262 if (!m_error_count)
1264 m_first_error_str = const_cast <char *> (errmsg);
1265 m_owns_first_error_str = has_ownership;
1268 if (m_owns_last_error_str)
1269 if (m_last_error_str != m_first_error_str)
1270 free (m_last_error_str);
1271 m_last_error_str = const_cast <char *> (errmsg);
1272 m_owns_last_error_str = has_ownership;
1274 m_error_count++;
1277 /* Get the message for the first error that occurred on this context, or
1278 NULL if no errors have occurred on it.
1280 Implements the post-error-checking part of
1281 gcc_jit_context_get_first_error. */
1283 const char *
1284 recording::context::get_first_error () const
1286 return m_first_error_str;
1289 /* Get the message for the last error that occurred on this context, or
1290 NULL if no errors have occurred on it.
1292 Implements the post-error-checking part of
1293 gcc_jit_context_get_last_error. */
1295 const char *
1296 recording::context::get_last_error () const
1298 return m_last_error_str;
1301 /* Lazily generate and record a recording::type representing an opaque
1302 struct named "FILE".
1304 For use if client code tries to dereference the result of
1305 get_type (GCC_JIT_TYPE_FILE_PTR). */
1307 recording::type *
1308 recording::context::get_opaque_FILE_type ()
1310 if (!m_FILE_type)
1311 m_FILE_type = new_struct_type (NULL, "FILE");
1312 return m_FILE_type;
1315 /* Dump a C-like representation of the given context to the given path.
1316 If UPDATE_LOCATIONS is true, update the locations within the
1317 context's mementos to point to the dumpfile.
1319 Implements the post-error-checking part of
1320 gcc_jit_context_dump_to_file. */
1322 void
1323 recording::context::dump_to_file (const char *path, bool update_locations)
1325 int i;
1326 dump d (*this, path, update_locations);
1328 /* Forward declaration of structs and unions. */
1329 compound_type *st;
1330 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1332 d.write ("%s;\n\n", st->get_debug_string ());
1335 /* Content of structs, where set. */
1336 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1337 if (st->get_fields ())
1339 st->get_fields ()->write_to_dump (d);
1340 d.write ("\n");
1343 /* Globals. */
1344 global *g;
1345 FOR_EACH_VEC_ELT (m_globals, i, g)
1347 g->write_to_dump (d);
1349 if (!m_globals.is_empty ())
1350 d.write ("\n");
1352 function *fn;
1353 FOR_EACH_VEC_ELT (m_functions, i, fn)
1355 fn->write_to_dump (d);
1359 static const char * const
1360 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
1361 "GCC_JIT_STR_OPTION_PROGNAME"
1364 static const char * const
1365 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
1366 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1369 static const char * const
1370 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
1371 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1372 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1373 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1374 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1375 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1376 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1377 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1378 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1381 /* Write C source code to PATH that attempts to replay the API
1382 calls made to this context (and its parents), for use in
1383 minimizing test cases for libgccjit.
1385 Implements the post-error-checking part of
1386 gcc_jit_context_dump_reproducer_to_file. */
1388 void
1389 recording::context::dump_reproducer_to_file (const char *path)
1391 JIT_LOG_SCOPE (get_logger ());
1392 reproducer r (*this, path);
1394 /* Generate the "ancestry" of this context, as a list. */
1395 auto_vec <context *> ascending_contexts;
1396 for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
1397 ascending_contexts.safe_push (ctxt);
1399 /* Reverse the list, giving a list of contexts from
1400 top-most parent context down through to youngest child context.
1401 We will use this list as the parameters of the functions in
1402 our generated file. */
1403 unsigned num_ctxts = ascending_contexts.length ();
1404 auto_vec <context *> contexts (num_ctxts);
1405 for (unsigned i = 0; i < num_ctxts; i++)
1406 contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
1408 /* contexts[0] should be the top-level context. */
1409 gcc_assert (contexts[0]);
1410 gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
1412 /* The final element in contexts should be "this". */
1413 gcc_assert (contexts[contexts.length () - 1] == this);
1414 gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
1415 == contexts[0]);
1417 r.write ("/* This code was autogenerated by"
1418 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1419 print_version (r.get_file (), " ", false);
1420 r.write ("*/\n");
1421 r.write ("#include <libgccjit.h>\n\n");
1422 r.write ("static void\nset_options (");
1423 r.write_params (contexts);
1424 r.write (");\n\n");
1425 r.write ("static void\ncreate_code (");
1426 r.write_params (contexts);
1427 r.write (");\n\n");
1428 r.write ("int\nmain (int argc, const char **argv)\n");
1429 r.write ("{\n");
1430 for (unsigned i = 0; i < num_ctxts; i++)
1431 r.write (" gcc_jit_context *%s;\n",
1432 r.get_identifier (contexts[i]));
1433 r.write (" gcc_jit_result *result;\n"
1434 "\n");
1436 /* Create the contexts.
1437 The top-level context is acquired from a clean slate, the others as
1438 children of the prior context. */
1439 r.write (" %s = gcc_jit_context_acquire ();\n",
1440 r.get_identifier (contexts[0]));
1441 for (unsigned i = 1; i < num_ctxts; i++)
1442 r.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1443 r.get_identifier (contexts[i]),
1444 r.get_identifier (contexts[i - 1]));
1445 r.write (" set_options (");
1446 r.write_args (contexts);
1447 r.write (");\n");
1448 r.write (" create_code (");
1449 r.write_args (contexts);
1450 r.write (");\n");
1452 r.write (" result = gcc_jit_context_compile (%s);\n",
1453 r.get_identifier (this));
1455 for (unsigned i = num_ctxts; i > 0; i--)
1456 r.write (" gcc_jit_context_release (%s);\n",
1457 r.get_identifier (contexts[i - 1]));
1459 r.write (" gcc_jit_result_release (result);\n"
1460 " return 0;\n"
1461 "}\n\n");
1463 /* Define (char *) variables for use in calls to
1464 gcc_jit_context_enable_dump. */
1465 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1467 if (m_requested_dumps.length ())
1469 r.write ("/* Requested dumps for %s. */\n",
1470 r.get_identifier (contexts[ctxt_idx]));
1471 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1472 r.write ("static char *dump_%p;\n",
1473 (void *)&m_requested_dumps[i]);
1474 r.write ("\n");
1478 /* Write out values of options. */
1479 r.write ("static void\nset_options (");
1480 r.write_params (contexts);
1481 r.write (")\n{\n");
1482 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1484 if (ctxt_idx > 0)
1485 r.write ("\n");
1487 r.write (" /* Set options for %s. */\n",
1488 r.get_identifier (contexts[ctxt_idx]));
1490 r.write (" /* String options. */\n");
1491 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1492 r.write (" gcc_jit_context_set_str_option (%s,\n"
1493 " %s,\n"
1494 " \"%s\");\n",
1495 r.get_identifier (contexts[ctxt_idx]),
1496 str_option_reproducer_strings[opt_idx],
1497 m_str_options[opt_idx] ? m_str_options[opt_idx] : "NULL");
1498 r.write (" /* Int options. */\n");
1499 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1500 r.write (" gcc_jit_context_set_int_option (%s,\n"
1501 " %s,\n"
1502 " %i);\n",
1503 r.get_identifier (contexts[ctxt_idx]),
1504 int_option_reproducer_strings[opt_idx],
1505 m_int_options[opt_idx]);
1506 r.write (" /* Boolean options. */\n");
1507 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1508 r.write (" gcc_jit_context_set_bool_option (%s,\n"
1509 " %s,\n"
1510 " %i);\n",
1511 r.get_identifier (contexts[ctxt_idx]),
1512 bool_option_reproducer_strings[opt_idx],
1513 m_bool_options[opt_idx]);
1515 if (m_requested_dumps.length ())
1517 r.write (" /* Requested dumps. */\n");
1518 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1519 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1521 r.write (" gcc_jit_context_enable_dump (%s,\n"
1522 " \"%s\",\n"
1523 " &dump_%p);\n",
1524 r.get_identifier (contexts[ctxt_idx]),
1525 m_requested_dumps[i].m_dumpname,
1526 (void *)&m_requested_dumps[i]);
1530 r.write ("}\n\n");
1532 r.write ("static void\ncreate_code (");
1533 r.write_params (contexts);
1534 r.write (")\n"
1535 "{\n");
1536 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1538 memento *m;
1539 int i;
1540 if (ctxt_idx > 0)
1541 r.write ("\n\n");
1543 r.write (" /* Replay of API calls for %s. */\n",
1544 r.get_identifier (contexts[ctxt_idx]));
1545 FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
1546 m->write_reproducer (r);
1548 r.write ("}\n");
1551 /* Copy the requested dumps within this context and all ancestors into
1552 OUT. */
1554 void
1555 recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
1557 if (m_parent_ctxt)
1558 m_parent_ctxt->get_all_requested_dumps (out);
1560 out->reserve (m_requested_dumps.length ());
1561 out->splice (m_requested_dumps);
1564 /* This is a pre-compilation check for the context (and any parents).
1566 Detect errors within the context, adding errors if any are found. */
1568 void
1569 recording::context::validate ()
1571 JIT_LOG_SCOPE (get_logger ());
1573 if (m_parent_ctxt)
1574 m_parent_ctxt->validate ();
1576 int i;
1577 function *fn;
1578 FOR_EACH_VEC_ELT (m_functions, i, fn)
1579 fn->validate ();
1582 /* The implementation of class gcc::jit::recording::memento. */
1584 /* Get a (const char *) debug description of the given memento, by
1585 calling the pure-virtual make_debug_string hook, caching the
1586 result.
1588 It is intended that this should only be called in debugging and
1589 error-handling paths, so this doesn't need to be particularly
1590 optimized. */
1592 const char *
1593 recording::memento::get_debug_string ()
1595 if (!m_debug_string)
1596 m_debug_string = make_debug_string ();
1597 return m_debug_string->c_str ();
1600 /* Default implementation of recording::memento::write_to_dump, writing
1601 an indented form of the memento's debug string to the dump. */
1603 void
1604 recording::memento::write_to_dump (dump &d)
1606 d.write(" %s\n", get_debug_string ());
1609 /* The implementation of class gcc::jit::recording::string. */
1611 /* Constructor for gcc::jit::recording::string::string, allocating a
1612 copy of the given text using new char[]. */
1614 recording::string::string (context *ctxt, const char *text)
1615 : memento (ctxt)
1617 m_len = strlen (text);
1618 m_buffer = new char[m_len + 1];
1619 strcpy (m_buffer, text);
1622 /* Destructor for gcc::jit::recording::string::string. */
1624 recording::string::~string ()
1626 delete[] m_buffer;
1629 /* Function for making gcc::jit::recording::string instances on a
1630 context via printf-style formatting.
1632 It is intended that this should only be called in debugging and
1633 error-handling paths, so this doesn't need to be particularly
1634 optimized, hence the double-copy of the string is acceptable. */
1636 recording::string *
1637 recording::string::from_printf (context *ctxt, const char *fmt, ...)
1639 va_list ap;
1640 char *buf = NULL;
1641 recording::string *result;
1643 va_start (ap, fmt);
1644 vasprintf (&buf, fmt, ap);
1645 va_end (ap);
1647 if (!buf)
1649 ctxt->add_error (NULL, "malloc failure");
1650 return NULL;
1653 result = ctxt->new_string (buf);
1654 free (buf);
1655 return result;
1658 /* Implementation of recording::memento::make_debug_string for strings,
1659 wrapping the given string in quotes and escaping as necessary. */
1661 recording::string *
1662 recording::string::make_debug_string ()
1664 /* Hack to avoid infinite recursion into strings when logging all
1665 mementos: don't re-escape strings: */
1666 if (m_buffer[0] == '"')
1667 return this;
1669 /* Wrap in quotes and do escaping etc */
1671 size_t sz = (1 /* opening quote */
1672 + (m_len * 2) /* each char might get escaped */
1673 + 1 /* closing quote */
1674 + 1); /* nil termintator */
1675 char *tmp = new char[sz];
1676 size_t len = 0;
1678 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1679 APPEND('"'); /* opening quote */
1680 for (size_t i = 0; i < m_len ; i++)
1682 char ch = m_buffer[i];
1683 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
1684 APPEND('\\');
1685 APPEND(ch);
1687 APPEND('"'); /* closing quote */
1688 #undef APPEND
1689 tmp[len] = '\0'; /* nil termintator */
1691 string *result = m_ctxt->new_string (tmp);
1693 delete[] tmp;
1694 return result;
1697 /* Implementation of recording::memento::write_reproducer for strings. */
1699 void
1700 recording::string::write_reproducer (reproducer &)
1702 /* Empty. */
1705 /* The implementation of class gcc::jit::recording::location. */
1707 /* Implementation of recording::memento::replay_into for locations.
1709 Create a new playback::location and store it into the
1710 recording::location's m_playback_obj field. */
1712 void
1713 recording::location::replay_into (replayer *r)
1715 m_playback_obj = r->new_location (this,
1716 m_filename->c_str (),
1717 m_line,
1718 m_column);
1721 /* Implementation of recording::memento::make_debug_string for locations,
1722 turning them into the usual form:
1723 FILENAME:LINE:COLUMN
1724 like we do when emitting diagnostics. */
1726 recording::string *
1727 recording::location::make_debug_string ()
1729 return string::from_printf (m_ctxt,
1730 "%s:%i:%i",
1731 m_filename->c_str (), m_line, m_column);
1734 /* Implementation of recording::memento::write_reproducer for locations. */
1736 void
1737 recording::location::write_reproducer (reproducer &r)
1739 const char *id = r.make_identifier (this, "loc");
1740 r.write (" gcc_jit_location *%s =\n"
1741 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1742 " %s, /* const char *filename */\n"
1743 " %i, /* int line */\n"
1744 " %i);/* int column */\n",
1746 r.get_identifier (get_context ()),
1747 m_filename->get_debug_string (),
1748 m_line, m_column);
1751 /* The implementation of class gcc::jit::recording::type. */
1753 /* Given a type T, get the type T*.
1755 If this doesn't already exist, generate a new memento_of_get_pointer
1756 instance and add it to this type's context's list of mementos.
1758 Otherwise, use the cached type.
1760 Implements the post-error-checking part of
1761 gcc_jit_type_get_pointer. */
1763 recording::type *
1764 recording::type::get_pointer ()
1766 if (!m_pointer_to_this_type)
1768 m_pointer_to_this_type = new memento_of_get_pointer (this);
1769 m_ctxt->record (m_pointer_to_this_type);
1771 return m_pointer_to_this_type;
1774 /* Given a type T, get the type const T.
1776 Implements the post-error-checking part of
1777 gcc_jit_type_get_const. */
1779 recording::type *
1780 recording::type::get_const ()
1782 recording::type *result = new memento_of_get_const (this);
1783 m_ctxt->record (result);
1784 return result;
1787 /* Given a type T, get the type volatile T.
1789 Implements the post-error-checking part of
1790 gcc_jit_type_get_volatile. */
1792 recording::type *
1793 recording::type::get_volatile ()
1795 recording::type *result = new memento_of_get_volatile (this);
1796 m_ctxt->record (result);
1797 return result;
1800 const char *
1801 recording::type::access_as_type (reproducer &r)
1803 return r.get_identifier (this);
1806 /* Implementation of pure virtual hook recording::type::dereference for
1807 recording::memento_of_get_type. */
1809 recording::type *
1810 recording::memento_of_get_type::dereference ()
1812 switch (m_kind)
1814 default: gcc_unreachable ();
1816 case GCC_JIT_TYPE_VOID:
1817 return NULL;
1819 case GCC_JIT_TYPE_VOID_PTR:
1820 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
1822 case GCC_JIT_TYPE_BOOL:
1823 case GCC_JIT_TYPE_CHAR:
1824 case GCC_JIT_TYPE_SIGNED_CHAR:
1825 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1826 case GCC_JIT_TYPE_SHORT:
1827 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1828 case GCC_JIT_TYPE_INT:
1829 case GCC_JIT_TYPE_UNSIGNED_INT:
1830 case GCC_JIT_TYPE_LONG:
1831 case GCC_JIT_TYPE_UNSIGNED_LONG:
1832 case GCC_JIT_TYPE_LONG_LONG:
1833 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1834 case GCC_JIT_TYPE_FLOAT:
1835 case GCC_JIT_TYPE_DOUBLE:
1836 case GCC_JIT_TYPE_LONG_DOUBLE:
1837 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1838 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1839 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
1840 /* Not a pointer: */
1841 return NULL;
1843 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1844 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
1846 case GCC_JIT_TYPE_SIZE_T:
1847 /* Not a pointer: */
1848 return NULL;
1850 case GCC_JIT_TYPE_FILE_PTR:
1851 /* Give the client code back an opaque "struct FILE". */
1852 return m_ctxt->get_opaque_FILE_type ();
1856 /* Implementation of pure virtual hook recording::type::is_int for
1857 recording::memento_of_get_type. */
1859 bool
1860 recording::memento_of_get_type::is_int () const
1862 switch (m_kind)
1864 default: gcc_unreachable ();
1866 case GCC_JIT_TYPE_VOID:
1867 return false;
1869 case GCC_JIT_TYPE_VOID_PTR:
1870 return false;
1872 case GCC_JIT_TYPE_BOOL:
1873 return false;
1875 case GCC_JIT_TYPE_CHAR:
1876 case GCC_JIT_TYPE_SIGNED_CHAR:
1877 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1878 case GCC_JIT_TYPE_SHORT:
1879 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1880 case GCC_JIT_TYPE_INT:
1881 case GCC_JIT_TYPE_UNSIGNED_INT:
1882 case GCC_JIT_TYPE_LONG:
1883 case GCC_JIT_TYPE_UNSIGNED_LONG:
1884 case GCC_JIT_TYPE_LONG_LONG:
1885 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1886 return true;
1888 case GCC_JIT_TYPE_FLOAT:
1889 case GCC_JIT_TYPE_DOUBLE:
1890 case GCC_JIT_TYPE_LONG_DOUBLE:
1891 return false;
1893 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1894 return false;
1896 case GCC_JIT_TYPE_SIZE_T:
1897 return true;
1899 case GCC_JIT_TYPE_FILE_PTR:
1900 return false;
1902 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1903 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1904 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
1905 return false;
1909 /* Implementation of pure virtual hook recording::type::is_float for
1910 recording::memento_of_get_type. */
1912 bool
1913 recording::memento_of_get_type::is_float () const
1915 switch (m_kind)
1917 default: gcc_unreachable ();
1919 case GCC_JIT_TYPE_VOID:
1920 return false;
1922 case GCC_JIT_TYPE_VOID_PTR:
1923 return false;
1925 case GCC_JIT_TYPE_BOOL:
1926 return false;
1928 case GCC_JIT_TYPE_CHAR:
1929 case GCC_JIT_TYPE_SIGNED_CHAR:
1930 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1931 case GCC_JIT_TYPE_SHORT:
1932 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1933 case GCC_JIT_TYPE_INT:
1934 case GCC_JIT_TYPE_UNSIGNED_INT:
1935 case GCC_JIT_TYPE_LONG:
1936 case GCC_JIT_TYPE_UNSIGNED_LONG:
1937 case GCC_JIT_TYPE_LONG_LONG:
1938 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1939 return false;
1941 case GCC_JIT_TYPE_FLOAT:
1942 case GCC_JIT_TYPE_DOUBLE:
1943 case GCC_JIT_TYPE_LONG_DOUBLE:
1944 return true;
1946 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1947 return false;
1949 case GCC_JIT_TYPE_SIZE_T:
1950 return false;
1952 case GCC_JIT_TYPE_FILE_PTR:
1953 return false;
1955 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1956 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1957 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
1958 return true;
1962 /* Implementation of pure virtual hook recording::type::is_bool for
1963 recording::memento_of_get_type. */
1965 bool
1966 recording::memento_of_get_type::is_bool () const
1968 switch (m_kind)
1970 default: gcc_unreachable ();
1972 case GCC_JIT_TYPE_VOID:
1973 return false;
1975 case GCC_JIT_TYPE_VOID_PTR:
1976 return false;
1978 case GCC_JIT_TYPE_BOOL:
1979 return true;
1981 case GCC_JIT_TYPE_CHAR:
1982 case GCC_JIT_TYPE_SIGNED_CHAR:
1983 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1984 case GCC_JIT_TYPE_SHORT:
1985 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1986 case GCC_JIT_TYPE_INT:
1987 case GCC_JIT_TYPE_UNSIGNED_INT:
1988 case GCC_JIT_TYPE_LONG:
1989 case GCC_JIT_TYPE_UNSIGNED_LONG:
1990 case GCC_JIT_TYPE_LONG_LONG:
1991 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1992 return false;
1994 case GCC_JIT_TYPE_FLOAT:
1995 case GCC_JIT_TYPE_DOUBLE:
1996 case GCC_JIT_TYPE_LONG_DOUBLE:
1997 return false;
1999 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2000 return false;
2002 case GCC_JIT_TYPE_SIZE_T:
2003 return false;
2005 case GCC_JIT_TYPE_FILE_PTR:
2006 return false;
2008 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2009 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2010 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2011 return false;
2015 /* Implementation of pure virtual hook recording::memento::replay_into
2016 for recording::memento_of_get_type. */
2018 void
2019 recording::memento_of_get_type::replay_into (replayer *r)
2021 set_playback_obj (r->get_type (m_kind));
2024 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2026 /* Descriptive strings for each of enum gcc_jit_types. */
2028 static const char * const get_type_strings[] = {
2029 "void", /* GCC_JIT_TYPE_VOID */
2030 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2032 "bool", /* GCC_JIT_TYPE_BOOL */
2034 "char", /* GCC_JIT_TYPE_CHAR */
2035 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2036 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2038 "short", /* GCC_JIT_TYPE_SHORT */
2039 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2041 "int", /* GCC_JIT_TYPE_INT */
2042 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2044 "long", /* GCC_JIT_TYPE_LONG */
2045 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2047 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2048 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2050 "float", /* GCC_JIT_TYPE_FLOAT */
2051 "double", /* GCC_JIT_TYPE_DOUBLE */
2052 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2054 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2056 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2058 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2060 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2061 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2062 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2066 /* Implementation of recording::memento::make_debug_string for
2067 results of get_type, using a simple table of type names. */
2069 recording::string *
2070 recording::memento_of_get_type::make_debug_string ()
2072 return m_ctxt->new_string (get_type_strings[m_kind]);
2075 static const char * const get_type_enum_strings[] = {
2076 "GCC_JIT_TYPE_VOID",
2077 "GCC_JIT_TYPE_VOID_PTR",
2078 "GCC_JIT_TYPE_BOOL",
2079 "GCC_JIT_TYPE_CHAR",
2080 "GCC_JIT_TYPE_SIGNED_CHAR",
2081 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2082 "GCC_JIT_TYPE_SHORT",
2083 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2084 "GCC_JIT_TYPE_INT",
2085 "GCC_JIT_TYPE_UNSIGNED_INT",
2086 "GCC_JIT_TYPE_LONG",
2087 "GCC_JIT_TYPE_UNSIGNED_LONG",
2088 "GCC_JIT_TYPE_LONG_LONG",
2089 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2090 "GCC_JIT_TYPE_FLOAT",
2091 "GCC_JIT_TYPE_DOUBLE",
2092 "GCC_JIT_TYPE_LONG_DOUBLE",
2093 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2094 "GCC_JIT_TYPE_SIZE_T",
2095 "GCC_JIT_TYPE_FILE_PTR",
2096 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2097 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2098 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2101 void
2102 recording::memento_of_get_type::write_reproducer (reproducer &r)
2104 const char *id = r.make_identifier (this, "type");
2105 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2107 r.get_identifier (get_context ()),
2108 get_type_enum_strings[m_kind]);
2111 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2113 /* Override of default implementation of
2114 recording::type::accepts_writes_from for get_pointer.
2116 Require a pointer type, and allowing writes to
2117 (const T *) from a (T*), but not the other way around. */
2119 bool
2120 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2122 /* Must be a pointer type: */
2123 type *rtype_points_to = rtype->is_pointer ();
2124 if (!rtype_points_to)
2125 return false;
2127 /* It's OK to assign to a (const T *) from a (T *). */
2128 return m_other_type->unqualified ()
2129 ->accepts_writes_from (rtype_points_to);
2132 /* Implementation of pure virtual hook recording::memento::replay_into
2133 for recording::memento_of_get_pointer. */
2135 void
2136 recording::memento_of_get_pointer::replay_into (replayer *)
2138 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2141 /* Implementation of recording::memento::make_debug_string for
2142 results of get_pointer, adding " *" to the underlying type,
2143 with special-casing to handle function pointer types. */
2145 recording::string *
2146 recording::memento_of_get_pointer::make_debug_string ()
2148 /* Special-case function pointer types, to put the "*" in parens between
2149 the return type and the params (for one level of dereferencing, at
2150 least). */
2151 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2152 return fn_type->make_debug_string_with_ptr ();
2154 return string::from_printf (m_ctxt,
2155 "%s *", m_other_type->get_debug_string ());
2158 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2160 void
2161 recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2163 /* We need to special-case function pointer types; see the notes in
2164 recording::function_type::write_deferred_reproducer. */
2165 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2167 fn_type->write_deferred_reproducer (r, this);
2168 return;
2171 const char *id = r.make_identifier (this, "type");
2172 r.write (" gcc_jit_type *%s =\n"
2173 " gcc_jit_type_get_pointer (%s);\n",
2175 r.get_identifier_as_type (m_other_type));
2178 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2180 /* Implementation of pure virtual hook recording::memento::replay_into
2181 for recording::memento_of_get_const. */
2183 void
2184 recording::memento_of_get_const::replay_into (replayer *)
2186 set_playback_obj (m_other_type->playback_type ()->get_const ());
2189 /* Implementation of recording::memento::make_debug_string for
2190 results of get_const, prepending "const ". */
2192 recording::string *
2193 recording::memento_of_get_const::make_debug_string ()
2195 return string::from_printf (m_ctxt,
2196 "const %s", m_other_type->get_debug_string ());
2199 /* Implementation of recording::memento::write_reproducer for const types. */
2201 void
2202 recording::memento_of_get_const::write_reproducer (reproducer &r)
2204 const char *id = r.make_identifier (this, "type");
2205 r.write (" gcc_jit_type *%s =\n"
2206 " gcc_jit_type_get_const (%s);\n",
2208 r.get_identifier_as_type (m_other_type));
2211 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2213 /* Implementation of pure virtual hook recording::memento::replay_into
2214 for recording::memento_of_get_volatile. */
2216 void
2217 recording::memento_of_get_volatile::replay_into (replayer *)
2219 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2222 /* Implementation of recording::memento::make_debug_string for
2223 results of get_volatile, prepending "volatile ". */
2225 recording::string *
2226 recording::memento_of_get_volatile::make_debug_string ()
2228 return string::from_printf (m_ctxt,
2229 "volatile %s", m_other_type->get_debug_string ());
2232 /* Implementation of recording::memento::write_reproducer for volatile
2233 types. */
2235 void
2236 recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2238 const char *id = r.make_identifier (this, "type");
2239 r.write (" gcc_jit_type *%s =\n"
2240 " gcc_jit_type_get_volatile (%s);\n",
2242 r.get_identifier_as_type (m_other_type));
2245 /* The implementation of class gcc::jit::recording::array_type */
2247 /* Implementation of pure virtual hook recording::type::dereference for
2248 recording::array_type. */
2250 recording::type *
2251 recording::array_type::dereference ()
2253 return m_element_type;
2256 /* Implementation of pure virtual hook recording::memento::replay_into
2257 for recording::array_type. */
2259 void
2260 recording::array_type::replay_into (replayer *r)
2262 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
2263 m_element_type->playback_type (),
2264 m_num_elements));
2267 /* Implementation of recording::memento::make_debug_string for
2268 results of new_array_type. */
2270 recording::string *
2271 recording::array_type::make_debug_string ()
2273 return string::from_printf (m_ctxt,
2274 "%s[%d]",
2275 m_element_type->get_debug_string (),
2276 m_num_elements);
2279 /* Implementation of recording::memento::write_reproducer for array
2280 types. */
2282 void
2283 recording::array_type::write_reproducer (reproducer &r)
2285 const char *id = r.make_identifier (this, "array_type");
2286 r.write (" gcc_jit_type *%s =\n"
2287 " gcc_jit_context_new_array_type (%s,\n"
2288 " %s, /* gcc_jit_location *loc */\n"
2289 " %s, /* gcc_jit_type *element_type */\n"
2290 " %i); /* int num_elements */\n",
2292 r.get_identifier (get_context ()),
2293 r.get_identifier (m_loc),
2294 r.get_identifier_as_type (m_element_type),
2295 m_num_elements);
2298 /* The implementation of class gcc::jit::recording::function_type */
2300 /* Constructor for gcc::jit::recording::function_type. */
2302 recording::function_type::function_type (context *ctxt,
2303 type *return_type,
2304 int num_params,
2305 type **param_types,
2306 int is_variadic)
2307 : type (ctxt),
2308 m_return_type (return_type),
2309 m_param_types (),
2310 m_is_variadic (is_variadic)
2312 for (int i = 0; i< num_params; i++)
2313 m_param_types.safe_push (param_types[i]);
2316 /* Implementation of pure virtual hook recording::type::dereference for
2317 recording::function_type. */
2319 recording::type *
2320 recording::function_type::dereference ()
2322 return NULL;
2325 /* Implementation of pure virtual hook recording::memento::replay_into
2326 for recording::function_type. */
2328 void
2329 recording::function_type::replay_into (replayer *r)
2331 /* Convert m_param_types to a vec of playback type. */
2332 auto_vec <playback::type *> param_types;
2333 int i;
2334 recording::type *type;
2335 param_types.create (m_param_types.length ());
2336 FOR_EACH_VEC_ELT (m_param_types, i, type)
2337 param_types.safe_push (type->playback_type ());
2339 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
2340 &param_types,
2341 m_is_variadic));
2344 /* Special-casing for make_debug_string for get_pointer results for
2345 handling (one level) of pointers to functions. */
2347 recording::string *
2348 recording::function_type::make_debug_string_with_ptr ()
2350 return make_debug_string_with ("(*) ");
2353 /* Implementation of recording::memento::make_debug_string for
2354 results of new_function_type. */
2356 recording::string *
2357 recording::function_type::make_debug_string ()
2359 return make_debug_string_with ("");
2362 /* Build a debug string representation of the form:
2364 RESULT_TYPE INSERT (PARAM_TYPES)
2366 for use when handling 0 and 1 level of indirection to this
2367 function type. */
2369 recording::string *
2370 recording::function_type::make_debug_string_with (const char *insert)
2372 /* First, build a buffer for the arguments. */
2373 /* Calculate length of said buffer. */
2374 size_t sz = 1; /* nil terminator */
2375 for (unsigned i = 0; i< m_param_types.length (); i++)
2377 sz += strlen (m_param_types[i]->get_debug_string ());
2378 sz += 2; /* ", " separator */
2380 if (m_is_variadic)
2381 sz += 5; /* ", ..." separator and ellipsis */
2383 /* Now allocate and populate the buffer. */
2384 char *argbuf = new char[sz];
2385 size_t len = 0;
2387 for (unsigned i = 0; i< m_param_types.length (); i++)
2389 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
2390 len += strlen (m_param_types[i]->get_debug_string ());
2391 if (i + 1 < m_param_types.length ())
2393 strcpy (argbuf + len, ", ");
2394 len += 2;
2397 if (m_is_variadic)
2399 if (m_param_types.length ())
2401 strcpy (argbuf + len, ", ");
2402 len += 2;
2404 strcpy (argbuf + len, "...");
2405 len += 3;
2407 argbuf[len] = '\0';
2409 /* ...and use it to get the string for the call as a whole. */
2410 string *result = string::from_printf (m_ctxt,
2411 "%s %s(%s)",
2412 m_return_type->get_debug_string (),
2413 insert,
2414 argbuf);
2416 delete[] argbuf;
2418 return result;
2421 /* Implementation of recording::memento::write_reproducer for function
2422 types. */
2424 void
2425 recording::function_type::write_reproducer (reproducer &)
2427 /* see notes below. */
2430 /* There's a get_pointer within context::new_function_ptr_type:
2431 the type received by client code isn't the memento for the
2432 function_type, but instead the result of get_pointer on it.
2434 Hence we can't directly write a reproducer that gives function_type.
2435 Instead we special-case things within get_pointer, detecting this
2436 case, calling the following function. */
2438 void
2439 recording::function_type::write_deferred_reproducer (reproducer &r,
2440 memento *ptr_type)
2442 gcc_assert (ptr_type);
2443 r.make_identifier (this, "function_type");
2444 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
2445 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
2446 r.write (" gcc_jit_type *%s[%i] = {\n",
2447 param_types_id,
2448 m_param_types.length ());
2449 int i;
2450 type *param_type;
2451 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2452 r.write (" %s,\n", r.get_identifier_as_type (param_type));
2453 r.write (" };\n");
2454 r.write (" gcc_jit_type *%s =\n"
2455 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2456 " %s, /* gcc_jit_location *loc */\n"
2457 " %s, /* gcc_jit_type *return_type */\n"
2458 " %i, /* int num_params */\n"
2459 " %s, /* gcc_jit_type **param_types */\n"
2460 " %i); /* int is_variadic */\n",
2461 ptr_id,
2462 r.get_identifier (get_context ()),
2463 "NULL", /* location is not stored */
2464 r.get_identifier_as_type (m_return_type),
2465 m_param_types.length (),
2466 param_types_id,
2467 m_is_variadic);
2470 /* The implementation of class gcc::jit::recording::field. */
2472 /* Implementation of pure virtual hook recording::memento::replay_into
2473 for recording::field. */
2475 void
2476 recording::field::replay_into (replayer *r)
2478 set_playback_obj (r->new_field (playback_location (r, m_loc),
2479 m_type->playback_type (),
2480 playback_string (m_name)));
2483 /* Override the default implementation of
2484 recording::memento::write_to_dump. Dump each field
2485 by dumping a line of the form:
2486 TYPE NAME;
2487 so that we can build up a struct/union field-byfield. */
2489 void
2490 recording::field::write_to_dump (dump &d)
2492 d.write (" %s %s;\n",
2493 m_type->get_debug_string (),
2494 m_name->c_str ());
2497 /* Implementation of recording::memento::make_debug_string for
2498 results of new_field. */
2500 recording::string *
2501 recording::field::make_debug_string ()
2503 return m_name;
2506 /* Implementation of recording::memento::write_reproducer for fields. */
2508 void
2509 recording::field::write_reproducer (reproducer &r)
2511 const char *id = r.make_identifier (this, "field");
2512 r.write(" gcc_jit_field *%s =\n"
2513 " gcc_jit_context_new_field (%s,\n"
2514 " %s, /* gcc_jit_location *loc */\n"
2515 " %s, /* gcc_jit_type *type, */\n"
2516 " %s); /* const char *name */\n",
2518 r.get_identifier (get_context ()),
2519 r.get_identifier (m_loc),
2520 r.get_identifier_as_type (m_type),
2521 m_name->get_debug_string ());
2524 /* The implementation of class gcc::jit::recording::compound_type */
2526 /* The constructor for gcc::jit::recording::compound_type. */
2528 recording::compound_type::compound_type (context *ctxt,
2529 location *loc,
2530 string *name)
2531 : type (ctxt),
2532 m_loc (loc),
2533 m_name (name),
2534 m_fields (NULL)
2538 /* Set the fields of a compound type.
2540 Implements the post-error-checking part of
2541 gcc_jit_struct_set_fields, and is also used by
2542 gcc_jit_context_new_union_type. */
2544 void
2545 recording::compound_type::set_fields (location *loc,
2546 int num_fields,
2547 field **field_array)
2549 m_loc = loc;
2550 gcc_assert (NULL == m_fields);
2552 m_fields = new fields (this, num_fields, field_array);
2553 m_ctxt->record (m_fields);
2556 /* Implementation of pure virtual hook recording::type::dereference for
2557 recording::compound_type. */
2559 recording::type *
2560 recording::compound_type::dereference ()
2562 return NULL; /* not a pointer */
2565 /* The implementation of class gcc::jit::recording::struct_. */
2567 /* The constructor for gcc::jit::recording::struct_. */
2569 recording::struct_::struct_ (context *ctxt,
2570 location *loc,
2571 string *name)
2572 : compound_type (ctxt, loc, name)
2576 /* Implementation of pure virtual hook recording::memento::replay_into
2577 for recording::struct_. */
2579 void
2580 recording::struct_::replay_into (replayer *r)
2582 set_playback_obj (
2583 r->new_compound_type (playback_location (r, get_loc ()),
2584 get_name ()->c_str (),
2585 true /* is_struct */));
2588 const char *
2589 recording::struct_::access_as_type (reproducer &r)
2591 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2592 r.get_identifier (this));
2595 /* Implementation of recording::memento::make_debug_string for
2596 structs. */
2598 recording::string *
2599 recording::struct_::make_debug_string ()
2601 return string::from_printf (m_ctxt,
2602 "struct %s", get_name ()->c_str ());
2605 void
2606 recording::struct_::write_reproducer (reproducer &r)
2608 const char *id = r.make_identifier (this, "struct");
2609 r.write (" gcc_jit_struct *%s =\n"
2610 " gcc_jit_context_new_opaque_struct (%s,\n"
2611 " %s, /* gcc_jit_location *loc */\n"
2612 " %s); /* const char *name */\n",
2614 r.get_identifier (get_context ()),
2615 r.get_identifier (get_loc ()),
2616 get_name ()->get_debug_string ());
2619 /* The implementation of class gcc::jit::recording::union_. */
2621 /* The constructor for gcc::jit::recording::union_. */
2623 recording::union_::union_ (context *ctxt,
2624 location *loc,
2625 string *name)
2626 : compound_type (ctxt, loc, name)
2630 /* Implementation of pure virtual hook recording::memento::replay_into
2631 for recording::union_. */
2633 void
2634 recording::union_::replay_into (replayer *r)
2636 set_playback_obj (
2637 r->new_compound_type (playback_location (r, get_loc ()),
2638 get_name ()->c_str (),
2639 false /* is_struct */));
2642 /* Implementation of recording::memento::make_debug_string for
2643 unions. */
2645 recording::string *
2646 recording::union_::make_debug_string ()
2648 return string::from_printf (m_ctxt,
2649 "union %s", get_name ()->c_str ());
2652 /* Implementation of recording::memento::write_reproducer for unions. */
2654 void
2655 recording::union_::write_reproducer (reproducer &r)
2657 const char *id = r.make_identifier (this, "union");
2659 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
2660 r.write (" gcc_jit_field *%s[%i] = {\n",
2661 fields_id,
2662 get_fields ()->length ());
2663 for (int i = 0; i < get_fields ()->length (); i++)
2664 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
2665 r.write (" };\n");
2667 r.write (" gcc_jit_type *%s =\n"
2668 " gcc_jit_context_new_union_type (%s,\n"
2669 " %s, /* gcc_jit_location *loc */\n"
2670 " %s, /* const char *name */\n"
2671 " %i, /* int num_fields */\n"
2672 " %s); /* gcc_jit_field **fields */\n",
2674 r.get_identifier (get_context ()),
2675 r.get_identifier (get_loc ()),
2676 get_name ()->get_debug_string (),
2677 get_fields ()->length (),
2678 fields_id);
2681 /* The implementation of class gcc::jit::recording::fields. */
2683 /* The constructor for gcc::jit::recording::fields. */
2685 recording::fields::fields (compound_type *struct_or_union,
2686 int num_fields,
2687 field **fields)
2688 : memento (struct_or_union->m_ctxt),
2689 m_struct_or_union (struct_or_union),
2690 m_fields ()
2692 for (int i = 0; i < num_fields; i++)
2694 gcc_assert (fields[i]->get_container () == NULL);
2695 fields[i]->set_container (m_struct_or_union);
2696 m_fields.safe_push (fields[i]);
2700 /* Implementation of pure virtual hook recording::memento::replay_into
2701 for recording::fields. */
2703 void
2704 recording::fields::replay_into (replayer *)
2706 auto_vec<playback::field *> playback_fields;
2707 playback_fields.create (m_fields.length ());
2708 for (unsigned i = 0; i < m_fields.length (); i++)
2709 playback_fields.safe_push (m_fields[i]->playback_field ());
2710 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
2713 /* Override the default implementation of
2714 recording::memento::write_to_dump by writing a union/struct
2715 declaration of this form:
2717 struct/union NAME {
2718 TYPE_1 NAME_1;
2719 TYPE_2 NAME_2;
2720 ....
2721 TYPE_N NAME_N;
2724 to the dump. */
2726 void
2727 recording::fields::write_to_dump (dump &d)
2729 int i;
2730 field *f;
2732 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
2733 FOR_EACH_VEC_ELT (m_fields, i, f)
2734 f->write_to_dump (d);
2735 d.write ("};\n");
2738 /* Implementation of recording::memento::write_reproducer for the fields
2739 subclass. */
2741 void
2742 recording::fields::write_reproducer (reproducer &r)
2744 if (m_struct_or_union)
2745 if (NULL == m_struct_or_union->dyn_cast_struct ())
2746 /* We have a union; the fields have already been written by
2747 union::write_reproducer. */
2748 return;
2750 const char *fields_id = r.make_identifier (this, "fields");
2751 r.write (" gcc_jit_field *%s[%i] = {\n",
2752 fields_id,
2753 m_fields.length ());
2754 int i;
2755 field *field;
2756 FOR_EACH_VEC_ELT (m_fields, i, field)
2757 r.write (" %s,\n", r.get_identifier (field));
2758 r.write (" };\n");
2760 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
2761 " %s, /* gcc_jit_location *loc */\n"
2762 " %i, /* int num_fields */\n"
2763 " %s); /* gcc_jit_field **fields */\n",
2764 r.get_identifier (m_struct_or_union),
2765 r.get_identifier ((memento *)NULL),
2766 m_fields.length (),
2767 fields_id);
2770 /* Implementation of recording::memento::make_debug_string for
2771 field tables. */
2773 recording::string *
2774 recording::fields::make_debug_string ()
2776 return string::from_printf (m_ctxt,
2777 "fields");
2780 /* The implementation of class gcc::jit::recording::rvalue. */
2782 /* Create a recording::access_field_rvalue instance and add it to
2783 the rvalue's context's list of mementos.
2785 Implements the post-error-checking part of
2786 gcc_jit_rvalue_access_field. */
2788 recording::rvalue *
2789 recording::rvalue::access_field (recording::location *loc,
2790 field *field)
2792 recording::rvalue *result =
2793 new access_field_rvalue (m_ctxt, loc, this, field);
2794 m_ctxt->record (result);
2795 return result;
2798 /* Create a recording::dereference_field_rvalue instance and add it to
2799 the rvalue's context's list of mementos.
2801 Implements the post-error-checking part of
2802 gcc_jit_rvalue_dereference_field. */
2804 recording::lvalue *
2805 recording::rvalue::dereference_field (recording::location *loc,
2806 field *field)
2808 recording::lvalue *result =
2809 new dereference_field_rvalue (m_ctxt, loc, this, field);
2810 m_ctxt->record (result);
2811 return result;
2814 /* Create a recording::dereference_rvalue instance and add it to the
2815 rvalue's context's list of mementos.
2817 Implements the post-error-checking part of
2818 gcc_jit_rvalue_dereference. */
2820 recording::lvalue *
2821 recording::rvalue::dereference (recording::location *loc)
2823 recording::lvalue *result =
2824 new dereference_rvalue (m_ctxt, loc, this);
2825 m_ctxt->record (result);
2826 return result;
2829 /* An rvalue visitor, for validating that every rvalue within an expression
2830 trees within "STMT" has the correct scope (e.g. no access to locals
2831 of a different function). */
2833 class rvalue_usage_validator : public recording::rvalue_visitor
2835 public:
2836 rvalue_usage_validator (const char *api_funcname,
2837 recording::context *ctxt,
2838 recording::statement *stmt);
2840 void
2841 visit (recording::rvalue *rvalue);
2843 private:
2844 const char *m_api_funcname;
2845 recording::context *m_ctxt;
2846 recording::statement *m_stmt;
2849 /* The trivial constructor for rvalue_usage_validator. */
2851 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
2852 recording::context *ctxt,
2853 recording::statement *stmt)
2854 : m_api_funcname (api_funcname),
2855 m_ctxt (ctxt),
2856 m_stmt (stmt)
2860 /* Verify that the given rvalue is in the correct scope. */
2862 void
2863 rvalue_usage_validator::visit (recording::rvalue *rvalue)
2865 gcc_assert (m_stmt->get_block ());
2866 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
2868 /* Most rvalues don't have a scope (only locals and params). */
2869 if (rvalue->get_scope ())
2871 if (rvalue->get_scope () != stmt_scope)
2872 m_ctxt->add_error
2873 (rvalue->get_loc (),
2874 "%s:"
2875 " rvalue %s (type: %s)"
2876 " has scope limited to function %s"
2877 " but was used within function %s"
2878 " (in statement: %s)",
2879 m_api_funcname,
2880 rvalue->get_debug_string (),
2881 rvalue->get_type ()->get_debug_string (),
2882 rvalue->get_scope ()->get_debug_string (),
2883 stmt_scope->get_debug_string (),
2884 m_stmt->get_debug_string ());
2886 else
2888 if (rvalue->dyn_cast_param ())
2889 m_ctxt->add_error
2890 (rvalue->get_loc (),
2891 "%s:"
2892 " param %s (type: %s)"
2893 " was used within function %s"
2894 " (in statement: %s)"
2895 " but is not associated with any function",
2896 m_api_funcname,
2897 rvalue->get_debug_string (),
2898 rvalue->get_type ()->get_debug_string (),
2899 stmt_scope->get_debug_string (),
2900 m_stmt->get_debug_string ());
2904 /* Verify that it's valid to use this rvalue (and all expressions
2905 in the tree below it) within the given statement.
2907 For example, we must reject attempts to use a local from one
2908 function within a different function here, or we'll get
2909 an ICE deep inside toplev::main. */
2911 void
2912 recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
2914 rvalue_usage_validator v (api_funcname,
2915 s->get_context (),
2918 /* Verify that it's OK to use this rvalue within s. */
2919 v.visit (this);
2921 /* Traverse the expression tree below "this", verifying all rvalues
2922 within it. */
2923 visit_children (&v);
2926 /* Set the scope of this rvalue to be the given function. This can only
2927 be done once on a given rvalue. */
2929 void
2930 recording::rvalue::set_scope (function *scope)
2932 gcc_assert (scope);
2933 gcc_assert (NULL == m_scope);
2934 m_scope = scope;
2938 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
2939 themselves.
2940 Instances of rvalue don't need an upcast call. */
2942 const char *
2943 recording::rvalue::access_as_rvalue (reproducer &r)
2945 return r.get_identifier (this);
2949 /* The implementation of class gcc::jit::recording::lvalue. */
2951 /* Create a recording::new_access_field_of_lvalue instance and add it to
2952 the lvalue's context's list of mementos.
2954 Implements the post-error-checking part of
2955 gcc_jit_lvalue_access_field. */
2957 recording::lvalue *
2958 recording::lvalue::access_field (recording::location *loc,
2959 field *field)
2961 recording::lvalue *result =
2962 new access_field_of_lvalue (m_ctxt, loc, this, field);
2963 m_ctxt->record (result);
2964 return result;
2967 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
2968 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
2969 upcast call. */
2971 const char *
2972 recording::lvalue::access_as_rvalue (reproducer &r)
2974 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
2975 r.get_identifier (this));
2978 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
2979 Instances of lvalue don't need to be upcast. */
2981 const char *
2982 recording::lvalue::access_as_lvalue (reproducer &r)
2984 return r.get_identifier (this);
2987 /* Create a recording::get_address_of_lvalue instance and add it to
2988 the lvalue's context's list of mementos.
2990 Implements the post-error-checking part of
2991 gcc_jit_lvalue_get_address. */
2993 recording::rvalue *
2994 recording::lvalue::get_address (recording::location *loc)
2996 recording::rvalue *result =
2997 new get_address_of_lvalue (m_ctxt, loc, this);
2998 m_ctxt->record (result);
2999 return result;
3002 /* The implementation of class gcc::jit::recording::param. */
3004 /* Implementation of pure virtual hook recording::memento::replay_into
3005 for recording::param. */
3007 void
3008 recording::param::replay_into (replayer *r)
3010 set_playback_obj (r->new_param (playback_location (r, m_loc),
3011 m_type->playback_type (),
3012 m_name->c_str ()));
3015 /* Implementation of recording::rvalue::access_as_rvalue for params.
3016 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3017 upcast call. */
3019 const char *
3020 recording::param::access_as_rvalue (reproducer &r)
3022 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3023 r.get_identifier (this));
3026 /* Implementation of recording::lvalue::access_as_lvalue for params.
3027 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3028 upcast call. */
3030 const char *
3031 recording::param::access_as_lvalue (reproducer &r)
3033 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3034 r.get_identifier (this));
3037 /* Implementation of recording::memento::write_reproducer for params. */
3039 void
3040 recording::param::write_reproducer (reproducer &r)
3042 const char *id = r.make_identifier (this, "param");
3043 r.write (" gcc_jit_param *%s =\n"
3044 " gcc_jit_context_new_param (%s,\n"
3045 " %s, /* gcc_jit_location *loc */\n"
3046 " %s, /*gcc_jit_type *type */\n"
3047 " %s); /* const char *name */\n",
3049 r.get_identifier (get_context ()),
3050 r.get_identifier (m_loc),
3051 r.get_identifier_as_type (m_type),
3052 m_name->get_debug_string ());
3055 /* The implementation of class gcc::jit::recording::function. */
3057 /* gcc::jit::recording::function's constructor. */
3059 recording::function::function (context *ctxt,
3060 recording::location *loc,
3061 enum gcc_jit_function_kind kind,
3062 type *return_type,
3063 recording::string *name,
3064 int num_params,
3065 recording::param **params,
3066 int is_variadic,
3067 enum built_in_function builtin_id)
3068 : memento (ctxt),
3069 m_loc (loc),
3070 m_kind (kind),
3071 m_return_type (return_type),
3072 m_name (name),
3073 m_params (),
3074 m_is_variadic (is_variadic),
3075 m_builtin_id (builtin_id),
3076 m_locals (),
3077 m_blocks ()
3079 for (int i = 0; i< num_params; i++)
3081 param *param = params[i];
3082 gcc_assert (param);
3084 /* Associate each param with this function.
3086 Verify that the param doesn't already have a function. */
3087 if (param->get_scope ())
3089 /* We've already rejected attempts to reuse a param between
3090 different functions (within gcc_jit_context_new_function), so
3091 if the param *does* already have a function, it must be being
3092 reused within the params array for this function. We must
3093 produce an error for this reuse (blocking the compile), since
3094 otherwise we'd have an ICE later on. */
3095 gcc_assert (this == param->get_scope ());
3096 ctxt->add_error
3097 (loc,
3098 "gcc_jit_context_new_function:"
3099 " parameter %s (type: %s)"
3100 " is used more than once when creating function %s",
3101 param->get_debug_string (),
3102 param->get_type ()->get_debug_string (),
3103 name->c_str ());
3105 else
3107 /* The normal, non-error case: associate this function with the
3108 param. */
3109 param->set_scope (this);
3112 m_params.safe_push (param);
3116 /* Implementation of pure virtual hook recording::memento::replay_into
3117 for recording::function. */
3119 void
3120 recording::function::replay_into (replayer *r)
3122 /* Convert m_params to a vec of playback param. */
3123 auto_vec <playback::param *> params;
3124 int i;
3125 recording::param *param;
3126 params.create (m_params.length ());
3127 FOR_EACH_VEC_ELT (m_params, i, param)
3128 params.safe_push (param->playback_param ());
3130 set_playback_obj (r->new_function (playback_location (r, m_loc),
3131 m_kind,
3132 m_return_type->playback_type (),
3133 m_name->c_str (),
3134 &params,
3135 m_is_variadic,
3136 m_builtin_id));
3139 /* Create a recording::local instance and add it to
3140 the functions's context's list of mementos, and to the function's
3141 list of locals.
3143 Implements the post-error-checking part of
3144 gcc_jit_function_new_local. */
3146 recording::lvalue *
3147 recording::function::new_local (recording::location *loc,
3148 type *type,
3149 const char *name)
3151 local *result = new local (this, loc, type, new_string (name));
3152 m_ctxt->record (result);
3153 m_locals.safe_push (result);
3154 return result;
3157 /* Create a recording::block instance and add it to
3158 the functions's context's list of mementos, and to the function's
3159 list of blocks.
3161 Implements the post-error-checking part of
3162 gcc_jit_function_new_block. */
3164 recording::block*
3165 recording::function::new_block (const char *name)
3167 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
3169 recording::block *result =
3170 new recording::block (this, m_blocks.length (), new_string (name));
3171 m_ctxt->record (result);
3172 m_blocks.safe_push (result);
3173 return result;
3176 /* Override the default implementation of
3177 recording::memento::write_to_dump by dumping a C-like
3178 representation of the function; either like a prototype
3179 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3180 all other kinds of function. */
3182 void
3183 recording::function::write_to_dump (dump &d)
3185 switch (m_kind)
3187 default: gcc_unreachable ();
3188 case GCC_JIT_FUNCTION_EXPORTED:
3189 case GCC_JIT_FUNCTION_IMPORTED:
3190 d.write ("extern ");
3191 break;
3192 case GCC_JIT_FUNCTION_INTERNAL:
3193 d.write ("static ");
3194 break;
3195 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
3196 d.write ("static inline ");
3197 break;
3199 d.write ("%s\n", m_return_type->get_debug_string ());
3201 if (d.update_locations ())
3202 m_loc = d.make_location ();
3204 d.write ("%s (", get_debug_string ());
3206 int i;
3207 recording::param *param;
3208 FOR_EACH_VEC_ELT (m_params, i, param)
3210 if (i > 0)
3211 d.write (", ");
3212 d.write ("%s %s",
3213 param->get_type ()->get_debug_string (),
3214 param->get_debug_string ());
3216 d.write (")");
3217 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
3219 d.write ("; /* (imported) */\n\n");
3221 else
3223 int i;
3224 local *var = NULL;
3225 block *b;
3226 d.write ("\n{\n");
3228 /* Write locals: */
3229 FOR_EACH_VEC_ELT (m_locals, i, var)
3230 var->write_to_dump (d);
3231 if (m_locals.length ())
3232 d.write ("\n");
3234 /* Write each block: */
3235 FOR_EACH_VEC_ELT (m_blocks, i, b)
3237 if (i > 0)
3238 d.write ("\n");
3239 b->write_to_dump (d);
3242 d.write ("}\n\n");
3246 /* Pre-compilation validation of a function, for those things we can't
3247 check until the context is (supposedly) fully-populated. */
3249 void
3250 recording::function::validate ()
3252 /* Complain about empty functions with non-void return type. */
3253 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
3254 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
3255 if (0 == m_blocks.length ())
3256 m_ctxt->add_error (m_loc,
3257 "function %s returns non-void (type: %s)"
3258 " but has no blocks",
3259 get_debug_string (),
3260 m_return_type->get_debug_string ());
3262 /* Check that all blocks are terminated. */
3263 int num_invalid_blocks = 0;
3265 int i;
3266 block *b;
3268 FOR_EACH_VEC_ELT (m_blocks, i, b)
3269 if (!b->validate ())
3270 num_invalid_blocks++;
3273 /* Check that all blocks are reachable. */
3274 if (m_blocks.length () > 0 && 0 == num_invalid_blocks)
3276 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3277 flag, starting at the initial block. */
3278 auto_vec<block *> worklist (m_blocks.length ());
3279 worklist.safe_push (m_blocks[0]);
3280 while (worklist.length () > 0)
3282 block *b = worklist.pop ();
3283 b->m_is_reachable = true;
3285 /* Add successor blocks that aren't yet marked to the worklist. */
3286 /* We checked that each block has a terminating statement above . */
3287 block *next1, *next2;
3288 int n = b->get_successor_blocks (&next1, &next2);
3289 switch (n)
3291 default:
3292 gcc_unreachable ();
3293 case 2:
3294 if (!next2->m_is_reachable)
3295 worklist.safe_push (next2);
3296 /* fallthrough */
3297 case 1:
3298 if (!next1->m_is_reachable)
3299 worklist.safe_push (next1);
3300 break;
3301 case 0:
3302 break;
3306 /* Now complain about any blocks that haven't been marked. */
3308 int i;
3309 block *b;
3310 FOR_EACH_VEC_ELT (m_blocks, i, b)
3311 if (!b->m_is_reachable)
3312 m_ctxt->add_error (b->get_loc (),
3313 "unreachable block: %s",
3314 b->get_debug_string ());
3319 /* Implements the post-error-checking part of
3320 gcc_jit_function_dump_to_dot. */
3322 void
3323 recording::function::dump_to_dot (const char *path)
3325 FILE *fp = fopen (path, "w");
3326 if (!fp)
3327 return;
3329 pretty_printer the_pp;
3330 the_pp.buffer->stream = fp;
3332 pretty_printer *pp = &the_pp;
3334 pp_printf (pp,
3335 "digraph %s {\n", get_debug_string ());
3337 /* Blocks: */
3339 int i;
3340 block *b;
3341 FOR_EACH_VEC_ELT (m_blocks, i, b)
3342 b->dump_to_dot (pp);
3345 /* Edges: */
3347 int i;
3348 block *b;
3349 FOR_EACH_VEC_ELT (m_blocks, i, b)
3350 b->dump_edges_to_dot (pp);
3353 pp_printf (pp, "}\n");
3354 pp_flush (pp);
3355 fclose (fp);
3358 /* Implementation of recording::memento::make_debug_string for
3359 functions. */
3361 recording::string *
3362 recording::function::make_debug_string ()
3364 return m_name;
3367 /* A table of enum gcc_jit_function_kind values expressed in string
3368 form. */
3370 static const char * const names_of_function_kinds[] = {
3371 "GCC_JIT_FUNCTION_EXPORTED",
3372 "GCC_JIT_FUNCTION_INTERNAL",
3373 "GCC_JIT_FUNCTION_IMPORTED",
3374 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3377 /* Implementation of recording::memento::write_reproducer for functions. */
3379 void
3380 recording::function::write_reproducer (reproducer &r)
3382 const char *id = r.make_identifier (this, "func");
3384 if (m_builtin_id)
3386 r.write (" gcc_jit_function *%s =\n"
3387 " gcc_jit_context_get_builtin_function (%s,\n"
3388 " %s);\n",
3390 r.get_identifier (get_context ()),
3391 m_name->get_debug_string ());
3392 return;
3394 const char *params_id = r.make_tmp_identifier ("params_for", this);
3395 r.write (" gcc_jit_param *%s[%i] = {\n",
3396 params_id,
3397 m_params.length ());
3398 int i;
3399 param *param;
3400 FOR_EACH_VEC_ELT (m_params, i, param)
3401 r.write (" %s,\n", r.get_identifier (param));
3402 r.write (" };\n");
3403 r.write (" gcc_jit_function *%s =\n"
3404 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3405 " %s, /* gcc_jit_location *loc */\n"
3406 " %s, /* enum gcc_jit_function_kind kind */\n"
3407 " %s, /* gcc_jit_type *return_type */\n"
3408 " %s, /* const char *name */\n"
3409 " %i, /* int num_params */\n"
3410 " %s, /* gcc_jit_param **params */\n"
3411 " %i); /* int is_variadic */\n",
3413 r.get_identifier (get_context ()),
3414 r.get_identifier (m_loc),
3415 names_of_function_kinds[m_kind],
3416 r.get_identifier_as_type (m_return_type),
3417 m_name->get_debug_string (),
3418 m_params.length (),
3419 params_id,
3420 m_is_variadic);
3424 /* The implementation of class gcc::jit::recording::block. */
3426 /* Create a recording::eval instance and add it to
3427 the block's context's list of mementos, and to the block's
3428 list of statements.
3430 Implements the heart of gcc_jit_block_add_eval. */
3432 recording::statement *
3433 recording::block::add_eval (recording::location *loc,
3434 recording::rvalue *rvalue)
3436 statement *result = new eval (this, loc, rvalue);
3437 m_ctxt->record (result);
3438 m_statements.safe_push (result);
3439 return result;
3442 /* Create a recording::assignment instance and add it to
3443 the block's context's list of mementos, and to the block's
3444 list of statements.
3446 Implements the heart of gcc_jit_block_add_assignment. */
3448 recording::statement *
3449 recording::block::add_assignment (recording::location *loc,
3450 recording::lvalue *lvalue,
3451 recording::rvalue *rvalue)
3453 statement *result = new assignment (this, loc, lvalue, rvalue);
3454 m_ctxt->record (result);
3455 m_statements.safe_push (result);
3456 return result;
3459 /* Create a recording::assignment_op instance and add it to
3460 the block's context's list of mementos, and to the block's
3461 list of statements.
3463 Implements the heart of gcc_jit_block_add_assignment_op. */
3465 recording::statement *
3466 recording::block::add_assignment_op (recording::location *loc,
3467 recording::lvalue *lvalue,
3468 enum gcc_jit_binary_op op,
3469 recording::rvalue *rvalue)
3471 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
3472 m_ctxt->record (result);
3473 m_statements.safe_push (result);
3474 return result;
3477 /* Create a recording::comment instance and add it to
3478 the block's context's list of mementos, and to the block's
3479 list of statements.
3481 Implements the heart of gcc_jit_block_add_comment. */
3483 recording::statement *
3484 recording::block::add_comment (recording::location *loc,
3485 const char *text)
3487 statement *result = new comment (this, loc, new_string (text));
3488 m_ctxt->record (result);
3489 m_statements.safe_push (result);
3490 return result;
3493 /* Create a recording::end_with_conditional instance and add it to
3494 the block's context's list of mementos, and to the block's
3495 list of statements.
3497 Implements the heart of gcc_jit_block_end_with_conditional. */
3499 recording::statement *
3500 recording::block::end_with_conditional (recording::location *loc,
3501 recording::rvalue *boolval,
3502 recording::block *on_true,
3503 recording::block *on_false)
3505 statement *result = new conditional (this, loc, boolval, on_true, on_false);
3506 m_ctxt->record (result);
3507 m_statements.safe_push (result);
3508 m_has_been_terminated = true;
3509 return result;
3512 /* Create a recording::end_with_jump instance and add it to
3513 the block's context's list of mementos, and to the block's
3514 list of statements.
3516 Implements the heart of gcc_jit_block_end_with_jump. */
3518 recording::statement *
3519 recording::block::end_with_jump (recording::location *loc,
3520 recording::block *target)
3522 statement *result = new jump (this, loc, target);
3523 m_ctxt->record (result);
3524 m_statements.safe_push (result);
3525 m_has_been_terminated = true;
3526 return result;
3529 /* Create a recording::end_with_return instance and add it to
3530 the block's context's list of mementos, and to the block's
3531 list of statements.
3533 Implements the post-error-checking parts of
3534 gcc_jit_block_end_with_return and
3535 gcc_jit_block_end_with_void_return. */
3537 recording::statement *
3538 recording::block::end_with_return (recording::location *loc,
3539 recording::rvalue *rvalue)
3541 /* This is used by both gcc_jit_function_add_return and
3542 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3543 the former and NULL for the latter. */
3544 statement *result = new return_ (this, loc, rvalue);
3545 m_ctxt->record (result);
3546 m_statements.safe_push (result);
3547 m_has_been_terminated = true;
3548 return result;
3551 /* Override the default implementation of
3552 recording::memento::write_to_dump for blocks by writing
3553 an unindented block name as a label, followed by the indented
3554 statements:
3556 BLOCK_NAME:
3557 STATEMENT_1;
3558 STATEMENT_2;
3560 STATEMENT_N; */
3562 void
3563 recording::block::write_to_dump (dump &d)
3565 d.write ("%s:\n", get_debug_string ());
3567 int i;
3568 statement *s;
3569 FOR_EACH_VEC_ELT (m_statements, i, s)
3570 s->write_to_dump (d);
3573 /* Validate a block by ensuring that it has been terminated. */
3575 bool
3576 recording::block::validate ()
3578 /* Check for termination. */
3579 if (!has_been_terminated ())
3581 statement *stmt = get_last_statement ();
3582 location *loc = stmt ? stmt->get_loc () : NULL;
3583 m_func->get_context ()->add_error (loc,
3584 "unterminated block in %s: %s",
3585 m_func->get_debug_string (),
3586 get_debug_string ());
3587 return false;
3590 return true;
3593 /* Get the source-location of a block by using that of the first
3594 statement within it, if any. */
3596 recording::location *
3597 recording::block::get_loc () const
3599 recording::statement *stmt = get_first_statement ();
3600 if (stmt)
3601 return stmt->get_loc ();
3602 else
3603 return NULL;
3606 /* Get the first statement within a block, if any. */
3608 recording::statement *
3609 recording::block::get_first_statement () const
3611 if (m_statements.length ())
3612 return m_statements[0];
3613 else
3614 return NULL;
3617 /* Get the last statement within a block, if any. */
3619 recording::statement *
3620 recording::block::get_last_statement () const
3622 if (m_statements.length ())
3623 return m_statements[m_statements.length () - 1];
3624 else
3625 return NULL;
3628 /* Assuming that this block has been terminated, get the number of
3629 successor blocks, which will be 0, 1 or 2, for return, unconditional
3630 jump, and conditional jump respectively.
3631 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
3632 is written to NEXT1, and the second (if any) to NEXT2.
3634 Used when validating functions, and when dumping dot representations
3635 of them. */
3638 recording::block::get_successor_blocks (block **next1, block **next2) const
3640 gcc_assert (m_has_been_terminated);
3641 gcc_assert (next1);
3642 gcc_assert (next2);
3643 statement *last_statement = get_last_statement ();
3644 gcc_assert (last_statement);
3645 return last_statement->get_successor_blocks (next1, next2);
3648 /* Implementation of pure virtual hook recording::memento::replay_into
3649 for recording::block. */
3651 void
3652 recording::block::replay_into (replayer *)
3654 set_playback_obj (m_func->playback_function ()
3655 ->new_block (playback_string (m_name)));
3658 /* Implementation of recording::memento::make_debug_string for
3659 blocks. */
3661 recording::string *
3662 recording::block::make_debug_string ()
3664 if (m_name)
3665 return m_name;
3666 else
3667 return string::from_printf (m_ctxt,
3668 "<UNNAMED BLOCK %p>",
3669 (void *)this);
3672 /* Implementation of recording::memento::write_reproducer for blocks. */
3674 void
3675 recording::block::write_reproducer (reproducer &r)
3677 const char *id = r.make_identifier (this, "block");
3678 r.write (" gcc_jit_block *%s =\n"
3679 " gcc_jit_function_new_block (%s, %s);\n",
3681 r.get_identifier (m_func),
3682 m_name ? m_name->get_debug_string () : "NULL");
3685 /* Dump a block in graphviz form into PP, capturing the block name (if
3686 any) and the statements. */
3688 void
3689 recording::block::dump_to_dot (pretty_printer *pp)
3691 pp_printf (pp,
3692 ("\tblock_%d "
3693 "[shape=record,style=filled,fillcolor=white,label=\"{"),
3694 m_index);
3695 pp_write_text_to_stream (pp);
3696 if (m_name)
3698 pp_string (pp, m_name->c_str ());
3699 pp_string (pp, ":");
3700 pp_newline (pp);
3701 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3704 int i;
3705 statement *s;
3706 FOR_EACH_VEC_ELT (m_statements, i, s)
3708 pp_string (pp, s->get_debug_string ());
3709 pp_newline (pp);
3710 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3713 pp_printf (pp,
3714 "}\"];\n\n");
3715 pp_flush (pp);
3718 /* Dump the out-edges of the block in graphviz form into PP. */
3720 void
3721 recording::block::dump_edges_to_dot (pretty_printer *pp)
3723 block *next[2];
3724 int num_succs = get_successor_blocks (&next[0], &next[1]);
3725 for (int i = 0; i < num_succs; i++)
3726 pp_printf (pp,
3727 "\tblock_%d:s -> block_%d:n;\n",
3728 m_index, next[i]->m_index);
3731 /* The implementation of class gcc::jit::recording::global. */
3733 /* Implementation of pure virtual hook recording::memento::replay_into
3734 for recording::global. */
3736 void
3737 recording::global::replay_into (replayer *r)
3739 set_playback_obj (r->new_global (playback_location (r, m_loc),
3740 m_kind,
3741 m_type->playback_type (),
3742 playback_string (m_name)));
3745 /* Override the default implementation of
3746 recording::memento::write_to_dump for globals.
3747 This will be of the form:
3749 GCC_JIT_GLOBAL_EXPORTED:
3750 "TYPE NAME;"
3751 e.g. "int foo;"
3753 GCC_JIT_GLOBAL_INTERNAL:
3754 "static TYPE NAME;"
3755 e.g. "static int foo;"
3757 GCC_JIT_GLOBAL_IMPORTED:
3758 "extern TYPE NAME;"
3759 e.g. "extern int foo;"
3761 These are written to the top of the dump by
3762 recording::context::dump_to_file. */
3764 void
3765 recording::global::write_to_dump (dump &d)
3767 if (d.update_locations ())
3768 m_loc = d.make_location ();
3770 switch (m_kind)
3772 default:
3773 gcc_unreachable ();
3775 case GCC_JIT_GLOBAL_EXPORTED:
3776 break;
3778 case GCC_JIT_GLOBAL_INTERNAL:
3779 d.write ("static ");
3780 break;
3782 case GCC_JIT_GLOBAL_IMPORTED:
3783 d.write ("extern ");
3784 break;
3786 d.write ("%s %s;\n",
3787 m_type->get_debug_string (),
3788 get_debug_string ());
3791 /* A table of enum gcc_jit_global_kind values expressed in string
3792 form. */
3794 static const char * const global_kind_reproducer_strings[] = {
3795 "GCC_JIT_GLOBAL_EXPORTED",
3796 "GCC_JIT_GLOBAL_INTERNAL",
3797 "GCC_JIT_GLOBAL_IMPORTED"
3800 /* Implementation of recording::memento::write_reproducer for globals. */
3802 void
3803 recording::global::write_reproducer (reproducer &r)
3805 const char *id = r.make_identifier (this, "block");
3806 r.write (" gcc_jit_lvalue *%s =\n"
3807 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
3808 " %s, /* gcc_jit_location *loc */\n"
3809 " %s, /* enum gcc_jit_global_kind kind */\n"
3810 " %s, /* gcc_jit_type *type */\n"
3811 " %s); /* const char *name */\n",
3813 r.get_identifier (get_context ()),
3814 r.get_identifier (m_loc),
3815 global_kind_reproducer_strings[m_kind],
3816 r.get_identifier_as_type (get_type ()),
3817 m_name->get_debug_string ());
3820 /* The implementation of the various const-handling classes:
3821 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
3823 /* Explicit specialization of the various mementos we're interested in. */
3824 template class recording::memento_of_new_rvalue_from_const <int>;
3825 template class recording::memento_of_new_rvalue_from_const <long>;
3826 template class recording::memento_of_new_rvalue_from_const <double>;
3827 template class recording::memento_of_new_rvalue_from_const <void *>;
3829 /* Implementation of the pure virtual hook recording::memento::replay_into
3830 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
3832 template <typename HOST_TYPE>
3833 void
3834 recording::
3835 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
3837 set_playback_obj
3838 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
3839 m_value));
3842 /* The make_debug_string and write_reproducer methods vary between the
3843 various
3844 memento_of_new_rvalue_from_const <HOST_TYPE>
3845 classes, so we explicitly write specializations of them.
3847 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
3848 namespaces are written out explicitly, which is why most of this file
3849 doesn't abbreviate things by entering the "recording" namespace.
3851 However, these specializations are required to be in the same namespace
3852 as the template, hence we now have to enter the gcc::jit::recording
3853 namespace. */
3855 namespace recording
3858 /* The make_debug_string specialization for <int>, which renders it as
3859 (TARGET_TYPE)LITERAL
3860 e.g.
3861 "(int)42". */
3863 template <>
3864 string *
3865 memento_of_new_rvalue_from_const <int>::make_debug_string ()
3867 return string::from_printf (m_ctxt,
3868 "(%s)%i",
3869 m_type->get_debug_string (),
3870 m_value);
3873 /* The write_reproducer specialization for <int>. */
3875 template <>
3876 void
3877 memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
3879 const char *id = r.make_identifier (this, "rvalue");
3880 r.write (" gcc_jit_rvalue *%s =\n"
3881 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
3882 " %s, /* gcc_jit_type *numeric_type */\n"
3883 " %i); /* int value */\n",
3885 r.get_identifier (get_context ()),
3886 r.get_identifier_as_type (m_type),
3887 m_value);
3890 /* The make_debug_string specialization for <long>, rendering it as
3891 (TARGET_TYPE)LITERAL
3892 e.g.
3893 "(long)42". */
3895 template <>
3896 string *
3897 memento_of_new_rvalue_from_const <long>::make_debug_string ()
3899 return string::from_printf (m_ctxt,
3900 "(%s)%li",
3901 m_type->get_debug_string (),
3902 m_value);
3905 /* The write_reproducer specialization for <long>. */
3907 template <>
3908 void
3909 recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
3911 const char *id = r.make_identifier (this, "rvalue");
3913 /* We have to special-case LONG_MIN, since e.g.
3914 -9223372036854775808L
3915 is parsed as
3916 -(9223372036854775808L)
3917 and hence we'd get:
3918 error: integer constant is so large that it is unsigned [-Werror]
3919 Workaround this by writing (LONG_MIN + 1) - 1. */
3920 if (m_value == LONG_MIN)
3922 r.write (" gcc_jit_rvalue *%s =\n"
3923 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
3924 " %s, /* gcc_jit_type *numeric_type */\n"
3925 " %ldL - 1); /* long value */\n",
3927 r.get_identifier (get_context ()),
3928 r.get_identifier_as_type (m_type),
3929 m_value + 1);;
3930 return;
3933 r.write (" gcc_jit_rvalue *%s =\n"
3934 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
3935 " %s, /* gcc_jit_type *numeric_type */\n"
3936 " %ldL); /* long value */\n",
3938 r.get_identifier (get_context ()),
3939 r.get_identifier_as_type (m_type),
3940 m_value);
3943 /* The make_debug_string specialization for <double>, rendering it as
3944 (TARGET_TYPE)LITERAL
3945 e.g.
3946 "(float)42.0". */
3948 template <>
3949 string *
3950 memento_of_new_rvalue_from_const <double>::make_debug_string ()
3952 return string::from_printf (m_ctxt,
3953 "(%s)%f",
3954 m_type->get_debug_string (),
3955 m_value);
3958 /* The write_reproducer specialization for <double>. */
3960 template <>
3961 void
3962 recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
3964 const char *id = r.make_identifier (this, "rvalue");
3965 r.write (" gcc_jit_rvalue *%s =\n"
3966 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
3967 " %s, /* gcc_jit_type *numeric_type */\n"
3968 " %f); /* double value */\n",
3970 r.get_identifier (get_context ()),
3971 r.get_identifier_as_type (m_type),
3972 m_value);
3975 /* The make_debug_string specialization for <void *>, rendering it as
3976 (TARGET_TYPE)HEX
3977 e.g.
3978 "(int *)0xdeadbeef"
3980 Zero is rendered as NULL e.g.
3981 "(int *)NULL". */
3983 template <>
3984 string *
3985 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
3987 if (m_value != NULL)
3988 return string::from_printf (m_ctxt,
3989 "(%s)%p",
3990 m_type->get_debug_string (), m_value);
3991 else
3992 return string::from_printf (m_ctxt,
3993 "(%s)NULL",
3994 m_type->get_debug_string ());
3997 /* Implementation of recording::memento::write_reproducer for <void *>
3998 values. */
4000 template <>
4001 void
4002 memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
4004 const char *id = r.make_identifier (this, "rvalue");
4005 if (m_value)
4006 r.write (" gcc_jit_rvalue *%s =\n"
4007 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4008 " %s, /* gcc_jit_type *pointer_type */\n"
4009 " (void *)%p); /* void *value */\n",
4011 r.get_identifier (get_context ()),
4012 r.get_identifier_as_type (m_type),
4013 m_value);
4014 else
4015 r.write (" gcc_jit_rvalue *%s =\n"
4016 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4017 " %s); /* gcc_jit_type *pointer_type */\n",
4019 r.get_identifier (get_context ()),
4020 r.get_identifier_as_type (m_type));
4023 /* We're done specializing make_debug_string and write_reproducer, so we
4024 can exit the gcc::jit::recording namespace. */
4026 } // namespace recording
4028 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4030 /* Implementation of pure virtual hook recording::memento::replay_into
4031 for recording::memento_of_new_string_literal. */
4033 void
4034 recording::memento_of_new_string_literal::replay_into (replayer *r)
4036 set_playback_obj (r->new_string_literal (m_value->c_str ()));
4039 /* Implementation of recording::memento::make_debug_string for
4040 string literals. */
4042 recording::string *
4043 recording::memento_of_new_string_literal::make_debug_string ()
4045 return string::from_printf (m_ctxt,
4046 "%s",
4047 m_value->get_debug_string ());
4050 /* Implementation of recording::memento::write_reproducer for string literal
4051 values. */
4053 void
4054 recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
4056 const char *id = r.make_identifier (this, "rvalue");
4057 r.write (" gcc_jit_rvalue *%s =\n"
4058 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4059 " %s); /* const char *value */\n",
4061 r.get_identifier (get_context ()),
4062 m_value->get_debug_string ());
4065 /* The implementation of class gcc::jit::recording::unary_op. */
4067 /* Implementation of pure virtual hook recording::memento::replay_into
4068 for recording::unary_op. */
4070 void
4071 recording::unary_op::replay_into (replayer *r)
4073 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
4074 m_op,
4075 get_type ()->playback_type (),
4076 m_a->playback_rvalue ()));
4079 /* Implementation of pure virtual hook recording::rvalue::visit_children
4080 for recording::unary_op. */
4081 void
4082 recording::unary_op::visit_children (rvalue_visitor *v)
4084 v->visit (m_a);
4087 /* Implementation of recording::memento::make_debug_string for
4088 unary ops. */
4090 static const char * const unary_op_strings[] = {
4091 "-", /* GCC_JIT_UNARY_OP_MINUS */
4092 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4093 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4094 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4097 recording::string *
4098 recording::unary_op::make_debug_string ()
4100 return string::from_printf (m_ctxt,
4101 "%s(%s)",
4102 unary_op_strings[m_op],
4103 m_a->get_debug_string ());
4106 static const char * const unary_op_reproducer_strings[] = {
4107 "GCC_JIT_UNARY_OP_MINUS",
4108 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4109 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4110 "GCC_JIT_UNARY_OP_ABS"
4113 /* Implementation of recording::memento::write_reproducer for unary ops. */
4115 void
4116 recording::unary_op::write_reproducer (reproducer &r)
4118 const char *id = r.make_identifier (this, "rvalue");
4119 r.write (" gcc_jit_rvalue *%s =\n"
4120 " gcc_jit_context_new_unary_op (%s,\n"
4121 " %s, /* gcc_jit_location *loc */\n"
4122 " %s, /* enum gcc_jit_unary_op op */\n"
4123 " %s, /* gcc_jit_type *result_type */\n"
4124 " %s); /* gcc_jit_rvalue *a */\n",
4126 r.get_identifier (get_context ()),
4127 r.get_identifier (m_loc),
4128 unary_op_reproducer_strings[m_op],
4129 r.get_identifier_as_type (get_type ()),
4130 r.get_identifier_as_rvalue (m_a));
4133 /* The implementation of class gcc::jit::recording::binary_op. */
4135 /* Implementation of pure virtual hook recording::memento::replay_into
4136 for recording::binary_op. */
4138 void
4139 recording::binary_op::replay_into (replayer *r)
4141 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
4142 m_op,
4143 get_type ()->playback_type (),
4144 m_a->playback_rvalue (),
4145 m_b->playback_rvalue ()));
4148 /* Implementation of pure virtual hook recording::rvalue::visit_children
4149 for recording::binary_op. */
4150 void
4151 recording::binary_op::visit_children (rvalue_visitor *v)
4153 v->visit (m_a);
4154 v->visit (m_b);
4157 /* Implementation of recording::memento::make_debug_string for
4158 binary ops. */
4160 static const char * const binary_op_strings[] = {
4161 "+", /* GCC_JIT_BINARY_OP_PLUS */
4162 "-", /* GCC_JIT_BINARY_OP_MINUS */
4163 "*", /* GCC_JIT_BINARY_OP_MULT */
4164 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4165 "%", /* GCC_JIT_BINARY_OP_MODULO */
4166 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4167 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4168 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4169 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4170 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4171 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4172 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4175 recording::string *
4176 recording::binary_op::make_debug_string ()
4178 return string::from_printf (m_ctxt,
4179 "%s %s %s",
4180 m_a->get_debug_string (),
4181 binary_op_strings[m_op],
4182 m_b->get_debug_string ());
4185 static const char * const binary_op_reproducer_strings[] = {
4186 "GCC_JIT_BINARY_OP_PLUS",
4187 "GCC_JIT_BINARY_OP_MINUS",
4188 "GCC_JIT_BINARY_OP_MULT",
4189 "GCC_JIT_BINARY_OP_DIVIDE",
4190 "GCC_JIT_BINARY_OP_MODULO",
4191 "GCC_JIT_BINARY_OP_BITWISE_AND",
4192 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4193 "GCC_JIT_BINARY_OP_BITWISE_OR",
4194 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4195 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4196 "GCC_JIT_BINARY_OP_LSHIFT",
4197 "GCC_JIT_BINARY_OP_RSHIFT"
4200 /* Implementation of recording::memento::write_reproducer for binary ops. */
4202 void
4203 recording::binary_op::write_reproducer (reproducer &r)
4205 const char *id = r.make_identifier (this, "rvalue");
4206 r.write (" gcc_jit_rvalue *%s =\n"
4207 " gcc_jit_context_new_binary_op (%s,\n"
4208 " %s, /* gcc_jit_location *loc */\n"
4209 " %s, /* enum gcc_jit_binary_op op */\n"
4210 " %s, /* gcc_jit_type *result_type */\n"
4211 " %s, /* gcc_jit_rvalue *a */\n"
4212 " %s); /* gcc_jit_rvalue *b */\n",
4214 r.get_identifier (get_context ()),
4215 r.get_identifier (m_loc),
4216 binary_op_reproducer_strings[m_op],
4217 r.get_identifier_as_type (get_type ()),
4218 r.get_identifier_as_rvalue (m_a),
4219 r.get_identifier_as_rvalue (m_b));
4222 /* The implementation of class gcc::jit::recording::comparison. */
4224 /* Implementation of recording::memento::make_debug_string for
4225 comparisons. */
4227 static const char * const comparison_strings[] =
4229 "==", /* GCC_JIT_COMPARISON_EQ */
4230 "!=", /* GCC_JIT_COMPARISON_NE */
4231 "<", /* GCC_JIT_COMPARISON_LT */
4232 "<=", /* GCC_JIT_COMPARISON_LE */
4233 ">", /* GCC_JIT_COMPARISON_GT */
4234 ">=", /* GCC_JIT_COMPARISON_GE */
4237 recording::string *
4238 recording::comparison::make_debug_string ()
4240 return string::from_printf (m_ctxt,
4241 "%s %s %s",
4242 m_a->get_debug_string (),
4243 comparison_strings[m_op],
4244 m_b->get_debug_string ());
4247 /* A table of enum gcc_jit_comparison values expressed in string
4248 form. */
4250 static const char * const comparison_reproducer_strings[] =
4252 "GCC_JIT_COMPARISON_EQ",
4253 "GCC_JIT_COMPARISON_NE",
4254 "GCC_JIT_COMPARISON_LT",
4255 "GCC_JIT_COMPARISON_LE",
4256 "GCC_JIT_COMPARISON_GT",
4257 "GCC_JIT_COMPARISON_GE"
4260 /* Implementation of recording::memento::write_reproducer for comparisons. */
4262 void
4263 recording::comparison::write_reproducer (reproducer &r)
4265 const char *id = r.make_identifier (this, "rvalue");
4266 r.write (" gcc_jit_rvalue *%s =\n"
4267 " gcc_jit_context_new_comparison (%s,\n"
4268 " %s, /* gcc_jit_location *loc */\n"
4269 " %s, /* enum gcc_jit_comparison op */\n"
4270 " %s, /* gcc_jit_rvalue *a */\n"
4271 " %s); /* gcc_jit_rvalue *b */\n",
4273 r.get_identifier (get_context ()),
4274 r.get_identifier (m_loc),
4275 comparison_reproducer_strings[m_op],
4276 r.get_identifier_as_rvalue (m_a),
4277 r.get_identifier_as_rvalue (m_b));
4280 /* Implementation of pure virtual hook recording::memento::replay_into
4281 for recording::comparison. */
4283 void
4284 recording::comparison::replay_into (replayer *r)
4286 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
4287 m_op,
4288 m_a->playback_rvalue (),
4289 m_b->playback_rvalue ()));
4292 /* Implementation of pure virtual hook recording::rvalue::visit_children
4293 for recording::comparison. */
4295 void
4296 recording::comparison::visit_children (rvalue_visitor *v)
4298 v->visit (m_a);
4299 v->visit (m_b);
4302 /* Implementation of pure virtual hook recording::memento::replay_into
4303 for recording::cast. */
4305 void
4306 recording::cast::replay_into (replayer *r)
4308 set_playback_obj (r->new_cast (playback_location (r, m_loc),
4309 m_rvalue->playback_rvalue (),
4310 get_type ()->playback_type ()));
4313 /* Implementation of pure virtual hook recording::rvalue::visit_children
4314 for recording::cast. */
4315 void
4316 recording::cast::visit_children (rvalue_visitor *v)
4318 v->visit (m_rvalue);
4321 /* Implementation of recording::memento::make_debug_string for
4322 casts. */
4324 recording::string *
4325 recording::cast::make_debug_string ()
4327 return string::from_printf (m_ctxt,
4328 "(%s)%s",
4329 get_type ()->get_debug_string (),
4330 m_rvalue->get_debug_string ());
4333 /* Implementation of recording::memento::write_reproducer for casts. */
4335 void
4336 recording::cast::write_reproducer (reproducer &r)
4338 const char *id = r.make_identifier (this, "rvalue");
4339 r.write (" gcc_jit_rvalue *%s =\n"
4340 " gcc_jit_context_new_cast (%s,\n"
4341 " %s, /* gcc_jit_location *loc */\n"
4342 " %s, /* gcc_jit_rvalue *rvalue */\n"
4343 " %s); /* gcc_jit_type *type */\n",
4345 r.get_identifier (get_context ()),
4346 r.get_identifier (m_loc),
4347 r.get_identifier_as_rvalue (m_rvalue),
4348 r.get_identifier_as_type (get_type ()));
4351 /* The implementation of class gcc::jit::recording::call. */
4353 /* The constructor for gcc::jit::recording::call. */
4355 recording::call::call (recording::context *ctxt,
4356 recording::location *loc,
4357 recording::function *func,
4358 int numargs,
4359 rvalue **args)
4360 : rvalue (ctxt, loc, func->get_return_type ()),
4361 m_func (func),
4362 m_args ()
4364 for (int i = 0; i< numargs; i++)
4365 m_args.safe_push (args[i]);
4368 /* Implementation of pure virtual hook recording::memento::replay_into
4369 for recording::call. */
4371 void
4372 recording::call::replay_into (replayer *r)
4374 auto_vec<playback::rvalue *> playback_args;
4375 playback_args.create (m_args.length ());
4376 for (unsigned i = 0; i< m_args.length (); i++)
4377 playback_args.safe_push (m_args[i]->playback_rvalue ());
4379 set_playback_obj (r->new_call (playback_location (r, m_loc),
4380 m_func->playback_function (),
4381 &playback_args));
4384 /* Implementation of pure virtual hook recording::rvalue::visit_children
4385 for recording::call. */
4387 void
4388 recording::call::visit_children (rvalue_visitor *v)
4390 for (unsigned i = 0; i< m_args.length (); i++)
4391 v->visit (m_args[i]);
4394 /* Implementation of recording::memento::make_debug_string for
4395 function calls. */
4397 recording::string *
4398 recording::call::make_debug_string ()
4400 /* First, build a buffer for the arguments. */
4401 /* Calculate length of said buffer. */
4402 size_t sz = 1; /* nil terminator */
4403 for (unsigned i = 0; i< m_args.length (); i++)
4405 sz += strlen (m_args[i]->get_debug_string ());
4406 sz += 2; /* ", " separator */
4409 /* Now allocate and populate the buffer. */
4410 char *argbuf = new char[sz];
4411 size_t len = 0;
4413 for (unsigned i = 0; i< m_args.length (); i++)
4415 strcpy (argbuf + len, m_args[i]->get_debug_string ());
4416 len += strlen (m_args[i]->get_debug_string ());
4417 if (i + 1 < m_args.length ())
4419 strcpy (argbuf + len, ", ");
4420 len += 2;
4423 argbuf[len] = '\0';
4425 /* ...and use it to get the string for the call as a whole. */
4426 string *result = string::from_printf (m_ctxt,
4427 "%s (%s)",
4428 m_func->get_debug_string (),
4429 argbuf);
4431 delete[] argbuf;
4433 return result;
4436 void
4437 recording::call::write_reproducer (reproducer &r)
4439 const char *id = r.make_identifier (this, "call");
4440 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4441 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4442 args_id,
4443 m_args.length ());
4444 for (unsigned i = 0; i< m_args.length (); i++)
4445 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4446 r.write (" };\n");
4447 r.write (" gcc_jit_rvalue *%s =\n"
4448 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4449 " %s, /* gcc_jit_location *loc */\n"
4450 " %s, /* gcc_jit_function *func */\n"
4451 " %i, /* int numargs */ \n"
4452 " %s); /* gcc_jit_rvalue **args*/\n",
4454 r.get_identifier (get_context ()),
4455 r.get_identifier (m_loc),
4456 r.get_identifier (m_func),
4457 m_args.length (),
4458 args_id);
4461 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4463 /* The constructor for recording::call_through_ptr. */
4465 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
4466 recording::location *loc,
4467 recording::rvalue *fn_ptr,
4468 int numargs,
4469 rvalue **args)
4470 : rvalue (ctxt, loc,
4471 fn_ptr->get_type ()->dereference ()
4472 ->as_a_function_type ()->get_return_type ()),
4473 m_fn_ptr (fn_ptr),
4474 m_args ()
4476 for (int i = 0; i< numargs; i++)
4477 m_args.safe_push (args[i]);
4480 /* Implementation of pure virtual hook recording::memento::replay_into
4481 for recording::call_through_ptr. */
4483 void
4484 recording::call_through_ptr::replay_into (replayer *r)
4486 auto_vec<playback::rvalue *> playback_args;
4487 playback_args.create (m_args.length ());
4488 for (unsigned i = 0; i< m_args.length (); i++)
4489 playback_args.safe_push (m_args[i]->playback_rvalue ());
4491 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
4492 m_fn_ptr->playback_rvalue (),
4493 &playback_args));
4496 /* Implementation of pure virtual hook recording::rvalue::visit_children
4497 for recording::call_through_ptr. */
4499 void
4500 recording::call_through_ptr::visit_children (rvalue_visitor *v)
4502 v->visit (m_fn_ptr);
4503 for (unsigned i = 0; i< m_args.length (); i++)
4504 v->visit (m_args[i]);
4507 /* Implementation of recording::memento::make_debug_string for
4508 calls through function ptrs. */
4510 recording::string *
4511 recording::call_through_ptr::make_debug_string ()
4513 /* First, build a buffer for the arguments. */
4514 /* Calculate length of said buffer. */
4515 size_t sz = 1; /* nil terminator */
4516 for (unsigned i = 0; i< m_args.length (); i++)
4518 sz += strlen (m_args[i]->get_debug_string ());
4519 sz += 2; /* ", " separator */
4522 /* Now allocate and populate the buffer. */
4523 char *argbuf = new char[sz];
4524 size_t len = 0;
4526 for (unsigned i = 0; i< m_args.length (); i++)
4528 strcpy (argbuf + len, m_args[i]->get_debug_string ());
4529 len += strlen (m_args[i]->get_debug_string ());
4530 if (i + 1 < m_args.length ())
4532 strcpy (argbuf + len, ", ");
4533 len += 2;
4536 argbuf[len] = '\0';
4538 /* ...and use it to get the string for the call as a whole. */
4539 string *result = string::from_printf (m_ctxt,
4540 "%s (%s)",
4541 m_fn_ptr->get_debug_string (),
4542 argbuf);
4544 delete[] argbuf;
4546 return result;
4549 /* Implementation of recording::memento::write_reproducer for
4550 call_through_ptr. */
4552 void
4553 recording::call_through_ptr::write_reproducer (reproducer &r)
4555 const char *id = r.make_identifier (this, "call");
4556 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4557 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4558 args_id,
4559 m_args.length ());
4560 for (unsigned i = 0; i< m_args.length (); i++)
4561 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4562 r.write (" };\n");
4563 r.write (" gcc_jit_rvalue *%s =\n"
4564 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
4565 " %s, /* gcc_jit_location *loc */\n"
4566 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
4567 " %i, /* int numargs */ \n"
4568 " %s); /* gcc_jit_rvalue **args*/\n",
4570 r.get_identifier (get_context ()),
4571 r.get_identifier (m_loc),
4572 r.get_identifier_as_rvalue (m_fn_ptr),
4573 m_args.length (),
4574 args_id);
4577 /* The implementation of class gcc::jit::recording::array_access. */
4579 /* Implementation of pure virtual hook recording::memento::replay_into
4580 for recording::array_access. */
4582 void
4583 recording::array_access::replay_into (replayer *r)
4585 set_playback_obj (
4586 r->new_array_access (playback_location (r, m_loc),
4587 m_ptr->playback_rvalue (),
4588 m_index->playback_rvalue ()));
4591 /* Implementation of pure virtual hook recording::rvalue::visit_children
4592 for recording::array_access. */
4594 void
4595 recording::array_access::visit_children (rvalue_visitor *v)
4597 v->visit (m_ptr);
4598 v->visit (m_index);
4601 /* Implementation of recording::memento::make_debug_string for
4602 array accesses. */
4604 recording::string *
4605 recording::array_access::make_debug_string ()
4607 return string::from_printf (m_ctxt,
4608 "%s[%s]",
4609 m_ptr->get_debug_string (),
4610 m_index->get_debug_string ());
4613 /* Implementation of recording::memento::write_reproducer for
4614 array_access. */
4616 void
4617 recording::array_access::write_reproducer (reproducer &r)
4619 const char *id = r.make_identifier (this, "lvalue");
4620 r.write (" gcc_jit_lvalue *%s = \n"
4621 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
4622 " %s, /*gcc_jit_location *loc */\n"
4623 " %s, /* gcc_jit_rvalue *ptr */\n"
4624 " %s); /* gcc_jit_rvalue *index */\n",
4626 r.get_identifier (get_context ()),
4627 r.get_identifier (m_loc),
4628 r.get_identifier_as_rvalue (m_ptr),
4629 r.get_identifier_as_rvalue (m_index));
4632 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
4634 /* Implementation of pure virtual hook recording::memento::replay_into
4635 for recording::access_field_of_lvalue. */
4637 void
4638 recording::access_field_of_lvalue::replay_into (replayer *r)
4640 set_playback_obj (
4641 m_lvalue->playback_lvalue ()
4642 ->access_field (playback_location (r, m_loc),
4643 m_field->playback_field ()));
4647 /* Implementation of pure virtual hook recording::rvalue::visit_children
4648 for recording::access_field_of_lvalue. */
4650 void
4651 recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
4653 v->visit (m_lvalue);
4656 /* Implementation of recording::memento::make_debug_string for
4657 accessing a field of an lvalue. */
4659 recording::string *
4660 recording::access_field_of_lvalue::make_debug_string ()
4662 return string::from_printf (m_ctxt,
4663 "%s.%s",
4664 m_lvalue->get_debug_string (),
4665 m_field->get_debug_string ());
4668 /* Implementation of recording::memento::write_reproducer for
4669 access_field_of_lvalue. */
4671 void
4672 recording::access_field_of_lvalue::write_reproducer (reproducer &r)
4674 const char *id = r.make_identifier (this, "lvalue");
4675 r.write (" gcc_jit_lvalue *%s = \n"
4676 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
4677 " %s, /*gcc_jit_location *loc */\n"
4678 " %s);\n",
4680 r.get_identifier_as_lvalue (m_lvalue),
4681 r.get_identifier (m_loc),
4682 r.get_identifier (m_field));
4685 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
4687 /* Implementation of pure virtual hook recording::memento::replay_into
4688 for recording::access_field_rvalue. */
4690 void
4691 recording::access_field_rvalue::replay_into (replayer *r)
4693 set_playback_obj (
4694 m_rvalue->playback_rvalue ()
4695 ->access_field (playback_location (r, m_loc),
4696 m_field->playback_field ()));
4699 /* Implementation of pure virtual hook recording::rvalue::visit_children
4700 for recording::access_field_rvalue. */
4702 void
4703 recording::access_field_rvalue::visit_children (rvalue_visitor *v)
4705 v->visit (m_rvalue);
4708 /* Implementation of recording::memento::make_debug_string for
4709 accessing a field of an rvalue. */
4711 recording::string *
4712 recording::access_field_rvalue::make_debug_string ()
4714 return string::from_printf (m_ctxt,
4715 "%s.%s",
4716 m_rvalue->get_debug_string (),
4717 m_field->get_debug_string ());
4720 /* Implementation of recording::memento::write_reproducer for
4721 access_field_rvalue. */
4723 void
4724 recording::access_field_rvalue::write_reproducer (reproducer &r)
4726 const char *id = r.make_identifier (this, "rvalue");
4727 r.write (" gcc_jit_rvalue *%s = \n"
4728 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
4729 " %s, /*gcc_jit_location *loc */\n"
4730 " %s);\n",
4732 r.get_identifier_as_rvalue (m_rvalue),
4733 r.get_identifier (m_loc),
4734 r.get_identifier (m_field));
4737 /* The implementation of class
4738 gcc::jit::recording::dereference_field_rvalue. */
4740 /* Implementation of pure virtual hook recording::memento::replay_into
4741 for recording::dereference_field_rvalue. */
4743 void
4744 recording::dereference_field_rvalue::replay_into (replayer *r)
4746 set_playback_obj (
4747 m_rvalue->playback_rvalue ()->
4748 dereference_field (playback_location (r, m_loc),
4749 m_field->playback_field ()));
4752 /* Implementation of pure virtual hook recording::rvalue::visit_children
4753 for recording::dereference_field_rvalue. */
4755 void
4756 recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
4758 v->visit (m_rvalue);
4761 /* Implementation of recording::memento::make_debug_string for
4762 dereferencing a field of an rvalue. */
4764 recording::string *
4765 recording::dereference_field_rvalue::make_debug_string ()
4767 return string::from_printf (m_ctxt,
4768 "%s->%s",
4769 m_rvalue->get_debug_string (),
4770 m_field->get_debug_string ());
4773 /* Implementation of recording::memento::write_reproducer for
4774 dereference_field_rvalue. */
4776 void
4777 recording::dereference_field_rvalue::write_reproducer (reproducer &r)
4779 const char *id = r.make_identifier (this, "lvalue");
4780 r.write (" gcc_jit_lvalue *%s=\n"
4781 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
4782 " %s, /* gcc_jit_location *loc */\n"
4783 " %s); /* gcc_jit_field *field */\n",
4785 r.get_identifier_as_rvalue (m_rvalue),
4786 r.get_identifier (m_loc),
4787 r.get_identifier (m_field));
4790 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
4792 /* Implementation of pure virtual hook recording::memento::replay_into
4793 for recording::dereference_rvalue. */
4795 void
4796 recording::dereference_rvalue::replay_into (replayer *r)
4798 set_playback_obj (
4799 m_rvalue->playback_rvalue ()->
4800 dereference (playback_location (r, m_loc)));
4803 /* Implementation of pure virtual hook recording::rvalue::visit_children
4804 for recording::dereference_rvalue. */
4806 void
4807 recording::dereference_rvalue::visit_children (rvalue_visitor *v)
4809 v->visit (m_rvalue);
4812 /* Implementation of recording::memento::make_debug_string for
4813 dereferencing an rvalue. */
4815 recording::string *
4816 recording::dereference_rvalue::make_debug_string ()
4818 return string::from_printf (m_ctxt,
4819 "*%s",
4820 m_rvalue->get_debug_string ());
4823 /* Implementation of recording::memento::write_reproducer for
4824 dereference_rvalue. */
4826 void
4827 recording::dereference_rvalue::write_reproducer (reproducer &r)
4829 const char *id = r.make_identifier (this, "dereference");
4830 r.write (" gcc_jit_lvalue *%s =\n"
4831 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
4832 " %s); /* gcc_jit_location *loc */\n",
4834 r.get_identifier_as_rvalue (m_rvalue),
4835 r.get_identifier (m_loc));
4838 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
4840 /* Implementation of pure virtual hook recording::memento::replay_into
4841 for recording::get_address_of_lvalue. */
4843 void
4844 recording::get_address_of_lvalue::replay_into (replayer *r)
4846 set_playback_obj (
4847 m_lvalue->playback_lvalue ()->
4848 get_address (playback_location (r, m_loc)));
4851 /* Implementation of pure virtual hook recording::rvalue::visit_children
4852 for recording::get_address_of_lvalue. */
4854 void
4855 recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
4857 v->visit (m_lvalue);
4860 /* Implementation of recording::memento::make_debug_string for
4861 getting the address of an lvalue. */
4863 recording::string *
4864 recording::get_address_of_lvalue::make_debug_string ()
4866 return string::from_printf (m_ctxt,
4867 "&%s",
4868 m_lvalue->get_debug_string ());
4871 /* Implementation of recording::memento::write_reproducer for
4872 get_address_of_lvalue. */
4874 void
4875 recording::get_address_of_lvalue::write_reproducer (reproducer &r)
4877 const char *id = r.make_identifier (this, "address_of");
4878 r.write (" gcc_jit_rvalue *%s =\n"
4879 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
4880 " %s); /* gcc_jit_location *loc */\n",
4882 r.get_identifier_as_lvalue (m_lvalue),
4883 r.get_identifier (m_loc));
4886 /* The implementation of class gcc::jit::recording::local. */
4888 /* Implementation of pure virtual hook recording::memento::replay_into
4889 for recording::local. */
4891 void
4892 recording::local::replay_into (replayer *r)
4894 set_playback_obj (
4895 m_func->playback_function ()
4896 ->new_local (playback_location (r, m_loc),
4897 m_type->playback_type (),
4898 playback_string (m_name)));
4901 /* Override the default implementation of
4902 recording::memento::write_to_dump for locals by writing
4903 TYPE NAME;
4904 for use at the top of the function body as if it were a
4905 declaration. */
4907 void
4908 recording::local::write_to_dump (dump &d)
4910 if (d.update_locations ())
4911 m_loc = d.make_location ();
4912 d.write(" %s %s;\n",
4913 m_type->get_debug_string (),
4914 get_debug_string ());
4917 void
4918 recording::local::write_reproducer (reproducer &r)
4920 const char *id = r.make_identifier (this, "local");
4921 r.write (" gcc_jit_lvalue *%s =\n"
4922 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
4923 " %s, /* gcc_jit_location *loc */\n"
4924 " %s, /* gcc_jit_type *type */\n"
4925 " %s); /* const char *name */\n",
4927 r.get_identifier (m_func),
4928 r.get_identifier (m_loc),
4929 r.get_identifier_as_type (m_type),
4930 m_name->get_debug_string ());
4933 /* The implementation of class gcc::jit::recording::statement. */
4935 /* We poison the default implementation of
4936 gcc::jit::recording::statement::get_successor_blocks
4937 since this vfunc must only ever be called on terminator
4938 statements. */
4941 recording::statement::get_successor_blocks (block **/*out_next1*/,
4942 block **/*out_next2*/) const
4944 /* The base class implementation is for non-terminating statements,
4945 and thus should never be called. */
4946 gcc_unreachable ();
4947 return 0;
4950 /* Extend the default implementation of
4951 recording::memento::write_to_dump for statements by (if requested)
4952 updating the location of the statement to the current location in
4953 the dumpfile. */
4955 void
4956 recording::statement::write_to_dump (dump &d)
4958 memento::write_to_dump (d);
4959 if (d.update_locations ())
4960 m_loc = d.make_location ();
4963 /* The implementation of class gcc::jit::recording::eval. */
4965 /* Implementation of pure virtual hook recording::memento::replay_into
4966 for recording::eval. */
4968 void
4969 recording::eval::replay_into (replayer *r)
4971 playback_block (get_block ())
4972 ->add_eval (playback_location (r),
4973 m_rvalue->playback_rvalue ());
4976 /* Implementation of recording::memento::make_debug_string for
4977 an eval statement. */
4979 recording::string *
4980 recording::eval::make_debug_string ()
4982 return string::from_printf (m_ctxt,
4983 "(void)%s;",
4984 m_rvalue->get_debug_string ());
4987 /* Implementation of recording::memento::write_reproducer for
4988 eval statements. */
4990 void
4991 recording::eval::write_reproducer (reproducer &r)
4993 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
4994 " %s, /* gcc_jit_location *loc */\n"
4995 " %s); /* gcc_jit_rvalue *rvalue */\n",
4996 r.get_identifier (get_block ()),
4997 r.get_identifier (get_loc ()),
4998 r.get_identifier_as_rvalue (m_rvalue));
5001 /* The implementation of class gcc::jit::recording::assignment. */
5003 /* Implementation of pure virtual hook recording::memento::replay_into
5004 for recording::assignment. */
5006 void
5007 recording::assignment::replay_into (replayer *r)
5009 playback_block (get_block ())
5010 ->add_assignment (playback_location (r),
5011 m_lvalue->playback_lvalue (),
5012 m_rvalue->playback_rvalue ());
5015 /* Implementation of recording::memento::make_debug_string for
5016 an assignment statement. */
5018 recording::string *
5019 recording::assignment::make_debug_string ()
5021 return string::from_printf (m_ctxt,
5022 "%s = %s;",
5023 m_lvalue->get_debug_string (),
5024 m_rvalue->get_debug_string ());
5027 /* Implementation of recording::memento::write_reproducer for
5028 assignment statements. */
5030 void
5031 recording::assignment::write_reproducer (reproducer &r)
5033 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5034 " %s, /* gcc_jit_location *loc */\n"
5035 " %s, /* gcc_jit_lvalue *lvalue */\n"
5036 " %s); /* gcc_jit_rvalue *rvalue */\n",
5037 r.get_identifier (get_block ()),
5038 r.get_identifier (get_loc ()),
5039 r.get_identifier_as_lvalue (m_lvalue),
5040 r.get_identifier_as_rvalue (m_rvalue));
5043 /* The implementation of class gcc::jit::recording::assignment_op. */
5045 /* Implementation of pure virtual hook recording::memento::replay_into
5046 for recording::assignment_op. */
5048 void
5049 recording::assignment_op::replay_into (replayer *r)
5051 playback::type *result_type =
5052 m_lvalue->playback_lvalue ()->get_type ();
5054 playback::rvalue *binary_op =
5055 r->new_binary_op (playback_location (r),
5056 m_op,
5057 result_type,
5058 m_lvalue->playback_rvalue (),
5059 m_rvalue->playback_rvalue ());
5061 playback_block (get_block ())
5062 ->add_assignment (playback_location (r),
5063 m_lvalue->playback_lvalue (),
5064 binary_op);
5067 /* Implementation of recording::memento::make_debug_string for
5068 an assignment_op statement. */
5070 recording::string *
5071 recording::assignment_op::make_debug_string ()
5073 return string::from_printf (m_ctxt,
5074 "%s %s= %s;",
5075 m_lvalue->get_debug_string (),
5076 binary_op_strings[m_op],
5077 m_rvalue->get_debug_string ());
5080 /* Implementation of recording::memento::write_reproducer for
5081 assignment_op statements. */
5083 void
5084 recording::assignment_op::write_reproducer (reproducer &r)
5086 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5087 " %s, /* gcc_jit_location *loc */\n"
5088 " %s, /* gcc_jit_lvalue *lvalue */\n"
5089 " %s, /* enum gcc_jit_binary_op op */\n"
5090 " %s); /* gcc_jit_rvalue *rvalue */\n",
5091 r.get_identifier (get_block ()),
5092 r.get_identifier (get_loc ()),
5093 r.get_identifier_as_lvalue (m_lvalue),
5094 binary_op_reproducer_strings[m_op],
5095 r.get_identifier_as_rvalue (m_rvalue));
5098 /* The implementation of class gcc::jit::recording::comment. */
5100 /* Implementation of pure virtual hook recording::memento::replay_into
5101 for recording::comment. */
5103 void
5104 recording::comment::replay_into (replayer *r)
5106 playback_block (get_block ())
5107 ->add_comment (playback_location (r),
5108 m_text->c_str ());
5111 /* Implementation of recording::memento::make_debug_string for
5112 a comment "statement". */
5114 recording::string *
5115 recording::comment::make_debug_string ()
5117 return string::from_printf (m_ctxt,
5118 "/* %s */",
5119 m_text->c_str ());
5122 /* Implementation of recording::memento::write_reproducer for
5123 comments. */
5125 void
5126 recording::comment::write_reproducer (reproducer &r)
5128 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5129 " %s, /* gcc_jit_location *loc */\n"
5130 " %s); /* const char *text */\n",
5131 r.get_identifier (get_block ()),
5132 r.get_identifier (get_loc ()),
5133 m_text->get_debug_string ());
5136 /* The implementation of class gcc::jit::recording::conditional. */
5138 /* Implementation of pure virtual hook recording::memento::replay_into
5139 for recording::conditional. */
5141 void
5142 recording::conditional::replay_into (replayer *r)
5144 playback_block (get_block ())
5145 ->add_conditional (playback_location (r),
5146 m_boolval->playback_rvalue (),
5147 playback_block (m_on_true),
5148 playback_block (m_on_false));
5151 /* Override the poisoned default implementation of
5152 gcc::jit::recording::statement::get_successor_blocks
5154 A conditional jump has 2 successor blocks. */
5157 recording::conditional::get_successor_blocks (block **out_next1,
5158 block **out_next2) const
5160 *out_next1 = m_on_true;
5161 *out_next2 = m_on_false;
5162 return 2;
5165 /* Implementation of recording::memento::make_debug_string for
5166 a conditional jump statement. */
5168 recording::string *
5169 recording::conditional::make_debug_string ()
5171 if (m_on_false)
5172 return string::from_printf (m_ctxt,
5173 "if (%s) goto %s; else goto %s;",
5174 m_boolval->get_debug_string (),
5175 m_on_true->get_debug_string (),
5176 m_on_false->get_debug_string ());
5177 else
5178 return string::from_printf (m_ctxt,
5179 "if (%s) goto %s;",
5180 m_boolval->get_debug_string (),
5181 m_on_true->get_debug_string ());
5184 /* Implementation of recording::memento::write_reproducer for
5185 conditional statements. */
5187 void
5188 recording::conditional::write_reproducer (reproducer &r)
5190 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5191 " %s, /* gcc_jit_location *loc */\n"
5192 " %s, /* gcc_jit_rvalue *boolval */\n"
5193 " %s, /* gcc_jit_block *on_true */\n"
5194 " %s); /* gcc_jit_block *on_false */\n",
5195 r.get_identifier (get_block ()),
5196 r.get_identifier (get_loc ()),
5197 r.get_identifier_as_rvalue (m_boolval),
5198 r.get_identifier (m_on_true),
5199 r.get_identifier (m_on_false));
5202 /* The implementation of class gcc::jit::recording::jump. */
5204 /* Implementation of pure virtual hook recording::memento::replay_into
5205 for recording::jump. */
5207 void
5208 recording::jump::replay_into (replayer *r)
5210 playback_block (get_block ())
5211 ->add_jump (playback_location (r),
5212 m_target->playback_block ());
5215 /* Override the poisoned default implementation of
5216 gcc::jit::recording::statement::get_successor_blocks
5218 An unconditional jump has 1 successor block. */
5221 recording::jump::get_successor_blocks (block **out_next1,
5222 block **/*out_next2*/) const
5224 *out_next1 = m_target;
5225 return 1;
5228 /* Implementation of recording::memento::make_debug_string for
5229 a unconditional jump statement. */
5231 recording::string *
5232 recording::jump::make_debug_string ()
5234 return string::from_printf (m_ctxt,
5235 "goto %s;",
5236 m_target->get_debug_string ());
5239 /* Implementation of recording::memento::write_reproducer for
5240 jump statements. */
5242 void
5243 recording::jump::write_reproducer (reproducer &r)
5245 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5246 " %s, /* gcc_jit_location *loc */\n"
5247 " %s); /* gcc_jit_block *target */\n",
5248 r.get_identifier (get_block ()),
5249 r.get_identifier (get_loc ()),
5250 r.get_identifier (m_target));
5253 /* The implementation of class gcc::jit::recording::return_. */
5255 /* Implementation of pure virtual hook recording::memento::replay_into
5256 for recording::return_. */
5258 void
5259 recording::return_::replay_into (replayer *r)
5261 playback_block (get_block ())
5262 ->add_return (playback_location (r),
5263 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
5266 /* Override the poisoned default implementation of
5267 gcc::jit::recording::statement::get_successor_blocks
5269 A return statement has no successor block. */
5272 recording::return_::get_successor_blocks (block **/*out_next1*/,
5273 block **/*out_next2*/) const
5275 return 0;
5278 /* Implementation of recording::memento::make_debug_string for
5279 a return statement (covers both those with and without rvalues). */
5281 recording::string *
5282 recording::return_::make_debug_string ()
5284 if (m_rvalue)
5285 return string::from_printf (m_ctxt,
5286 "return %s;",
5287 m_rvalue->get_debug_string ());
5288 else
5289 return string::from_printf (m_ctxt,
5290 "return;");
5293 /* Implementation of recording::memento::write_reproducer for
5294 return statements. */
5296 void
5297 recording::return_::write_reproducer (reproducer &r)
5299 if (m_rvalue)
5300 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5301 " %s, /* gcc_jit_location *loc */\n"
5302 " %s); /* gcc_jit_rvalue *rvalue */\n",
5303 r.get_identifier (get_block ()),
5304 r.get_identifier (get_loc ()),
5305 r.get_identifier_as_rvalue (m_rvalue));
5306 else
5307 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5308 " %s); /* gcc_jit_location *loc */\n",
5309 r.get_identifier (get_block ()),
5310 r.get_identifier (get_loc ()));
5313 } // namespace gcc::jit
5315 } // namespace gcc