1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2018 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
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/>. */
23 #include "coretypes.h"
25 #include "pretty-print.h"
30 #include "jit-builtins.h"
31 #include "jit-recording.h"
32 #include "jit-playback.h"
39 dump::dump (recording::context
&ctxt
,
41 bool update_locations
)
43 m_filename (filename
),
44 m_update_locations (update_locations
),
48 m_file
= fopen (filename
, "w");
51 "error opening dump file %s for writing: %s",
60 int err
= fclose (m_file
);
62 m_ctxt
.add_error (NULL
,
63 "error closing dump file %s: %s",
69 /* Write the given message to the dump, using printf-formatting
70 conventions, updating the line/column within the dump.
72 Emit an error on the context if a failure occurs. */
75 dump::write (const char *fmt
, ...)
81 /* If there was an error opening the file, we've already reported it.
82 Don't attempt further work. */
87 len
= vasprintf (&buf
, fmt
, ap
);
90 if (buf
== NULL
|| len
< 0)
92 m_ctxt
.add_error (NULL
, "malloc failure writing to dumpfile %s",
97 if (fwrite (buf
, strlen (buf
), 1, m_file
) != 1)
98 m_ctxt
.add_error (NULL
, "error writing to dump file %s",
101 /* Flush after each line, to ease debugging crashes. */
104 /* Update line/column: */
105 for (const char *ptr
= buf
; *ptr
; ptr
++)
119 /* Construct a gcc::jit::recording::location instance for the current
120 location within the dump. */
122 recording::location
*
123 dump::make_location () const
125 return m_ctxt
.new_location (m_filename
, m_line
, m_column
,
126 /* We need to flag such locations as *not*
127 created by the user, so that
128 reproducer::get_identifier can cope with
129 them appearing *after* the memento that
134 /* A collection of allocations, all of which can be released together, to
135 avoid needing to track and release them individually. */
143 xstrdup_printf (const char *, ...)
144 ATTRIBUTE_RETURNS_NONNULL
148 xstrdup_printf_va (const char *, va_list ap
)
149 ATTRIBUTE_RETURNS_NONNULL
153 auto_vec
<void *> m_buffers
;
156 /* allocator's destructor. Call "free" on all of the allocations. */
158 allocator::~allocator ()
162 FOR_EACH_VEC_ELT (m_buffers
, i
, buffer
)
166 /* Formatted printing, allocating to a buffer (or exiting the process if
167 the allocation fails).
169 The buffer exists until the allocator is cleaned up, and is freed at
170 that point, so the caller doesn't need to track the result. */
173 allocator::xstrdup_printf (const char *fmt
, ...)
178 result
= xstrdup_printf_va (fmt
, ap
);
183 /* Formatted printing, allocating to a buffer (or exiting the process if
184 the allocation fails).
186 The buffer exists until the allocator is cleaned up, and is freed at
187 that point, so the caller doesn't need to track the result. */
190 allocator::xstrdup_printf_va (const char *fmt
, va_list ap
)
192 char *result
= xvasprintf (fmt
, ap
);
193 m_buffers
.safe_push (result
);
197 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
198 implementing gcc_jit_context_dump_reproducer_to_file. */
200 class reproducer
: public dump
203 reproducer (recording::context
&ctxt
,
204 const char *filename
);
207 write_params (const vec
<recording::context
*> &contexts
);
210 write_args (const vec
<recording::context
*> &contexts
);
213 make_identifier (recording::memento
*m
, const char *prefix
);
216 make_tmp_identifier (const char *prefix
, recording::memento
*m
);
219 get_identifier (recording::context
*ctxt
);
222 get_identifier (recording::memento
*m
);
225 get_identifier_as_rvalue (recording::rvalue
*m
);
228 get_identifier_as_lvalue (recording::lvalue
*m
);
231 get_identifier_as_type (recording::type
*m
);
234 xstrdup_printf (const char *, ...)
235 ATTRIBUTE_RETURNS_NONNULL
239 const char * ensure_identifier_is_unique (const char *candidate
, void *ptr
);
242 hash_map
<recording::memento
*, const char *> m_map_memento_to_identifier
;
244 struct hash_traits
: public string_hash
246 static void remove (const char *) {}
248 hash_set
<const char *, hash_traits
> m_set_identifiers
;
249 allocator m_allocator
;
252 /* gcc::jit::reproducer's constructor. */
254 reproducer::reproducer (recording::context
&ctxt
,
255 const char *filename
) :
256 dump (ctxt
, filename
, 0),
257 m_map_memento_to_identifier (),
258 m_set_identifiers (),
263 /* Write out a list of contexts as a set of parameters within a
264 C function declaration. */
267 reproducer::write_params (const vec
<recording::context
*> &contexts
)
270 recording::context
*ctxt
;
271 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
273 write ("gcc_jit_context *%s",
274 get_identifier (ctxt
));
275 if (i
< contexts
.length () - 1)
281 /* Write out a list of contexts as a set of arguments within a call
285 reproducer::write_args (const vec
<recording::context
*> &contexts
)
288 recording::context
*ctxt
;
289 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
292 get_identifier (ctxt
));
293 if (i
< contexts
.length () - 1)
299 /* Ensure that STR is a valid C identifier by overwriting
300 any invalid chars in-place with underscores.
302 This doesn't special-case the first character. */
305 convert_to_identifier (char *str
)
307 for (char *p
= str
; *p
; p
++)
312 /* Given CANDIDATE, a possible C identifier for use in a reproducer,
313 ensure that it is unique within the generated source file by
314 appending PTR to it if necessary. Return the resulting string.
316 The reproducer will eventually clean up the buffer in its dtor. */
319 reproducer::ensure_identifier_is_unique (const char *candidate
, void *ptr
)
321 if (m_set_identifiers
.contains (candidate
))
322 candidate
= m_allocator
.xstrdup_printf ("%s_%p", candidate
, ptr
);
323 gcc_assert (!m_set_identifiers
.contains (candidate
));
324 m_set_identifiers
.add (candidate
);
328 /* Generate a C identifier for the given memento, associating the generated
329 buffer with the memento (for future calls to get_identifier et al).
331 The reproducer will eventually clean up the buffer in its dtor. */
333 reproducer::make_identifier (recording::memento
*m
, const char *prefix
)
336 if (strlen (m
->get_debug_string ()) < 100)
338 char *buf
= m_allocator
.xstrdup_printf ("%s_%s",
340 m
->get_debug_string ());
341 convert_to_identifier (buf
);
345 result
= m_allocator
.xstrdup_printf ("%s_%p",
347 result
= ensure_identifier_is_unique (result
, m
);
348 m_map_memento_to_identifier
.put (m
, result
);
352 /* Generate a C identifier for a temporary variable.
353 The reproducer will eventually clean up the buffer in its dtor. */
356 reproducer::make_tmp_identifier (const char *prefix
, recording::memento
*m
)
358 return m_allocator
.xstrdup_printf ("%s_%s",
359 prefix
, get_identifier (m
));
362 /* Generate a C identifier for the given context.
363 The reproducer will eventually clean up the buffer in its dtor. */
366 reproducer::get_identifier (recording::context
*ctxt
)
368 return m_allocator
.xstrdup_printf ("ctxt_%p",
372 /* Locate the C identifier for the given memento, which is assumed to
373 have already been created via make_identifier. */
376 reproducer::get_identifier (recording::memento
*m
)
381 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
382 and hence these locations appear in the context's memento list
383 out-of-order: they appear in the context's memento list *after*
384 the memento that refers to them. For this case, it's simplest to
385 pretend that they're NULL when writing out the code to recreate the
386 memento that uses them. */
387 if (recording::location
*loc
= m
->dyn_cast_location ())
388 if (!loc
->created_by_user ())
391 const char **slot
= m_map_memento_to_identifier
.get (m
);
394 get_context ().add_error (NULL
,
395 "unable to find identifier for %p: %s",
397 m
->get_debug_string ());
403 /* Locate the C identifier for the given rvalue, wrapping it within
404 a gcc_*_as_rvalue upcast if necessary. */
407 reproducer::get_identifier_as_rvalue (recording::rvalue
*m
)
409 return m
->access_as_rvalue (*this);
412 /* Locate the C identifier for the given lvalue, wrapping it within
413 a gcc_*_as_lvalue upcast if necessary. */
416 reproducer::get_identifier_as_lvalue (recording::lvalue
*m
)
418 return m
->access_as_lvalue (*this);
421 /* Locate the C identifier for the given type, wrapping it within
422 a gcc_*_as_type upcast if necessary. */
425 reproducer::get_identifier_as_type (recording::type
*m
)
427 return m
->access_as_type (*this);
430 /* Formatted printing, allocating to a buffer (or exiting the process if
431 the allocation fails).
433 The buffer exists until the allocator is cleaned up, and is freed at
434 that point, so the caller doesn't need to track the result.
436 Note that we can't use ggc_printf since we're not within the compiler
437 proper (when within gcc_jit_context_dump_reproducer_to_file). */
440 reproducer::xstrdup_printf (const char *fmt
, ...)
445 result
= m_allocator
.xstrdup_printf_va (fmt
, ap
);
450 /* A helper class for implementing make_debug_string, for building
451 a temporary string from a vec of rvalues. */
453 class comma_separated_string
456 comma_separated_string (const auto_vec
<recording::rvalue
*> &rvalues
,
457 enum recording::precedence prec
);
458 ~comma_separated_string ();
460 const char *as_char_ptr () const { return m_buf
; }
466 /* comma_separated_string's ctor
469 comma_separated_string::comma_separated_string
470 (const auto_vec
<recording::rvalue
*> &rvalues
,
471 enum recording::precedence prec
)
474 /* Calculate length of said buffer. */
475 size_t sz
= 1; /* nil terminator */
476 for (unsigned i
= 0; i
< rvalues
.length (); i
++)
478 sz
+= strlen (rvalues
[i
]->get_debug_string_parens (prec
));
479 sz
+= 2; /* ", " separator */
482 /* Now allocate and populate the buffer. */
483 m_buf
= new char[sz
];
486 for (unsigned i
= 0; i
< rvalues
.length (); i
++)
488 strcpy (m_buf
+ len
, rvalues
[i
]->get_debug_string_parens (prec
));
489 len
+= strlen (rvalues
[i
]->get_debug_string_parens (prec
));
490 if (i
+ 1 < rvalues
.length ())
492 strcpy (m_buf
+ len
, ", ");
499 /* comma_separated_string's dtor. */
501 comma_separated_string::~comma_separated_string ()
506 /**********************************************************************
508 **********************************************************************/
510 /* Get the playback::location for the given recording::location,
511 handling a NULL input with a NULL output. */
514 recording::playback_location (replayer
*r
, recording::location
*loc
)
517 return loc
->playback_location (r
);
522 /* Get a const char * for the given recording::string
523 handling a NULL input with a NULL output. */
526 recording::playback_string (recording::string
*str
)
529 return str
->c_str ();
534 /* Get the playback::block for the given recording::block,
535 handling a NULL input with a NULL output. */
538 recording::playback_block (recording::block
*b
)
541 return b
->playback_block ();
546 /* Methods of cc::jit::recording::context. */
548 /* The constructor for gcc::jit::recording::context, used by
549 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
551 recording::context::context (context
*parent_ctxt
)
553 m_parent_ctxt (parent_ctxt
),
554 m_toplevel_ctxt (m_parent_ctxt
? m_parent_ctxt
->m_toplevel_ctxt
: this),
557 m_first_error_str (NULL
),
558 m_owns_first_error_str (false),
559 m_last_error_str (NULL
),
560 m_owns_last_error_str (false),
566 m_builtins_manager(NULL
)
570 /* Inherit options from parent. */
572 i
< sizeof (m_str_options
) / sizeof (m_str_options
[0]);
575 const char *parent_opt
= parent_ctxt
->m_str_options
[i
];
576 m_str_options
[i
] = parent_opt
? xstrdup (parent_opt
) : NULL
;
578 memcpy (m_int_options
,
579 parent_ctxt
->m_int_options
,
580 sizeof (m_int_options
));
581 memcpy (m_bool_options
,
582 parent_ctxt
->m_bool_options
,
583 sizeof (m_bool_options
));
584 memcpy (m_inner_bool_options
,
585 parent_ctxt
->m_inner_bool_options
,
586 sizeof (m_inner_bool_options
));
587 set_logger (parent_ctxt
->get_logger ());
591 memset (m_str_options
, 0, sizeof (m_str_options
));
592 memset (m_int_options
, 0, sizeof (m_int_options
));
593 memset (m_bool_options
, 0, sizeof (m_bool_options
));
594 memset (m_inner_bool_options
, 0, sizeof (m_inner_bool_options
));
597 memset (m_basic_types
, 0, sizeof (m_basic_types
));
600 /* The destructor for gcc::jit::recording::context, implicitly used by
601 gcc_jit_context_release. */
603 recording::context::~context ()
605 JIT_LOG_SCOPE (get_logger ());
608 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
613 for (i
= 0; i
< GCC_JIT_NUM_STR_OPTIONS
; ++i
)
614 free (m_str_options
[i
]);
617 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
620 if (m_builtins_manager
)
621 delete m_builtins_manager
;
623 if (m_owns_first_error_str
)
624 free (m_first_error_str
);
626 if (m_owns_last_error_str
)
627 if (m_last_error_str
!= m_first_error_str
)
628 free (m_last_error_str
);
631 /* Add the given mememto to the list of those tracked by this
632 gcc::jit::recording::context, so that e.g. it can be deleted
633 when this context is released. */
636 recording::context::record (memento
*m
)
640 m_mementos
.safe_push (m
);
643 /* Replay this context (and any parents) into the given replayer. */
646 recording::context::replay_into (replayer
*r
)
648 JIT_LOG_SCOPE (get_logger ());
652 /* If we have a parent context, we must replay it. This will
653 recursively walk backwards up the historical tree, then replay things
654 forwards "in historical order", starting with the ultimate parent
655 context, until we reach the "this" context.
657 Note that we fully replay the parent, then fully replay the child,
658 which means that inter-context references can only exist from child
659 to parent, not the other way around.
661 All of this replaying is suboptimal - it would be better to do the
662 work for the parent context *once*, rather than replaying the parent
663 every time we replay each child. However, fixing this requires deep
664 surgery to lifetime-management: we'd need every context family tree
665 to have its own GC heap, and to initialize the GCC code to use that
666 heap (with a mutex on such a heap). */
668 m_parent_ctxt
->replay_into (r
);
670 if (r
->errors_occurred ())
673 /* Replay this context's saved operations into r. */
674 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
676 /* Disabled low-level debugging, here if we need it: print what
678 Note that the calls to get_debug_string might lead to more
679 mementos being created for the strings.
680 This can also be used to exercise the debug_string
683 printf ("context %p replaying (%p): %s\n",
684 (void *)this, (void *)m
, m
->get_debug_string ());
688 if (r
->errors_occurred ())
693 /* During a playback, we associate objects from the recording with
694 their counterparts during this playback.
696 For simplicity, we store this within the recording objects.
698 The following method cleans away these associations, to ensure that
699 we never have out-of-date associations lingering on subsequent
700 playbacks (the objects pointed to are GC-managed, but the
701 recording objects don't own refs to them). */
704 recording::context::disassociate_from_playback ()
706 JIT_LOG_SCOPE (get_logger ());
711 m_parent_ctxt
->disassociate_from_playback ();
713 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
715 m
->set_playback_obj (NULL
);
719 /* Create a recording::string instance and add it to this context's list
722 This creates a fresh copy of the given 0-terminated buffer. */
725 recording::context::new_string (const char *text
)
730 recording::string
*result
= new string (this, text
);
735 /* Create a recording::location instance and add it to this context's
738 Implements the post-error-checking part of
739 gcc_jit_context_new_location. */
741 recording::location
*
742 recording::context::new_location (const char *filename
,
745 bool created_by_user
)
747 recording::location
*result
=
748 new recording::location (this,
749 new_string (filename
),
756 /* If we haven't seen this enum value yet, create a recording::type
757 instance and add it to this context's list of mementos.
759 If we have seen it before, reuse our cached value, so that repeated
760 calls on the context give the same object.
762 If we have a parent context, the cache is within the ultimate
765 Implements the post-error-checking part of
766 gcc_jit_context_get_type. */
769 recording::context::get_type (enum gcc_jit_types kind
)
771 if (!m_basic_types
[kind
])
774 m_basic_types
[kind
] = m_parent_ctxt
->get_type (kind
);
777 recording::type
*result
= new memento_of_get_type (this, kind
);
779 m_basic_types
[kind
] = result
;
783 return m_basic_types
[kind
];
786 /* Get a recording::type instance for the given size and signedness.
787 This is implemented in terms of recording::context::get_type
790 Implements the post-error-checking part of
791 gcc_jit_context_get_int_type. */
794 recording::context::get_int_type (int num_bytes
, int is_signed
)
796 /* We can't use a switch here since some of the values are macros affected
797 by options; e.g. i386.h has
798 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
799 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
800 are in bits, rather than bytes.
802 const int num_bits
= num_bytes
* 8;
803 if (num_bits
== INT_TYPE_SIZE
)
804 return get_type (is_signed
806 : GCC_JIT_TYPE_UNSIGNED_INT
);
807 if (num_bits
== CHAR_TYPE_SIZE
)
808 return get_type (is_signed
809 ? GCC_JIT_TYPE_SIGNED_CHAR
810 : GCC_JIT_TYPE_UNSIGNED_CHAR
);
811 if (num_bits
== SHORT_TYPE_SIZE
)
812 return get_type (is_signed
814 : GCC_JIT_TYPE_UNSIGNED_SHORT
);
815 if (num_bits
== LONG_TYPE_SIZE
)
816 return get_type (is_signed
818 : GCC_JIT_TYPE_UNSIGNED_LONG
);
819 if (num_bits
== LONG_LONG_TYPE_SIZE
)
820 return get_type (is_signed
821 ? GCC_JIT_TYPE_LONG_LONG
822 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
824 /* Some other size, not corresponding to the C int types. */
825 /* To be written: support arbitrary other sizes, sharing by
826 memoizing at the recording::context level? */
830 /* Create a recording::type instance and add it to this context's list
833 Implements the post-error-checking part of
834 gcc_jit_context_new_array_type. */
837 recording::context::new_array_type (recording::location
*loc
,
838 recording::type
*element_type
,
841 if (struct_
*s
= element_type
->dyn_cast_struct ())
842 if (!s
->get_fields ())
845 "cannot create an array of type %s"
846 " until the fields have been set",
847 s
->get_name ()->c_str ());
850 recording::type
*result
=
851 new recording::array_type (this, loc
, element_type
, num_elements
);
856 /* Create a recording::field instance and add it to this context's list
859 Implements the post-error-checking part of
860 gcc_jit_context_new_field. */
863 recording::context::new_field (recording::location
*loc
,
864 recording::type
*type
,
867 recording::field
*result
=
868 new recording::field (this, loc
, type
, new_string (name
));
873 /* Create a recording::struct_ instance and add it to this context's
874 list of mementos and list of compound types.
876 Implements the post-error-checking part of
877 gcc_jit_context_new_struct_type. */
880 recording::context::new_struct_type (recording::location
*loc
,
883 recording::struct_
*result
= new struct_ (this, loc
, new_string (name
));
885 m_compound_types
.safe_push (result
);
889 /* Create a recording::union_ instance and add it to this context's
890 list of mementos and list of compound types.
892 Implements the first post-error-checking part of
893 gcc_jit_context_new_union_type. */
896 recording::context::new_union_type (recording::location
*loc
,
899 recording::union_
*result
= new union_ (this, loc
, new_string (name
));
901 m_compound_types
.safe_push (result
);
905 /* Create a recording::function_type instance and add it to this context's
908 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
910 recording::function_type
*
911 recording::context::new_function_type (recording::type
*return_type
,
913 recording::type
**param_types
,
916 recording::function_type
*fn_type
917 = new function_type (this,
926 /* Create a recording::type instance and add it to this context's list
929 Implements the post-error-checking part of
930 gcc_jit_context_new_function_ptr_type. */
933 recording::context::new_function_ptr_type (recording::location
*, /* unused loc */
934 recording::type
*return_type
,
936 recording::type
**param_types
,
939 recording::function_type
*fn_type
940 = new_function_type (return_type
,
945 /* Return a pointer-type to the function type. */
946 return fn_type
->get_pointer ();
949 /* Create a recording::param instance and add it to this context's list
952 Implements the post-error-checking part of
953 gcc_jit_context_new_param. */
956 recording::context::new_param (recording::location
*loc
,
957 recording::type
*type
,
960 recording::param
*result
= new recording::param (this, loc
, type
, new_string (name
));
965 /* Create a recording::function instance and add it to this context's list
966 of mementos and list of functions.
968 Implements the post-error-checking part of
969 gcc_jit_context_new_function. */
971 recording::function
*
972 recording::context::new_function (recording::location
*loc
,
973 enum gcc_jit_function_kind kind
,
974 recording::type
*return_type
,
977 recording::param
**params
,
979 enum built_in_function builtin_id
)
981 recording::function
*result
=
982 new recording::function (this,
983 loc
, kind
, return_type
,
985 num_params
, params
, is_variadic
,
988 m_functions
.safe_push (result
);
993 /* Locate the builtins_manager (if any) for this family of contexts,
994 creating it if it doesn't exist already.
996 All of the recording contexts in a family share one builtins_manager:
997 if we have a child context, follow the parent links to get the
998 ultimate ancestor context, and look for it/store it there. */
1001 recording::context::get_builtins_manager ()
1004 return m_parent_ctxt
->get_builtins_manager ();
1006 if (!m_builtins_manager
)
1007 m_builtins_manager
= new builtins_manager (this);
1009 return m_builtins_manager
;
1012 /* Get a recording::function instance, which is lazily-created and added
1013 to the context's lists of mementos.
1015 Implements the post-error-checking part of
1016 gcc_jit_context_get_builtin_function. */
1018 recording::function
*
1019 recording::context::get_builtin_function (const char *name
)
1021 builtins_manager
*bm
= get_builtins_manager ();
1022 return bm
->get_builtin_function (name
);
1025 /* Create a recording::global instance and add it to this context's list
1028 Implements the post-error-checking part of
1029 gcc_jit_context_new_global. */
1032 recording::context::new_global (recording::location
*loc
,
1033 enum gcc_jit_global_kind kind
,
1034 recording::type
*type
,
1037 recording::global
*result
=
1038 new recording::global (this, loc
, kind
, type
, new_string (name
));
1040 m_globals
.safe_push (result
);
1045 /* Create a recording::memento_of_new_string_literal instance and add it
1046 to this context's list of mementos.
1048 Implements the post-error-checking part of
1049 gcc_jit_context_new_string_literal. */
1052 recording::context::new_string_literal (const char *value
)
1054 recording::rvalue
*result
=
1055 new memento_of_new_string_literal (this, NULL
, new_string (value
));
1060 /* Create a recording::memento_of_new_rvalue_from_vector instance and add it
1061 to this context's list of mementos.
1063 Implements the post-error-checking part of
1064 gcc_jit_context_new_rvalue_from_vector. */
1067 recording::context::new_rvalue_from_vector (location
*loc
,
1071 recording::rvalue
*result
1072 = new memento_of_new_rvalue_from_vector (this, loc
, type
, elements
);
1077 /* Create a recording::unary_op instance and add it to this context's
1080 Implements the post-error-checking part of
1081 gcc_jit_context_new_unary_op. */
1084 recording::context::new_unary_op (recording::location
*loc
,
1085 enum gcc_jit_unary_op op
,
1086 recording::type
*result_type
,
1087 recording::rvalue
*a
)
1089 recording::rvalue
*result
=
1090 new unary_op (this, loc
, op
, result_type
, a
);
1095 /* Create a recording::binary_op instance and add it to this context's
1098 Implements the post-error-checking part of
1099 gcc_jit_context_new_binary_op. */
1102 recording::context::new_binary_op (recording::location
*loc
,
1103 enum gcc_jit_binary_op op
,
1104 recording::type
*result_type
,
1105 recording::rvalue
*a
,
1106 recording::rvalue
*b
)
1108 recording::rvalue
*result
=
1109 new binary_op (this, loc
, op
, result_type
, a
, b
);
1114 /* Create a recording::comparison instance and add it to this context's
1117 Implements the post-error-checking part of
1118 gcc_jit_context_new_comparison. */
1121 recording::context::new_comparison (recording::location
*loc
,
1122 enum gcc_jit_comparison op
,
1123 recording::rvalue
*a
,
1124 recording::rvalue
*b
)
1126 recording::rvalue
*result
= new comparison (this, loc
, op
, a
, b
);
1131 /* Create a recording::cast instance and add it to this context's list
1134 Implements the post-error-checking part of
1135 gcc_jit_context_new_cast. */
1138 recording::context::new_cast (recording::location
*loc
,
1139 recording::rvalue
*expr
,
1140 recording::type
*type_
)
1142 recording::rvalue
*result
= new cast (this, loc
, expr
, type_
);
1147 /* Create a recording::call instance and add it to this context's list
1150 Implements the post-error-checking part of
1151 gcc_jit_context_new_call. */
1154 recording::context::new_call (recording::location
*loc
,
1156 int numargs
, recording::rvalue
**args
)
1158 recording::rvalue
*result
= new call (this, loc
, func
, numargs
, args
);
1163 /* Create a recording::call_through_ptr instance and add it to this
1164 context's list of mementos.
1166 Implements the post-error-checking part of
1167 gcc_jit_context_new_call_through_ptr. */
1170 recording::context::new_call_through_ptr (recording::location
*loc
,
1171 recording::rvalue
*fn_ptr
,
1173 recording::rvalue
**args
)
1175 recording::rvalue
*result
= new call_through_ptr (this, loc
, fn_ptr
, numargs
, args
);
1180 /* Create a recording::array_access instance and add it to this context's list
1183 Implements the post-error-checking part of
1184 gcc_jit_context_new_array_access. */
1187 recording::context::new_array_access (recording::location
*loc
,
1188 recording::rvalue
*ptr
,
1189 recording::rvalue
*index
)
1191 recording::lvalue
*result
= new array_access (this, loc
, ptr
, index
);
1196 /* Create a recording::case_ instance and add it to this context's list
1199 Implements the post-error-checking part of
1200 gcc_jit_context_new_case. */
1203 recording::context::new_case (recording::rvalue
*min_value
,
1204 recording::rvalue
*max_value
,
1205 recording::block
*block
)
1207 recording::case_
*result
= new case_ (this, min_value
, max_value
, block
);
1212 /* Set the given string option for this context, or add an error if
1213 it's not recognized.
1215 Implements the post-error-checking part of
1216 gcc_jit_context_set_str_option. */
1219 recording::context::set_str_option (enum gcc_jit_str_option opt
,
1222 if (opt
< 0 || opt
>= GCC_JIT_NUM_STR_OPTIONS
)
1225 "unrecognized (enum gcc_jit_str_option) value: %i", opt
);
1228 free (m_str_options
[opt
]);
1229 m_str_options
[opt
] = value
? xstrdup (value
) : NULL
;
1230 log_str_option (opt
);
1233 /* Set the given integer option for this context, or add an error if
1234 it's not recognized.
1236 Implements the post-error-checking part of
1237 gcc_jit_context_set_int_option. */
1240 recording::context::set_int_option (enum gcc_jit_int_option opt
,
1243 if (opt
< 0 || opt
>= GCC_JIT_NUM_INT_OPTIONS
)
1246 "unrecognized (enum gcc_jit_int_option) value: %i", opt
);
1249 m_int_options
[opt
] = value
;
1250 log_int_option (opt
);
1253 /* Set the given boolean option for this context, or add an error if
1254 it's not recognized.
1256 Implements the post-error-checking part of
1257 gcc_jit_context_set_bool_option. */
1260 recording::context::set_bool_option (enum gcc_jit_bool_option opt
,
1263 if (opt
< 0 || opt
>= GCC_JIT_NUM_BOOL_OPTIONS
)
1266 "unrecognized (enum gcc_jit_bool_option) value: %i", opt
);
1269 m_bool_options
[opt
] = value
? true : false;
1270 log_bool_option (opt
);
1274 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt
,
1277 gcc_assert (inner_opt
>= 0 && inner_opt
< NUM_INNER_BOOL_OPTIONS
);
1278 m_inner_bool_options
[inner_opt
] = value
? true : false;
1279 log_inner_bool_option (inner_opt
);
1283 /* Add the given optname to this context's list of extra options.
1285 Implements the post-error-checking part of
1286 gcc_jit_context_add_command_line_option. */
1289 recording::context::add_command_line_option (const char *optname
)
1291 m_command_line_options
.safe_push (xstrdup (optname
));
1294 /* Add any user-provided extra options, starting with any from
1296 Called by playback::context::make_fake_args. */
1299 recording::context::append_command_line_options (vec
<char *> *argvec
)
1302 m_parent_ctxt
->append_command_line_options (argvec
);
1306 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1307 argvec
->safe_push (xstrdup (optname
));
1310 /* Add the given dumpname/out_ptr pair to this context's list of requested
1313 Implements the post-error-checking part of
1314 gcc_jit_context_enable_dump. */
1317 recording::context::enable_dump (const char *dumpname
,
1321 gcc_assert (dumpname
);
1322 gcc_assert (out_ptr
);
1324 d
.m_dumpname
= dumpname
;
1325 d
.m_out_ptr
= out_ptr
;
1327 m_requested_dumps
.safe_push (d
);
1330 /* Validate this context, and if it passes, compile it to memory
1333 Implements the post-error-checking part of
1334 gcc_jit_context_compile. */
1337 recording::context::compile ()
1339 JIT_LOG_SCOPE (get_logger ());
1345 if (errors_occurred ())
1348 /* Set up a compile_to_memory playback context. */
1349 ::gcc::jit::playback::compile_to_memory
replayer (this);
1352 replayer
.compile ();
1354 /* Get the jit::result (or NULL) from the
1355 compile_to_memory playback context. */
1356 return replayer
.get_result_obj ();
1359 /* Validate this context, and if it passes, compile it to a file
1362 Implements the post-error-checking part of
1363 gcc_jit_context_compile_to_file. */
1366 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind
,
1367 const char *output_path
)
1369 JIT_LOG_SCOPE (get_logger ());
1375 if (errors_occurred ())
1378 /* Set up a compile_to_file playback context. */
1379 ::gcc::jit::playback::compile_to_file
replayer (this,
1384 replayer
.compile ();
1387 /* Format the given error using printf's conventions, print
1388 it to stderr, and add it to the context. */
1391 recording::context::add_error (location
*loc
, const char *fmt
, ...)
1395 add_error_va (loc
, fmt
, ap
);
1399 /* Format the given error using printf's conventions, print
1400 it to stderr, and add it to the context. */
1403 recording::context::add_error_va (location
*loc
, const char *fmt
, va_list ap
)
1410 JIT_LOG_SCOPE (get_logger ());
1412 len
= vasprintf (&malloced_msg
, fmt
, ap
);
1413 if (malloced_msg
== NULL
|| len
< 0)
1415 errmsg
= "out of memory generating error message";
1416 has_ownership
= false;
1420 errmsg
= malloced_msg
;
1421 has_ownership
= true;
1424 get_logger ()->log ("error %i: %s", m_error_count
, errmsg
);
1426 const char *ctxt_progname
=
1427 get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
1429 ctxt_progname
= "libgccjit.so";
1432 fprintf (stderr
, "%s: %s: error: %s\n",
1434 loc
->get_debug_string (),
1437 fprintf (stderr
, "%s: error: %s\n",
1443 m_first_error_str
= const_cast <char *> (errmsg
);
1444 m_owns_first_error_str
= has_ownership
;
1447 if (m_owns_last_error_str
)
1448 if (m_last_error_str
!= m_first_error_str
)
1449 free (m_last_error_str
);
1450 m_last_error_str
= const_cast <char *> (errmsg
);
1451 m_owns_last_error_str
= has_ownership
;
1456 /* Get the message for the first error that occurred on this context, or
1457 NULL if no errors have occurred on it.
1459 Implements the post-error-checking part of
1460 gcc_jit_context_get_first_error. */
1463 recording::context::get_first_error () const
1465 return m_first_error_str
;
1468 /* Get the message for the last error that occurred on this context, or
1469 NULL if no errors have occurred on it.
1471 Implements the post-error-checking part of
1472 gcc_jit_context_get_last_error. */
1475 recording::context::get_last_error () const
1477 return m_last_error_str
;
1480 /* Lazily generate and record a recording::type representing an opaque
1481 struct named "FILE".
1483 For use if client code tries to dereference the result of
1484 get_type (GCC_JIT_TYPE_FILE_PTR). */
1487 recording::context::get_opaque_FILE_type ()
1490 m_FILE_type
= new_struct_type (NULL
, "FILE");
1494 /* Dump a C-like representation of the given context to the given path.
1495 If UPDATE_LOCATIONS is true, update the locations within the
1496 context's mementos to point to the dumpfile.
1498 Implements the post-error-checking part of
1499 gcc_jit_context_dump_to_file. */
1502 recording::context::dump_to_file (const char *path
, bool update_locations
)
1505 dump
d (*this, path
, update_locations
);
1507 /* Forward declaration of structs and unions. */
1509 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1511 d
.write ("%s;\n\n", st
->get_debug_string ());
1514 /* Content of structs, where set. */
1515 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1516 if (st
->get_fields ())
1518 st
->get_fields ()->write_to_dump (d
);
1524 FOR_EACH_VEC_ELT (m_globals
, i
, g
)
1526 g
->write_to_dump (d
);
1528 if (!m_globals
.is_empty ())
1532 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1534 fn
->write_to_dump (d
);
1538 static const char * const
1539 str_option_reproducer_strings
[GCC_JIT_NUM_STR_OPTIONS
] = {
1540 "GCC_JIT_STR_OPTION_PROGNAME"
1543 static const char * const
1544 int_option_reproducer_strings
[GCC_JIT_NUM_INT_OPTIONS
] = {
1545 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1548 static const char * const
1549 bool_option_reproducer_strings
[GCC_JIT_NUM_BOOL_OPTIONS
] = {
1550 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1551 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1552 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1553 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1554 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1555 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1556 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1557 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1560 static const char * const
1561 inner_bool_option_reproducer_strings
[NUM_INNER_BOOL_OPTIONS
] = {
1562 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1563 "gcc_jit_context_set_bool_use_external_driver"
1566 /* Write the current value of all options to the log file (if any). */
1569 recording::context::log_all_options () const
1576 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1577 log_str_option ((enum gcc_jit_str_option
)opt_idx
);
1579 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1580 log_int_option ((enum gcc_jit_int_option
)opt_idx
);
1582 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1583 log_bool_option ((enum gcc_jit_bool_option
)opt_idx
);
1584 for (opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1585 log_inner_bool_option ((enum inner_bool_option
)opt_idx
);
1588 /* Write the current value of the given string option to the
1589 log file (if any). */
1592 recording::context::log_str_option (enum gcc_jit_str_option opt
) const
1594 gcc_assert (opt
< GCC_JIT_NUM_STR_OPTIONS
);
1597 if (m_str_options
[opt
])
1599 str_option_reproducer_strings
[opt
],
1600 m_str_options
[opt
]);
1603 str_option_reproducer_strings
[opt
]);
1607 /* Write the current value of the given int option to the
1608 log file (if any). */
1611 recording::context::log_int_option (enum gcc_jit_int_option opt
) const
1613 gcc_assert (opt
< GCC_JIT_NUM_INT_OPTIONS
);
1616 int_option_reproducer_strings
[opt
],
1617 m_int_options
[opt
]);
1620 /* Write the current value of the given bool option to the
1621 log file (if any). */
1624 recording::context::log_bool_option (enum gcc_jit_bool_option opt
) const
1626 gcc_assert (opt
< GCC_JIT_NUM_BOOL_OPTIONS
);
1629 bool_option_reproducer_strings
[opt
],
1630 m_bool_options
[opt
] ? "true" : "false");
1633 /* Write the current value of the given "inner" bool option to the
1634 log file (if any). */
1637 recording::context::log_inner_bool_option (enum inner_bool_option opt
) const
1639 gcc_assert (opt
< NUM_INNER_BOOL_OPTIONS
);
1642 inner_bool_option_reproducer_strings
[opt
],
1643 m_inner_bool_options
[opt
] ? "true" : "false");
1646 /* Write C source code to PATH that attempts to replay the API
1647 calls made to this context (and its parents), for use in
1648 minimizing test cases for libgccjit.
1650 Implements the post-error-checking part of
1651 gcc_jit_context_dump_reproducer_to_file. */
1654 recording::context::dump_reproducer_to_file (const char *path
)
1656 JIT_LOG_SCOPE (get_logger ());
1657 reproducer
r (*this, path
);
1659 /* Generate the "ancestry" of this context, as a list. */
1660 auto_vec
<context
*> ascending_contexts
;
1661 for (context
*ctxt
= this; ctxt
; ctxt
= ctxt
->m_parent_ctxt
)
1662 ascending_contexts
.safe_push (ctxt
);
1664 /* Reverse the list, giving a list of contexts from
1665 top-most parent context down through to youngest child context.
1666 We will use this list as the parameters of the functions in
1667 our generated file. */
1668 unsigned num_ctxts
= ascending_contexts
.length ();
1669 auto_vec
<context
*> contexts (num_ctxts
);
1670 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1671 contexts
.safe_push (ascending_contexts
[num_ctxts
- (i
+ 1)]);
1673 /* contexts[0] should be the top-level context. */
1674 gcc_assert (contexts
[0]);
1675 gcc_assert (contexts
[0]->m_toplevel_ctxt
== contexts
[0]);
1677 /* The final element in contexts should be "this". */
1678 gcc_assert (contexts
[contexts
.length () - 1] == this);
1679 gcc_assert (contexts
[contexts
.length () - 1]->m_toplevel_ctxt
1682 r
.write ("/* This code was autogenerated by"
1683 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1684 print_version (r
.get_file (), " ", false);
1686 r
.write ("#include <libgccjit.h>\n\n");
1687 r
.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1688 r
.write ("static void\nset_options (");
1689 r
.write_params (contexts
);
1691 r
.write ("static void\ncreate_code (");
1692 r
.write_params (contexts
);
1694 r
.write ("int\nmain (int argc, const char **argv)\n");
1696 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1697 r
.write (" gcc_jit_context *%s;\n",
1698 r
.get_identifier (contexts
[i
]));
1699 r
.write (" gcc_jit_result *result;\n"
1702 /* Create the contexts.
1703 The top-level context is acquired from a clean slate, the others as
1704 children of the prior context. */
1705 r
.write (" %s = gcc_jit_context_acquire ();\n",
1706 r
.get_identifier (contexts
[0]));
1707 for (unsigned i
= 1; i
< num_ctxts
; i
++)
1708 r
.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1709 r
.get_identifier (contexts
[i
]),
1710 r
.get_identifier (contexts
[i
- 1]));
1711 r
.write (" set_options (");
1712 r
.write_args (contexts
);
1714 r
.write (" create_code (");
1715 r
.write_args (contexts
);
1718 r
.write (" result = gcc_jit_context_compile (%s);\n",
1719 r
.get_identifier (this));
1721 for (unsigned i
= num_ctxts
; i
> 0; i
--)
1722 r
.write (" gcc_jit_context_release (%s);\n",
1723 r
.get_identifier (contexts
[i
- 1]));
1725 r
.write (" gcc_jit_result_release (result);\n"
1729 /* Define (char *) variables for use in calls to
1730 gcc_jit_context_enable_dump. */
1731 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1733 if (m_requested_dumps
.length ())
1735 r
.write ("/* Requested dumps for %s. */\n",
1736 r
.get_identifier (contexts
[ctxt_idx
]));
1737 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1738 r
.write ("static char *dump_%p;\n",
1739 (void *)&m_requested_dumps
[i
]);
1744 /* Write out values of options. */
1745 r
.write ("static void\nset_options (");
1746 r
.write_params (contexts
);
1748 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1753 r
.write (" /* Set options for %s. */\n",
1754 r
.get_identifier (contexts
[ctxt_idx
]));
1756 r
.write (" /* String options. */\n");
1757 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1759 r
.write (" gcc_jit_context_set_str_option (%s,\n"
1761 r
.get_identifier (contexts
[ctxt_idx
]),
1762 str_option_reproducer_strings
[opt_idx
]);
1763 if (m_str_options
[opt_idx
])
1764 r
.write (" \"%s\");\n",
1765 m_str_options
[opt_idx
]);
1767 r
.write (" NULL);\n");
1769 r
.write (" /* Int options. */\n");
1770 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1771 r
.write (" gcc_jit_context_set_int_option (%s,\n"
1774 r
.get_identifier (contexts
[ctxt_idx
]),
1775 int_option_reproducer_strings
[opt_idx
],
1776 m_int_options
[opt_idx
]);
1777 r
.write (" /* Boolean options. */\n");
1778 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1779 r
.write (" gcc_jit_context_set_bool_option (%s,\n"
1782 r
.get_identifier (contexts
[ctxt_idx
]),
1783 bool_option_reproducer_strings
[opt_idx
],
1784 m_bool_options
[opt_idx
]);
1785 for (int opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1786 r
.write (" %s (%s, %i);\n",
1787 inner_bool_option_reproducer_strings
[opt_idx
],
1788 r
.get_identifier (contexts
[ctxt_idx
]),
1789 m_inner_bool_options
[opt_idx
]);
1791 if (!m_command_line_options
.is_empty ())
1795 r
.write (" /* User-provided command-line options. */\n");
1796 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1797 r
.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1798 r
.get_identifier (contexts
[ctxt_idx
]),
1802 if (m_requested_dumps
.length ())
1804 r
.write (" /* Requested dumps. */\n");
1805 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1806 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1808 r
.write (" gcc_jit_context_enable_dump (%s,\n"
1811 r
.get_identifier (contexts
[ctxt_idx
]),
1812 m_requested_dumps
[i
].m_dumpname
,
1813 (void *)&m_requested_dumps
[i
]);
1819 r
.write ("static void\ncreate_code (");
1820 r
.write_params (contexts
);
1823 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1830 r
.write (" /* Replay of API calls for %s. */\n",
1831 r
.get_identifier (contexts
[ctxt_idx
]));
1832 FOR_EACH_VEC_ELT (contexts
[ctxt_idx
]->m_mementos
, i
, m
)
1833 m
->write_reproducer (r
);
1838 /* Copy the requested dumps within this context and all ancestors into
1842 recording::context::get_all_requested_dumps (vec
<recording::requested_dump
> *out
)
1845 m_parent_ctxt
->get_all_requested_dumps (out
);
1847 out
->reserve (m_requested_dumps
.length ());
1848 out
->splice (m_requested_dumps
);
1851 /* This is a pre-compilation check for the context (and any parents).
1853 Detect errors within the context, adding errors if any are found. */
1856 recording::context::validate ()
1858 JIT_LOG_SCOPE (get_logger ());
1861 m_parent_ctxt
->validate ();
1865 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1869 /* The implementation of class gcc::jit::recording::memento. */
1871 /* Get a (const char *) debug description of the given memento, by
1872 calling the pure-virtual make_debug_string hook, caching the
1875 It is intended that this should only be called in debugging and
1876 error-handling paths, so this doesn't need to be particularly
1880 recording::memento::get_debug_string ()
1882 if (!m_debug_string
)
1883 m_debug_string
= make_debug_string ();
1884 return m_debug_string
->c_str ();
1887 /* Default implementation of recording::memento::write_to_dump, writing
1888 an indented form of the memento's debug string to the dump. */
1891 recording::memento::write_to_dump (dump
&d
)
1893 d
.write(" %s\n", get_debug_string ());
1896 /* The implementation of class gcc::jit::recording::string. */
1898 /* Constructor for gcc::jit::recording::string::string, allocating a
1899 copy of the given text using new char[]. */
1901 recording::string::string (context
*ctxt
, const char *text
)
1904 m_len
= strlen (text
);
1905 m_buffer
= new char[m_len
+ 1];
1906 strcpy (m_buffer
, text
);
1909 /* Destructor for gcc::jit::recording::string::string. */
1911 recording::string::~string ()
1916 /* Function for making gcc::jit::recording::string instances on a
1917 context via printf-style formatting.
1919 It is intended that this should only be called in debugging and
1920 error-handling paths, so this doesn't need to be particularly
1921 optimized, hence the double-copy of the string is acceptable. */
1924 recording::string::from_printf (context
*ctxt
, const char *fmt
, ...)
1929 recording::string
*result
;
1932 len
= vasprintf (&buf
, fmt
, ap
);
1935 if (buf
== NULL
|| len
< 0)
1937 ctxt
->add_error (NULL
, "malloc failure");
1941 result
= ctxt
->new_string (buf
);
1946 /* Implementation of recording::memento::make_debug_string for strings,
1947 wrapping the given string in quotes and escaping as necessary. */
1950 recording::string::make_debug_string ()
1952 /* Hack to avoid infinite recursion into strings when logging all
1953 mementos: don't re-escape strings: */
1954 if (m_buffer
[0] == '"')
1957 /* Wrap in quotes and do escaping etc */
1959 size_t sz
= (1 /* opening quote */
1960 + (m_len
* 2) /* each char might get escaped */
1961 + 1 /* closing quote */
1962 + 1); /* nil termintator */
1963 char *tmp
= new char[sz
];
1966 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1967 APPEND('"'); /* opening quote */
1968 for (size_t i
= 0; i
< m_len
; i
++)
1970 char ch
= m_buffer
[i
];
1971 if (ch
== '\t' || ch
== '\n' || ch
== '\\' || ch
== '"')
1975 APPEND('"'); /* closing quote */
1977 tmp
[len
] = '\0'; /* nil termintator */
1979 string
*result
= m_ctxt
->new_string (tmp
);
1985 /* Implementation of recording::memento::write_reproducer for strings. */
1988 recording::string::write_reproducer (reproducer
&)
1993 /* The implementation of class gcc::jit::recording::location. */
1995 /* Implementation of recording::memento::replay_into for locations.
1997 Create a new playback::location and store it into the
1998 recording::location's m_playback_obj field. */
2001 recording::location::replay_into (replayer
*r
)
2003 m_playback_obj
= r
->new_location (this,
2004 m_filename
->c_str (),
2009 /* Implementation of recording::memento::make_debug_string for locations,
2010 turning them into the usual form:
2011 FILENAME:LINE:COLUMN
2012 like we do when emitting diagnostics. */
2015 recording::location::make_debug_string ()
2017 return string::from_printf (m_ctxt
,
2019 m_filename
->c_str (), m_line
, m_column
);
2022 /* Implementation of recording::memento::write_reproducer for locations. */
2025 recording::location::write_reproducer (reproducer
&r
)
2027 const char *id
= r
.make_identifier (this, "loc");
2028 r
.write (" gcc_jit_location *%s =\n"
2029 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
2030 " %s, /* const char *filename */\n"
2031 " %i, /* int line */\n"
2032 " %i);/* int column */\n",
2034 r
.get_identifier (get_context ()),
2035 m_filename
->get_debug_string (),
2039 /* The implementation of class gcc::jit::recording::type. */
2041 /* Given a type T, get the type T*.
2043 If this doesn't already exist, generate a new memento_of_get_pointer
2044 instance and add it to this type's context's list of mementos.
2046 Otherwise, use the cached type.
2048 Implements the post-error-checking part of
2049 gcc_jit_type_get_pointer. */
2052 recording::type::get_pointer ()
2054 if (!m_pointer_to_this_type
)
2056 m_pointer_to_this_type
= new memento_of_get_pointer (this);
2057 m_ctxt
->record (m_pointer_to_this_type
);
2059 return m_pointer_to_this_type
;
2062 /* Given a type T, get the type const T.
2064 Implements the post-error-checking part of
2065 gcc_jit_type_get_const. */
2068 recording::type::get_const ()
2070 recording::type
*result
= new memento_of_get_const (this);
2071 m_ctxt
->record (result
);
2075 /* Given a type T, get the type volatile T.
2077 Implements the post-error-checking part of
2078 gcc_jit_type_get_volatile. */
2081 recording::type::get_volatile ()
2083 recording::type
*result
= new memento_of_get_volatile (this);
2084 m_ctxt
->record (result
);
2088 /* Given a type, get an aligned version of the type.
2090 Implements the post-error-checking part of
2091 gcc_jit_type_get_aligned. */
2094 recording::type::get_aligned (size_t alignment_in_bytes
)
2096 recording::type
*result
2097 = new memento_of_get_aligned (this, alignment_in_bytes
);
2098 m_ctxt
->record (result
);
2102 /* Given a type, get a vector version of the type.
2104 Implements the post-error-checking part of
2105 gcc_jit_type_get_vector. */
2108 recording::type::get_vector (size_t num_units
)
2110 recording::type
*result
2111 = new vector_type (this, num_units
);
2112 m_ctxt
->record (result
);
2117 recording::type::access_as_type (reproducer
&r
)
2119 return r
.get_identifier (this);
2122 /* Implementation of pure virtual hook recording::type::dereference for
2123 recording::memento_of_get_type. */
2126 recording::memento_of_get_type::dereference ()
2130 default: gcc_unreachable ();
2132 case GCC_JIT_TYPE_VOID
:
2135 case GCC_JIT_TYPE_VOID_PTR
:
2136 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
2138 case GCC_JIT_TYPE_BOOL
:
2139 case GCC_JIT_TYPE_CHAR
:
2140 case GCC_JIT_TYPE_SIGNED_CHAR
:
2141 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2142 case GCC_JIT_TYPE_SHORT
:
2143 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2144 case GCC_JIT_TYPE_INT
:
2145 case GCC_JIT_TYPE_UNSIGNED_INT
:
2146 case GCC_JIT_TYPE_LONG
:
2147 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2148 case GCC_JIT_TYPE_LONG_LONG
:
2149 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2150 case GCC_JIT_TYPE_FLOAT
:
2151 case GCC_JIT_TYPE_DOUBLE
:
2152 case GCC_JIT_TYPE_LONG_DOUBLE
:
2153 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2154 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2155 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2156 /* Not a pointer: */
2159 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2160 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
2162 case GCC_JIT_TYPE_SIZE_T
:
2163 /* Not a pointer: */
2166 case GCC_JIT_TYPE_FILE_PTR
:
2167 /* Give the client code back an opaque "struct FILE". */
2168 return m_ctxt
->get_opaque_FILE_type ();
2172 /* Implementation of pure virtual hook recording::type::is_int for
2173 recording::memento_of_get_type. */
2176 recording::memento_of_get_type::is_int () const
2180 default: gcc_unreachable ();
2182 case GCC_JIT_TYPE_VOID
:
2185 case GCC_JIT_TYPE_VOID_PTR
:
2188 case GCC_JIT_TYPE_BOOL
:
2191 case GCC_JIT_TYPE_CHAR
:
2192 case GCC_JIT_TYPE_SIGNED_CHAR
:
2193 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2194 case GCC_JIT_TYPE_SHORT
:
2195 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2196 case GCC_JIT_TYPE_INT
:
2197 case GCC_JIT_TYPE_UNSIGNED_INT
:
2198 case GCC_JIT_TYPE_LONG
:
2199 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2200 case GCC_JIT_TYPE_LONG_LONG
:
2201 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2204 case GCC_JIT_TYPE_FLOAT
:
2205 case GCC_JIT_TYPE_DOUBLE
:
2206 case GCC_JIT_TYPE_LONG_DOUBLE
:
2209 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2212 case GCC_JIT_TYPE_SIZE_T
:
2215 case GCC_JIT_TYPE_FILE_PTR
:
2218 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2219 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2220 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2225 /* Implementation of pure virtual hook recording::type::is_float for
2226 recording::memento_of_get_type. */
2229 recording::memento_of_get_type::is_float () const
2233 default: gcc_unreachable ();
2235 case GCC_JIT_TYPE_VOID
:
2238 case GCC_JIT_TYPE_VOID_PTR
:
2241 case GCC_JIT_TYPE_BOOL
:
2244 case GCC_JIT_TYPE_CHAR
:
2245 case GCC_JIT_TYPE_SIGNED_CHAR
:
2246 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2247 case GCC_JIT_TYPE_SHORT
:
2248 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2249 case GCC_JIT_TYPE_INT
:
2250 case GCC_JIT_TYPE_UNSIGNED_INT
:
2251 case GCC_JIT_TYPE_LONG
:
2252 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2253 case GCC_JIT_TYPE_LONG_LONG
:
2254 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2257 case GCC_JIT_TYPE_FLOAT
:
2258 case GCC_JIT_TYPE_DOUBLE
:
2259 case GCC_JIT_TYPE_LONG_DOUBLE
:
2262 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2265 case GCC_JIT_TYPE_SIZE_T
:
2268 case GCC_JIT_TYPE_FILE_PTR
:
2271 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2272 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2273 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2278 /* Implementation of pure virtual hook recording::type::is_bool for
2279 recording::memento_of_get_type. */
2282 recording::memento_of_get_type::is_bool () const
2286 default: gcc_unreachable ();
2288 case GCC_JIT_TYPE_VOID
:
2291 case GCC_JIT_TYPE_VOID_PTR
:
2294 case GCC_JIT_TYPE_BOOL
:
2297 case GCC_JIT_TYPE_CHAR
:
2298 case GCC_JIT_TYPE_SIGNED_CHAR
:
2299 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2300 case GCC_JIT_TYPE_SHORT
:
2301 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2302 case GCC_JIT_TYPE_INT
:
2303 case GCC_JIT_TYPE_UNSIGNED_INT
:
2304 case GCC_JIT_TYPE_LONG
:
2305 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2306 case GCC_JIT_TYPE_LONG_LONG
:
2307 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2310 case GCC_JIT_TYPE_FLOAT
:
2311 case GCC_JIT_TYPE_DOUBLE
:
2312 case GCC_JIT_TYPE_LONG_DOUBLE
:
2315 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2318 case GCC_JIT_TYPE_SIZE_T
:
2321 case GCC_JIT_TYPE_FILE_PTR
:
2324 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2325 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2326 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2331 /* Implementation of pure virtual hook recording::memento::replay_into
2332 for recording::memento_of_get_type. */
2335 recording::memento_of_get_type::replay_into (replayer
*r
)
2337 set_playback_obj (r
->get_type (m_kind
));
2340 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2342 /* Descriptive strings for each of enum gcc_jit_types. */
2344 static const char * const get_type_strings
[] = {
2345 "void", /* GCC_JIT_TYPE_VOID */
2346 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2348 "bool", /* GCC_JIT_TYPE_BOOL */
2350 "char", /* GCC_JIT_TYPE_CHAR */
2351 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2352 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2354 "short", /* GCC_JIT_TYPE_SHORT */
2355 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2357 "int", /* GCC_JIT_TYPE_INT */
2358 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2360 "long", /* GCC_JIT_TYPE_LONG */
2361 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2363 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2364 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2366 "float", /* GCC_JIT_TYPE_FLOAT */
2367 "double", /* GCC_JIT_TYPE_DOUBLE */
2368 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2370 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2372 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2374 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2376 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2377 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2378 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2382 /* Implementation of recording::memento::make_debug_string for
2383 results of get_type, using a simple table of type names. */
2386 recording::memento_of_get_type::make_debug_string ()
2388 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
2391 static const char * const get_type_enum_strings
[] = {
2392 "GCC_JIT_TYPE_VOID",
2393 "GCC_JIT_TYPE_VOID_PTR",
2394 "GCC_JIT_TYPE_BOOL",
2395 "GCC_JIT_TYPE_CHAR",
2396 "GCC_JIT_TYPE_SIGNED_CHAR",
2397 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2398 "GCC_JIT_TYPE_SHORT",
2399 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2401 "GCC_JIT_TYPE_UNSIGNED_INT",
2402 "GCC_JIT_TYPE_LONG",
2403 "GCC_JIT_TYPE_UNSIGNED_LONG",
2404 "GCC_JIT_TYPE_LONG_LONG",
2405 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2406 "GCC_JIT_TYPE_FLOAT",
2407 "GCC_JIT_TYPE_DOUBLE",
2408 "GCC_JIT_TYPE_LONG_DOUBLE",
2409 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2410 "GCC_JIT_TYPE_SIZE_T",
2411 "GCC_JIT_TYPE_FILE_PTR",
2412 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2413 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2414 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2418 recording::memento_of_get_type::write_reproducer (reproducer
&r
)
2420 const char *id
= r
.make_identifier (this, "type");
2421 r
.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2423 r
.get_identifier (get_context ()),
2424 get_type_enum_strings
[m_kind
]);
2427 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2429 /* Override of default implementation of
2430 recording::type::accepts_writes_from for get_pointer.
2432 Require a pointer type, and allowing writes to
2433 (const T *) from a (T*), but not the other way around. */
2436 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
2438 /* Must be a pointer type: */
2439 type
*rtype_points_to
= rtype
->is_pointer ();
2440 if (!rtype_points_to
)
2443 /* It's OK to assign to a (const T *) from a (T *). */
2444 return m_other_type
->unqualified ()
2445 ->accepts_writes_from (rtype_points_to
);
2448 /* Implementation of pure virtual hook recording::memento::replay_into
2449 for recording::memento_of_get_pointer. */
2452 recording::memento_of_get_pointer::replay_into (replayer
*)
2454 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
2457 /* Implementation of recording::memento::make_debug_string for
2458 results of get_pointer, adding " *" to the underlying type,
2459 with special-casing to handle function pointer types. */
2462 recording::memento_of_get_pointer::make_debug_string ()
2464 /* Special-case function pointer types, to put the "*" in parens between
2465 the return type and the params (for one level of dereferencing, at
2467 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2468 return fn_type
->make_debug_string_with_ptr ();
2470 return string::from_printf (m_ctxt
,
2471 "%s *", m_other_type
->get_debug_string ());
2474 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2477 recording::memento_of_get_pointer::write_reproducer (reproducer
&r
)
2479 /* We need to special-case function pointer types; see the notes in
2480 recording::function_type::write_deferred_reproducer. */
2481 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2483 fn_type
->write_deferred_reproducer (r
, this);
2487 const char *id
= r
.make_identifier (this, "type");
2488 r
.write (" gcc_jit_type *%s =\n"
2489 " gcc_jit_type_get_pointer (%s);\n",
2491 r
.get_identifier_as_type (m_other_type
));
2494 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2496 /* Implementation of pure virtual hook recording::memento::replay_into
2497 for recording::memento_of_get_const. */
2500 recording::memento_of_get_const::replay_into (replayer
*)
2502 set_playback_obj (m_other_type
->playback_type ()->get_const ());
2505 /* Implementation of recording::memento::make_debug_string for
2506 results of get_const, prepending "const ". */
2509 recording::memento_of_get_const::make_debug_string ()
2511 return string::from_printf (m_ctxt
,
2512 "const %s", m_other_type
->get_debug_string ());
2515 /* Implementation of recording::memento::write_reproducer for const types. */
2518 recording::memento_of_get_const::write_reproducer (reproducer
&r
)
2520 const char *id
= r
.make_identifier (this, "type");
2521 r
.write (" gcc_jit_type *%s =\n"
2522 " gcc_jit_type_get_const (%s);\n",
2524 r
.get_identifier_as_type (m_other_type
));
2527 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2529 /* Implementation of pure virtual hook recording::memento::replay_into
2530 for recording::memento_of_get_volatile. */
2533 recording::memento_of_get_volatile::replay_into (replayer
*)
2535 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
2538 /* Implementation of recording::memento::make_debug_string for
2539 results of get_volatile, prepending "volatile ". */
2542 recording::memento_of_get_volatile::make_debug_string ()
2544 return string::from_printf (m_ctxt
,
2545 "volatile %s", m_other_type
->get_debug_string ());
2548 /* Implementation of recording::memento::write_reproducer for volatile
2552 recording::memento_of_get_volatile::write_reproducer (reproducer
&r
)
2554 const char *id
= r
.make_identifier (this, "type");
2555 r
.write (" gcc_jit_type *%s =\n"
2556 " gcc_jit_type_get_volatile (%s);\n",
2558 r
.get_identifier_as_type (m_other_type
));
2561 /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
2563 /* Implementation of pure virtual hook recording::memento::replay_into
2564 for recording::memento_of_get_aligned. */
2567 recording::memento_of_get_aligned::replay_into (replayer
*)
2570 (m_other_type
->playback_type ()->get_aligned (m_alignment_in_bytes
));
2573 /* Implementation of recording::memento::make_debug_string for
2574 results of get_aligned. */
2577 recording::memento_of_get_aligned::make_debug_string ()
2579 return string::from_printf (m_ctxt
,
2580 "%s __attribute__((aligned(%zi)))",
2581 m_other_type
->get_debug_string (),
2582 m_alignment_in_bytes
);
2585 /* Implementation of recording::memento::write_reproducer for aligned
2589 recording::memento_of_get_aligned::write_reproducer (reproducer
&r
)
2591 const char *id
= r
.make_identifier (this, "type");
2592 r
.write (" gcc_jit_type *%s =\n"
2593 " gcc_jit_type_get_aligned (%s, %zi);\n",
2595 r
.get_identifier_as_type (m_other_type
),
2596 m_alignment_in_bytes
);
2599 /* The implementation of class gcc::jit::recording::vector_type. */
2601 /* Implementation of pure virtual hook recording::memento::replay_into
2602 for recording::vector_type. */
2605 recording::vector_type::replay_into (replayer
*)
2608 (m_other_type
->playback_type ()->get_vector (m_num_units
));
2611 /* Implementation of recording::memento::make_debug_string for
2612 results of get_vector. */
2615 recording::vector_type::make_debug_string ()
2617 return string::from_printf
2619 "%s __attribute__((vector_size(sizeof (%s) * %zi)))",
2620 m_other_type
->get_debug_string (),
2621 m_other_type
->get_debug_string (),
2625 /* Implementation of recording::memento::write_reproducer for vector types. */
2628 recording::vector_type::write_reproducer (reproducer
&r
)
2630 const char *id
= r
.make_identifier (this, "type");
2631 r
.write (" gcc_jit_type *%s =\n"
2632 " gcc_jit_type_get_vector (%s, %zi);\n",
2634 r
.get_identifier_as_type (m_other_type
),
2638 /* The implementation of class gcc::jit::recording::array_type */
2640 /* Implementation of pure virtual hook recording::type::dereference for
2641 recording::array_type. */
2644 recording::array_type::dereference ()
2646 return m_element_type
;
2649 /* Implementation of pure virtual hook recording::memento::replay_into
2650 for recording::array_type. */
2653 recording::array_type::replay_into (replayer
*r
)
2655 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
2656 m_element_type
->playback_type (),
2660 /* Implementation of recording::memento::make_debug_string for
2661 results of new_array_type. */
2664 recording::array_type::make_debug_string ()
2666 return string::from_printf (m_ctxt
,
2668 m_element_type
->get_debug_string (),
2672 /* Implementation of recording::memento::write_reproducer for array
2676 recording::array_type::write_reproducer (reproducer
&r
)
2678 const char *id
= r
.make_identifier (this, "array_type");
2679 r
.write (" gcc_jit_type *%s =\n"
2680 " gcc_jit_context_new_array_type (%s,\n"
2681 " %s, /* gcc_jit_location *loc */\n"
2682 " %s, /* gcc_jit_type *element_type */\n"
2683 " %i); /* int num_elements */\n",
2685 r
.get_identifier (get_context ()),
2686 r
.get_identifier (m_loc
),
2687 r
.get_identifier_as_type (m_element_type
),
2691 /* The implementation of class gcc::jit::recording::function_type */
2693 /* Constructor for gcc::jit::recording::function_type. */
2695 recording::function_type::function_type (context
*ctxt
,
2701 m_return_type (return_type
),
2703 m_is_variadic (is_variadic
)
2705 for (int i
= 0; i
< num_params
; i
++)
2706 m_param_types
.safe_push (param_types
[i
]);
2709 /* Implementation of pure virtual hook recording::type::dereference for
2710 recording::function_type. */
2713 recording::function_type::dereference ()
2718 /* Implementation of virtual hook recording::type::is_same_type_as for
2719 recording::function_type.
2721 We override this to avoid requiring identity of function pointer types,
2722 so that if client code has obtained the same signature in
2723 different ways (e.g. via gcc_jit_context_new_function_ptr_type
2724 vs gcc_jit_function_get_address), the different function_type
2725 instances are treated as compatible.
2727 We can't use type::accepts_writes_from for this as we need a stronger
2728 notion of "sameness": if we have a fn_ptr type that has args that are
2729 themselves fn_ptr types, then those args still need to match exactly.
2731 Alternatively, we could consolidate attempts to create identical
2732 function_type instances so that pointer equality works, but that runs
2733 into issues about the lifetimes of the cache (w.r.t. nested contexts). */
2736 recording::function_type::is_same_type_as (type
*other
)
2740 function_type
*other_fn_type
= other
->dyn_cast_function_type ();
2744 /* Everything must match. */
2746 if (!m_return_type
->is_same_type_as (other_fn_type
->m_return_type
))
2749 if (m_param_types
.length () != other_fn_type
->m_param_types
.length ())
2754 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
2755 if (!param_type
->is_same_type_as (other_fn_type
->m_param_types
[i
]))
2758 if (m_is_variadic
!= other_fn_type
->m_is_variadic
)
2761 /* Passed all tests. */
2765 /* Implementation of pure virtual hook recording::memento::replay_into
2766 for recording::function_type. */
2769 recording::function_type::replay_into (replayer
*r
)
2771 /* Convert m_param_types to a vec of playback type. */
2772 auto_vec
<playback::type
*> param_types
;
2774 recording::type
*type
;
2775 param_types
.create (m_param_types
.length ());
2776 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
2777 param_types
.safe_push (type
->playback_type ());
2779 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
2784 /* Special-casing for make_debug_string for get_pointer results for
2785 handling (one level) of pointers to functions. */
2788 recording::function_type::make_debug_string_with_ptr ()
2790 return make_debug_string_with ("(*) ");
2793 /* Implementation of recording::memento::make_debug_string for
2794 results of new_function_type. */
2797 recording::function_type::make_debug_string ()
2799 return make_debug_string_with ("");
2802 /* Build a debug string representation of the form:
2804 RESULT_TYPE INSERT (PARAM_TYPES)
2806 for use when handling 0 and 1 level of indirection to this
2810 recording::function_type::make_debug_string_with (const char *insert
)
2812 /* First, build a buffer for the arguments. */
2813 /* Calculate length of said buffer. */
2814 size_t sz
= 1; /* nil terminator */
2815 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2817 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
2818 sz
+= 2; /* ", " separator */
2821 sz
+= 5; /* ", ..." separator and ellipsis */
2823 /* Now allocate and populate the buffer. */
2824 char *argbuf
= new char[sz
];
2827 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2829 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
2830 len
+= strlen (m_param_types
[i
]->get_debug_string ());
2831 if (i
+ 1 < m_param_types
.length ())
2833 strcpy (argbuf
+ len
, ", ");
2839 if (m_param_types
.length ())
2841 strcpy (argbuf
+ len
, ", ");
2844 strcpy (argbuf
+ len
, "...");
2849 /* ...and use it to get the string for the call as a whole. */
2850 string
*result
= string::from_printf (m_ctxt
,
2852 m_return_type
->get_debug_string (),
2861 /* Implementation of recording::memento::write_reproducer for function
2865 recording::function_type::write_reproducer (reproducer
&)
2867 /* see notes below. */
2870 /* There's a get_pointer within context::new_function_ptr_type:
2871 the type received by client code isn't the memento for the
2872 function_type, but instead the result of get_pointer on it.
2874 Hence we can't directly write a reproducer that gives function_type.
2875 Instead we special-case things within get_pointer, detecting this
2876 case, calling the following function. */
2879 recording::function_type::write_deferred_reproducer (reproducer
&r
,
2882 gcc_assert (ptr_type
);
2883 r
.make_identifier (this, "function_type");
2884 const char *ptr_id
= r
.make_identifier (ptr_type
, "ptr_to");
2885 const char *param_types_id
= r
.make_tmp_identifier ("params_for", this);
2886 r
.write (" gcc_jit_type *%s[%i] = {\n",
2888 m_param_types
.length ());
2891 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
2892 r
.write (" %s,\n", r
.get_identifier_as_type (param_type
));
2894 r
.write (" gcc_jit_type *%s =\n"
2895 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2896 " %s, /* gcc_jit_location *loc */\n"
2897 " %s, /* gcc_jit_type *return_type */\n"
2898 " %i, /* int num_params */\n"
2899 " %s, /* gcc_jit_type **param_types */\n"
2900 " %i); /* int is_variadic */\n",
2902 r
.get_identifier (get_context ()),
2903 "NULL", /* location is not stored */
2904 r
.get_identifier_as_type (m_return_type
),
2905 m_param_types
.length (),
2910 /* The implementation of class gcc::jit::recording::field. */
2912 /* Implementation of pure virtual hook recording::memento::replay_into
2913 for recording::field. */
2916 recording::field::replay_into (replayer
*r
)
2918 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
2919 m_type
->playback_type (),
2920 playback_string (m_name
)));
2923 /* Override the default implementation of
2924 recording::memento::write_to_dump. Dump each field
2925 by dumping a line of the form:
2927 so that we can build up a struct/union field-byfield. */
2930 recording::field::write_to_dump (dump
&d
)
2932 d
.write (" %s %s;\n",
2933 m_type
->get_debug_string (),
2937 /* Implementation of recording::memento::make_debug_string for
2938 results of new_field. */
2941 recording::field::make_debug_string ()
2946 /* Implementation of recording::memento::write_reproducer for fields. */
2949 recording::field::write_reproducer (reproducer
&r
)
2951 const char *id
= r
.make_identifier (this, "field");
2952 r
.write(" gcc_jit_field *%s =\n"
2953 " gcc_jit_context_new_field (%s,\n"
2954 " %s, /* gcc_jit_location *loc */\n"
2955 " %s, /* gcc_jit_type *type, */\n"
2956 " %s); /* const char *name */\n",
2958 r
.get_identifier (get_context ()),
2959 r
.get_identifier (m_loc
),
2960 r
.get_identifier_as_type (m_type
),
2961 m_name
->get_debug_string ());
2964 /* The implementation of class gcc::jit::recording::compound_type */
2966 /* The constructor for gcc::jit::recording::compound_type. */
2968 recording::compound_type::compound_type (context
*ctxt
,
2978 /* Set the fields of a compound type.
2980 Implements the post-error-checking part of
2981 gcc_jit_struct_set_fields, and is also used by
2982 gcc_jit_context_new_union_type. */
2985 recording::compound_type::set_fields (location
*loc
,
2987 field
**field_array
)
2990 gcc_assert (m_fields
== NULL
);
2992 m_fields
= new fields (this, num_fields
, field_array
);
2993 m_ctxt
->record (m_fields
);
2996 /* Implementation of pure virtual hook recording::type::dereference for
2997 recording::compound_type. */
3000 recording::compound_type::dereference ()
3002 return NULL
; /* not a pointer */
3005 /* The implementation of class gcc::jit::recording::struct_. */
3007 /* The constructor for gcc::jit::recording::struct_. */
3009 recording::struct_::struct_ (context
*ctxt
,
3012 : compound_type (ctxt
, loc
, name
)
3016 /* Implementation of pure virtual hook recording::memento::replay_into
3017 for recording::struct_. */
3020 recording::struct_::replay_into (replayer
*r
)
3023 r
->new_compound_type (playback_location (r
, get_loc ()),
3024 get_name ()->c_str (),
3025 true /* is_struct */));
3029 recording::struct_::access_as_type (reproducer
&r
)
3031 return r
.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
3032 r
.get_identifier (this));
3035 /* Implementation of recording::memento::make_debug_string for
3039 recording::struct_::make_debug_string ()
3041 return string::from_printf (m_ctxt
,
3042 "struct %s", get_name ()->c_str ());
3046 recording::struct_::write_reproducer (reproducer
&r
)
3048 const char *id
= r
.make_identifier (this, "struct");
3049 r
.write (" gcc_jit_struct *%s =\n"
3050 " gcc_jit_context_new_opaque_struct (%s,\n"
3051 " %s, /* gcc_jit_location *loc */\n"
3052 " %s); /* const char *name */\n",
3054 r
.get_identifier (get_context ()),
3055 r
.get_identifier (get_loc ()),
3056 get_name ()->get_debug_string ());
3059 /* The implementation of class gcc::jit::recording::union_. */
3061 /* The constructor for gcc::jit::recording::union_. */
3063 recording::union_::union_ (context
*ctxt
,
3066 : compound_type (ctxt
, loc
, name
)
3070 /* Implementation of pure virtual hook recording::memento::replay_into
3071 for recording::union_. */
3074 recording::union_::replay_into (replayer
*r
)
3077 r
->new_compound_type (playback_location (r
, get_loc ()),
3078 get_name ()->c_str (),
3079 false /* is_struct */));
3082 /* Implementation of recording::memento::make_debug_string for
3086 recording::union_::make_debug_string ()
3088 return string::from_printf (m_ctxt
,
3089 "union %s", get_name ()->c_str ());
3092 /* Implementation of recording::memento::write_reproducer for unions. */
3095 recording::union_::write_reproducer (reproducer
&r
)
3097 const char *id
= r
.make_identifier (this, "union");
3099 const char *fields_id
= r
.make_tmp_identifier ("fields_for", this);
3100 r
.write (" gcc_jit_field *%s[%i] = {\n",
3102 get_fields ()->length ());
3103 for (int i
= 0; i
< get_fields ()->length (); i
++)
3104 r
.write (" %s,\n", r
.get_identifier (get_fields ()->get_field (i
)));
3107 r
.write (" gcc_jit_type *%s =\n"
3108 " gcc_jit_context_new_union_type (%s,\n"
3109 " %s, /* gcc_jit_location *loc */\n"
3110 " %s, /* const char *name */\n"
3111 " %i, /* int num_fields */\n"
3112 " %s); /* gcc_jit_field **fields */\n",
3114 r
.get_identifier (get_context ()),
3115 r
.get_identifier (get_loc ()),
3116 get_name ()->get_debug_string (),
3117 get_fields ()->length (),
3121 /* The implementation of class gcc::jit::recording::fields. */
3123 /* The constructor for gcc::jit::recording::fields. */
3125 recording::fields::fields (compound_type
*struct_or_union
,
3128 : memento (struct_or_union
->m_ctxt
),
3129 m_struct_or_union (struct_or_union
),
3132 for (int i
= 0; i
< num_fields
; i
++)
3134 gcc_assert (fields
[i
]->get_container () == NULL
);
3135 fields
[i
]->set_container (m_struct_or_union
);
3136 m_fields
.safe_push (fields
[i
]);
3140 /* Implementation of pure virtual hook recording::memento::replay_into
3141 for recording::fields. */
3144 recording::fields::replay_into (replayer
*)
3146 auto_vec
<playback::field
*> playback_fields
;
3147 playback_fields
.create (m_fields
.length ());
3148 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
3149 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
3150 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
3153 /* Override the default implementation of
3154 recording::memento::write_to_dump by writing a union/struct
3155 declaration of this form:
3167 recording::fields::write_to_dump (dump
&d
)
3172 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
3173 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
3174 f
->write_to_dump (d
);
3178 /* Implementation of recording::memento::write_reproducer for the fields
3182 recording::fields::write_reproducer (reproducer
&r
)
3184 if (m_struct_or_union
)
3185 if (m_struct_or_union
->dyn_cast_struct () == NULL
)
3186 /* We have a union; the fields have already been written by
3187 union::write_reproducer. */
3190 const char *fields_id
= r
.make_identifier (this, "fields");
3191 r
.write (" gcc_jit_field *%s[%i] = {\n",
3193 m_fields
.length ());
3196 FOR_EACH_VEC_ELT (m_fields
, i
, field
)
3197 r
.write (" %s,\n", r
.get_identifier (field
));
3200 r
.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
3201 " %s, /* gcc_jit_location *loc */\n"
3202 " %i, /* int num_fields */\n"
3203 " %s); /* gcc_jit_field **fields */\n",
3204 r
.get_identifier (m_struct_or_union
),
3205 r
.get_identifier ((memento
*)NULL
),
3210 /* Implementation of recording::memento::make_debug_string for
3214 recording::fields::make_debug_string ()
3216 return string::from_printf (m_ctxt
,
3220 /* The implementation of class gcc::jit::recording::rvalue. */
3222 /* Create a recording::access_field_rvalue instance and add it to
3223 the rvalue's context's list of mementos.
3225 Implements the post-error-checking part of
3226 gcc_jit_rvalue_access_field. */
3229 recording::rvalue::access_field (recording::location
*loc
,
3232 recording::rvalue
*result
=
3233 new access_field_rvalue (m_ctxt
, loc
, this, field
);
3234 m_ctxt
->record (result
);
3238 /* Create a recording::dereference_field_rvalue instance and add it to
3239 the rvalue's context's list of mementos.
3241 Implements the post-error-checking part of
3242 gcc_jit_rvalue_dereference_field. */
3245 recording::rvalue::dereference_field (recording::location
*loc
,
3248 recording::lvalue
*result
=
3249 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
3250 m_ctxt
->record (result
);
3254 /* Create a recording::dereference_rvalue instance and add it to the
3255 rvalue's context's list of mementos.
3257 Implements the post-error-checking part of
3258 gcc_jit_rvalue_dereference. */
3261 recording::rvalue::dereference (recording::location
*loc
)
3263 recording::lvalue
*result
=
3264 new dereference_rvalue (m_ctxt
, loc
, this);
3265 m_ctxt
->record (result
);
3269 /* An rvalue visitor, for validating that every rvalue within an expression
3270 trees within "STMT" has the correct scope (e.g. no access to locals
3271 of a different function). */
3273 class rvalue_usage_validator
: public recording::rvalue_visitor
3276 rvalue_usage_validator (const char *api_funcname
,
3277 recording::context
*ctxt
,
3278 recording::statement
*stmt
);
3281 visit (recording::rvalue
*rvalue
) FINAL OVERRIDE
;
3284 const char *m_api_funcname
;
3285 recording::context
*m_ctxt
;
3286 recording::statement
*m_stmt
;
3289 /* The trivial constructor for rvalue_usage_validator. */
3291 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname
,
3292 recording::context
*ctxt
,
3293 recording::statement
*stmt
)
3294 : m_api_funcname (api_funcname
),
3300 /* Verify that the given rvalue is in the correct scope. */
3303 rvalue_usage_validator::visit (recording::rvalue
*rvalue
)
3305 gcc_assert (m_stmt
->get_block ());
3306 recording::function
*stmt_scope
= m_stmt
->get_block ()->get_function ();
3308 /* Most rvalues don't have a scope (only locals and params). */
3309 if (rvalue
->get_scope ())
3311 if (rvalue
->get_scope () != stmt_scope
)
3313 (rvalue
->get_loc (),
3315 " rvalue %s (type: %s)"
3316 " has scope limited to function %s"
3317 " but was used within function %s"
3318 " (in statement: %s)",
3320 rvalue
->get_debug_string (),
3321 rvalue
->get_type ()->get_debug_string (),
3322 rvalue
->get_scope ()->get_debug_string (),
3323 stmt_scope
->get_debug_string (),
3324 m_stmt
->get_debug_string ());
3328 if (rvalue
->dyn_cast_param ())
3330 (rvalue
->get_loc (),
3332 " param %s (type: %s)"
3333 " was used within function %s"
3334 " (in statement: %s)"
3335 " but is not associated with any function",
3337 rvalue
->get_debug_string (),
3338 rvalue
->get_type ()->get_debug_string (),
3339 stmt_scope
->get_debug_string (),
3340 m_stmt
->get_debug_string ());
3344 /* Verify that it's valid to use this rvalue (and all expressions
3345 in the tree below it) within the given statement.
3347 For example, we must reject attempts to use a local from one
3348 function within a different function here, or we'll get
3349 an ICE deep inside toplev::main. */
3352 recording::rvalue::verify_valid_within_stmt (const char *api_funcname
, statement
*s
)
3354 rvalue_usage_validator
v (api_funcname
,
3358 /* Verify that it's OK to use this rvalue within s. */
3361 /* Traverse the expression tree below "this", verifying all rvalues
3363 visit_children (&v
);
3366 /* Set the scope of this rvalue to be the given function. This can only
3367 be done once on a given rvalue. */
3370 recording::rvalue::set_scope (function
*scope
)
3373 gcc_assert (m_scope
== NULL
);
3378 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3380 Instances of rvalue don't need an upcast call. */
3383 recording::rvalue::access_as_rvalue (reproducer
&r
)
3385 return r
.get_identifier (this);
3388 /* Return a debug string for the given rvalue, wrapping it in parentheses
3389 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3390 stronger precedence that this rvalue's precedence.
3404 since MULT has strong precedence than PLUS and MINUS, whereas for:
3416 since PLUS has weaker precedence than MULT and DIVIDE. */
3419 recording::rvalue::get_debug_string_parens (enum precedence outer_prec
)
3421 enum precedence this_prec
= get_precedence ();
3423 /* If this_prec has stronger precedence than outer_prec, we don't
3424 need to wrap this in parens within the outer debug string.
3425 Stronger precedences occur earlier than weaker within the enum,
3426 so this is a less than test. Equal precedences don't need
3428 if (this_prec
<= outer_prec
)
3429 return get_debug_string();
3431 /* Otherwise, we need parentheses. */
3433 /* Lazily-build and cache m_parenthesized_string. */
3434 if (!m_parenthesized_string
)
3436 const char *debug_string
= get_debug_string ();
3437 m_parenthesized_string
= string::from_printf (get_context (),
3441 gcc_assert (m_parenthesized_string
);
3442 return m_parenthesized_string
->c_str ();
3446 /* The implementation of class gcc::jit::recording::lvalue. */
3448 /* Create a recording::new_access_field_of_lvalue instance and add it to
3449 the lvalue's context's list of mementos.
3451 Implements the post-error-checking part of
3452 gcc_jit_lvalue_access_field. */
3455 recording::lvalue::access_field (recording::location
*loc
,
3458 recording::lvalue
*result
=
3459 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
3460 m_ctxt
->record (result
);
3464 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3465 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3469 recording::lvalue::access_as_rvalue (reproducer
&r
)
3471 return r
.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3472 r
.get_identifier (this));
3475 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3476 Instances of lvalue don't need to be upcast. */
3479 recording::lvalue::access_as_lvalue (reproducer
&r
)
3481 return r
.get_identifier (this);
3484 /* Create a recording::get_address_of_lvalue instance and add it to
3485 the lvalue's context's list of mementos.
3487 Implements the post-error-checking part of
3488 gcc_jit_lvalue_get_address. */
3491 recording::lvalue::get_address (recording::location
*loc
)
3493 recording::rvalue
*result
=
3494 new get_address_of_lvalue (m_ctxt
, loc
, this);
3495 m_ctxt
->record (result
);
3499 /* The implementation of class gcc::jit::recording::param. */
3501 /* Implementation of pure virtual hook recording::memento::replay_into
3502 for recording::param. */
3505 recording::param::replay_into (replayer
*r
)
3507 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
3508 m_type
->playback_type (),
3512 /* Implementation of recording::rvalue::access_as_rvalue for params.
3513 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3517 recording::param::access_as_rvalue (reproducer
&r
)
3519 return r
.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3520 r
.get_identifier (this));
3523 /* Implementation of recording::lvalue::access_as_lvalue for params.
3524 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3528 recording::param::access_as_lvalue (reproducer
&r
)
3530 return r
.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3531 r
.get_identifier (this));
3534 /* Implementation of recording::memento::write_reproducer for params. */
3537 recording::param::write_reproducer (reproducer
&r
)
3539 const char *id
= r
.make_identifier (this, "param");
3540 r
.write (" gcc_jit_param *%s =\n"
3541 " gcc_jit_context_new_param (%s,\n"
3542 " %s, /* gcc_jit_location *loc */\n"
3543 " %s, /*gcc_jit_type *type */\n"
3544 " %s); /* const char *name */\n",
3546 r
.get_identifier (get_context ()),
3547 r
.get_identifier (m_loc
),
3548 r
.get_identifier_as_type (m_type
),
3549 m_name
->get_debug_string ());
3552 /* The implementation of class gcc::jit::recording::function. */
3554 /* gcc::jit::recording::function's constructor. */
3556 recording::function::function (context
*ctxt
,
3557 recording::location
*loc
,
3558 enum gcc_jit_function_kind kind
,
3560 recording::string
*name
,
3562 recording::param
**params
,
3564 enum built_in_function builtin_id
)
3568 m_return_type (return_type
),
3571 m_is_variadic (is_variadic
),
3572 m_builtin_id (builtin_id
),
3575 m_fn_ptr_type (NULL
)
3577 for (int i
= 0; i
< num_params
; i
++)
3579 param
*param
= params
[i
];
3582 /* Associate each param with this function.
3584 Verify that the param doesn't already have a function. */
3585 if (param
->get_scope ())
3587 /* We've already rejected attempts to reuse a param between
3588 different functions (within gcc_jit_context_new_function), so
3589 if the param *does* already have a function, it must be being
3590 reused within the params array for this function. We must
3591 produce an error for this reuse (blocking the compile), since
3592 otherwise we'd have an ICE later on. */
3593 gcc_assert (this == param
->get_scope ());
3596 "gcc_jit_context_new_function:"
3597 " parameter %s (type: %s)"
3598 " is used more than once when creating function %s",
3599 param
->get_debug_string (),
3600 param
->get_type ()->get_debug_string (),
3605 /* The normal, non-error case: associate this function with the
3607 param
->set_scope (this);
3610 m_params
.safe_push (param
);
3614 /* Implementation of pure virtual hook recording::memento::replay_into
3615 for recording::function. */
3618 recording::function::replay_into (replayer
*r
)
3620 /* Convert m_params to a vec of playback param. */
3621 auto_vec
<playback::param
*> params
;
3623 recording::param
*param
;
3624 params
.create (m_params
.length ());
3625 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3626 params
.safe_push (param
->playback_param ());
3628 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
3630 m_return_type
->playback_type (),
3637 /* Create a recording::local instance and add it to
3638 the functions's context's list of mementos, and to the function's
3641 Implements the post-error-checking part of
3642 gcc_jit_function_new_local. */
3645 recording::function::new_local (recording::location
*loc
,
3649 local
*result
= new local (this, loc
, type
, new_string (name
));
3650 m_ctxt
->record (result
);
3651 m_locals
.safe_push (result
);
3655 /* Create a recording::block instance and add it to
3656 the functions's context's list of mementos, and to the function's
3659 Implements the post-error-checking part of
3660 gcc_jit_function_new_block. */
3663 recording::function::new_block (const char *name
)
3665 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
3667 recording::block
*result
=
3668 new recording::block (this, m_blocks
.length (), new_string (name
));
3669 m_ctxt
->record (result
);
3670 m_blocks
.safe_push (result
);
3674 /* Override the default implementation of
3675 recording::memento::write_to_dump by dumping a C-like
3676 representation of the function; either like a prototype
3677 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3678 all other kinds of function. */
3681 recording::function::write_to_dump (dump
&d
)
3685 default: gcc_unreachable ();
3686 case GCC_JIT_FUNCTION_EXPORTED
:
3687 case GCC_JIT_FUNCTION_IMPORTED
:
3688 d
.write ("extern ");
3690 case GCC_JIT_FUNCTION_INTERNAL
:
3691 d
.write ("static ");
3693 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
3694 d
.write ("static inline ");
3697 d
.write ("%s\n", m_return_type
->get_debug_string ());
3699 if (d
.update_locations ())
3700 m_loc
= d
.make_location ();
3702 d
.write ("%s (", get_debug_string ());
3705 recording::param
*param
;
3706 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3711 param
->get_type ()->get_debug_string (),
3712 param
->get_debug_string ());
3715 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
3717 d
.write ("; /* (imported) */\n\n");
3727 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
3728 var
->write_to_dump (d
);
3729 if (m_locals
.length ())
3732 /* Write each block: */
3733 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3737 b
->write_to_dump (d
);
3744 /* Pre-compilation validation of a function, for those things we can't
3745 check until the context is (supposedly) fully-populated. */
3748 recording::function::validate ()
3750 /* Complain about empty functions with non-void return type. */
3751 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
3752 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
3753 if (m_blocks
.length () == 0)
3754 m_ctxt
->add_error (m_loc
,
3755 "function %s returns non-void (type: %s)"
3756 " but has no blocks",
3757 get_debug_string (),
3758 m_return_type
->get_debug_string ());
3760 /* Check that all blocks are terminated. */
3761 int num_invalid_blocks
= 0;
3766 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3767 if (!b
->validate ())
3768 num_invalid_blocks
++;
3771 /* Check that all blocks are reachable. */
3772 if (!m_ctxt
->get_inner_bool_option
3773 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS
)
3774 && m_blocks
.length () > 0 && num_invalid_blocks
== 0)
3776 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3777 flag, starting at the initial block. */
3778 auto_vec
<block
*> worklist (m_blocks
.length ());
3779 worklist
.safe_push (m_blocks
[0]);
3780 while (worklist
.length () > 0)
3782 block
*b
= worklist
.pop ();
3783 b
->m_is_reachable
= true;
3785 /* Add successor blocks that aren't yet marked to the worklist. */
3786 /* We checked that each block has a terminating statement above . */
3787 vec
<block
*> successors
= b
->get_successor_blocks ();
3790 FOR_EACH_VEC_ELT (successors
, i
, succ
)
3791 if (!succ
->m_is_reachable
)
3792 worklist
.safe_push (succ
);
3793 successors
.release ();
3796 /* Now complain about any blocks that haven't been marked. */
3800 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3801 if (!b
->m_is_reachable
)
3802 m_ctxt
->add_error (b
->get_loc (),
3803 "unreachable block: %s",
3804 b
->get_debug_string ());
3809 /* Implements the post-error-checking part of
3810 gcc_jit_function_dump_to_dot. */
3813 recording::function::dump_to_dot (const char *path
)
3815 FILE *fp
= fopen (path
, "w");
3819 pretty_printer the_pp
;
3820 the_pp
.buffer
->stream
= fp
;
3822 pretty_printer
*pp
= &the_pp
;
3825 "digraph %s {\n", get_debug_string ());
3831 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3832 b
->dump_to_dot (pp
);
3839 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3840 b
->dump_edges_to_dot (pp
);
3843 pp_printf (pp
, "}\n");
3848 /* Implements the post-error-checking part of
3849 gcc_jit_function_get_address. */
3852 recording::function::get_address (recording::location
*loc
)
3854 /* Lazily create and cache the function pointer type. */
3857 /* Make a recording::function_type for this function. */
3858 auto_vec
<recording::type
*> param_types (m_params
.length ());
3860 recording::param
*param
;
3861 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3862 param_types
.safe_push (param
->get_type ());
3863 recording::function_type
*fn_type
3864 = m_ctxt
->new_function_type (m_return_type
,
3866 param_types
.address (),
3868 m_fn_ptr_type
= fn_type
->get_pointer ();
3870 gcc_assert (m_fn_ptr_type
);
3872 rvalue
*result
= new function_pointer (get_context (), loc
, this, m_fn_ptr_type
);
3873 m_ctxt
->record (result
);
3877 /* Implementation of recording::memento::make_debug_string for
3881 recording::function::make_debug_string ()
3886 /* A table of enum gcc_jit_function_kind values expressed in string
3889 static const char * const names_of_function_kinds
[] = {
3890 "GCC_JIT_FUNCTION_EXPORTED",
3891 "GCC_JIT_FUNCTION_INTERNAL",
3892 "GCC_JIT_FUNCTION_IMPORTED",
3893 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3896 /* Implementation of recording::memento::write_reproducer for functions. */
3899 recording::function::write_reproducer (reproducer
&r
)
3901 const char *id
= r
.make_identifier (this, "func");
3905 r
.write (" gcc_jit_function *%s =\n"
3906 " gcc_jit_context_get_builtin_function (%s,\n"
3909 r
.get_identifier (get_context ()),
3910 m_name
->get_debug_string ());
3913 const char *params_id
= r
.make_tmp_identifier ("params_for", this);
3914 r
.write (" gcc_jit_param *%s[%i] = {\n",
3916 m_params
.length ());
3919 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3920 r
.write (" %s,\n", r
.get_identifier (param
));
3922 r
.write (" gcc_jit_function *%s =\n"
3923 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3924 " %s, /* gcc_jit_location *loc */\n"
3925 " %s, /* enum gcc_jit_function_kind kind */\n"
3926 " %s, /* gcc_jit_type *return_type */\n"
3927 " %s, /* const char *name */\n"
3928 " %i, /* int num_params */\n"
3929 " %s, /* gcc_jit_param **params */\n"
3930 " %i); /* int is_variadic */\n",
3932 r
.get_identifier (get_context ()),
3933 r
.get_identifier (m_loc
),
3934 names_of_function_kinds
[m_kind
],
3935 r
.get_identifier_as_type (m_return_type
),
3936 m_name
->get_debug_string (),
3943 /* The implementation of class gcc::jit::recording::block. */
3945 /* Create a recording::eval instance and add it to
3946 the block's context's list of mementos, and to the block's
3949 Implements the heart of gcc_jit_block_add_eval. */
3951 recording::statement
*
3952 recording::block::add_eval (recording::location
*loc
,
3953 recording::rvalue
*rvalue
)
3955 statement
*result
= new eval (this, loc
, rvalue
);
3956 m_ctxt
->record (result
);
3957 m_statements
.safe_push (result
);
3961 /* Create a recording::assignment instance and add it to
3962 the block's context's list of mementos, and to the block's
3965 Implements the heart of gcc_jit_block_add_assignment. */
3967 recording::statement
*
3968 recording::block::add_assignment (recording::location
*loc
,
3969 recording::lvalue
*lvalue
,
3970 recording::rvalue
*rvalue
)
3972 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
3973 m_ctxt
->record (result
);
3974 m_statements
.safe_push (result
);
3978 /* Create a recording::assignment_op instance and add it to
3979 the block's context's list of mementos, and to the block's
3982 Implements the heart of gcc_jit_block_add_assignment_op. */
3984 recording::statement
*
3985 recording::block::add_assignment_op (recording::location
*loc
,
3986 recording::lvalue
*lvalue
,
3987 enum gcc_jit_binary_op op
,
3988 recording::rvalue
*rvalue
)
3990 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
3991 m_ctxt
->record (result
);
3992 m_statements
.safe_push (result
);
3996 /* Create a recording::comment instance and add it to
3997 the block's context's list of mementos, and to the block's
4000 Implements the heart of gcc_jit_block_add_comment. */
4002 recording::statement
*
4003 recording::block::add_comment (recording::location
*loc
,
4006 statement
*result
= new comment (this, loc
, new_string (text
));
4007 m_ctxt
->record (result
);
4008 m_statements
.safe_push (result
);
4012 /* Create a recording::end_with_conditional instance and add it to
4013 the block's context's list of mementos, and to the block's
4016 Implements the heart of gcc_jit_block_end_with_conditional. */
4018 recording::statement
*
4019 recording::block::end_with_conditional (recording::location
*loc
,
4020 recording::rvalue
*boolval
,
4021 recording::block
*on_true
,
4022 recording::block
*on_false
)
4024 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
4025 m_ctxt
->record (result
);
4026 m_statements
.safe_push (result
);
4027 m_has_been_terminated
= true;
4031 /* Create a recording::end_with_jump instance and add it to
4032 the block's context's list of mementos, and to the block's
4035 Implements the heart of gcc_jit_block_end_with_jump. */
4037 recording::statement
*
4038 recording::block::end_with_jump (recording::location
*loc
,
4039 recording::block
*target
)
4041 statement
*result
= new jump (this, loc
, target
);
4042 m_ctxt
->record (result
);
4043 m_statements
.safe_push (result
);
4044 m_has_been_terminated
= true;
4048 /* Create a recording::end_with_return instance and add it to
4049 the block's context's list of mementos, and to the block's
4052 Implements the post-error-checking parts of
4053 gcc_jit_block_end_with_return and
4054 gcc_jit_block_end_with_void_return. */
4056 recording::statement
*
4057 recording::block::end_with_return (recording::location
*loc
,
4058 recording::rvalue
*rvalue
)
4060 /* This is used by both gcc_jit_function_add_return and
4061 gcc_jit_function_add_void_return; rvalue will be non-NULL for
4062 the former and NULL for the latter. */
4063 statement
*result
= new return_ (this, loc
, rvalue
);
4064 m_ctxt
->record (result
);
4065 m_statements
.safe_push (result
);
4066 m_has_been_terminated
= true;
4070 /* Create a recording::switch_ instance and add it to
4071 the block's context's list of mementos, and to the block's
4074 Implements the heart of gcc_jit_block_end_with_switch. */
4076 recording::statement
*
4077 recording::block::end_with_switch (recording::location
*loc
,
4078 recording::rvalue
*expr
,
4079 recording::block
*default_block
,
4081 recording::case_
**cases
)
4083 statement
*result
= new switch_ (this, loc
,
4088 m_ctxt
->record (result
);
4089 m_statements
.safe_push (result
);
4090 m_has_been_terminated
= true;
4094 /* Override the default implementation of
4095 recording::memento::write_to_dump for blocks by writing
4096 an unindented block name as a label, followed by the indented
4106 recording::block::write_to_dump (dump
&d
)
4108 d
.write ("%s:\n", get_debug_string ());
4112 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
4113 s
->write_to_dump (d
);
4116 /* Validate a block by ensuring that it has been terminated. */
4119 recording::block::validate ()
4121 /* Check for termination. */
4122 if (!has_been_terminated ())
4124 statement
*stmt
= get_last_statement ();
4125 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
4126 m_func
->get_context ()->add_error (loc
,
4127 "unterminated block in %s: %s",
4128 m_func
->get_debug_string (),
4129 get_debug_string ());
4136 /* Get the source-location of a block by using that of the first
4137 statement within it, if any. */
4139 recording::location
*
4140 recording::block::get_loc () const
4142 recording::statement
*stmt
= get_first_statement ();
4144 return stmt
->get_loc ();
4149 /* Get the first statement within a block, if any. */
4151 recording::statement
*
4152 recording::block::get_first_statement () const
4154 if (m_statements
.length ())
4155 return m_statements
[0];
4160 /* Get the last statement within a block, if any. */
4162 recording::statement
*
4163 recording::block::get_last_statement () const
4165 if (m_statements
.length ())
4166 return m_statements
[m_statements
.length () - 1];
4171 /* Assuming that this block has been terminated, get the successor blocks
4172 as a vector. Ownership of the vector transfers to the caller, which
4173 must call its release () method.
4175 Used when validating functions, and when dumping dot representations
4178 vec
<recording::block
*>
4179 recording::block::get_successor_blocks () const
4181 gcc_assert (m_has_been_terminated
);
4182 statement
*last_statement
= get_last_statement ();
4183 gcc_assert (last_statement
);
4184 return last_statement
->get_successor_blocks ();
4187 /* Implementation of pure virtual hook recording::memento::replay_into
4188 for recording::block. */
4191 recording::block::replay_into (replayer
*)
4193 set_playback_obj (m_func
->playback_function ()
4194 ->new_block (playback_string (m_name
)));
4197 /* Implementation of recording::memento::make_debug_string for
4201 recording::block::make_debug_string ()
4206 return string::from_printf (m_ctxt
,
4207 "<UNNAMED BLOCK %p>",
4211 /* Implementation of recording::memento::write_reproducer for blocks. */
4214 recording::block::write_reproducer (reproducer
&r
)
4216 const char *id
= r
.make_identifier (this, "block");
4217 r
.write (" gcc_jit_block *%s =\n"
4218 " gcc_jit_function_new_block (%s, %s);\n",
4220 r
.get_identifier (m_func
),
4221 m_name
? m_name
->get_debug_string () : "NULL");
4224 /* Dump a block in graphviz form into PP, capturing the block name (if
4225 any) and the statements. */
4228 recording::block::dump_to_dot (pretty_printer
*pp
)
4232 "[shape=record,style=filled,fillcolor=white,label=\"{"),
4234 pp_write_text_to_stream (pp
);
4237 pp_string (pp
, m_name
->c_str ());
4238 pp_string (pp
, ":");
4240 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
4245 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
4247 pp_string (pp
, s
->get_debug_string ());
4249 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
4257 /* Dump the out-edges of the block in graphviz form into PP. */
4260 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
4262 vec
<block
*> successors
= get_successor_blocks ();
4265 FOR_EACH_VEC_ELT (successors
, i
, succ
)
4267 "\tblock_%d:s -> block_%d:n;\n",
4268 m_index
, succ
->m_index
);
4269 successors
.release ();
4272 /* The implementation of class gcc::jit::recording::global. */
4274 /* Implementation of pure virtual hook recording::memento::replay_into
4275 for recording::global. */
4278 recording::global::replay_into (replayer
*r
)
4280 set_playback_obj (r
->new_global (playback_location (r
, m_loc
),
4282 m_type
->playback_type (),
4283 playback_string (m_name
)));
4286 /* Override the default implementation of
4287 recording::memento::write_to_dump for globals.
4288 This will be of the form:
4290 GCC_JIT_GLOBAL_EXPORTED:
4294 GCC_JIT_GLOBAL_INTERNAL:
4296 e.g. "static int foo;"
4298 GCC_JIT_GLOBAL_IMPORTED:
4300 e.g. "extern int foo;"
4302 These are written to the top of the dump by
4303 recording::context::dump_to_file. */
4306 recording::global::write_to_dump (dump
&d
)
4308 if (d
.update_locations ())
4309 m_loc
= d
.make_location ();
4316 case GCC_JIT_GLOBAL_EXPORTED
:
4319 case GCC_JIT_GLOBAL_INTERNAL
:
4320 d
.write ("static ");
4323 case GCC_JIT_GLOBAL_IMPORTED
:
4324 d
.write ("extern ");
4327 d
.write ("%s %s;\n",
4328 m_type
->get_debug_string (),
4329 get_debug_string ());
4332 /* A table of enum gcc_jit_global_kind values expressed in string
4335 static const char * const global_kind_reproducer_strings
[] = {
4336 "GCC_JIT_GLOBAL_EXPORTED",
4337 "GCC_JIT_GLOBAL_INTERNAL",
4338 "GCC_JIT_GLOBAL_IMPORTED"
4341 /* Implementation of recording::memento::write_reproducer for globals. */
4344 recording::global::write_reproducer (reproducer
&r
)
4346 const char *id
= r
.make_identifier (this, "block");
4347 r
.write (" gcc_jit_lvalue *%s =\n"
4348 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4349 " %s, /* gcc_jit_location *loc */\n"
4350 " %s, /* enum gcc_jit_global_kind kind */\n"
4351 " %s, /* gcc_jit_type *type */\n"
4352 " %s); /* const char *name */\n",
4354 r
.get_identifier (get_context ()),
4355 r
.get_identifier (m_loc
),
4356 global_kind_reproducer_strings
[m_kind
],
4357 r
.get_identifier_as_type (get_type ()),
4358 m_name
->get_debug_string ());
4361 /* The implementation of the various const-handling classes:
4362 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4364 /* Explicit specialization of the various mementos we're interested in. */
4365 template class recording::memento_of_new_rvalue_from_const
<int>;
4366 template class recording::memento_of_new_rvalue_from_const
<long>;
4367 template class recording::memento_of_new_rvalue_from_const
<double>;
4368 template class recording::memento_of_new_rvalue_from_const
<void *>;
4370 /* Implementation of the pure virtual hook recording::memento::replay_into
4371 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4373 template <typename HOST_TYPE
>
4376 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
4379 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
4383 /* The make_debug_string and write_reproducer methods vary between the
4385 memento_of_new_rvalue_from_const <HOST_TYPE>
4386 classes, so we explicitly write specializations of them.
4388 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4389 namespaces are written out explicitly, which is why most of this file
4390 doesn't abbreviate things by entering the "recording" namespace.
4392 However, these specializations are required to be in the same namespace
4393 as the template, hence we now have to enter the gcc::jit::recording
4399 /* The make_debug_string specialization for <int>, which renders it as
4400 (TARGET_TYPE)LITERAL
4406 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
4408 return string::from_printf (m_ctxt
,
4410 m_type
->get_debug_string (),
4414 /* The get_wide_int specialization for <int>. */
4418 memento_of_new_rvalue_from_const
<int>::get_wide_int (wide_int
*out
) const
4420 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
4424 /* The write_reproducer specialization for <int>. */
4428 memento_of_new_rvalue_from_const
<int>::write_reproducer (reproducer
&r
)
4430 const char *id
= r
.make_identifier (this, "rvalue");
4431 r
.write (" gcc_jit_rvalue *%s =\n"
4432 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4433 " %s, /* gcc_jit_type *numeric_type */\n"
4434 " %i); /* int value */\n",
4436 r
.get_identifier (get_context ()),
4437 r
.get_identifier_as_type (m_type
),
4441 /* The make_debug_string specialization for <long>, rendering it as
4442 (TARGET_TYPE)LITERAL
4448 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
4450 return string::from_printf (m_ctxt
,
4452 m_type
->get_debug_string (),
4456 /* The get_wide_int specialization for <long>. */
4460 memento_of_new_rvalue_from_const
<long>::get_wide_int (wide_int
*out
) const
4462 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
4466 /* The write_reproducer specialization for <long>. */
4470 recording::memento_of_new_rvalue_from_const
<long>::write_reproducer (reproducer
&r
)
4472 const char *id
= r
.make_identifier (this, "rvalue");
4474 /* We have to special-case LONG_MIN, since e.g.
4475 -9223372036854775808L
4477 -(9223372036854775808L)
4479 error: integer constant is so large that it is unsigned [-Werror]
4480 Workaround this by writing (LONG_MIN + 1) - 1. */
4481 if (m_value
== LONG_MIN
)
4483 r
.write (" gcc_jit_rvalue *%s =\n"
4484 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4485 " %s, /* gcc_jit_type *numeric_type */\n"
4486 " %ldL - 1); /* long value */\n",
4488 r
.get_identifier (get_context ()),
4489 r
.get_identifier_as_type (m_type
),
4494 r
.write (" gcc_jit_rvalue *%s =\n"
4495 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4496 " %s, /* gcc_jit_type *numeric_type */\n"
4497 " %ldL); /* long value */\n",
4499 r
.get_identifier (get_context ()),
4500 r
.get_identifier_as_type (m_type
),
4504 /* The make_debug_string specialization for <double>, rendering it as
4505 (TARGET_TYPE)LITERAL
4511 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
4513 return string::from_printf (m_ctxt
,
4515 m_type
->get_debug_string (),
4519 /* The get_wide_int specialization for <double>. */
4523 memento_of_new_rvalue_from_const
<double>::get_wide_int (wide_int
*) const
4528 /* The write_reproducer specialization for <double>. */
4532 recording::memento_of_new_rvalue_from_const
<double>::write_reproducer (reproducer
&r
)
4534 const char *id
= r
.make_identifier (this, "rvalue");
4535 r
.write (" gcc_jit_rvalue *%s =\n"
4536 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4537 " %s, /* gcc_jit_type *numeric_type */\n"
4538 " %f); /* double value */\n",
4540 r
.get_identifier (get_context ()),
4541 r
.get_identifier_as_type (m_type
),
4545 /* The make_debug_string specialization for <void *>, rendering it as
4550 Zero is rendered as NULL e.g.
4555 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
4557 if (m_value
!= NULL
)
4558 return string::from_printf (m_ctxt
,
4560 m_type
->get_debug_string (), m_value
);
4562 return string::from_printf (m_ctxt
,
4564 m_type
->get_debug_string ());
4567 /* The get_wide_int specialization for <void *>. */
4571 memento_of_new_rvalue_from_const
<void *>::get_wide_int (wide_int
*) const
4576 /* Implementation of recording::memento::write_reproducer for <void *>
4581 memento_of_new_rvalue_from_const
<void *>::write_reproducer (reproducer
&r
)
4583 const char *id
= r
.make_identifier (this, "rvalue");
4585 r
.write (" gcc_jit_rvalue *%s =\n"
4586 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4587 " %s, /* gcc_jit_type *pointer_type */\n"
4588 " (void *)%p); /* void *value */\n",
4590 r
.get_identifier (get_context ()),
4591 r
.get_identifier_as_type (m_type
),
4594 r
.write (" gcc_jit_rvalue *%s =\n"
4595 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4596 " %s); /* gcc_jit_type *pointer_type */\n",
4598 r
.get_identifier (get_context ()),
4599 r
.get_identifier_as_type (m_type
));
4602 /* We're done specializing make_debug_string and write_reproducer, so we
4603 can exit the gcc::jit::recording namespace. */
4605 } // namespace recording
4607 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4609 /* Implementation of pure virtual hook recording::memento::replay_into
4610 for recording::memento_of_new_string_literal. */
4613 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
4615 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
4618 /* Implementation of recording::memento::make_debug_string for
4622 recording::memento_of_new_string_literal::make_debug_string ()
4624 return string::from_printf (m_ctxt
,
4626 m_value
->get_debug_string ());
4629 /* Implementation of recording::memento::write_reproducer for string literal
4633 recording::memento_of_new_string_literal::write_reproducer (reproducer
&r
)
4635 const char *id
= r
.make_identifier (this, "rvalue");
4636 r
.write (" gcc_jit_rvalue *%s =\n"
4637 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4638 " %s); /* const char *value */\n",
4640 r
.get_identifier (get_context ()),
4641 m_value
->get_debug_string ());
4644 /* The implementation of class
4645 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
4647 /* The constructor for
4648 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
4650 recording::memento_of_new_rvalue_from_vector::
4651 memento_of_new_rvalue_from_vector (context
*ctxt
,
4655 : rvalue (ctxt
, loc
, type
),
4656 m_vector_type (type
),
4659 for (unsigned i
= 0; i
< type
->get_num_units (); i
++)
4660 m_elements
.safe_push (elements
[i
]);
4663 /* Implementation of pure virtual hook recording::memento::replay_into
4664 for recording::memento_of_new_rvalue_from_vector. */
4667 recording::memento_of_new_rvalue_from_vector::replay_into (replayer
*r
)
4669 auto_vec
<playback::rvalue
*> playback_elements
;
4670 playback_elements
.create (m_elements
.length ());
4671 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
4672 playback_elements
.safe_push (m_elements
[i
]->playback_rvalue ());
4674 set_playback_obj (r
->new_rvalue_from_vector (playback_location (r
, m_loc
),
4675 m_type
->playback_type (),
4676 playback_elements
));
4679 /* Implementation of pure virtual hook recording::rvalue::visit_children
4680 for recording::memento_of_new_rvalue_from_vector. */
4683 recording::memento_of_new_rvalue_from_vector::visit_children (rvalue_visitor
*v
)
4685 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
4686 v
->visit (m_elements
[i
]);
4689 /* Implementation of recording::memento::make_debug_string for
4693 recording::memento_of_new_rvalue_from_vector::make_debug_string ()
4695 comma_separated_string
elements (m_elements
, get_precedence ());
4697 /* Now build a string. */
4698 string
*result
= string::from_printf (m_ctxt
,
4700 elements
.as_char_ptr ());
4706 /* Implementation of recording::memento::write_reproducer for
4710 recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer
&r
)
4712 const char *id
= r
.make_identifier (this, "vector");
4713 const char *elements_id
= r
.make_tmp_identifier ("elements_for_", this);
4714 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4716 m_elements
.length ());
4717 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
4718 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_elements
[i
]));
4720 r
.write (" gcc_jit_rvalue *%s =\n"
4721 " gcc_jit_context_new_rvalue_from_vector (%s, /* gcc_jit_context *ctxt */\n"
4722 " %s, /* gcc_jit_location *loc */\n"
4723 " %s, /* gcc_jit_type *vec_type */\n"
4724 " %i, /* size_t num_elements */ \n"
4725 " %s); /* gcc_jit_rvalue **elements*/\n",
4727 r
.get_identifier (get_context ()),
4728 r
.get_identifier (m_loc
),
4729 r
.get_identifier (m_vector_type
),
4730 m_elements
.length (),
4734 /* The implementation of class gcc::jit::recording::unary_op. */
4736 /* Implementation of pure virtual hook recording::memento::replay_into
4737 for recording::unary_op. */
4740 recording::unary_op::replay_into (replayer
*r
)
4742 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
4744 get_type ()->playback_type (),
4745 m_a
->playback_rvalue ()));
4748 /* Implementation of pure virtual hook recording::rvalue::visit_children
4749 for recording::unary_op. */
4751 recording::unary_op::visit_children (rvalue_visitor
*v
)
4756 /* Implementation of recording::memento::make_debug_string for
4759 static const char * const unary_op_strings
[] = {
4760 "-", /* GCC_JIT_UNARY_OP_MINUS */
4761 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4762 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4763 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4767 recording::unary_op::make_debug_string ()
4769 return string::from_printf (m_ctxt
,
4771 unary_op_strings
[m_op
],
4772 m_a
->get_debug_string ());
4775 static const char * const unary_op_reproducer_strings
[] = {
4776 "GCC_JIT_UNARY_OP_MINUS",
4777 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4778 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4779 "GCC_JIT_UNARY_OP_ABS"
4782 /* Implementation of recording::memento::write_reproducer for unary ops. */
4785 recording::unary_op::write_reproducer (reproducer
&r
)
4787 const char *id
= r
.make_identifier (this, "rvalue");
4788 r
.write (" gcc_jit_rvalue *%s =\n"
4789 " gcc_jit_context_new_unary_op (%s,\n"
4790 " %s, /* gcc_jit_location *loc */\n"
4791 " %s, /* enum gcc_jit_unary_op op */\n"
4792 " %s, /* gcc_jit_type *result_type */\n"
4793 " %s); /* gcc_jit_rvalue *a */\n",
4795 r
.get_identifier (get_context ()),
4796 r
.get_identifier (m_loc
),
4797 unary_op_reproducer_strings
[m_op
],
4798 r
.get_identifier_as_type (get_type ()),
4799 r
.get_identifier_as_rvalue (m_a
));
4802 /* The implementation of class gcc::jit::recording::binary_op. */
4804 /* Implementation of pure virtual hook recording::memento::replay_into
4805 for recording::binary_op. */
4808 recording::binary_op::replay_into (replayer
*r
)
4810 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
4812 get_type ()->playback_type (),
4813 m_a
->playback_rvalue (),
4814 m_b
->playback_rvalue ()));
4817 /* Implementation of pure virtual hook recording::rvalue::visit_children
4818 for recording::binary_op. */
4820 recording::binary_op::visit_children (rvalue_visitor
*v
)
4826 /* Implementation of recording::memento::make_debug_string for
4829 static const char * const binary_op_strings
[] = {
4830 "+", /* GCC_JIT_BINARY_OP_PLUS */
4831 "-", /* GCC_JIT_BINARY_OP_MINUS */
4832 "*", /* GCC_JIT_BINARY_OP_MULT */
4833 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4834 "%", /* GCC_JIT_BINARY_OP_MODULO */
4835 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4836 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4837 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4838 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4839 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4840 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4841 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4845 recording::binary_op::make_debug_string ()
4847 enum precedence prec
= get_precedence ();
4848 return string::from_printf (m_ctxt
,
4850 m_a
->get_debug_string_parens (prec
),
4851 binary_op_strings
[m_op
],
4852 m_b
->get_debug_string_parens (prec
));
4855 static const char * const binary_op_reproducer_strings
[] = {
4856 "GCC_JIT_BINARY_OP_PLUS",
4857 "GCC_JIT_BINARY_OP_MINUS",
4858 "GCC_JIT_BINARY_OP_MULT",
4859 "GCC_JIT_BINARY_OP_DIVIDE",
4860 "GCC_JIT_BINARY_OP_MODULO",
4861 "GCC_JIT_BINARY_OP_BITWISE_AND",
4862 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4863 "GCC_JIT_BINARY_OP_BITWISE_OR",
4864 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4865 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4866 "GCC_JIT_BINARY_OP_LSHIFT",
4867 "GCC_JIT_BINARY_OP_RSHIFT"
4870 /* Implementation of recording::memento::write_reproducer for binary ops. */
4873 recording::binary_op::write_reproducer (reproducer
&r
)
4875 const char *id
= r
.make_identifier (this, "rvalue");
4876 r
.write (" gcc_jit_rvalue *%s =\n"
4877 " gcc_jit_context_new_binary_op (%s,\n"
4878 " %s, /* gcc_jit_location *loc */\n"
4879 " %s, /* enum gcc_jit_binary_op op */\n"
4880 " %s, /* gcc_jit_type *result_type */\n"
4881 " %s, /* gcc_jit_rvalue *a */\n"
4882 " %s); /* gcc_jit_rvalue *b */\n",
4884 r
.get_identifier (get_context ()),
4885 r
.get_identifier (m_loc
),
4886 binary_op_reproducer_strings
[m_op
],
4887 r
.get_identifier_as_type (get_type ()),
4888 r
.get_identifier_as_rvalue (m_a
),
4889 r
.get_identifier_as_rvalue (m_b
));
4892 namespace recording
{
4893 static const enum precedence binary_op_precedence
[] = {
4894 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_PLUS */
4895 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_MINUS */
4897 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MULT */
4898 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_DIVIDE */
4899 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MODULO */
4901 PRECEDENCE_BITWISE_AND
, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4902 PRECEDENCE_BITWISE_XOR
, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4903 PRECEDENCE_BITWISE_IOR
, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4904 PRECEDENCE_LOGICAL_AND
, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4905 PRECEDENCE_LOGICAL_OR
, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4906 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_LSHIFT */
4907 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_RSHIFT */
4909 } /* namespace recording */
4911 enum recording::precedence
4912 recording::binary_op::get_precedence () const
4914 return binary_op_precedence
[m_op
];
4917 /* The implementation of class gcc::jit::recording::comparison. */
4919 /* Implementation of recording::memento::make_debug_string for
4922 static const char * const comparison_strings
[] =
4924 "==", /* GCC_JIT_COMPARISON_EQ */
4925 "!=", /* GCC_JIT_COMPARISON_NE */
4926 "<", /* GCC_JIT_COMPARISON_LT */
4927 "<=", /* GCC_JIT_COMPARISON_LE */
4928 ">", /* GCC_JIT_COMPARISON_GT */
4929 ">=", /* GCC_JIT_COMPARISON_GE */
4933 recording::comparison::make_debug_string ()
4935 enum precedence prec
= get_precedence ();
4936 return string::from_printf (m_ctxt
,
4938 m_a
->get_debug_string_parens (prec
),
4939 comparison_strings
[m_op
],
4940 m_b
->get_debug_string_parens (prec
));
4943 /* A table of enum gcc_jit_comparison values expressed in string
4946 static const char * const comparison_reproducer_strings
[] =
4948 "GCC_JIT_COMPARISON_EQ",
4949 "GCC_JIT_COMPARISON_NE",
4950 "GCC_JIT_COMPARISON_LT",
4951 "GCC_JIT_COMPARISON_LE",
4952 "GCC_JIT_COMPARISON_GT",
4953 "GCC_JIT_COMPARISON_GE"
4956 /* Implementation of recording::memento::write_reproducer for comparisons. */
4959 recording::comparison::write_reproducer (reproducer
&r
)
4961 const char *id
= r
.make_identifier (this, "rvalue");
4962 r
.write (" gcc_jit_rvalue *%s =\n"
4963 " gcc_jit_context_new_comparison (%s,\n"
4964 " %s, /* gcc_jit_location *loc */\n"
4965 " %s, /* enum gcc_jit_comparison op */\n"
4966 " %s, /* gcc_jit_rvalue *a */\n"
4967 " %s); /* gcc_jit_rvalue *b */\n",
4969 r
.get_identifier (get_context ()),
4970 r
.get_identifier (m_loc
),
4971 comparison_reproducer_strings
[m_op
],
4972 r
.get_identifier_as_rvalue (m_a
),
4973 r
.get_identifier_as_rvalue (m_b
));
4976 /* Implementation of pure virtual hook recording::memento::replay_into
4977 for recording::comparison. */
4980 recording::comparison::replay_into (replayer
*r
)
4982 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
4984 m_a
->playback_rvalue (),
4985 m_b
->playback_rvalue ()));
4988 /* Implementation of pure virtual hook recording::rvalue::visit_children
4989 for recording::comparison. */
4992 recording::comparison::visit_children (rvalue_visitor
*v
)
4998 namespace recording
{
4999 static const enum precedence comparison_precedence
[] =
5001 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_EQ */
5002 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_NE */
5004 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LT */
5005 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LE */
5006 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GT */
5007 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GE */
5009 } /* namespace recording */
5011 enum recording::precedence
5012 recording::comparison::get_precedence () const
5014 return comparison_precedence
[m_op
];
5017 /* Implementation of pure virtual hook recording::memento::replay_into
5018 for recording::cast. */
5021 recording::cast::replay_into (replayer
*r
)
5023 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
5024 m_rvalue
->playback_rvalue (),
5025 get_type ()->playback_type ()));
5028 /* Implementation of pure virtual hook recording::rvalue::visit_children
5029 for recording::cast. */
5031 recording::cast::visit_children (rvalue_visitor
*v
)
5033 v
->visit (m_rvalue
);
5036 /* Implementation of recording::memento::make_debug_string for
5040 recording::cast::make_debug_string ()
5042 enum precedence prec
= get_precedence ();
5043 return string::from_printf (m_ctxt
,
5045 get_type ()->get_debug_string (),
5046 m_rvalue
->get_debug_string_parens (prec
));
5049 /* Implementation of recording::memento::write_reproducer for casts. */
5052 recording::cast::write_reproducer (reproducer
&r
)
5054 const char *id
= r
.make_identifier (this, "rvalue");
5055 r
.write (" gcc_jit_rvalue *%s =\n"
5056 " gcc_jit_context_new_cast (%s,\n"
5057 " %s, /* gcc_jit_location *loc */\n"
5058 " %s, /* gcc_jit_rvalue *rvalue */\n"
5059 " %s); /* gcc_jit_type *type */\n",
5061 r
.get_identifier (get_context ()),
5062 r
.get_identifier (m_loc
),
5063 r
.get_identifier_as_rvalue (m_rvalue
),
5064 r
.get_identifier_as_type (get_type ()));
5067 /* The implementation of class gcc::jit::recording::base_call. */
5069 /* The constructor for gcc::jit::recording::base_call. */
5071 recording::base_call::base_call (context
*ctxt
,
5076 : rvalue (ctxt
, loc
, type_
),
5078 m_require_tail_call (0)
5080 for (int i
= 0; i
< numargs
; i
++)
5081 m_args
.safe_push (args
[i
]);
5084 /* Subroutine for use by call and call_though_ptr's write_reproducer
5088 recording::base_call::write_reproducer_tail_call (reproducer
&r
,
5091 if (m_require_tail_call
)
5093 r
.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
5094 " %i); /* int require_tail_call*/\n",
5100 /* The implementation of class gcc::jit::recording::call. */
5102 /* The constructor for gcc::jit::recording::call. */
5104 recording::call::call (recording::context
*ctxt
,
5105 recording::location
*loc
,
5106 recording::function
*func
,
5109 : base_call (ctxt
, loc
, func
->get_return_type (), numargs
, args
),
5114 /* Implementation of pure virtual hook recording::memento::replay_into
5115 for recording::call. */
5118 recording::call::replay_into (replayer
*r
)
5120 auto_vec
<playback::rvalue
*> playback_args
;
5121 playback_args
.create (m_args
.length ());
5122 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5123 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
5125 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
5126 m_func
->playback_function (),
5128 m_require_tail_call
));
5131 /* Implementation of pure virtual hook recording::rvalue::visit_children
5132 for recording::call. */
5135 recording::call::visit_children (rvalue_visitor
*v
)
5137 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5138 v
->visit (m_args
[i
]);
5141 /* Implementation of recording::memento::make_debug_string for
5145 recording::call::make_debug_string ()
5147 /* First, build a buffer for the arguments. */
5148 comma_separated_string
args (m_args
, get_precedence ());
5150 /* ...and use it to get the string for the call as a whole. */
5151 string
*result
= string::from_printf (m_ctxt
,
5153 m_func
->get_debug_string (),
5154 args
.as_char_ptr ());
5160 recording::call::write_reproducer (reproducer
&r
)
5162 const char *id
= r
.make_identifier (this, "call");
5163 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
5164 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
5167 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5168 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
5170 r
.write (" gcc_jit_rvalue *%s =\n"
5171 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
5172 " %s, /* gcc_jit_location *loc */\n"
5173 " %s, /* gcc_jit_function *func */\n"
5174 " %i, /* int numargs */ \n"
5175 " %s); /* gcc_jit_rvalue **args*/\n",
5177 r
.get_identifier (get_context ()),
5178 r
.get_identifier (m_loc
),
5179 r
.get_identifier (m_func
),
5182 write_reproducer_tail_call (r
, id
);
5185 /* The implementation of class gcc::jit::recording::call_through_ptr. */
5187 /* The constructor for recording::call_through_ptr. */
5189 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
5190 recording::location
*loc
,
5191 recording::rvalue
*fn_ptr
,
5194 : base_call (ctxt
, loc
,
5195 fn_ptr
->get_type ()->dereference ()
5196 ->as_a_function_type ()->get_return_type (),
5202 /* Implementation of pure virtual hook recording::memento::replay_into
5203 for recording::call_through_ptr. */
5206 recording::call_through_ptr::replay_into (replayer
*r
)
5208 auto_vec
<playback::rvalue
*> playback_args
;
5209 playback_args
.create (m_args
.length ());
5210 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5211 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
5213 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
5214 m_fn_ptr
->playback_rvalue (),
5216 m_require_tail_call
));
5219 /* Implementation of pure virtual hook recording::rvalue::visit_children
5220 for recording::call_through_ptr. */
5223 recording::call_through_ptr::visit_children (rvalue_visitor
*v
)
5225 v
->visit (m_fn_ptr
);
5226 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5227 v
->visit (m_args
[i
]);
5230 /* Implementation of recording::memento::make_debug_string for
5231 calls through function ptrs. */
5234 recording::call_through_ptr::make_debug_string ()
5236 enum precedence prec
= get_precedence ();
5237 /* First, build a buffer for the arguments. */
5238 /* Calculate length of said buffer. */
5239 size_t sz
= 1; /* nil terminator */
5240 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5242 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
5243 sz
+= 2; /* ", " separator */
5246 /* Now allocate and populate the buffer. */
5247 char *argbuf
= new char[sz
];
5250 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5252 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
5253 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
5254 if (i
+ 1 < m_args
.length ())
5256 strcpy (argbuf
+ len
, ", ");
5262 /* ...and use it to get the string for the call as a whole. */
5263 string
*result
= string::from_printf (m_ctxt
,
5265 m_fn_ptr
->get_debug_string_parens (prec
),
5273 /* Implementation of recording::memento::write_reproducer for
5274 call_through_ptr. */
5277 recording::call_through_ptr::write_reproducer (reproducer
&r
)
5279 const char *id
= r
.make_identifier (this, "call");
5280 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
5281 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
5284 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5285 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
5287 r
.write (" gcc_jit_rvalue *%s =\n"
5288 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
5289 " %s, /* gcc_jit_location *loc */\n"
5290 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
5291 " %i, /* int numargs */ \n"
5292 " %s); /* gcc_jit_rvalue **args*/\n",
5294 r
.get_identifier (get_context ()),
5295 r
.get_identifier (m_loc
),
5296 r
.get_identifier_as_rvalue (m_fn_ptr
),
5299 write_reproducer_tail_call (r
, id
);
5302 /* The implementation of class gcc::jit::recording::array_access. */
5304 /* Implementation of pure virtual hook recording::memento::replay_into
5305 for recording::array_access. */
5308 recording::array_access::replay_into (replayer
*r
)
5311 r
->new_array_access (playback_location (r
, m_loc
),
5312 m_ptr
->playback_rvalue (),
5313 m_index
->playback_rvalue ()));
5316 /* Implementation of pure virtual hook recording::rvalue::visit_children
5317 for recording::array_access. */
5320 recording::array_access::visit_children (rvalue_visitor
*v
)
5326 /* Implementation of recording::memento::make_debug_string for
5330 recording::array_access::make_debug_string ()
5332 enum precedence prec
= get_precedence ();
5333 return string::from_printf (m_ctxt
,
5335 m_ptr
->get_debug_string_parens (prec
),
5336 m_index
->get_debug_string_parens (prec
));
5339 /* Implementation of recording::memento::write_reproducer for
5343 recording::array_access::write_reproducer (reproducer
&r
)
5345 const char *id
= r
.make_identifier (this, "lvalue");
5346 r
.write (" gcc_jit_lvalue *%s = \n"
5347 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
5348 " %s, /*gcc_jit_location *loc */\n"
5349 " %s, /* gcc_jit_rvalue *ptr */\n"
5350 " %s); /* gcc_jit_rvalue *index */\n",
5352 r
.get_identifier (get_context ()),
5353 r
.get_identifier (m_loc
),
5354 r
.get_identifier_as_rvalue (m_ptr
),
5355 r
.get_identifier_as_rvalue (m_index
));
5358 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
5360 /* Implementation of pure virtual hook recording::memento::replay_into
5361 for recording::access_field_of_lvalue. */
5364 recording::access_field_of_lvalue::replay_into (replayer
*r
)
5367 m_lvalue
->playback_lvalue ()
5368 ->access_field (playback_location (r
, m_loc
),
5369 m_field
->playback_field ()));
5373 /* Implementation of pure virtual hook recording::rvalue::visit_children
5374 for recording::access_field_of_lvalue. */
5377 recording::access_field_of_lvalue::visit_children (rvalue_visitor
*v
)
5379 v
->visit (m_lvalue
);
5382 /* Implementation of recording::memento::make_debug_string for
5383 accessing a field of an lvalue. */
5386 recording::access_field_of_lvalue::make_debug_string ()
5388 enum precedence prec
= get_precedence ();
5389 return string::from_printf (m_ctxt
,
5391 m_lvalue
->get_debug_string_parens (prec
),
5392 m_field
->get_debug_string ());
5395 /* Implementation of recording::memento::write_reproducer for
5396 access_field_of_lvalue. */
5399 recording::access_field_of_lvalue::write_reproducer (reproducer
&r
)
5401 const char *id
= r
.make_identifier (this, "lvalue");
5402 r
.write (" gcc_jit_lvalue *%s = \n"
5403 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5404 " %s, /*gcc_jit_location *loc */\n"
5407 r
.get_identifier_as_lvalue (m_lvalue
),
5408 r
.get_identifier (m_loc
),
5409 r
.get_identifier (m_field
));
5412 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
5414 /* Implementation of pure virtual hook recording::memento::replay_into
5415 for recording::access_field_rvalue. */
5418 recording::access_field_rvalue::replay_into (replayer
*r
)
5421 m_rvalue
->playback_rvalue ()
5422 ->access_field (playback_location (r
, m_loc
),
5423 m_field
->playback_field ()));
5426 /* Implementation of pure virtual hook recording::rvalue::visit_children
5427 for recording::access_field_rvalue. */
5430 recording::access_field_rvalue::visit_children (rvalue_visitor
*v
)
5432 v
->visit (m_rvalue
);
5435 /* Implementation of recording::memento::make_debug_string for
5436 accessing a field of an rvalue. */
5439 recording::access_field_rvalue::make_debug_string ()
5441 enum precedence prec
= get_precedence ();
5442 return string::from_printf (m_ctxt
,
5444 m_rvalue
->get_debug_string_parens (prec
),
5445 m_field
->get_debug_string ());
5448 /* Implementation of recording::memento::write_reproducer for
5449 access_field_rvalue. */
5452 recording::access_field_rvalue::write_reproducer (reproducer
&r
)
5454 const char *id
= r
.make_identifier (this, "rvalue");
5455 r
.write (" gcc_jit_rvalue *%s = \n"
5456 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5457 " %s, /*gcc_jit_location *loc */\n"
5460 r
.get_identifier_as_rvalue (m_rvalue
),
5461 r
.get_identifier (m_loc
),
5462 r
.get_identifier (m_field
));
5465 /* The implementation of class
5466 gcc::jit::recording::dereference_field_rvalue. */
5468 /* Implementation of pure virtual hook recording::memento::replay_into
5469 for recording::dereference_field_rvalue. */
5472 recording::dereference_field_rvalue::replay_into (replayer
*r
)
5475 m_rvalue
->playback_rvalue ()->
5476 dereference_field (playback_location (r
, m_loc
),
5477 m_field
->playback_field ()));
5480 /* Implementation of pure virtual hook recording::rvalue::visit_children
5481 for recording::dereference_field_rvalue. */
5484 recording::dereference_field_rvalue::visit_children (rvalue_visitor
*v
)
5486 v
->visit (m_rvalue
);
5489 /* Implementation of recording::memento::make_debug_string for
5490 dereferencing a field of an rvalue. */
5493 recording::dereference_field_rvalue::make_debug_string ()
5495 enum precedence prec
= get_precedence ();
5496 return string::from_printf (m_ctxt
,
5498 m_rvalue
->get_debug_string_parens (prec
),
5499 m_field
->get_debug_string ());
5502 /* Implementation of recording::memento::write_reproducer for
5503 dereference_field_rvalue. */
5506 recording::dereference_field_rvalue::write_reproducer (reproducer
&r
)
5508 const char *id
= r
.make_identifier (this, "lvalue");
5509 r
.write (" gcc_jit_lvalue *%s=\n"
5510 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5511 " %s, /* gcc_jit_location *loc */\n"
5512 " %s); /* gcc_jit_field *field */\n",
5514 r
.get_identifier_as_rvalue (m_rvalue
),
5515 r
.get_identifier (m_loc
),
5516 r
.get_identifier (m_field
));
5519 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5521 /* Implementation of pure virtual hook recording::memento::replay_into
5522 for recording::dereference_rvalue. */
5525 recording::dereference_rvalue::replay_into (replayer
*r
)
5528 m_rvalue
->playback_rvalue ()->
5529 dereference (playback_location (r
, m_loc
)));
5532 /* Implementation of pure virtual hook recording::rvalue::visit_children
5533 for recording::dereference_rvalue. */
5536 recording::dereference_rvalue::visit_children (rvalue_visitor
*v
)
5538 v
->visit (m_rvalue
);
5541 /* Implementation of recording::memento::make_debug_string for
5542 dereferencing an rvalue. */
5545 recording::dereference_rvalue::make_debug_string ()
5547 enum precedence prec
= get_precedence ();
5548 return string::from_printf (m_ctxt
,
5550 m_rvalue
->get_debug_string_parens (prec
));
5553 /* Implementation of recording::memento::write_reproducer for
5554 dereference_rvalue. */
5557 recording::dereference_rvalue::write_reproducer (reproducer
&r
)
5559 const char *id
= r
.make_identifier (this, "dereference");
5560 r
.write (" gcc_jit_lvalue *%s =\n"
5561 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5562 " %s); /* gcc_jit_location *loc */\n",
5564 r
.get_identifier_as_rvalue (m_rvalue
),
5565 r
.get_identifier (m_loc
));
5568 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5570 /* Implementation of pure virtual hook recording::memento::replay_into
5571 for recording::get_address_of_lvalue. */
5574 recording::get_address_of_lvalue::replay_into (replayer
*r
)
5577 m_lvalue
->playback_lvalue ()->
5578 get_address (playback_location (r
, m_loc
)));
5581 /* Implementation of pure virtual hook recording::rvalue::visit_children
5582 for recording::get_address_of_lvalue. */
5585 recording::get_address_of_lvalue::visit_children (rvalue_visitor
*v
)
5587 v
->visit (m_lvalue
);
5590 /* Implementation of recording::memento::make_debug_string for
5591 getting the address of an lvalue. */
5594 recording::get_address_of_lvalue::make_debug_string ()
5596 enum precedence prec
= get_precedence ();
5597 return string::from_printf (m_ctxt
,
5599 m_lvalue
->get_debug_string_parens (prec
));
5602 /* Implementation of recording::memento::write_reproducer for
5603 get_address_of_lvalue. */
5606 recording::get_address_of_lvalue::write_reproducer (reproducer
&r
)
5608 const char *id
= r
.make_identifier (this, "address_of");
5609 r
.write (" gcc_jit_rvalue *%s =\n"
5610 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5611 " %s); /* gcc_jit_location *loc */\n",
5613 r
.get_identifier_as_lvalue (m_lvalue
),
5614 r
.get_identifier (m_loc
));
5617 /* The implementation of class gcc::jit::recording::function_pointer. */
5619 /* Implementation of pure virtual hook recording::memento::replay_into
5620 for recording::function_pointer. */
5623 recording::function_pointer::replay_into (replayer
*r
)
5626 m_fn
->playback_function ()->
5627 get_address (playback_location (r
, m_loc
)));
5631 recording::function_pointer::visit_children (rvalue_visitor
*)
5636 /* Implementation of recording::memento::make_debug_string for
5637 getting the address of an lvalue. */
5640 recording::function_pointer::make_debug_string ()
5642 return string::from_printf (m_ctxt
,
5644 m_fn
->get_debug_string ());
5647 /* Implementation of recording::memento::write_reproducer for
5648 function_pointer. */
5651 recording::function_pointer::write_reproducer (reproducer
&r
)
5653 const char *id
= r
.make_identifier (this, "address_of");
5654 r
.write (" gcc_jit_rvalue *%s =\n"
5655 " gcc_jit_function_get_address (%s, /* gcc_jit_function *fn */\n"
5656 " %s); /* gcc_jit_location *loc */\n",
5658 r
.get_identifier (m_fn
),
5659 r
.get_identifier (m_loc
));
5662 /* The implementation of class gcc::jit::recording::local. */
5664 /* Implementation of pure virtual hook recording::memento::replay_into
5665 for recording::local. */
5668 recording::local::replay_into (replayer
*r
)
5671 m_func
->playback_function ()
5672 ->new_local (playback_location (r
, m_loc
),
5673 m_type
->playback_type (),
5674 playback_string (m_name
)));
5677 /* Override the default implementation of
5678 recording::memento::write_to_dump for locals by writing
5680 for use at the top of the function body as if it were a
5684 recording::local::write_to_dump (dump
&d
)
5686 if (d
.update_locations ())
5687 m_loc
= d
.make_location ();
5688 d
.write(" %s %s;\n",
5689 m_type
->get_debug_string (),
5690 get_debug_string ());
5694 recording::local::write_reproducer (reproducer
&r
)
5696 const char *id
= r
.make_identifier (this, "local");
5697 r
.write (" gcc_jit_lvalue *%s =\n"
5698 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5699 " %s, /* gcc_jit_location *loc */\n"
5700 " %s, /* gcc_jit_type *type */\n"
5701 " %s); /* const char *name */\n",
5703 r
.get_identifier (m_func
),
5704 r
.get_identifier (m_loc
),
5705 r
.get_identifier_as_type (m_type
),
5706 m_name
->get_debug_string ());
5709 /* The implementation of class gcc::jit::recording::statement. */
5711 /* We poison the default implementation of
5712 gcc::jit::recording::statement::get_successor_blocks
5713 since this vfunc must only ever be called on terminator
5716 vec
<recording::block
*>
5717 recording::statement::get_successor_blocks () const
5719 /* The base class implementation is for non-terminating statements,
5720 and thus should never be called. */
5722 vec
<block
*> result
;
5727 /* Extend the default implementation of
5728 recording::memento::write_to_dump for statements by (if requested)
5729 updating the location of the statement to the current location in
5733 recording::statement::write_to_dump (dump
&d
)
5735 memento::write_to_dump (d
);
5736 if (d
.update_locations ())
5737 m_loc
= d
.make_location ();
5740 /* The implementation of class gcc::jit::recording::eval. */
5742 /* Implementation of pure virtual hook recording::memento::replay_into
5743 for recording::eval. */
5746 recording::eval::replay_into (replayer
*r
)
5748 playback_block (get_block ())
5749 ->add_eval (playback_location (r
),
5750 m_rvalue
->playback_rvalue ());
5753 /* Implementation of recording::memento::make_debug_string for
5754 an eval statement. */
5757 recording::eval::make_debug_string ()
5759 return string::from_printf (m_ctxt
,
5761 m_rvalue
->get_debug_string ());
5764 /* Implementation of recording::memento::write_reproducer for
5768 recording::eval::write_reproducer (reproducer
&r
)
5770 r
.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5771 " %s, /* gcc_jit_location *loc */\n"
5772 " %s); /* gcc_jit_rvalue *rvalue */\n",
5773 r
.get_identifier (get_block ()),
5774 r
.get_identifier (get_loc ()),
5775 r
.get_identifier_as_rvalue (m_rvalue
));
5778 /* The implementation of class gcc::jit::recording::assignment. */
5780 /* Implementation of pure virtual hook recording::memento::replay_into
5781 for recording::assignment. */
5784 recording::assignment::replay_into (replayer
*r
)
5786 playback_block (get_block ())
5787 ->add_assignment (playback_location (r
),
5788 m_lvalue
->playback_lvalue (),
5789 m_rvalue
->playback_rvalue ());
5792 /* Implementation of recording::memento::make_debug_string for
5793 an assignment statement. */
5796 recording::assignment::make_debug_string ()
5798 return string::from_printf (m_ctxt
,
5800 m_lvalue
->get_debug_string (),
5801 m_rvalue
->get_debug_string ());
5804 /* Implementation of recording::memento::write_reproducer for
5805 assignment statements. */
5808 recording::assignment::write_reproducer (reproducer
&r
)
5810 r
.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5811 " %s, /* gcc_jit_location *loc */\n"
5812 " %s, /* gcc_jit_lvalue *lvalue */\n"
5813 " %s); /* gcc_jit_rvalue *rvalue */\n",
5814 r
.get_identifier (get_block ()),
5815 r
.get_identifier (get_loc ()),
5816 r
.get_identifier_as_lvalue (m_lvalue
),
5817 r
.get_identifier_as_rvalue (m_rvalue
));
5820 /* The implementation of class gcc::jit::recording::assignment_op. */
5822 /* Implementation of pure virtual hook recording::memento::replay_into
5823 for recording::assignment_op. */
5826 recording::assignment_op::replay_into (replayer
*r
)
5828 playback::type
*result_type
=
5829 m_lvalue
->playback_lvalue ()->get_type ();
5831 playback::rvalue
*binary_op
=
5832 r
->new_binary_op (playback_location (r
),
5835 m_lvalue
->playback_rvalue (),
5836 m_rvalue
->playback_rvalue ());
5838 playback_block (get_block ())
5839 ->add_assignment (playback_location (r
),
5840 m_lvalue
->playback_lvalue (),
5844 /* Implementation of recording::memento::make_debug_string for
5845 an assignment_op statement. */
5848 recording::assignment_op::make_debug_string ()
5850 return string::from_printf (m_ctxt
,
5852 m_lvalue
->get_debug_string (),
5853 binary_op_strings
[m_op
],
5854 m_rvalue
->get_debug_string ());
5857 /* Implementation of recording::memento::write_reproducer for
5858 assignment_op statements. */
5861 recording::assignment_op::write_reproducer (reproducer
&r
)
5863 r
.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5864 " %s, /* gcc_jit_location *loc */\n"
5865 " %s, /* gcc_jit_lvalue *lvalue */\n"
5866 " %s, /* enum gcc_jit_binary_op op */\n"
5867 " %s); /* gcc_jit_rvalue *rvalue */\n",
5868 r
.get_identifier (get_block ()),
5869 r
.get_identifier (get_loc ()),
5870 r
.get_identifier_as_lvalue (m_lvalue
),
5871 binary_op_reproducer_strings
[m_op
],
5872 r
.get_identifier_as_rvalue (m_rvalue
));
5875 /* The implementation of class gcc::jit::recording::comment. */
5877 /* Implementation of pure virtual hook recording::memento::replay_into
5878 for recording::comment. */
5881 recording::comment::replay_into (replayer
*r
)
5883 playback_block (get_block ())
5884 ->add_comment (playback_location (r
),
5888 /* Implementation of recording::memento::make_debug_string for
5889 a comment "statement". */
5892 recording::comment::make_debug_string ()
5894 return string::from_printf (m_ctxt
,
5899 /* Implementation of recording::memento::write_reproducer for
5903 recording::comment::write_reproducer (reproducer
&r
)
5905 r
.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5906 " %s, /* gcc_jit_location *loc */\n"
5907 " %s); /* const char *text */\n",
5908 r
.get_identifier (get_block ()),
5909 r
.get_identifier (get_loc ()),
5910 m_text
->get_debug_string ());
5913 /* The implementation of class gcc::jit::recording::conditional. */
5915 /* Implementation of pure virtual hook recording::memento::replay_into
5916 for recording::conditional. */
5919 recording::conditional::replay_into (replayer
*r
)
5921 playback_block (get_block ())
5922 ->add_conditional (playback_location (r
),
5923 m_boolval
->playback_rvalue (),
5924 playback_block (m_on_true
),
5925 playback_block (m_on_false
));
5928 /* Override the poisoned default implementation of
5929 gcc::jit::recording::statement::get_successor_blocks
5931 A conditional jump has 2 successor blocks. */
5933 vec
<recording::block
*>
5934 recording::conditional::get_successor_blocks () const
5936 vec
<block
*> result
;
5938 result
.quick_push (m_on_true
);
5939 result
.quick_push (m_on_false
);
5943 /* Implementation of recording::memento::make_debug_string for
5944 a conditional jump statement. */
5947 recording::conditional::make_debug_string ()
5950 return string::from_printf (m_ctxt
,
5951 "if (%s) goto %s; else goto %s;",
5952 m_boolval
->get_debug_string (),
5953 m_on_true
->get_debug_string (),
5954 m_on_false
->get_debug_string ());
5956 return string::from_printf (m_ctxt
,
5958 m_boolval
->get_debug_string (),
5959 m_on_true
->get_debug_string ());
5962 /* Implementation of recording::memento::write_reproducer for
5963 conditional statements. */
5966 recording::conditional::write_reproducer (reproducer
&r
)
5968 r
.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5969 " %s, /* gcc_jit_location *loc */\n"
5970 " %s, /* gcc_jit_rvalue *boolval */\n"
5971 " %s, /* gcc_jit_block *on_true */\n"
5972 " %s); /* gcc_jit_block *on_false */\n",
5973 r
.get_identifier (get_block ()),
5974 r
.get_identifier (get_loc ()),
5975 r
.get_identifier_as_rvalue (m_boolval
),
5976 r
.get_identifier (m_on_true
),
5977 r
.get_identifier (m_on_false
));
5980 /* The implementation of class gcc::jit::recording::jump. */
5982 /* Implementation of pure virtual hook recording::memento::replay_into
5983 for recording::jump. */
5986 recording::jump::replay_into (replayer
*r
)
5988 playback_block (get_block ())
5989 ->add_jump (playback_location (r
),
5990 m_target
->playback_block ());
5993 /* Override the poisoned default implementation of
5994 gcc::jit::recording::statement::get_successor_blocks
5996 An unconditional jump has 1 successor block. */
5998 vec
<recording::block
*>
5999 recording::jump::get_successor_blocks () const
6001 vec
<block
*> result
;
6003 result
.quick_push (m_target
);
6007 /* Implementation of recording::memento::make_debug_string for
6008 a unconditional jump statement. */
6011 recording::jump::make_debug_string ()
6013 return string::from_printf (m_ctxt
,
6015 m_target
->get_debug_string ());
6018 /* Implementation of recording::memento::write_reproducer for
6022 recording::jump::write_reproducer (reproducer
&r
)
6024 r
.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
6025 " %s, /* gcc_jit_location *loc */\n"
6026 " %s); /* gcc_jit_block *target */\n",
6027 r
.get_identifier (get_block ()),
6028 r
.get_identifier (get_loc ()),
6029 r
.get_identifier (m_target
));
6032 /* The implementation of class gcc::jit::recording::return_. */
6034 /* Implementation of pure virtual hook recording::memento::replay_into
6035 for recording::return_. */
6038 recording::return_::replay_into (replayer
*r
)
6040 playback_block (get_block ())
6041 ->add_return (playback_location (r
),
6042 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
6045 /* Override the poisoned default implementation of
6046 gcc::jit::recording::statement::get_successor_blocks
6048 A return statement has no successor block. */
6050 vec
<recording::block
*>
6051 recording::return_::get_successor_blocks () const
6053 vec
<block
*> result
;
6058 /* Implementation of recording::memento::make_debug_string for
6059 a return statement (covers both those with and without rvalues). */
6062 recording::return_::make_debug_string ()
6065 return string::from_printf (m_ctxt
,
6067 m_rvalue
->get_debug_string ());
6069 return string::from_printf (m_ctxt
,
6073 /* Implementation of recording::memento::write_reproducer for
6074 return statements. */
6077 recording::return_::write_reproducer (reproducer
&r
)
6080 r
.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
6081 " %s, /* gcc_jit_location *loc */\n"
6082 " %s); /* gcc_jit_rvalue *rvalue */\n",
6083 r
.get_identifier (get_block ()),
6084 r
.get_identifier (get_loc ()),
6085 r
.get_identifier_as_rvalue (m_rvalue
));
6087 r
.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
6088 " %s); /* gcc_jit_location *loc */\n",
6089 r
.get_identifier (get_block ()),
6090 r
.get_identifier (get_loc ()));
6093 /* The implementation of class gcc::jit::recording::case_. */
6096 recording::case_::write_reproducer (reproducer
&r
)
6098 const char *id
= r
.make_identifier (this, "case");
6100 " gcc_jit_case *%s = \n"
6101 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
6102 " %s, /* gcc_jit_rvalue *min_value */\n"
6103 " %s, /* gcc_jit_rvalue *max_value */\n"
6104 " %s); /* gcc_jit_block *dest_block */\n";
6107 r
.get_identifier (get_context ()),
6108 r
.get_identifier_as_rvalue (m_min_value
),
6109 r
.get_identifier_as_rvalue (m_max_value
),
6110 r
.get_identifier (m_dest_block
));
6114 recording::case_::make_debug_string ()
6116 return string::from_printf (get_context (),
6117 "case %s ... %s: goto %s;",
6118 m_min_value
->get_debug_string (),
6119 m_max_value
->get_debug_string (),
6120 m_dest_block
->get_debug_string ());
6123 /* The implementation of class gcc::jit::recording::switch_. */
6125 /* gcc::jit::recording::switch_'s constructor. */
6127 recording::switch_::switch_ (block
*b
,
6130 block
*default_block
,
6133 : statement (b
, loc
),
6135 m_default_block (default_block
)
6137 m_cases
.reserve_exact (num_cases
);
6138 for (int i
= 0; i
< num_cases
; i
++)
6139 m_cases
.quick_push (cases
[i
]);
6142 /* Implementation of pure virtual hook recording::memento::replay_into
6143 for recording::switch_. */
6146 recording::switch_::replay_into (replayer
*r
)
6148 auto_vec
<playback::case_
> pcases
;
6150 recording::case_
*rcase
;
6151 pcases
.reserve_exact (m_cases
.length ());
6152 FOR_EACH_VEC_ELT (m_cases
, i
, rcase
)
6154 playback::case_
pcase (rcase
->get_min_value ()->playback_rvalue (),
6155 rcase
->get_max_value ()->playback_rvalue (),
6156 rcase
->get_dest_block ()->playback_block ());
6157 pcases
.safe_push (pcase
);
6159 playback_block (get_block ())
6160 ->add_switch (playback_location (r
),
6161 m_expr
->playback_rvalue (),
6162 m_default_block
->playback_block (),
6166 /* Override the poisoned default implementation of
6167 gcc::jit::recording::statement::get_successor_blocks
6169 A switch statement has (NUM_CASES + 1) successor blocks. */
6171 vec
<recording::block
*>
6172 recording::switch_::get_successor_blocks () const
6174 vec
<block
*> result
;
6175 result
.create (m_cases
.length () + 1);
6176 result
.quick_push (m_default_block
);
6179 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
6180 result
.quick_push (c
->get_dest_block ());
6184 /* Implementation of recording::memento::make_debug_string for
6185 a switch statement. */
6188 recording::switch_::make_debug_string ()
6190 auto_vec
<char> cases_str
;
6193 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
6195 size_t len
= strlen (c
->get_debug_string ());
6196 unsigned idx
= cases_str
.length ();
6197 cases_str
.safe_grow (idx
+ 1 + len
);
6198 cases_str
[idx
] = ' ';
6199 memcpy (&(cases_str
[idx
+ 1]),
6200 c
->get_debug_string (),
6203 cases_str
.safe_push ('\0');
6205 return string::from_printf (m_ctxt
,
6206 "switch (%s) {default: goto %s;%s}",
6207 m_expr
->get_debug_string (),
6208 m_default_block
->get_debug_string (),
6212 /* Implementation of recording::memento::write_reproducer for
6213 switch statements. */
6216 recording::switch_::write_reproducer (reproducer
&r
)
6218 r
.make_identifier (this, "switch");
6221 const char *cases_id
=
6222 r
.make_tmp_identifier ("cases_for", this);
6223 r
.write (" gcc_jit_case *%s[%i] = {\n",
6226 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
6227 r
.write (" %s,\n", r
.get_identifier (c
));
6230 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
6231 " %s, /* gcc_jit_location *loc */\n"
6232 " %s, /* gcc_jit_rvalue *expr */\n"
6233 " %s, /* gcc_jit_block *default_block */\n"
6234 " %i, /* int num_cases */\n"
6235 " %s); /* gcc_jit_case **cases */\n";
6237 r
.get_identifier (get_block ()),
6238 r
.get_identifier (get_loc ()),
6239 r
.get_identifier_as_rvalue (m_expr
),
6240 r
.get_identifier (m_default_block
),
6245 } // namespace gcc::jit