1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2015 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
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"
31 #include "jit-common.h"
32 #include "jit-builtins.h"
33 #include "jit-logging.h"
34 #include "jit-recording.h"
35 #include "jit-playback.h"
42 dump::dump (recording::context
&ctxt
,
44 bool update_locations
)
46 m_filename (filename
),
47 m_update_locations (update_locations
),
51 m_file
= fopen (filename
, "w");
54 "error opening dump file %s for writing: %s",
63 int err
= fclose (m_file
);
65 m_ctxt
.add_error (NULL
,
66 "error closing dump file %s: %s",
72 /* Write the given message to the dump, using printf-formatting
73 conventions, updating the line/column within the dump.
75 Emit an error on the context if a failure occurs. */
78 dump::write (const char *fmt
, ...)
83 /* If there was an error opening the file, we've already reported it.
84 Don't attempt further work. */
89 vasprintf (&buf
, fmt
, ap
);
94 m_ctxt
.add_error (NULL
, "malloc failure writing to dumpfile %s",
99 if (fwrite (buf
, strlen (buf
), 1, m_file
) != 1)
100 m_ctxt
.add_error (NULL
, "error writing to dump file %s",
103 /* Flush after each line, to ease debugging crashes. */
106 /* Update line/column: */
107 for (const char *ptr
= buf
; *ptr
; ptr
++)
121 /* Construct a gcc::jit::recording::location instance for the current
122 location within the dump. */
124 recording::location
*
125 dump::make_location () const
127 return m_ctxt
.new_location (m_filename
, m_line
, m_column
,
128 /* We need to flag such locations as *not*
129 created by the user, so that
130 reproducer::get_identifier can cope with
131 them appearing *after* the memento that
136 /* A collection of allocations, all of which can be released together, to
137 avoid needing to track and release them individually. */
145 xstrdup_printf (const char *, ...)
146 ATTRIBUTE_RETURNS_NONNULL
150 xstrdup_printf_va (const char *, va_list ap
)
151 ATTRIBUTE_RETURNS_NONNULL
155 auto_vec
<void *> m_buffers
;
158 /* allocator's destructor. Call "free" on all of the allocations. */
160 allocator::~allocator ()
164 FOR_EACH_VEC_ELT (m_buffers
, i
, buffer
)
168 /* Formatted printing, allocating to a buffer (or exiting the process if
169 the allocation fails).
171 The buffer exists until the allocator is cleaned up, and is freed at
172 that point, so the caller doesn't need to track the result. */
175 allocator::xstrdup_printf (const char *fmt
, ...)
180 result
= xstrdup_printf_va (fmt
, ap
);
185 /* Formatted printing, allocating to a buffer (or exiting the process if
186 the allocation fails).
188 The buffer exists until the allocator is cleaned up, and is freed at
189 that point, so the caller doesn't need to track the result. */
192 allocator::xstrdup_printf_va (const char *fmt
, va_list ap
)
194 char *result
= xvasprintf (fmt
, ap
);
195 m_buffers
.safe_push (result
);
199 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
200 implementing gcc_jit_context_dump_reproducer_to_file. */
202 class reproducer
: public dump
205 reproducer (recording::context
&ctxt
,
206 const char *filename
);
209 write_params (const vec
<recording::context
*> &contexts
);
212 write_args (const vec
<recording::context
*> &contexts
);
215 make_identifier (recording::memento
*m
, const char *prefix
);
218 make_tmp_identifier (const char *prefix
, recording::memento
*m
);
221 get_identifier (recording::context
*ctxt
);
224 get_identifier (recording::memento
*m
);
227 get_identifier_as_rvalue (recording::rvalue
*m
);
230 get_identifier_as_lvalue (recording::lvalue
*m
);
233 get_identifier_as_type (recording::type
*m
);
236 xstrdup_printf (const char *, ...)
237 ATTRIBUTE_RETURNS_NONNULL
241 hash_map
<recording::memento
*, const char *> m_identifiers
;
242 allocator m_allocator
;
245 /* gcc::jit::reproducer's constructor. */
247 reproducer::reproducer (recording::context
&ctxt
,
248 const char *filename
) :
249 dump (ctxt
, filename
, 0),
255 /* Write out a list of contexts as a set of parameters within a
256 C function declaration. */
259 reproducer::write_params (const vec
<recording::context
*> &contexts
)
262 recording::context
*ctxt
;
263 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
265 write ("gcc_jit_context *%s",
266 get_identifier (ctxt
));
267 if (i
< contexts
.length () - 1)
273 /* Write out a list of contexts as a set of arguments within a call
277 reproducer::write_args (const vec
<recording::context
*> &contexts
)
280 recording::context
*ctxt
;
281 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
284 get_identifier (ctxt
));
285 if (i
< contexts
.length () - 1)
291 /* Generate a C identifier for the given memento, associating the generated
292 buffer with the memento (for future calls to get_identifier et al).
294 The reproducer will eventually clean up the buffer in its dtor. */
296 reproducer::make_identifier (recording::memento
*m
, const char *prefix
)
299 if (strlen (m
->get_debug_string ()) < 100)
301 result
= m_allocator
.xstrdup_printf ("%s_%s_%p",
303 m
->get_debug_string (),
305 for (char *p
= result
; *p
; p
++)
310 result
= m_allocator
.xstrdup_printf ("%s_%p",
312 m_identifiers
.put (m
, result
);
316 /* Generate a C identifier for a temporary variable.
317 The reproducer will eventually clean up the buffer in its dtor. */
320 reproducer::make_tmp_identifier (const char *prefix
, recording::memento
*m
)
322 return m_allocator
.xstrdup_printf ("%s_%s",
323 prefix
, get_identifier (m
));
326 /* Generate a C identifier for the given context.
327 The reproducer will eventually clean up the buffer in its dtor. */
330 reproducer::get_identifier (recording::context
*ctxt
)
332 return m_allocator
.xstrdup_printf ("ctxt_%p",
336 /* Locate the C identifier for the given memento, which is assumed to
337 have already been created via make_identifier. */
340 reproducer::get_identifier (recording::memento
*m
)
345 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
346 and hence these locations appear in the context's memento list
347 out-of-order: they appear in the context's memento list *after*
348 the memento that refers to them. For this case, it's simplest to
349 pretend that they're NULL when writing out the code to recreate the
350 memento that uses them. */
351 if (recording::location
*loc
= m
->dyn_cast_location ())
352 if (!loc
->created_by_user ())
355 const char **slot
= m_identifiers
.get (m
);
358 get_context ().add_error (NULL
,
359 "unable to find identifier for %p: %s",
361 m
->get_debug_string ());
367 /* Locate the C identifier for the given rvalue, wrapping it within
368 a gcc_*_as_rvalue upcast if necessary. */
371 reproducer::get_identifier_as_rvalue (recording::rvalue
*m
)
373 return m
->access_as_rvalue (*this);
376 /* Locate the C identifier for the given lvalue, wrapping it within
377 a gcc_*_as_lvalue upcast if necessary. */
380 reproducer::get_identifier_as_lvalue (recording::lvalue
*m
)
382 return m
->access_as_lvalue (*this);
385 /* Locate the C identifier for the given type, wrapping it within
386 a gcc_*_as_type upcast if necessary. */
389 reproducer::get_identifier_as_type (recording::type
*m
)
391 return m
->access_as_type (*this);
394 /* Formatted printing, allocating to a buffer (or exiting the process if
395 the allocation fails).
397 The buffer exists until the allocator is cleaned up, and is freed at
398 that point, so the caller doesn't need to track the result.
400 Note that we can't use ggc_printf since we're not within the compiler
401 proper (when within gcc_jit_context_dump_reproducer_to_file). */
404 reproducer::xstrdup_printf (const char *fmt
, ...)
409 result
= m_allocator
.xstrdup_printf_va (fmt
, ap
);
414 /**********************************************************************
416 **********************************************************************/
418 /* Get the playback::location for the given recording::location,
419 handling a NULL input with a NULL output. */
422 recording::playback_location (replayer
*r
, recording::location
*loc
)
425 return loc
->playback_location (r
);
430 /* Get a const char * for the given recording::string
431 handling a NULL input with a NULL output. */
434 recording::playback_string (recording::string
*str
)
437 return str
->c_str ();
442 /* Get the playback::block for the given recording::block,
443 handling a NULL input with a NULL output. */
446 recording::playback_block (recording::block
*b
)
449 return b
->playback_block ();
454 /* Methods of cc::jit::recording::context. */
456 /* The constructor for gcc::jit::recording::context, used by
457 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
459 recording::context::context (context
*parent_ctxt
)
461 m_parent_ctxt (parent_ctxt
),
462 m_toplevel_ctxt (m_parent_ctxt
? m_parent_ctxt
->m_toplevel_ctxt
: this),
464 m_first_error_str (NULL
),
465 m_owns_first_error_str (false),
466 m_last_error_str (NULL
),
467 m_owns_last_error_str (false),
473 m_builtins_manager(NULL
)
477 /* Inherit options from parent. */
479 i
< sizeof (m_str_options
) / sizeof (m_str_options
[0]);
482 const char *parent_opt
= parent_ctxt
->m_str_options
[i
];
483 m_str_options
[i
] = parent_opt
? xstrdup (parent_opt
) : NULL
;
485 memcpy (m_int_options
,
486 parent_ctxt
->m_int_options
,
487 sizeof (m_int_options
));
488 memcpy (m_bool_options
,
489 parent_ctxt
->m_bool_options
,
490 sizeof (m_bool_options
));
491 set_logger (parent_ctxt
->get_logger ());
495 memset (m_str_options
, 0, sizeof (m_str_options
));
496 memset (m_int_options
, 0, sizeof (m_int_options
));
497 memset (m_bool_options
, 0, sizeof (m_bool_options
));
500 memset (m_basic_types
, 0, sizeof (m_basic_types
));
503 /* The destructor for gcc::jit::recording::context, implicitly used by
504 gcc_jit_context_release. */
506 recording::context::~context ()
508 JIT_LOG_SCOPE (get_logger ());
511 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
516 for (i
= 0; i
< GCC_JIT_NUM_STR_OPTIONS
; ++i
)
517 free (m_str_options
[i
]);
519 if (m_builtins_manager
)
520 delete m_builtins_manager
;
522 if (m_owns_first_error_str
)
523 free (m_first_error_str
);
525 if (m_owns_last_error_str
)
526 if (m_last_error_str
!= m_first_error_str
)
527 free (m_last_error_str
);
530 /* Add the given mememto to the list of those tracked by this
531 gcc::jit::recording::context, so that e.g. it can be deleted
532 when this context is released. */
535 recording::context::record (memento
*m
)
539 m_mementos
.safe_push (m
);
542 /* Replay this context (and any parents) into the given replayer. */
545 recording::context::replay_into (replayer
*r
)
547 JIT_LOG_SCOPE (get_logger ());
551 /* If we have a parent context, we must replay it. This will
552 recursively walk backwards up the historical tree, then replay things
553 forwards "in historical order", starting with the ultimate parent
554 context, until we reach the "this" context.
556 Note that we fully replay the parent, then fully replay the child,
557 which means that inter-context references can only exist from child
558 to parent, not the other way around.
560 All of this replaying is suboptimal - it would be better to do the
561 work for the parent context *once*, rather than replaying the parent
562 every time we replay each child. However, fixing this requires deep
563 surgery to lifetime-management: we'd need every context family tree
564 to have its own GC heap, and to initialize the GCC code to use that
565 heap (with a mutex on such a heap). */
567 m_parent_ctxt
->replay_into (r
);
569 if (r
->errors_occurred ())
572 /* Replay this context's saved operations into r. */
573 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
575 /* Disabled low-level debugging, here if we need it: print what
577 Note that the calls to get_debug_string might lead to more
578 mementos being created for the strings.
579 This can also be used to exercise the debug_string
582 printf ("context %p replaying (%p): %s\n",
583 (void *)this, (void *)m
, m
->get_debug_string ());
587 if (r
->errors_occurred ())
592 /* During a playback, we associate objects from the recording with
593 their counterparts during this playback.
595 For simplicity, we store this within the recording objects.
597 The following method cleans away these associations, to ensure that
598 we never have out-of-date associations lingering on subsequent
599 playbacks (the objects pointed to are GC-managed, but the
600 recording objects don't own refs to them). */
603 recording::context::disassociate_from_playback ()
605 JIT_LOG_SCOPE (get_logger ());
610 m_parent_ctxt
->disassociate_from_playback ();
612 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
614 m
->set_playback_obj (NULL
);
618 /* Create a recording::string instance and add it to this context's list
621 This creates a fresh copy of the given 0-terminated buffer. */
624 recording::context::new_string (const char *text
)
629 recording::string
*result
= new string (this, text
);
634 /* Create a recording::location instance and add it to this context's
637 Implements the post-error-checking part of
638 gcc_jit_context_new_location. */
640 recording::location
*
641 recording::context::new_location (const char *filename
,
644 bool created_by_user
)
646 recording::location
*result
=
647 new recording::location (this,
648 new_string (filename
),
655 /* If we haven't seen this enum value yet, create a recording::type
656 instance and add it to this context's list of mementos.
658 If we have seen it before, reuse our cached value, so that repeated
659 calls on the context give the same object.
661 If we have a parent context, the cache is within the ultimate
664 Implements the post-error-checking part of
665 gcc_jit_context_get_type. */
668 recording::context::get_type (enum gcc_jit_types kind
)
670 if (!m_basic_types
[kind
])
673 m_basic_types
[kind
] = m_parent_ctxt
->get_type (kind
);
676 recording::type
*result
= new memento_of_get_type (this, kind
);
678 m_basic_types
[kind
] = result
;
682 return m_basic_types
[kind
];
685 /* Get a recording::type instance for the given size and signedness.
686 This is implemented in terms of recording::context::get_type
689 Implements the post-error-checking part of
690 gcc_jit_context_get_int_type. */
693 recording::context::get_int_type (int num_bytes
, int is_signed
)
695 /* We can't use a switch here since some of the values are macros affected
696 by options; e.g. i386.h has
697 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
698 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
699 are in bits, rather than bytes.
701 const int num_bits
= num_bytes
* 8;
702 if (num_bits
== INT_TYPE_SIZE
)
703 return get_type (is_signed
705 : GCC_JIT_TYPE_UNSIGNED_INT
);
706 if (num_bits
== CHAR_TYPE_SIZE
)
707 return get_type (is_signed
708 ? GCC_JIT_TYPE_SIGNED_CHAR
709 : GCC_JIT_TYPE_UNSIGNED_CHAR
);
710 if (num_bits
== SHORT_TYPE_SIZE
)
711 return get_type (is_signed
713 : GCC_JIT_TYPE_UNSIGNED_SHORT
);
714 if (num_bits
== LONG_TYPE_SIZE
)
715 return get_type (is_signed
717 : GCC_JIT_TYPE_UNSIGNED_LONG
);
718 if (num_bits
== LONG_LONG_TYPE_SIZE
)
719 return get_type (is_signed
720 ? GCC_JIT_TYPE_LONG_LONG
721 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
723 /* Some other size, not corresponding to the C int types. */
724 /* To be written: support arbitrary other sizes, sharing by
725 memoizing at the recording::context level? */
729 /* Create a recording::type instance and add it to this context's list
732 Implements the post-error-checking part of
733 gcc_jit_context_new_array_type. */
736 recording::context::new_array_type (recording::location
*loc
,
737 recording::type
*element_type
,
740 if (struct_
*s
= element_type
->dyn_cast_struct ())
741 if (!s
->get_fields ())
744 "cannot create an array of type %s"
745 " until the fields have been set",
746 s
->get_name ()->c_str ());
749 recording::type
*result
=
750 new recording::array_type (this, loc
, element_type
, num_elements
);
755 /* Create a recording::field instance and add it to this context's list
758 Implements the post-error-checking part of
759 gcc_jit_context_new_field. */
762 recording::context::new_field (recording::location
*loc
,
763 recording::type
*type
,
766 recording::field
*result
=
767 new recording::field (this, loc
, type
, new_string (name
));
772 /* Create a recording::struct_ instance and add it to this context's
773 list of mementos and list of compound types.
775 Implements the post-error-checking part of
776 gcc_jit_context_new_struct_type. */
779 recording::context::new_struct_type (recording::location
*loc
,
782 recording::struct_
*result
= new struct_ (this, loc
, new_string (name
));
784 m_compound_types
.safe_push (result
);
788 /* Create a recording::union_ instance and add it to this context's
789 list of mementos and list of compound types.
791 Implements the first post-error-checking part of
792 gcc_jit_context_new_union_type. */
795 recording::context::new_union_type (recording::location
*loc
,
798 recording::union_
*result
= new union_ (this, loc
, new_string (name
));
800 m_compound_types
.safe_push (result
);
804 /* Create a recording::function_type instance and add it to this context's
807 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
809 recording::function_type
*
810 recording::context::new_function_type (recording::type
*return_type
,
812 recording::type
**param_types
,
815 recording::function_type
*fn_type
816 = new function_type (this,
825 /* Create a recording::type instance and add it to this context's list
828 Implements the post-error-checking part of
829 gcc_jit_context_new_function_ptr_type. */
832 recording::context::new_function_ptr_type (recording::location
*, /* unused loc */
833 recording::type
*return_type
,
835 recording::type
**param_types
,
838 recording::function_type
*fn_type
839 = new_function_type (return_type
,
844 /* Return a pointer-type to the the function type. */
845 return fn_type
->get_pointer ();
848 /* Create a recording::param instance and add it to this context's list
851 Implements the post-error-checking part of
852 gcc_jit_context_new_param. */
855 recording::context::new_param (recording::location
*loc
,
856 recording::type
*type
,
859 recording::param
*result
= new recording::param (this, loc
, type
, new_string (name
));
864 /* Create a recording::function instance and add it to this context's list
865 of mementos and list of functions.
867 Implements the post-error-checking part of
868 gcc_jit_context_new_function. */
870 recording::function
*
871 recording::context::new_function (recording::location
*loc
,
872 enum gcc_jit_function_kind kind
,
873 recording::type
*return_type
,
876 recording::param
**params
,
878 enum built_in_function builtin_id
)
880 recording::function
*result
=
881 new recording::function (this,
882 loc
, kind
, return_type
,
884 num_params
, params
, is_variadic
,
887 m_functions
.safe_push (result
);
892 /* Locate the builtins_manager (if any) for this family of contexts,
893 creating it if it doesn't exist already.
895 All of the recording contexts in a family share one builtins_manager:
896 if we have a child context, follow the parent links to get the
897 ultimate ancestor context, and look for it/store it there. */
900 recording::context::get_builtins_manager ()
903 return m_parent_ctxt
->get_builtins_manager ();
905 if (!m_builtins_manager
)
906 m_builtins_manager
= new builtins_manager (this);
908 return m_builtins_manager
;
911 /* Get a recording::function instance, which is lazily-created and added
912 to the context's lists of mementos.
914 Implements the post-error-checking part of
915 gcc_jit_context_get_builtin_function. */
917 recording::function
*
918 recording::context::get_builtin_function (const char *name
)
920 builtins_manager
*bm
= get_builtins_manager ();
921 return bm
->get_builtin_function (name
);
924 /* Create a recording::global instance and add it to this context's list
927 Implements the post-error-checking part of
928 gcc_jit_context_new_global. */
931 recording::context::new_global (recording::location
*loc
,
932 enum gcc_jit_global_kind kind
,
933 recording::type
*type
,
936 recording::global
*result
=
937 new recording::global (this, loc
, kind
, type
, new_string (name
));
939 m_globals
.safe_push (result
);
944 /* Create a recording::memento_of_new_string_literal instance and add it
945 to this context's list of mementos.
947 Implements the post-error-checking part of
948 gcc_jit_context_new_string_literal. */
951 recording::context::new_string_literal (const char *value
)
953 recording::rvalue
*result
=
954 new memento_of_new_string_literal (this, NULL
, new_string (value
));
959 /* Create a recording::unary_op instance and add it to this context's
962 Implements the post-error-checking part of
963 gcc_jit_context_new_unary_op. */
966 recording::context::new_unary_op (recording::location
*loc
,
967 enum gcc_jit_unary_op op
,
968 recording::type
*result_type
,
969 recording::rvalue
*a
)
971 recording::rvalue
*result
=
972 new unary_op (this, loc
, op
, result_type
, a
);
977 /* Create a recording::binary_op instance and add it to this context's
980 Implements the post-error-checking part of
981 gcc_jit_context_new_binary_op. */
984 recording::context::new_binary_op (recording::location
*loc
,
985 enum gcc_jit_binary_op op
,
986 recording::type
*result_type
,
987 recording::rvalue
*a
,
988 recording::rvalue
*b
)
990 recording::rvalue
*result
=
991 new binary_op (this, loc
, op
, result_type
, a
, b
);
996 /* Create a recording::comparison instance and add it to this context's
999 Implements the post-error-checking part of
1000 gcc_jit_context_new_comparison. */
1003 recording::context::new_comparison (recording::location
*loc
,
1004 enum gcc_jit_comparison op
,
1005 recording::rvalue
*a
,
1006 recording::rvalue
*b
)
1008 recording::rvalue
*result
= new comparison (this, loc
, op
, a
, b
);
1013 /* Create a recording::cast instance and add it to this context's list
1016 Implements the post-error-checking part of
1017 gcc_jit_context_new_cast. */
1020 recording::context::new_cast (recording::location
*loc
,
1021 recording::rvalue
*expr
,
1022 recording::type
*type_
)
1024 recording::rvalue
*result
= new cast (this, loc
, expr
, type_
);
1029 /* Create a recording::call instance and add it to this context's list
1032 Implements the post-error-checking part of
1033 gcc_jit_context_new_call. */
1036 recording::context::new_call (recording::location
*loc
,
1038 int numargs
, recording::rvalue
**args
)
1040 recording::rvalue
*result
= new call (this, loc
, func
, numargs
, args
);
1045 /* Create a recording::call_through_ptr instance and add it to this
1046 context's list of mementos.
1048 Implements the post-error-checking part of
1049 gcc_jit_context_new_call_through_ptr. */
1052 recording::context::new_call_through_ptr (recording::location
*loc
,
1053 recording::rvalue
*fn_ptr
,
1055 recording::rvalue
**args
)
1057 recording::rvalue
*result
= new call_through_ptr (this, loc
, fn_ptr
, numargs
, args
);
1062 /* Create a recording::array_access instance and add it to this context's list
1065 Implements the post-error-checking part of
1066 gcc_jit_context_new_array_access. */
1069 recording::context::new_array_access (recording::location
*loc
,
1070 recording::rvalue
*ptr
,
1071 recording::rvalue
*index
)
1073 recording::lvalue
*result
= new array_access (this, loc
, ptr
, index
);
1078 /* Set the given string option for this context, or add an error if
1079 it's not recognized.
1081 Implements the post-error-checking part of
1082 gcc_jit_context_set_str_option. */
1085 recording::context::set_str_option (enum gcc_jit_str_option opt
,
1088 if (opt
< 0 || opt
>= GCC_JIT_NUM_STR_OPTIONS
)
1091 "unrecognized (enum gcc_jit_str_option) value: %i", opt
);
1094 free (m_str_options
[opt
]);
1095 m_str_options
[opt
] = value
? xstrdup (value
) : NULL
;
1098 /* Set the given integer option for this context, or add an error if
1099 it's not recognized.
1101 Implements the post-error-checking part of
1102 gcc_jit_context_set_int_option. */
1105 recording::context::set_int_option (enum gcc_jit_int_option opt
,
1108 if (opt
< 0 || opt
>= GCC_JIT_NUM_INT_OPTIONS
)
1111 "unrecognized (enum gcc_jit_int_option) value: %i", opt
);
1114 m_int_options
[opt
] = value
;
1117 /* Set the given boolean option for this context, or add an error if
1118 it's not recognized.
1120 Implements the post-error-checking part of
1121 gcc_jit_context_set_bool_option. */
1124 recording::context::set_bool_option (enum gcc_jit_bool_option opt
,
1127 if (opt
< 0 || opt
>= GCC_JIT_NUM_BOOL_OPTIONS
)
1130 "unrecognized (enum gcc_jit_bool_option) value: %i", opt
);
1133 m_bool_options
[opt
] = value
? true : false;
1136 /* Add the given dumpname/out_ptr pair to this context's list of requested
1139 Implements the post-error-checking part of
1140 gcc_jit_context_enable_dump. */
1143 recording::context::enable_dump (const char *dumpname
,
1147 gcc_assert (dumpname
);
1148 gcc_assert (out_ptr
);
1150 d
.m_dumpname
= dumpname
;
1151 d
.m_out_ptr
= out_ptr
;
1153 m_requested_dumps
.safe_push (d
);
1156 /* Validate this context, and if it passes, compile it to memory
1159 Implements the post-error-checking part of
1160 gcc_jit_context_compile. */
1163 recording::context::compile ()
1165 JIT_LOG_SCOPE (get_logger ());
1169 if (errors_occurred ())
1172 /* Set up a compile_to_memory playback context. */
1173 ::gcc::jit::playback::compile_to_memory
replayer (this);
1176 replayer
.compile ();
1178 /* Get the jit::result (or NULL) from the
1179 compile_to_memory playback context. */
1180 return replayer
.get_result_obj ();
1183 /* Validate this context, and if it passes, compile it to a file
1186 Implements the post-error-checking part of
1187 gcc_jit_context_compile_to_file. */
1190 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind
,
1191 const char *output_path
)
1193 JIT_LOG_SCOPE (get_logger ());
1197 if (errors_occurred ())
1200 /* Set up a compile_to_file playback context. */
1201 ::gcc::jit::playback::compile_to_file
replayer (this,
1206 replayer
.compile ();
1209 /* Format the given error using printf's conventions, print
1210 it to stderr, and add it to the context. */
1213 recording::context::add_error (location
*loc
, const char *fmt
, ...)
1217 add_error_va (loc
, fmt
, ap
);
1221 /* Format the given error using printf's conventions, print
1222 it to stderr, and add it to the context. */
1225 recording::context::add_error_va (location
*loc
, const char *fmt
, va_list ap
)
1231 JIT_LOG_SCOPE (get_logger ());
1233 vasprintf (&malloced_msg
, fmt
, ap
);
1236 errmsg
= malloced_msg
;
1237 has_ownership
= true;
1241 errmsg
= "out of memory generating error message";
1242 has_ownership
= false;
1245 get_logger ()->log ("error %i: %s", m_error_count
, errmsg
);
1247 const char *ctxt_progname
=
1248 get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
1250 ctxt_progname
= "libgccjit.so";
1253 fprintf (stderr
, "%s: %s: error: %s\n",
1255 loc
->get_debug_string (),
1258 fprintf (stderr
, "%s: error: %s\n",
1264 m_first_error_str
= const_cast <char *> (errmsg
);
1265 m_owns_first_error_str
= has_ownership
;
1268 if (m_owns_last_error_str
)
1269 if (m_last_error_str
!= m_first_error_str
)
1270 free (m_last_error_str
);
1271 m_last_error_str
= const_cast <char *> (errmsg
);
1272 m_owns_last_error_str
= has_ownership
;
1277 /* Get the message for the first error that occurred on this context, or
1278 NULL if no errors have occurred on it.
1280 Implements the post-error-checking part of
1281 gcc_jit_context_get_first_error. */
1284 recording::context::get_first_error () const
1286 return m_first_error_str
;
1289 /* Get the message for the last error that occurred on this context, or
1290 NULL if no errors have occurred on it.
1292 Implements the post-error-checking part of
1293 gcc_jit_context_get_last_error. */
1296 recording::context::get_last_error () const
1298 return m_last_error_str
;
1301 /* Lazily generate and record a recording::type representing an opaque
1302 struct named "FILE".
1304 For use if client code tries to dereference the result of
1305 get_type (GCC_JIT_TYPE_FILE_PTR). */
1308 recording::context::get_opaque_FILE_type ()
1311 m_FILE_type
= new_struct_type (NULL
, "FILE");
1315 /* Dump a C-like representation of the given context to the given path.
1316 If UPDATE_LOCATIONS is true, update the locations within the
1317 context's mementos to point to the dumpfile.
1319 Implements the post-error-checking part of
1320 gcc_jit_context_dump_to_file. */
1323 recording::context::dump_to_file (const char *path
, bool update_locations
)
1326 dump
d (*this, path
, update_locations
);
1328 /* Forward declaration of structs and unions. */
1330 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1332 d
.write ("%s;\n\n", st
->get_debug_string ());
1335 /* Content of structs, where set. */
1336 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1337 if (st
->get_fields ())
1339 st
->get_fields ()->write_to_dump (d
);
1345 FOR_EACH_VEC_ELT (m_globals
, i
, g
)
1347 g
->write_to_dump (d
);
1349 if (!m_globals
.is_empty ())
1353 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1355 fn
->write_to_dump (d
);
1359 static const char * const
1360 str_option_reproducer_strings
[GCC_JIT_NUM_STR_OPTIONS
] = {
1361 "GCC_JIT_STR_OPTION_PROGNAME"
1364 static const char * const
1365 int_option_reproducer_strings
[GCC_JIT_NUM_INT_OPTIONS
] = {
1366 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1369 static const char * const
1370 bool_option_reproducer_strings
[GCC_JIT_NUM_BOOL_OPTIONS
] = {
1371 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1372 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1373 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1374 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1375 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1376 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1377 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1378 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1381 /* Write C source code to PATH that attempts to replay the API
1382 calls made to this context (and its parents), for use in
1383 minimizing test cases for libgccjit.
1385 Implements the post-error-checking part of
1386 gcc_jit_context_dump_reproducer_to_file. */
1389 recording::context::dump_reproducer_to_file (const char *path
)
1391 JIT_LOG_SCOPE (get_logger ());
1392 reproducer
r (*this, path
);
1394 /* Generate the "ancestry" of this context, as a list. */
1395 auto_vec
<context
*> ascending_contexts
;
1396 for (context
*ctxt
= this; ctxt
; ctxt
= ctxt
->m_parent_ctxt
)
1397 ascending_contexts
.safe_push (ctxt
);
1399 /* Reverse the list, giving a list of contexts from
1400 top-most parent context down through to youngest child context.
1401 We will use this list as the parameters of the functions in
1402 our generated file. */
1403 unsigned num_ctxts
= ascending_contexts
.length ();
1404 auto_vec
<context
*> contexts (num_ctxts
);
1405 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1406 contexts
.safe_push (ascending_contexts
[num_ctxts
- (i
+ 1)]);
1408 /* contexts[0] should be the top-level context. */
1409 gcc_assert (contexts
[0]);
1410 gcc_assert (contexts
[0]->m_toplevel_ctxt
== contexts
[0]);
1412 /* The final element in contexts should be "this". */
1413 gcc_assert (contexts
[contexts
.length () - 1] == this);
1414 gcc_assert (contexts
[contexts
.length () - 1]->m_toplevel_ctxt
1417 r
.write ("/* This code was autogenerated by"
1418 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1419 print_version (r
.get_file (), " ", false);
1421 r
.write ("#include <libgccjit.h>\n\n");
1422 r
.write ("static void\nset_options (");
1423 r
.write_params (contexts
);
1425 r
.write ("static void\ncreate_code (");
1426 r
.write_params (contexts
);
1428 r
.write ("int\nmain (int argc, const char **argv)\n");
1430 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1431 r
.write (" gcc_jit_context *%s;\n",
1432 r
.get_identifier (contexts
[i
]));
1433 r
.write (" gcc_jit_result *result;\n"
1436 /* Create the contexts.
1437 The top-level context is acquired from a clean slate, the others as
1438 children of the prior context. */
1439 r
.write (" %s = gcc_jit_context_acquire ();\n",
1440 r
.get_identifier (contexts
[0]));
1441 for (unsigned i
= 1; i
< num_ctxts
; i
++)
1442 r
.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1443 r
.get_identifier (contexts
[i
]),
1444 r
.get_identifier (contexts
[i
- 1]));
1445 r
.write (" set_options (");
1446 r
.write_args (contexts
);
1448 r
.write (" create_code (");
1449 r
.write_args (contexts
);
1452 r
.write (" result = gcc_jit_context_compile (%s);\n",
1453 r
.get_identifier (this));
1455 for (unsigned i
= num_ctxts
; i
> 0; i
--)
1456 r
.write (" gcc_jit_context_release (%s);\n",
1457 r
.get_identifier (contexts
[i
- 1]));
1459 r
.write (" gcc_jit_result_release (result);\n"
1463 /* Define (char *) variables for use in calls to
1464 gcc_jit_context_enable_dump. */
1465 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1467 if (m_requested_dumps
.length ())
1469 r
.write ("/* Requested dumps for %s. */\n",
1470 r
.get_identifier (contexts
[ctxt_idx
]));
1471 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1472 r
.write ("static char *dump_%p;\n",
1473 (void *)&m_requested_dumps
[i
]);
1478 /* Write out values of options. */
1479 r
.write ("static void\nset_options (");
1480 r
.write_params (contexts
);
1482 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1487 r
.write (" /* Set options for %s. */\n",
1488 r
.get_identifier (contexts
[ctxt_idx
]));
1490 r
.write (" /* String options. */\n");
1491 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1492 r
.write (" gcc_jit_context_set_str_option (%s,\n"
1495 r
.get_identifier (contexts
[ctxt_idx
]),
1496 str_option_reproducer_strings
[opt_idx
],
1497 m_str_options
[opt_idx
] ? m_str_options
[opt_idx
] : "NULL");
1498 r
.write (" /* Int options. */\n");
1499 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1500 r
.write (" gcc_jit_context_set_int_option (%s,\n"
1503 r
.get_identifier (contexts
[ctxt_idx
]),
1504 int_option_reproducer_strings
[opt_idx
],
1505 m_int_options
[opt_idx
]);
1506 r
.write (" /* Boolean options. */\n");
1507 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1508 r
.write (" gcc_jit_context_set_bool_option (%s,\n"
1511 r
.get_identifier (contexts
[ctxt_idx
]),
1512 bool_option_reproducer_strings
[opt_idx
],
1513 m_bool_options
[opt_idx
]);
1515 if (m_requested_dumps
.length ())
1517 r
.write (" /* Requested dumps. */\n");
1518 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1519 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1521 r
.write (" gcc_jit_context_enable_dump (%s,\n"
1524 r
.get_identifier (contexts
[ctxt_idx
]),
1525 m_requested_dumps
[i
].m_dumpname
,
1526 (void *)&m_requested_dumps
[i
]);
1532 r
.write ("static void\ncreate_code (");
1533 r
.write_params (contexts
);
1536 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1543 r
.write (" /* Replay of API calls for %s. */\n",
1544 r
.get_identifier (contexts
[ctxt_idx
]));
1545 FOR_EACH_VEC_ELT (contexts
[ctxt_idx
]->m_mementos
, i
, m
)
1546 m
->write_reproducer (r
);
1551 /* Copy the requested dumps within this context and all ancestors into
1555 recording::context::get_all_requested_dumps (vec
<recording::requested_dump
> *out
)
1558 m_parent_ctxt
->get_all_requested_dumps (out
);
1560 out
->reserve (m_requested_dumps
.length ());
1561 out
->splice (m_requested_dumps
);
1564 /* This is a pre-compilation check for the context (and any parents).
1566 Detect errors within the context, adding errors if any are found. */
1569 recording::context::validate ()
1571 JIT_LOG_SCOPE (get_logger ());
1574 m_parent_ctxt
->validate ();
1578 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1582 /* The implementation of class gcc::jit::recording::memento. */
1584 /* Get a (const char *) debug description of the given memento, by
1585 calling the pure-virtual make_debug_string hook, caching the
1588 It is intended that this should only be called in debugging and
1589 error-handling paths, so this doesn't need to be particularly
1593 recording::memento::get_debug_string ()
1595 if (!m_debug_string
)
1596 m_debug_string
= make_debug_string ();
1597 return m_debug_string
->c_str ();
1600 /* Default implementation of recording::memento::write_to_dump, writing
1601 an indented form of the memento's debug string to the dump. */
1604 recording::memento::write_to_dump (dump
&d
)
1606 d
.write(" %s\n", get_debug_string ());
1609 /* The implementation of class gcc::jit::recording::string. */
1611 /* Constructor for gcc::jit::recording::string::string, allocating a
1612 copy of the given text using new char[]. */
1614 recording::string::string (context
*ctxt
, const char *text
)
1617 m_len
= strlen (text
);
1618 m_buffer
= new char[m_len
+ 1];
1619 strcpy (m_buffer
, text
);
1622 /* Destructor for gcc::jit::recording::string::string. */
1624 recording::string::~string ()
1629 /* Function for making gcc::jit::recording::string instances on a
1630 context via printf-style formatting.
1632 It is intended that this should only be called in debugging and
1633 error-handling paths, so this doesn't need to be particularly
1634 optimized, hence the double-copy of the string is acceptable. */
1637 recording::string::from_printf (context
*ctxt
, const char *fmt
, ...)
1641 recording::string
*result
;
1644 vasprintf (&buf
, fmt
, ap
);
1649 ctxt
->add_error (NULL
, "malloc failure");
1653 result
= ctxt
->new_string (buf
);
1658 /* Implementation of recording::memento::make_debug_string for strings,
1659 wrapping the given string in quotes and escaping as necessary. */
1662 recording::string::make_debug_string ()
1664 /* Hack to avoid infinite recursion into strings when logging all
1665 mementos: don't re-escape strings: */
1666 if (m_buffer
[0] == '"')
1669 /* Wrap in quotes and do escaping etc */
1671 size_t sz
= (1 /* opening quote */
1672 + (m_len
* 2) /* each char might get escaped */
1673 + 1 /* closing quote */
1674 + 1); /* nil termintator */
1675 char *tmp
= new char[sz
];
1678 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1679 APPEND('"'); /* opening quote */
1680 for (size_t i
= 0; i
< m_len
; i
++)
1682 char ch
= m_buffer
[i
];
1683 if (ch
== '\t' || ch
== '\n' || ch
== '\\' || ch
== '"')
1687 APPEND('"'); /* closing quote */
1689 tmp
[len
] = '\0'; /* nil termintator */
1691 string
*result
= m_ctxt
->new_string (tmp
);
1697 /* Implementation of recording::memento::write_reproducer for strings. */
1700 recording::string::write_reproducer (reproducer
&)
1705 /* The implementation of class gcc::jit::recording::location. */
1707 /* Implementation of recording::memento::replay_into for locations.
1709 Create a new playback::location and store it into the
1710 recording::location's m_playback_obj field. */
1713 recording::location::replay_into (replayer
*r
)
1715 m_playback_obj
= r
->new_location (this,
1716 m_filename
->c_str (),
1721 /* Implementation of recording::memento::make_debug_string for locations,
1722 turning them into the usual form:
1723 FILENAME:LINE:COLUMN
1724 like we do when emitting diagnostics. */
1727 recording::location::make_debug_string ()
1729 return string::from_printf (m_ctxt
,
1731 m_filename
->c_str (), m_line
, m_column
);
1734 /* Implementation of recording::memento::write_reproducer for locations. */
1737 recording::location::write_reproducer (reproducer
&r
)
1739 const char *id
= r
.make_identifier (this, "loc");
1740 r
.write (" gcc_jit_location *%s =\n"
1741 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1742 " %s, /* const char *filename */\n"
1743 " %i, /* int line */\n"
1744 " %i);/* int column */\n",
1746 r
.get_identifier (get_context ()),
1747 m_filename
->get_debug_string (),
1751 /* The implementation of class gcc::jit::recording::type. */
1753 /* Given a type T, get the type T*.
1755 If this doesn't already exist, generate a new memento_of_get_pointer
1756 instance and add it to this type's context's list of mementos.
1758 Otherwise, use the cached type.
1760 Implements the post-error-checking part of
1761 gcc_jit_type_get_pointer. */
1764 recording::type::get_pointer ()
1766 if (!m_pointer_to_this_type
)
1768 m_pointer_to_this_type
= new memento_of_get_pointer (this);
1769 m_ctxt
->record (m_pointer_to_this_type
);
1771 return m_pointer_to_this_type
;
1774 /* Given a type T, get the type const T.
1776 Implements the post-error-checking part of
1777 gcc_jit_type_get_const. */
1780 recording::type::get_const ()
1782 recording::type
*result
= new memento_of_get_const (this);
1783 m_ctxt
->record (result
);
1787 /* Given a type T, get the type volatile T.
1789 Implements the post-error-checking part of
1790 gcc_jit_type_get_volatile. */
1793 recording::type::get_volatile ()
1795 recording::type
*result
= new memento_of_get_volatile (this);
1796 m_ctxt
->record (result
);
1801 recording::type::access_as_type (reproducer
&r
)
1803 return r
.get_identifier (this);
1806 /* Implementation of pure virtual hook recording::type::dereference for
1807 recording::memento_of_get_type. */
1810 recording::memento_of_get_type::dereference ()
1814 default: gcc_unreachable ();
1816 case GCC_JIT_TYPE_VOID
:
1819 case GCC_JIT_TYPE_VOID_PTR
:
1820 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
1822 case GCC_JIT_TYPE_BOOL
:
1823 case GCC_JIT_TYPE_CHAR
:
1824 case GCC_JIT_TYPE_SIGNED_CHAR
:
1825 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1826 case GCC_JIT_TYPE_SHORT
:
1827 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1828 case GCC_JIT_TYPE_INT
:
1829 case GCC_JIT_TYPE_UNSIGNED_INT
:
1830 case GCC_JIT_TYPE_LONG
:
1831 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1832 case GCC_JIT_TYPE_LONG_LONG
:
1833 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1834 case GCC_JIT_TYPE_FLOAT
:
1835 case GCC_JIT_TYPE_DOUBLE
:
1836 case GCC_JIT_TYPE_LONG_DOUBLE
:
1837 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1838 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1839 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1840 /* Not a pointer: */
1843 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1844 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
1846 case GCC_JIT_TYPE_SIZE_T
:
1847 /* Not a pointer: */
1850 case GCC_JIT_TYPE_FILE_PTR
:
1851 /* Give the client code back an opaque "struct FILE". */
1852 return m_ctxt
->get_opaque_FILE_type ();
1856 /* Implementation of pure virtual hook recording::type::is_int for
1857 recording::memento_of_get_type. */
1860 recording::memento_of_get_type::is_int () const
1864 default: gcc_unreachable ();
1866 case GCC_JIT_TYPE_VOID
:
1869 case GCC_JIT_TYPE_VOID_PTR
:
1872 case GCC_JIT_TYPE_BOOL
:
1875 case GCC_JIT_TYPE_CHAR
:
1876 case GCC_JIT_TYPE_SIGNED_CHAR
:
1877 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1878 case GCC_JIT_TYPE_SHORT
:
1879 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1880 case GCC_JIT_TYPE_INT
:
1881 case GCC_JIT_TYPE_UNSIGNED_INT
:
1882 case GCC_JIT_TYPE_LONG
:
1883 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1884 case GCC_JIT_TYPE_LONG_LONG
:
1885 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1888 case GCC_JIT_TYPE_FLOAT
:
1889 case GCC_JIT_TYPE_DOUBLE
:
1890 case GCC_JIT_TYPE_LONG_DOUBLE
:
1893 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1896 case GCC_JIT_TYPE_SIZE_T
:
1899 case GCC_JIT_TYPE_FILE_PTR
:
1902 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1903 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1904 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1909 /* Implementation of pure virtual hook recording::type::is_float for
1910 recording::memento_of_get_type. */
1913 recording::memento_of_get_type::is_float () const
1917 default: gcc_unreachable ();
1919 case GCC_JIT_TYPE_VOID
:
1922 case GCC_JIT_TYPE_VOID_PTR
:
1925 case GCC_JIT_TYPE_BOOL
:
1928 case GCC_JIT_TYPE_CHAR
:
1929 case GCC_JIT_TYPE_SIGNED_CHAR
:
1930 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1931 case GCC_JIT_TYPE_SHORT
:
1932 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1933 case GCC_JIT_TYPE_INT
:
1934 case GCC_JIT_TYPE_UNSIGNED_INT
:
1935 case GCC_JIT_TYPE_LONG
:
1936 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1937 case GCC_JIT_TYPE_LONG_LONG
:
1938 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1941 case GCC_JIT_TYPE_FLOAT
:
1942 case GCC_JIT_TYPE_DOUBLE
:
1943 case GCC_JIT_TYPE_LONG_DOUBLE
:
1946 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1949 case GCC_JIT_TYPE_SIZE_T
:
1952 case GCC_JIT_TYPE_FILE_PTR
:
1955 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1956 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1957 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1962 /* Implementation of pure virtual hook recording::type::is_bool for
1963 recording::memento_of_get_type. */
1966 recording::memento_of_get_type::is_bool () const
1970 default: gcc_unreachable ();
1972 case GCC_JIT_TYPE_VOID
:
1975 case GCC_JIT_TYPE_VOID_PTR
:
1978 case GCC_JIT_TYPE_BOOL
:
1981 case GCC_JIT_TYPE_CHAR
:
1982 case GCC_JIT_TYPE_SIGNED_CHAR
:
1983 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1984 case GCC_JIT_TYPE_SHORT
:
1985 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1986 case GCC_JIT_TYPE_INT
:
1987 case GCC_JIT_TYPE_UNSIGNED_INT
:
1988 case GCC_JIT_TYPE_LONG
:
1989 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1990 case GCC_JIT_TYPE_LONG_LONG
:
1991 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1994 case GCC_JIT_TYPE_FLOAT
:
1995 case GCC_JIT_TYPE_DOUBLE
:
1996 case GCC_JIT_TYPE_LONG_DOUBLE
:
1999 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2002 case GCC_JIT_TYPE_SIZE_T
:
2005 case GCC_JIT_TYPE_FILE_PTR
:
2008 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2009 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2010 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2015 /* Implementation of pure virtual hook recording::memento::replay_into
2016 for recording::memento_of_get_type. */
2019 recording::memento_of_get_type::replay_into (replayer
*r
)
2021 set_playback_obj (r
->get_type (m_kind
));
2024 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2026 /* Descriptive strings for each of enum gcc_jit_types. */
2028 static const char * const get_type_strings
[] = {
2029 "void", /* GCC_JIT_TYPE_VOID */
2030 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2032 "bool", /* GCC_JIT_TYPE_BOOL */
2034 "char", /* GCC_JIT_TYPE_CHAR */
2035 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2036 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2038 "short", /* GCC_JIT_TYPE_SHORT */
2039 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2041 "int", /* GCC_JIT_TYPE_INT */
2042 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2044 "long", /* GCC_JIT_TYPE_LONG */
2045 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2047 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2048 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2050 "float", /* GCC_JIT_TYPE_FLOAT */
2051 "double", /* GCC_JIT_TYPE_DOUBLE */
2052 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2054 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2056 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2058 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2060 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2061 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2062 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2066 /* Implementation of recording::memento::make_debug_string for
2067 results of get_type, using a simple table of type names. */
2070 recording::memento_of_get_type::make_debug_string ()
2072 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
2075 static const char * const get_type_enum_strings
[] = {
2076 "GCC_JIT_TYPE_VOID",
2077 "GCC_JIT_TYPE_VOID_PTR",
2078 "GCC_JIT_TYPE_BOOL",
2079 "GCC_JIT_TYPE_CHAR",
2080 "GCC_JIT_TYPE_SIGNED_CHAR",
2081 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2082 "GCC_JIT_TYPE_SHORT",
2083 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2085 "GCC_JIT_TYPE_UNSIGNED_INT",
2086 "GCC_JIT_TYPE_LONG",
2087 "GCC_JIT_TYPE_UNSIGNED_LONG",
2088 "GCC_JIT_TYPE_LONG_LONG",
2089 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2090 "GCC_JIT_TYPE_FLOAT",
2091 "GCC_JIT_TYPE_DOUBLE",
2092 "GCC_JIT_TYPE_LONG_DOUBLE",
2093 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2094 "GCC_JIT_TYPE_SIZE_T",
2095 "GCC_JIT_TYPE_FILE_PTR",
2096 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2097 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2098 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2102 recording::memento_of_get_type::write_reproducer (reproducer
&r
)
2104 const char *id
= r
.make_identifier (this, "type");
2105 r
.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2107 r
.get_identifier (get_context ()),
2108 get_type_enum_strings
[m_kind
]);
2111 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2113 /* Override of default implementation of
2114 recording::type::accepts_writes_from for get_pointer.
2116 Require a pointer type, and allowing writes to
2117 (const T *) from a (T*), but not the other way around. */
2120 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
2122 /* Must be a pointer type: */
2123 type
*rtype_points_to
= rtype
->is_pointer ();
2124 if (!rtype_points_to
)
2127 /* It's OK to assign to a (const T *) from a (T *). */
2128 return m_other_type
->unqualified ()
2129 ->accepts_writes_from (rtype_points_to
);
2132 /* Implementation of pure virtual hook recording::memento::replay_into
2133 for recording::memento_of_get_pointer. */
2136 recording::memento_of_get_pointer::replay_into (replayer
*)
2138 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
2141 /* Implementation of recording::memento::make_debug_string for
2142 results of get_pointer, adding " *" to the underlying type,
2143 with special-casing to handle function pointer types. */
2146 recording::memento_of_get_pointer::make_debug_string ()
2148 /* Special-case function pointer types, to put the "*" in parens between
2149 the return type and the params (for one level of dereferencing, at
2151 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2152 return fn_type
->make_debug_string_with_ptr ();
2154 return string::from_printf (m_ctxt
,
2155 "%s *", m_other_type
->get_debug_string ());
2158 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2161 recording::memento_of_get_pointer::write_reproducer (reproducer
&r
)
2163 /* We need to special-case function pointer types; see the notes in
2164 recording::function_type::write_deferred_reproducer. */
2165 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2167 fn_type
->write_deferred_reproducer (r
, this);
2171 const char *id
= r
.make_identifier (this, "type");
2172 r
.write (" gcc_jit_type *%s =\n"
2173 " gcc_jit_type_get_pointer (%s);\n",
2175 r
.get_identifier_as_type (m_other_type
));
2178 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2180 /* Implementation of pure virtual hook recording::memento::replay_into
2181 for recording::memento_of_get_const. */
2184 recording::memento_of_get_const::replay_into (replayer
*)
2186 set_playback_obj (m_other_type
->playback_type ()->get_const ());
2189 /* Implementation of recording::memento::make_debug_string for
2190 results of get_const, prepending "const ". */
2193 recording::memento_of_get_const::make_debug_string ()
2195 return string::from_printf (m_ctxt
,
2196 "const %s", m_other_type
->get_debug_string ());
2199 /* Implementation of recording::memento::write_reproducer for const types. */
2202 recording::memento_of_get_const::write_reproducer (reproducer
&r
)
2204 const char *id
= r
.make_identifier (this, "type");
2205 r
.write (" gcc_jit_type *%s =\n"
2206 " gcc_jit_type_get_const (%s);\n",
2208 r
.get_identifier_as_type (m_other_type
));
2211 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2213 /* Implementation of pure virtual hook recording::memento::replay_into
2214 for recording::memento_of_get_volatile. */
2217 recording::memento_of_get_volatile::replay_into (replayer
*)
2219 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
2222 /* Implementation of recording::memento::make_debug_string for
2223 results of get_volatile, prepending "volatile ". */
2226 recording::memento_of_get_volatile::make_debug_string ()
2228 return string::from_printf (m_ctxt
,
2229 "volatile %s", m_other_type
->get_debug_string ());
2232 /* Implementation of recording::memento::write_reproducer for volatile
2236 recording::memento_of_get_volatile::write_reproducer (reproducer
&r
)
2238 const char *id
= r
.make_identifier (this, "type");
2239 r
.write (" gcc_jit_type *%s =\n"
2240 " gcc_jit_type_get_volatile (%s);\n",
2242 r
.get_identifier_as_type (m_other_type
));
2245 /* The implementation of class gcc::jit::recording::array_type */
2247 /* Implementation of pure virtual hook recording::type::dereference for
2248 recording::array_type. */
2251 recording::array_type::dereference ()
2253 return m_element_type
;
2256 /* Implementation of pure virtual hook recording::memento::replay_into
2257 for recording::array_type. */
2260 recording::array_type::replay_into (replayer
*r
)
2262 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
2263 m_element_type
->playback_type (),
2267 /* Implementation of recording::memento::make_debug_string for
2268 results of new_array_type. */
2271 recording::array_type::make_debug_string ()
2273 return string::from_printf (m_ctxt
,
2275 m_element_type
->get_debug_string (),
2279 /* Implementation of recording::memento::write_reproducer for array
2283 recording::array_type::write_reproducer (reproducer
&r
)
2285 const char *id
= r
.make_identifier (this, "array_type");
2286 r
.write (" gcc_jit_type *%s =\n"
2287 " gcc_jit_context_new_array_type (%s,\n"
2288 " %s, /* gcc_jit_location *loc */\n"
2289 " %s, /* gcc_jit_type *element_type */\n"
2290 " %i); /* int num_elements */\n",
2292 r
.get_identifier (get_context ()),
2293 r
.get_identifier (m_loc
),
2294 r
.get_identifier_as_type (m_element_type
),
2298 /* The implementation of class gcc::jit::recording::function_type */
2300 /* Constructor for gcc::jit::recording::function_type. */
2302 recording::function_type::function_type (context
*ctxt
,
2308 m_return_type (return_type
),
2310 m_is_variadic (is_variadic
)
2312 for (int i
= 0; i
< num_params
; i
++)
2313 m_param_types
.safe_push (param_types
[i
]);
2316 /* Implementation of pure virtual hook recording::type::dereference for
2317 recording::function_type. */
2320 recording::function_type::dereference ()
2325 /* Implementation of pure virtual hook recording::memento::replay_into
2326 for recording::function_type. */
2329 recording::function_type::replay_into (replayer
*r
)
2331 /* Convert m_param_types to a vec of playback type. */
2332 auto_vec
<playback::type
*> param_types
;
2334 recording::type
*type
;
2335 param_types
.create (m_param_types
.length ());
2336 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
2337 param_types
.safe_push (type
->playback_type ());
2339 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
2344 /* Special-casing for make_debug_string for get_pointer results for
2345 handling (one level) of pointers to functions. */
2348 recording::function_type::make_debug_string_with_ptr ()
2350 return make_debug_string_with ("(*) ");
2353 /* Implementation of recording::memento::make_debug_string for
2354 results of new_function_type. */
2357 recording::function_type::make_debug_string ()
2359 return make_debug_string_with ("");
2362 /* Build a debug string representation of the form:
2364 RESULT_TYPE INSERT (PARAM_TYPES)
2366 for use when handling 0 and 1 level of indirection to this
2370 recording::function_type::make_debug_string_with (const char *insert
)
2372 /* First, build a buffer for the arguments. */
2373 /* Calculate length of said buffer. */
2374 size_t sz
= 1; /* nil terminator */
2375 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2377 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
2378 sz
+= 2; /* ", " separator */
2381 sz
+= 5; /* ", ..." separator and ellipsis */
2383 /* Now allocate and populate the buffer. */
2384 char *argbuf
= new char[sz
];
2387 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2389 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
2390 len
+= strlen (m_param_types
[i
]->get_debug_string ());
2391 if (i
+ 1 < m_param_types
.length ())
2393 strcpy (argbuf
+ len
, ", ");
2399 if (m_param_types
.length ())
2401 strcpy (argbuf
+ len
, ", ");
2404 strcpy (argbuf
+ len
, "...");
2409 /* ...and use it to get the string for the call as a whole. */
2410 string
*result
= string::from_printf (m_ctxt
,
2412 m_return_type
->get_debug_string (),
2421 /* Implementation of recording::memento::write_reproducer for function
2425 recording::function_type::write_reproducer (reproducer
&)
2427 /* see notes below. */
2430 /* There's a get_pointer within context::new_function_ptr_type:
2431 the type received by client code isn't the memento for the
2432 function_type, but instead the result of get_pointer on it.
2434 Hence we can't directly write a reproducer that gives function_type.
2435 Instead we special-case things within get_pointer, detecting this
2436 case, calling the following function. */
2439 recording::function_type::write_deferred_reproducer (reproducer
&r
,
2442 gcc_assert (ptr_type
);
2443 r
.make_identifier (this, "function_type");
2444 const char *ptr_id
= r
.make_identifier (ptr_type
, "ptr_to");
2445 const char *param_types_id
= r
.make_tmp_identifier ("params_for", this);
2446 r
.write (" gcc_jit_type *%s[%i] = {\n",
2448 m_param_types
.length ());
2451 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
2452 r
.write (" %s,\n", r
.get_identifier_as_type (param_type
));
2454 r
.write (" gcc_jit_type *%s =\n"
2455 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2456 " %s, /* gcc_jit_location *loc */\n"
2457 " %s, /* gcc_jit_type *return_type */\n"
2458 " %i, /* int num_params */\n"
2459 " %s, /* gcc_jit_type **param_types */\n"
2460 " %i); /* int is_variadic */\n",
2462 r
.get_identifier (get_context ()),
2463 "NULL", /* location is not stored */
2464 r
.get_identifier_as_type (m_return_type
),
2465 m_param_types
.length (),
2470 /* The implementation of class gcc::jit::recording::field. */
2472 /* Implementation of pure virtual hook recording::memento::replay_into
2473 for recording::field. */
2476 recording::field::replay_into (replayer
*r
)
2478 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
2479 m_type
->playback_type (),
2480 playback_string (m_name
)));
2483 /* Override the default implementation of
2484 recording::memento::write_to_dump. Dump each field
2485 by dumping a line of the form:
2487 so that we can build up a struct/union field-byfield. */
2490 recording::field::write_to_dump (dump
&d
)
2492 d
.write (" %s %s;\n",
2493 m_type
->get_debug_string (),
2497 /* Implementation of recording::memento::make_debug_string for
2498 results of new_field. */
2501 recording::field::make_debug_string ()
2506 /* Implementation of recording::memento::write_reproducer for fields. */
2509 recording::field::write_reproducer (reproducer
&r
)
2511 const char *id
= r
.make_identifier (this, "field");
2512 r
.write(" gcc_jit_field *%s =\n"
2513 " gcc_jit_context_new_field (%s,\n"
2514 " %s, /* gcc_jit_location *loc */\n"
2515 " %s, /* gcc_jit_type *type, */\n"
2516 " %s); /* const char *name */\n",
2518 r
.get_identifier (get_context ()),
2519 r
.get_identifier (m_loc
),
2520 r
.get_identifier_as_type (m_type
),
2521 m_name
->get_debug_string ());
2524 /* The implementation of class gcc::jit::recording::compound_type */
2526 /* The constructor for gcc::jit::recording::compound_type. */
2528 recording::compound_type::compound_type (context
*ctxt
,
2538 /* Set the fields of a compound type.
2540 Implements the post-error-checking part of
2541 gcc_jit_struct_set_fields, and is also used by
2542 gcc_jit_context_new_union_type. */
2545 recording::compound_type::set_fields (location
*loc
,
2547 field
**field_array
)
2550 gcc_assert (NULL
== m_fields
);
2552 m_fields
= new fields (this, num_fields
, field_array
);
2553 m_ctxt
->record (m_fields
);
2556 /* Implementation of pure virtual hook recording::type::dereference for
2557 recording::compound_type. */
2560 recording::compound_type::dereference ()
2562 return NULL
; /* not a pointer */
2565 /* The implementation of class gcc::jit::recording::struct_. */
2567 /* The constructor for gcc::jit::recording::struct_. */
2569 recording::struct_::struct_ (context
*ctxt
,
2572 : compound_type (ctxt
, loc
, name
)
2576 /* Implementation of pure virtual hook recording::memento::replay_into
2577 for recording::struct_. */
2580 recording::struct_::replay_into (replayer
*r
)
2583 r
->new_compound_type (playback_location (r
, get_loc ()),
2584 get_name ()->c_str (),
2585 true /* is_struct */));
2589 recording::struct_::access_as_type (reproducer
&r
)
2591 return r
.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2592 r
.get_identifier (this));
2595 /* Implementation of recording::memento::make_debug_string for
2599 recording::struct_::make_debug_string ()
2601 return string::from_printf (m_ctxt
,
2602 "struct %s", get_name ()->c_str ());
2606 recording::struct_::write_reproducer (reproducer
&r
)
2608 const char *id
= r
.make_identifier (this, "struct");
2609 r
.write (" gcc_jit_struct *%s =\n"
2610 " gcc_jit_context_new_opaque_struct (%s,\n"
2611 " %s, /* gcc_jit_location *loc */\n"
2612 " %s); /* const char *name */\n",
2614 r
.get_identifier (get_context ()),
2615 r
.get_identifier (get_loc ()),
2616 get_name ()->get_debug_string ());
2619 /* The implementation of class gcc::jit::recording::union_. */
2621 /* The constructor for gcc::jit::recording::union_. */
2623 recording::union_::union_ (context
*ctxt
,
2626 : compound_type (ctxt
, loc
, name
)
2630 /* Implementation of pure virtual hook recording::memento::replay_into
2631 for recording::union_. */
2634 recording::union_::replay_into (replayer
*r
)
2637 r
->new_compound_type (playback_location (r
, get_loc ()),
2638 get_name ()->c_str (),
2639 false /* is_struct */));
2642 /* Implementation of recording::memento::make_debug_string for
2646 recording::union_::make_debug_string ()
2648 return string::from_printf (m_ctxt
,
2649 "union %s", get_name ()->c_str ());
2652 /* Implementation of recording::memento::write_reproducer for unions. */
2655 recording::union_::write_reproducer (reproducer
&r
)
2657 const char *id
= r
.make_identifier (this, "union");
2659 const char *fields_id
= r
.make_tmp_identifier ("fields_for", this);
2660 r
.write (" gcc_jit_field *%s[%i] = {\n",
2662 get_fields ()->length ());
2663 for (int i
= 0; i
< get_fields ()->length (); i
++)
2664 r
.write (" %s,\n", r
.get_identifier (get_fields ()->get_field (i
)));
2667 r
.write (" gcc_jit_type *%s =\n"
2668 " gcc_jit_context_new_union_type (%s,\n"
2669 " %s, /* gcc_jit_location *loc */\n"
2670 " %s, /* const char *name */\n"
2671 " %i, /* int num_fields */\n"
2672 " %s); /* gcc_jit_field **fields */\n",
2674 r
.get_identifier (get_context ()),
2675 r
.get_identifier (get_loc ()),
2676 get_name ()->get_debug_string (),
2677 get_fields ()->length (),
2681 /* The implementation of class gcc::jit::recording::fields. */
2683 /* The constructor for gcc::jit::recording::fields. */
2685 recording::fields::fields (compound_type
*struct_or_union
,
2688 : memento (struct_or_union
->m_ctxt
),
2689 m_struct_or_union (struct_or_union
),
2692 for (int i
= 0; i
< num_fields
; i
++)
2694 gcc_assert (fields
[i
]->get_container () == NULL
);
2695 fields
[i
]->set_container (m_struct_or_union
);
2696 m_fields
.safe_push (fields
[i
]);
2700 /* Implementation of pure virtual hook recording::memento::replay_into
2701 for recording::fields. */
2704 recording::fields::replay_into (replayer
*)
2706 auto_vec
<playback::field
*> playback_fields
;
2707 playback_fields
.create (m_fields
.length ());
2708 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
2709 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
2710 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
2713 /* Override the default implementation of
2714 recording::memento::write_to_dump by writing a union/struct
2715 declaration of this form:
2727 recording::fields::write_to_dump (dump
&d
)
2732 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
2733 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
2734 f
->write_to_dump (d
);
2738 /* Implementation of recording::memento::write_reproducer for the fields
2742 recording::fields::write_reproducer (reproducer
&r
)
2744 if (m_struct_or_union
)
2745 if (NULL
== m_struct_or_union
->dyn_cast_struct ())
2746 /* We have a union; the fields have already been written by
2747 union::write_reproducer. */
2750 const char *fields_id
= r
.make_identifier (this, "fields");
2751 r
.write (" gcc_jit_field *%s[%i] = {\n",
2753 m_fields
.length ());
2756 FOR_EACH_VEC_ELT (m_fields
, i
, field
)
2757 r
.write (" %s,\n", r
.get_identifier (field
));
2760 r
.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
2761 " %s, /* gcc_jit_location *loc */\n"
2762 " %i, /* int num_fields */\n"
2763 " %s); /* gcc_jit_field **fields */\n",
2764 r
.get_identifier (m_struct_or_union
),
2765 r
.get_identifier ((memento
*)NULL
),
2770 /* Implementation of recording::memento::make_debug_string for
2774 recording::fields::make_debug_string ()
2776 return string::from_printf (m_ctxt
,
2780 /* The implementation of class gcc::jit::recording::rvalue. */
2782 /* Create a recording::access_field_rvalue instance and add it to
2783 the rvalue's context's list of mementos.
2785 Implements the post-error-checking part of
2786 gcc_jit_rvalue_access_field. */
2789 recording::rvalue::access_field (recording::location
*loc
,
2792 recording::rvalue
*result
=
2793 new access_field_rvalue (m_ctxt
, loc
, this, field
);
2794 m_ctxt
->record (result
);
2798 /* Create a recording::dereference_field_rvalue instance and add it to
2799 the rvalue's context's list of mementos.
2801 Implements the post-error-checking part of
2802 gcc_jit_rvalue_dereference_field. */
2805 recording::rvalue::dereference_field (recording::location
*loc
,
2808 recording::lvalue
*result
=
2809 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
2810 m_ctxt
->record (result
);
2814 /* Create a recording::dereference_rvalue instance and add it to the
2815 rvalue's context's list of mementos.
2817 Implements the post-error-checking part of
2818 gcc_jit_rvalue_dereference. */
2821 recording::rvalue::dereference (recording::location
*loc
)
2823 recording::lvalue
*result
=
2824 new dereference_rvalue (m_ctxt
, loc
, this);
2825 m_ctxt
->record (result
);
2829 /* An rvalue visitor, for validating that every rvalue within an expression
2830 trees within "STMT" has the correct scope (e.g. no access to locals
2831 of a different function). */
2833 class rvalue_usage_validator
: public recording::rvalue_visitor
2836 rvalue_usage_validator (const char *api_funcname
,
2837 recording::context
*ctxt
,
2838 recording::statement
*stmt
);
2841 visit (recording::rvalue
*rvalue
);
2844 const char *m_api_funcname
;
2845 recording::context
*m_ctxt
;
2846 recording::statement
*m_stmt
;
2849 /* The trivial constructor for rvalue_usage_validator. */
2851 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname
,
2852 recording::context
*ctxt
,
2853 recording::statement
*stmt
)
2854 : m_api_funcname (api_funcname
),
2860 /* Verify that the given rvalue is in the correct scope. */
2863 rvalue_usage_validator::visit (recording::rvalue
*rvalue
)
2865 gcc_assert (m_stmt
->get_block ());
2866 recording::function
*stmt_scope
= m_stmt
->get_block ()->get_function ();
2868 /* Most rvalues don't have a scope (only locals and params). */
2869 if (rvalue
->get_scope ())
2871 if (rvalue
->get_scope () != stmt_scope
)
2873 (rvalue
->get_loc (),
2875 " rvalue %s (type: %s)"
2876 " has scope limited to function %s"
2877 " but was used within function %s"
2878 " (in statement: %s)",
2880 rvalue
->get_debug_string (),
2881 rvalue
->get_type ()->get_debug_string (),
2882 rvalue
->get_scope ()->get_debug_string (),
2883 stmt_scope
->get_debug_string (),
2884 m_stmt
->get_debug_string ());
2888 if (rvalue
->dyn_cast_param ())
2890 (rvalue
->get_loc (),
2892 " param %s (type: %s)"
2893 " was used within function %s"
2894 " (in statement: %s)"
2895 " but is not associated with any function",
2897 rvalue
->get_debug_string (),
2898 rvalue
->get_type ()->get_debug_string (),
2899 stmt_scope
->get_debug_string (),
2900 m_stmt
->get_debug_string ());
2904 /* Verify that it's valid to use this rvalue (and all expressions
2905 in the tree below it) within the given statement.
2907 For example, we must reject attempts to use a local from one
2908 function within a different function here, or we'll get
2909 an ICE deep inside toplev::main. */
2912 recording::rvalue::verify_valid_within_stmt (const char *api_funcname
, statement
*s
)
2914 rvalue_usage_validator
v (api_funcname
,
2918 /* Verify that it's OK to use this rvalue within s. */
2921 /* Traverse the expression tree below "this", verifying all rvalues
2923 visit_children (&v
);
2926 /* Set the scope of this rvalue to be the given function. This can only
2927 be done once on a given rvalue. */
2930 recording::rvalue::set_scope (function
*scope
)
2933 gcc_assert (NULL
== m_scope
);
2938 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
2940 Instances of rvalue don't need an upcast call. */
2943 recording::rvalue::access_as_rvalue (reproducer
&r
)
2945 return r
.get_identifier (this);
2949 /* The implementation of class gcc::jit::recording::lvalue. */
2951 /* Create a recording::new_access_field_of_lvalue instance and add it to
2952 the lvalue's context's list of mementos.
2954 Implements the post-error-checking part of
2955 gcc_jit_lvalue_access_field. */
2958 recording::lvalue::access_field (recording::location
*loc
,
2961 recording::lvalue
*result
=
2962 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
2963 m_ctxt
->record (result
);
2967 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
2968 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
2972 recording::lvalue::access_as_rvalue (reproducer
&r
)
2974 return r
.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
2975 r
.get_identifier (this));
2978 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
2979 Instances of lvalue don't need to be upcast. */
2982 recording::lvalue::access_as_lvalue (reproducer
&r
)
2984 return r
.get_identifier (this);
2987 /* Create a recording::get_address_of_lvalue instance and add it to
2988 the lvalue's context's list of mementos.
2990 Implements the post-error-checking part of
2991 gcc_jit_lvalue_get_address. */
2994 recording::lvalue::get_address (recording::location
*loc
)
2996 recording::rvalue
*result
=
2997 new get_address_of_lvalue (m_ctxt
, loc
, this);
2998 m_ctxt
->record (result
);
3002 /* The implementation of class gcc::jit::recording::param. */
3004 /* Implementation of pure virtual hook recording::memento::replay_into
3005 for recording::param. */
3008 recording::param::replay_into (replayer
*r
)
3010 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
3011 m_type
->playback_type (),
3015 /* Implementation of recording::rvalue::access_as_rvalue for params.
3016 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3020 recording::param::access_as_rvalue (reproducer
&r
)
3022 return r
.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3023 r
.get_identifier (this));
3026 /* Implementation of recording::lvalue::access_as_lvalue for params.
3027 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3031 recording::param::access_as_lvalue (reproducer
&r
)
3033 return r
.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3034 r
.get_identifier (this));
3037 /* Implementation of recording::memento::write_reproducer for params. */
3040 recording::param::write_reproducer (reproducer
&r
)
3042 const char *id
= r
.make_identifier (this, "param");
3043 r
.write (" gcc_jit_param *%s =\n"
3044 " gcc_jit_context_new_param (%s,\n"
3045 " %s, /* gcc_jit_location *loc */\n"
3046 " %s, /*gcc_jit_type *type */\n"
3047 " %s); /* const char *name */\n",
3049 r
.get_identifier (get_context ()),
3050 r
.get_identifier (m_loc
),
3051 r
.get_identifier_as_type (m_type
),
3052 m_name
->get_debug_string ());
3055 /* The implementation of class gcc::jit::recording::function. */
3057 /* gcc::jit::recording::function's constructor. */
3059 recording::function::function (context
*ctxt
,
3060 recording::location
*loc
,
3061 enum gcc_jit_function_kind kind
,
3063 recording::string
*name
,
3065 recording::param
**params
,
3067 enum built_in_function builtin_id
)
3071 m_return_type (return_type
),
3074 m_is_variadic (is_variadic
),
3075 m_builtin_id (builtin_id
),
3079 for (int i
= 0; i
< num_params
; i
++)
3081 param
*param
= params
[i
];
3084 /* Associate each param with this function.
3086 Verify that the param doesn't already have a function. */
3087 if (param
->get_scope ())
3089 /* We've already rejected attempts to reuse a param between
3090 different functions (within gcc_jit_context_new_function), so
3091 if the param *does* already have a function, it must be being
3092 reused within the params array for this function. We must
3093 produce an error for this reuse (blocking the compile), since
3094 otherwise we'd have an ICE later on. */
3095 gcc_assert (this == param
->get_scope ());
3098 "gcc_jit_context_new_function:"
3099 " parameter %s (type: %s)"
3100 " is used more than once when creating function %s",
3101 param
->get_debug_string (),
3102 param
->get_type ()->get_debug_string (),
3107 /* The normal, non-error case: associate this function with the
3109 param
->set_scope (this);
3112 m_params
.safe_push (param
);
3116 /* Implementation of pure virtual hook recording::memento::replay_into
3117 for recording::function. */
3120 recording::function::replay_into (replayer
*r
)
3122 /* Convert m_params to a vec of playback param. */
3123 auto_vec
<playback::param
*> params
;
3125 recording::param
*param
;
3126 params
.create (m_params
.length ());
3127 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3128 params
.safe_push (param
->playback_param ());
3130 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
3132 m_return_type
->playback_type (),
3139 /* Create a recording::local instance and add it to
3140 the functions's context's list of mementos, and to the function's
3143 Implements the post-error-checking part of
3144 gcc_jit_function_new_local. */
3147 recording::function::new_local (recording::location
*loc
,
3151 local
*result
= new local (this, loc
, type
, new_string (name
));
3152 m_ctxt
->record (result
);
3153 m_locals
.safe_push (result
);
3157 /* Create a recording::block instance and add it to
3158 the functions's context's list of mementos, and to the function's
3161 Implements the post-error-checking part of
3162 gcc_jit_function_new_block. */
3165 recording::function::new_block (const char *name
)
3167 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
3169 recording::block
*result
=
3170 new recording::block (this, m_blocks
.length (), new_string (name
));
3171 m_ctxt
->record (result
);
3172 m_blocks
.safe_push (result
);
3176 /* Override the default implementation of
3177 recording::memento::write_to_dump by dumping a C-like
3178 representation of the function; either like a prototype
3179 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3180 all other kinds of function. */
3183 recording::function::write_to_dump (dump
&d
)
3187 default: gcc_unreachable ();
3188 case GCC_JIT_FUNCTION_EXPORTED
:
3189 case GCC_JIT_FUNCTION_IMPORTED
:
3190 d
.write ("extern ");
3192 case GCC_JIT_FUNCTION_INTERNAL
:
3193 d
.write ("static ");
3195 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
3196 d
.write ("static inline ");
3199 d
.write ("%s\n", m_return_type
->get_debug_string ());
3201 if (d
.update_locations ())
3202 m_loc
= d
.make_location ();
3204 d
.write ("%s (", get_debug_string ());
3207 recording::param
*param
;
3208 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3213 param
->get_type ()->get_debug_string (),
3214 param
->get_debug_string ());
3217 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
3219 d
.write ("; /* (imported) */\n\n");
3229 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
3230 var
->write_to_dump (d
);
3231 if (m_locals
.length ())
3234 /* Write each block: */
3235 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3239 b
->write_to_dump (d
);
3246 /* Pre-compilation validation of a function, for those things we can't
3247 check until the context is (supposedly) fully-populated. */
3250 recording::function::validate ()
3252 /* Complain about empty functions with non-void return type. */
3253 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
3254 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
3255 if (0 == m_blocks
.length ())
3256 m_ctxt
->add_error (m_loc
,
3257 "function %s returns non-void (type: %s)"
3258 " but has no blocks",
3259 get_debug_string (),
3260 m_return_type
->get_debug_string ());
3262 /* Check that all blocks are terminated. */
3263 int num_invalid_blocks
= 0;
3268 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3269 if (!b
->validate ())
3270 num_invalid_blocks
++;
3273 /* Check that all blocks are reachable. */
3274 if (m_blocks
.length () > 0 && 0 == num_invalid_blocks
)
3276 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3277 flag, starting at the initial block. */
3278 auto_vec
<block
*> worklist (m_blocks
.length ());
3279 worklist
.safe_push (m_blocks
[0]);
3280 while (worklist
.length () > 0)
3282 block
*b
= worklist
.pop ();
3283 b
->m_is_reachable
= true;
3285 /* Add successor blocks that aren't yet marked to the worklist. */
3286 /* We checked that each block has a terminating statement above . */
3287 block
*next1
, *next2
;
3288 int n
= b
->get_successor_blocks (&next1
, &next2
);
3294 if (!next2
->m_is_reachable
)
3295 worklist
.safe_push (next2
);
3298 if (!next1
->m_is_reachable
)
3299 worklist
.safe_push (next1
);
3306 /* Now complain about any blocks that haven't been marked. */
3310 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3311 if (!b
->m_is_reachable
)
3312 m_ctxt
->add_error (b
->get_loc (),
3313 "unreachable block: %s",
3314 b
->get_debug_string ());
3319 /* Implements the post-error-checking part of
3320 gcc_jit_function_dump_to_dot. */
3323 recording::function::dump_to_dot (const char *path
)
3325 FILE *fp
= fopen (path
, "w");
3329 pretty_printer the_pp
;
3330 the_pp
.buffer
->stream
= fp
;
3332 pretty_printer
*pp
= &the_pp
;
3335 "digraph %s {\n", get_debug_string ());
3341 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3342 b
->dump_to_dot (pp
);
3349 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3350 b
->dump_edges_to_dot (pp
);
3353 pp_printf (pp
, "}\n");
3358 /* Implementation of recording::memento::make_debug_string for
3362 recording::function::make_debug_string ()
3367 /* A table of enum gcc_jit_function_kind values expressed in string
3370 static const char * const names_of_function_kinds
[] = {
3371 "GCC_JIT_FUNCTION_EXPORTED",
3372 "GCC_JIT_FUNCTION_INTERNAL",
3373 "GCC_JIT_FUNCTION_IMPORTED",
3374 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3377 /* Implementation of recording::memento::write_reproducer for functions. */
3380 recording::function::write_reproducer (reproducer
&r
)
3382 const char *id
= r
.make_identifier (this, "func");
3386 r
.write (" gcc_jit_function *%s =\n"
3387 " gcc_jit_context_get_builtin_function (%s,\n"
3390 r
.get_identifier (get_context ()),
3391 m_name
->get_debug_string ());
3394 const char *params_id
= r
.make_tmp_identifier ("params_for", this);
3395 r
.write (" gcc_jit_param *%s[%i] = {\n",
3397 m_params
.length ());
3400 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3401 r
.write (" %s,\n", r
.get_identifier (param
));
3403 r
.write (" gcc_jit_function *%s =\n"
3404 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3405 " %s, /* gcc_jit_location *loc */\n"
3406 " %s, /* enum gcc_jit_function_kind kind */\n"
3407 " %s, /* gcc_jit_type *return_type */\n"
3408 " %s, /* const char *name */\n"
3409 " %i, /* int num_params */\n"
3410 " %s, /* gcc_jit_param **params */\n"
3411 " %i); /* int is_variadic */\n",
3413 r
.get_identifier (get_context ()),
3414 r
.get_identifier (m_loc
),
3415 names_of_function_kinds
[m_kind
],
3416 r
.get_identifier_as_type (m_return_type
),
3417 m_name
->get_debug_string (),
3424 /* The implementation of class gcc::jit::recording::block. */
3426 /* Create a recording::eval instance and add it to
3427 the block's context's list of mementos, and to the block's
3430 Implements the heart of gcc_jit_block_add_eval. */
3432 recording::statement
*
3433 recording::block::add_eval (recording::location
*loc
,
3434 recording::rvalue
*rvalue
)
3436 statement
*result
= new eval (this, loc
, rvalue
);
3437 m_ctxt
->record (result
);
3438 m_statements
.safe_push (result
);
3442 /* Create a recording::assignment instance and add it to
3443 the block's context's list of mementos, and to the block's
3446 Implements the heart of gcc_jit_block_add_assignment. */
3448 recording::statement
*
3449 recording::block::add_assignment (recording::location
*loc
,
3450 recording::lvalue
*lvalue
,
3451 recording::rvalue
*rvalue
)
3453 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
3454 m_ctxt
->record (result
);
3455 m_statements
.safe_push (result
);
3459 /* Create a recording::assignment_op instance and add it to
3460 the block's context's list of mementos, and to the block's
3463 Implements the heart of gcc_jit_block_add_assignment_op. */
3465 recording::statement
*
3466 recording::block::add_assignment_op (recording::location
*loc
,
3467 recording::lvalue
*lvalue
,
3468 enum gcc_jit_binary_op op
,
3469 recording::rvalue
*rvalue
)
3471 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
3472 m_ctxt
->record (result
);
3473 m_statements
.safe_push (result
);
3477 /* Create a recording::comment instance and add it to
3478 the block's context's list of mementos, and to the block's
3481 Implements the heart of gcc_jit_block_add_comment. */
3483 recording::statement
*
3484 recording::block::add_comment (recording::location
*loc
,
3487 statement
*result
= new comment (this, loc
, new_string (text
));
3488 m_ctxt
->record (result
);
3489 m_statements
.safe_push (result
);
3493 /* Create a recording::end_with_conditional instance and add it to
3494 the block's context's list of mementos, and to the block's
3497 Implements the heart of gcc_jit_block_end_with_conditional. */
3499 recording::statement
*
3500 recording::block::end_with_conditional (recording::location
*loc
,
3501 recording::rvalue
*boolval
,
3502 recording::block
*on_true
,
3503 recording::block
*on_false
)
3505 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
3506 m_ctxt
->record (result
);
3507 m_statements
.safe_push (result
);
3508 m_has_been_terminated
= true;
3512 /* Create a recording::end_with_jump instance and add it to
3513 the block's context's list of mementos, and to the block's
3516 Implements the heart of gcc_jit_block_end_with_jump. */
3518 recording::statement
*
3519 recording::block::end_with_jump (recording::location
*loc
,
3520 recording::block
*target
)
3522 statement
*result
= new jump (this, loc
, target
);
3523 m_ctxt
->record (result
);
3524 m_statements
.safe_push (result
);
3525 m_has_been_terminated
= true;
3529 /* Create a recording::end_with_return instance and add it to
3530 the block's context's list of mementos, and to the block's
3533 Implements the post-error-checking parts of
3534 gcc_jit_block_end_with_return and
3535 gcc_jit_block_end_with_void_return. */
3537 recording::statement
*
3538 recording::block::end_with_return (recording::location
*loc
,
3539 recording::rvalue
*rvalue
)
3541 /* This is used by both gcc_jit_function_add_return and
3542 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3543 the former and NULL for the latter. */
3544 statement
*result
= new return_ (this, loc
, rvalue
);
3545 m_ctxt
->record (result
);
3546 m_statements
.safe_push (result
);
3547 m_has_been_terminated
= true;
3551 /* Override the default implementation of
3552 recording::memento::write_to_dump for blocks by writing
3553 an unindented block name as a label, followed by the indented
3563 recording::block::write_to_dump (dump
&d
)
3565 d
.write ("%s:\n", get_debug_string ());
3569 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
3570 s
->write_to_dump (d
);
3573 /* Validate a block by ensuring that it has been terminated. */
3576 recording::block::validate ()
3578 /* Check for termination. */
3579 if (!has_been_terminated ())
3581 statement
*stmt
= get_last_statement ();
3582 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
3583 m_func
->get_context ()->add_error (loc
,
3584 "unterminated block in %s: %s",
3585 m_func
->get_debug_string (),
3586 get_debug_string ());
3593 /* Get the source-location of a block by using that of the first
3594 statement within it, if any. */
3596 recording::location
*
3597 recording::block::get_loc () const
3599 recording::statement
*stmt
= get_first_statement ();
3601 return stmt
->get_loc ();
3606 /* Get the first statement within a block, if any. */
3608 recording::statement
*
3609 recording::block::get_first_statement () const
3611 if (m_statements
.length ())
3612 return m_statements
[0];
3617 /* Get the last statement within a block, if any. */
3619 recording::statement
*
3620 recording::block::get_last_statement () const
3622 if (m_statements
.length ())
3623 return m_statements
[m_statements
.length () - 1];
3628 /* Assuming that this block has been terminated, get the number of
3629 successor blocks, which will be 0, 1 or 2, for return, unconditional
3630 jump, and conditional jump respectively.
3631 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
3632 is written to NEXT1, and the second (if any) to NEXT2.
3634 Used when validating functions, and when dumping dot representations
3638 recording::block::get_successor_blocks (block
**next1
, block
**next2
) const
3640 gcc_assert (m_has_been_terminated
);
3643 statement
*last_statement
= get_last_statement ();
3644 gcc_assert (last_statement
);
3645 return last_statement
->get_successor_blocks (next1
, next2
);
3648 /* Implementation of pure virtual hook recording::memento::replay_into
3649 for recording::block. */
3652 recording::block::replay_into (replayer
*)
3654 set_playback_obj (m_func
->playback_function ()
3655 ->new_block (playback_string (m_name
)));
3658 /* Implementation of recording::memento::make_debug_string for
3662 recording::block::make_debug_string ()
3667 return string::from_printf (m_ctxt
,
3668 "<UNNAMED BLOCK %p>",
3672 /* Implementation of recording::memento::write_reproducer for blocks. */
3675 recording::block::write_reproducer (reproducer
&r
)
3677 const char *id
= r
.make_identifier (this, "block");
3678 r
.write (" gcc_jit_block *%s =\n"
3679 " gcc_jit_function_new_block (%s, %s);\n",
3681 r
.get_identifier (m_func
),
3682 m_name
? m_name
->get_debug_string () : "NULL");
3685 /* Dump a block in graphviz form into PP, capturing the block name (if
3686 any) and the statements. */
3689 recording::block::dump_to_dot (pretty_printer
*pp
)
3693 "[shape=record,style=filled,fillcolor=white,label=\"{"),
3695 pp_write_text_to_stream (pp
);
3698 pp_string (pp
, m_name
->c_str ());
3699 pp_string (pp
, ":");
3701 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
3706 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
3708 pp_string (pp
, s
->get_debug_string ());
3710 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
3718 /* Dump the out-edges of the block in graphviz form into PP. */
3721 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
3724 int num_succs
= get_successor_blocks (&next
[0], &next
[1]);
3725 for (int i
= 0; i
< num_succs
; i
++)
3727 "\tblock_%d:s -> block_%d:n;\n",
3728 m_index
, next
[i
]->m_index
);
3731 /* The implementation of class gcc::jit::recording::global. */
3733 /* Implementation of pure virtual hook recording::memento::replay_into
3734 for recording::global. */
3737 recording::global::replay_into (replayer
*r
)
3739 set_playback_obj (r
->new_global (playback_location (r
, m_loc
),
3741 m_type
->playback_type (),
3742 playback_string (m_name
)));
3745 /* Override the default implementation of
3746 recording::memento::write_to_dump for globals.
3747 This will be of the form:
3749 GCC_JIT_GLOBAL_EXPORTED:
3753 GCC_JIT_GLOBAL_INTERNAL:
3755 e.g. "static int foo;"
3757 GCC_JIT_GLOBAL_IMPORTED:
3759 e.g. "extern int foo;"
3761 These are written to the top of the dump by
3762 recording::context::dump_to_file. */
3765 recording::global::write_to_dump (dump
&d
)
3767 if (d
.update_locations ())
3768 m_loc
= d
.make_location ();
3775 case GCC_JIT_GLOBAL_EXPORTED
:
3778 case GCC_JIT_GLOBAL_INTERNAL
:
3779 d
.write ("static ");
3782 case GCC_JIT_GLOBAL_IMPORTED
:
3783 d
.write ("extern ");
3786 d
.write ("%s %s;\n",
3787 m_type
->get_debug_string (),
3788 get_debug_string ());
3791 /* A table of enum gcc_jit_global_kind values expressed in string
3794 static const char * const global_kind_reproducer_strings
[] = {
3795 "GCC_JIT_GLOBAL_EXPORTED",
3796 "GCC_JIT_GLOBAL_INTERNAL",
3797 "GCC_JIT_GLOBAL_IMPORTED"
3800 /* Implementation of recording::memento::write_reproducer for globals. */
3803 recording::global::write_reproducer (reproducer
&r
)
3805 const char *id
= r
.make_identifier (this, "block");
3806 r
.write (" gcc_jit_lvalue *%s =\n"
3807 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
3808 " %s, /* gcc_jit_location *loc */\n"
3809 " %s, /* enum gcc_jit_global_kind kind */\n"
3810 " %s, /* gcc_jit_type *type */\n"
3811 " %s); /* const char *name */\n",
3813 r
.get_identifier (get_context ()),
3814 r
.get_identifier (m_loc
),
3815 global_kind_reproducer_strings
[m_kind
],
3816 r
.get_identifier_as_type (get_type ()),
3817 m_name
->get_debug_string ());
3820 /* The implementation of the various const-handling classes:
3821 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
3823 /* Explicit specialization of the various mementos we're interested in. */
3824 template class recording::memento_of_new_rvalue_from_const
<int>;
3825 template class recording::memento_of_new_rvalue_from_const
<long>;
3826 template class recording::memento_of_new_rvalue_from_const
<double>;
3827 template class recording::memento_of_new_rvalue_from_const
<void *>;
3829 /* Implementation of the pure virtual hook recording::memento::replay_into
3830 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
3832 template <typename HOST_TYPE
>
3835 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
3838 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
3842 /* The make_debug_string and write_reproducer methods vary between the
3844 memento_of_new_rvalue_from_const <HOST_TYPE>
3845 classes, so we explicitly write specializations of them.
3847 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
3848 namespaces are written out explicitly, which is why most of this file
3849 doesn't abbreviate things by entering the "recording" namespace.
3851 However, these specializations are required to be in the same namespace
3852 as the template, hence we now have to enter the gcc::jit::recording
3858 /* The make_debug_string specialization for <int>, which renders it as
3859 (TARGET_TYPE)LITERAL
3865 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
3867 return string::from_printf (m_ctxt
,
3869 m_type
->get_debug_string (),
3873 /* The write_reproducer specialization for <int>. */
3877 memento_of_new_rvalue_from_const
<int>::write_reproducer (reproducer
&r
)
3879 const char *id
= r
.make_identifier (this, "rvalue");
3880 r
.write (" gcc_jit_rvalue *%s =\n"
3881 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
3882 " %s, /* gcc_jit_type *numeric_type */\n"
3883 " %i); /* int value */\n",
3885 r
.get_identifier (get_context ()),
3886 r
.get_identifier_as_type (m_type
),
3890 /* The make_debug_string specialization for <long>, rendering it as
3891 (TARGET_TYPE)LITERAL
3897 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
3899 return string::from_printf (m_ctxt
,
3901 m_type
->get_debug_string (),
3905 /* The write_reproducer specialization for <long>. */
3909 recording::memento_of_new_rvalue_from_const
<long>::write_reproducer (reproducer
&r
)
3911 const char *id
= r
.make_identifier (this, "rvalue");
3913 /* We have to special-case LONG_MIN, since e.g.
3914 -9223372036854775808L
3916 -(9223372036854775808L)
3918 error: integer constant is so large that it is unsigned [-Werror]
3919 Workaround this by writing (LONG_MIN + 1) - 1. */
3920 if (m_value
== LONG_MIN
)
3922 r
.write (" gcc_jit_rvalue *%s =\n"
3923 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
3924 " %s, /* gcc_jit_type *numeric_type */\n"
3925 " %ldL - 1); /* long value */\n",
3927 r
.get_identifier (get_context ()),
3928 r
.get_identifier_as_type (m_type
),
3933 r
.write (" gcc_jit_rvalue *%s =\n"
3934 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
3935 " %s, /* gcc_jit_type *numeric_type */\n"
3936 " %ldL); /* long value */\n",
3938 r
.get_identifier (get_context ()),
3939 r
.get_identifier_as_type (m_type
),
3943 /* The make_debug_string specialization for <double>, rendering it as
3944 (TARGET_TYPE)LITERAL
3950 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
3952 return string::from_printf (m_ctxt
,
3954 m_type
->get_debug_string (),
3958 /* The write_reproducer specialization for <double>. */
3962 recording::memento_of_new_rvalue_from_const
<double>::write_reproducer (reproducer
&r
)
3964 const char *id
= r
.make_identifier (this, "rvalue");
3965 r
.write (" gcc_jit_rvalue *%s =\n"
3966 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
3967 " %s, /* gcc_jit_type *numeric_type */\n"
3968 " %f); /* double value */\n",
3970 r
.get_identifier (get_context ()),
3971 r
.get_identifier_as_type (m_type
),
3975 /* The make_debug_string specialization for <void *>, rendering it as
3980 Zero is rendered as NULL e.g.
3985 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
3987 if (m_value
!= NULL
)
3988 return string::from_printf (m_ctxt
,
3990 m_type
->get_debug_string (), m_value
);
3992 return string::from_printf (m_ctxt
,
3994 m_type
->get_debug_string ());
3997 /* Implementation of recording::memento::write_reproducer for <void *>
4002 memento_of_new_rvalue_from_const
<void *>::write_reproducer (reproducer
&r
)
4004 const char *id
= r
.make_identifier (this, "rvalue");
4006 r
.write (" gcc_jit_rvalue *%s =\n"
4007 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4008 " %s, /* gcc_jit_type *pointer_type */\n"
4009 " (void *)%p); /* void *value */\n",
4011 r
.get_identifier (get_context ()),
4012 r
.get_identifier_as_type (m_type
),
4015 r
.write (" gcc_jit_rvalue *%s =\n"
4016 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4017 " %s); /* gcc_jit_type *pointer_type */\n",
4019 r
.get_identifier (get_context ()),
4020 r
.get_identifier_as_type (m_type
));
4023 /* We're done specializing make_debug_string and write_reproducer, so we
4024 can exit the gcc::jit::recording namespace. */
4026 } // namespace recording
4028 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4030 /* Implementation of pure virtual hook recording::memento::replay_into
4031 for recording::memento_of_new_string_literal. */
4034 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
4036 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
4039 /* Implementation of recording::memento::make_debug_string for
4043 recording::memento_of_new_string_literal::make_debug_string ()
4045 return string::from_printf (m_ctxt
,
4047 m_value
->get_debug_string ());
4050 /* Implementation of recording::memento::write_reproducer for string literal
4054 recording::memento_of_new_string_literal::write_reproducer (reproducer
&r
)
4056 const char *id
= r
.make_identifier (this, "rvalue");
4057 r
.write (" gcc_jit_rvalue *%s =\n"
4058 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4059 " %s); /* const char *value */\n",
4061 r
.get_identifier (get_context ()),
4062 m_value
->get_debug_string ());
4065 /* The implementation of class gcc::jit::recording::unary_op. */
4067 /* Implementation of pure virtual hook recording::memento::replay_into
4068 for recording::unary_op. */
4071 recording::unary_op::replay_into (replayer
*r
)
4073 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
4075 get_type ()->playback_type (),
4076 m_a
->playback_rvalue ()));
4079 /* Implementation of pure virtual hook recording::rvalue::visit_children
4080 for recording::unary_op. */
4082 recording::unary_op::visit_children (rvalue_visitor
*v
)
4087 /* Implementation of recording::memento::make_debug_string for
4090 static const char * const unary_op_strings
[] = {
4091 "-", /* GCC_JIT_UNARY_OP_MINUS */
4092 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4093 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4094 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4098 recording::unary_op::make_debug_string ()
4100 return string::from_printf (m_ctxt
,
4102 unary_op_strings
[m_op
],
4103 m_a
->get_debug_string ());
4106 static const char * const unary_op_reproducer_strings
[] = {
4107 "GCC_JIT_UNARY_OP_MINUS",
4108 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4109 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4110 "GCC_JIT_UNARY_OP_ABS"
4113 /* Implementation of recording::memento::write_reproducer for unary ops. */
4116 recording::unary_op::write_reproducer (reproducer
&r
)
4118 const char *id
= r
.make_identifier (this, "rvalue");
4119 r
.write (" gcc_jit_rvalue *%s =\n"
4120 " gcc_jit_context_new_unary_op (%s,\n"
4121 " %s, /* gcc_jit_location *loc */\n"
4122 " %s, /* enum gcc_jit_unary_op op */\n"
4123 " %s, /* gcc_jit_type *result_type */\n"
4124 " %s); /* gcc_jit_rvalue *a */\n",
4126 r
.get_identifier (get_context ()),
4127 r
.get_identifier (m_loc
),
4128 unary_op_reproducer_strings
[m_op
],
4129 r
.get_identifier_as_type (get_type ()),
4130 r
.get_identifier_as_rvalue (m_a
));
4133 /* The implementation of class gcc::jit::recording::binary_op. */
4135 /* Implementation of pure virtual hook recording::memento::replay_into
4136 for recording::binary_op. */
4139 recording::binary_op::replay_into (replayer
*r
)
4141 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
4143 get_type ()->playback_type (),
4144 m_a
->playback_rvalue (),
4145 m_b
->playback_rvalue ()));
4148 /* Implementation of pure virtual hook recording::rvalue::visit_children
4149 for recording::binary_op. */
4151 recording::binary_op::visit_children (rvalue_visitor
*v
)
4157 /* Implementation of recording::memento::make_debug_string for
4160 static const char * const binary_op_strings
[] = {
4161 "+", /* GCC_JIT_BINARY_OP_PLUS */
4162 "-", /* GCC_JIT_BINARY_OP_MINUS */
4163 "*", /* GCC_JIT_BINARY_OP_MULT */
4164 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4165 "%", /* GCC_JIT_BINARY_OP_MODULO */
4166 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4167 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4168 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4169 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4170 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4171 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4172 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4176 recording::binary_op::make_debug_string ()
4178 return string::from_printf (m_ctxt
,
4180 m_a
->get_debug_string (),
4181 binary_op_strings
[m_op
],
4182 m_b
->get_debug_string ());
4185 static const char * const binary_op_reproducer_strings
[] = {
4186 "GCC_JIT_BINARY_OP_PLUS",
4187 "GCC_JIT_BINARY_OP_MINUS",
4188 "GCC_JIT_BINARY_OP_MULT",
4189 "GCC_JIT_BINARY_OP_DIVIDE",
4190 "GCC_JIT_BINARY_OP_MODULO",
4191 "GCC_JIT_BINARY_OP_BITWISE_AND",
4192 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4193 "GCC_JIT_BINARY_OP_BITWISE_OR",
4194 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4195 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4196 "GCC_JIT_BINARY_OP_LSHIFT",
4197 "GCC_JIT_BINARY_OP_RSHIFT"
4200 /* Implementation of recording::memento::write_reproducer for binary ops. */
4203 recording::binary_op::write_reproducer (reproducer
&r
)
4205 const char *id
= r
.make_identifier (this, "rvalue");
4206 r
.write (" gcc_jit_rvalue *%s =\n"
4207 " gcc_jit_context_new_binary_op (%s,\n"
4208 " %s, /* gcc_jit_location *loc */\n"
4209 " %s, /* enum gcc_jit_binary_op op */\n"
4210 " %s, /* gcc_jit_type *result_type */\n"
4211 " %s, /* gcc_jit_rvalue *a */\n"
4212 " %s); /* gcc_jit_rvalue *b */\n",
4214 r
.get_identifier (get_context ()),
4215 r
.get_identifier (m_loc
),
4216 binary_op_reproducer_strings
[m_op
],
4217 r
.get_identifier_as_type (get_type ()),
4218 r
.get_identifier_as_rvalue (m_a
),
4219 r
.get_identifier_as_rvalue (m_b
));
4222 /* The implementation of class gcc::jit::recording::comparison. */
4224 /* Implementation of recording::memento::make_debug_string for
4227 static const char * const comparison_strings
[] =
4229 "==", /* GCC_JIT_COMPARISON_EQ */
4230 "!=", /* GCC_JIT_COMPARISON_NE */
4231 "<", /* GCC_JIT_COMPARISON_LT */
4232 "<=", /* GCC_JIT_COMPARISON_LE */
4233 ">", /* GCC_JIT_COMPARISON_GT */
4234 ">=", /* GCC_JIT_COMPARISON_GE */
4238 recording::comparison::make_debug_string ()
4240 return string::from_printf (m_ctxt
,
4242 m_a
->get_debug_string (),
4243 comparison_strings
[m_op
],
4244 m_b
->get_debug_string ());
4247 /* A table of enum gcc_jit_comparison values expressed in string
4250 static const char * const comparison_reproducer_strings
[] =
4252 "GCC_JIT_COMPARISON_EQ",
4253 "GCC_JIT_COMPARISON_NE",
4254 "GCC_JIT_COMPARISON_LT",
4255 "GCC_JIT_COMPARISON_LE",
4256 "GCC_JIT_COMPARISON_GT",
4257 "GCC_JIT_COMPARISON_GE"
4260 /* Implementation of recording::memento::write_reproducer for comparisons. */
4263 recording::comparison::write_reproducer (reproducer
&r
)
4265 const char *id
= r
.make_identifier (this, "rvalue");
4266 r
.write (" gcc_jit_rvalue *%s =\n"
4267 " gcc_jit_context_new_comparison (%s,\n"
4268 " %s, /* gcc_jit_location *loc */\n"
4269 " %s, /* enum gcc_jit_comparison op */\n"
4270 " %s, /* gcc_jit_rvalue *a */\n"
4271 " %s); /* gcc_jit_rvalue *b */\n",
4273 r
.get_identifier (get_context ()),
4274 r
.get_identifier (m_loc
),
4275 comparison_reproducer_strings
[m_op
],
4276 r
.get_identifier_as_rvalue (m_a
),
4277 r
.get_identifier_as_rvalue (m_b
));
4280 /* Implementation of pure virtual hook recording::memento::replay_into
4281 for recording::comparison. */
4284 recording::comparison::replay_into (replayer
*r
)
4286 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
4288 m_a
->playback_rvalue (),
4289 m_b
->playback_rvalue ()));
4292 /* Implementation of pure virtual hook recording::rvalue::visit_children
4293 for recording::comparison. */
4296 recording::comparison::visit_children (rvalue_visitor
*v
)
4302 /* Implementation of pure virtual hook recording::memento::replay_into
4303 for recording::cast. */
4306 recording::cast::replay_into (replayer
*r
)
4308 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
4309 m_rvalue
->playback_rvalue (),
4310 get_type ()->playback_type ()));
4313 /* Implementation of pure virtual hook recording::rvalue::visit_children
4314 for recording::cast. */
4316 recording::cast::visit_children (rvalue_visitor
*v
)
4318 v
->visit (m_rvalue
);
4321 /* Implementation of recording::memento::make_debug_string for
4325 recording::cast::make_debug_string ()
4327 return string::from_printf (m_ctxt
,
4329 get_type ()->get_debug_string (),
4330 m_rvalue
->get_debug_string ());
4333 /* Implementation of recording::memento::write_reproducer for casts. */
4336 recording::cast::write_reproducer (reproducer
&r
)
4338 const char *id
= r
.make_identifier (this, "rvalue");
4339 r
.write (" gcc_jit_rvalue *%s =\n"
4340 " gcc_jit_context_new_cast (%s,\n"
4341 " %s, /* gcc_jit_location *loc */\n"
4342 " %s, /* gcc_jit_rvalue *rvalue */\n"
4343 " %s); /* gcc_jit_type *type */\n",
4345 r
.get_identifier (get_context ()),
4346 r
.get_identifier (m_loc
),
4347 r
.get_identifier_as_rvalue (m_rvalue
),
4348 r
.get_identifier_as_type (get_type ()));
4351 /* The implementation of class gcc::jit::recording::call. */
4353 /* The constructor for gcc::jit::recording::call. */
4355 recording::call::call (recording::context
*ctxt
,
4356 recording::location
*loc
,
4357 recording::function
*func
,
4360 : rvalue (ctxt
, loc
, func
->get_return_type ()),
4364 for (int i
= 0; i
< numargs
; i
++)
4365 m_args
.safe_push (args
[i
]);
4368 /* Implementation of pure virtual hook recording::memento::replay_into
4369 for recording::call. */
4372 recording::call::replay_into (replayer
*r
)
4374 auto_vec
<playback::rvalue
*> playback_args
;
4375 playback_args
.create (m_args
.length ());
4376 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4377 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
4379 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
4380 m_func
->playback_function (),
4384 /* Implementation of pure virtual hook recording::rvalue::visit_children
4385 for recording::call. */
4388 recording::call::visit_children (rvalue_visitor
*v
)
4390 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4391 v
->visit (m_args
[i
]);
4394 /* Implementation of recording::memento::make_debug_string for
4398 recording::call::make_debug_string ()
4400 /* First, build a buffer for the arguments. */
4401 /* Calculate length of said buffer. */
4402 size_t sz
= 1; /* nil terminator */
4403 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4405 sz
+= strlen (m_args
[i
]->get_debug_string ());
4406 sz
+= 2; /* ", " separator */
4409 /* Now allocate and populate the buffer. */
4410 char *argbuf
= new char[sz
];
4413 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4415 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string ());
4416 len
+= strlen (m_args
[i
]->get_debug_string ());
4417 if (i
+ 1 < m_args
.length ())
4419 strcpy (argbuf
+ len
, ", ");
4425 /* ...and use it to get the string for the call as a whole. */
4426 string
*result
= string::from_printf (m_ctxt
,
4428 m_func
->get_debug_string (),
4437 recording::call::write_reproducer (reproducer
&r
)
4439 const char *id
= r
.make_identifier (this, "call");
4440 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
4441 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4444 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4445 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
4447 r
.write (" gcc_jit_rvalue *%s =\n"
4448 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4449 " %s, /* gcc_jit_location *loc */\n"
4450 " %s, /* gcc_jit_function *func */\n"
4451 " %i, /* int numargs */ \n"
4452 " %s); /* gcc_jit_rvalue **args*/\n",
4454 r
.get_identifier (get_context ()),
4455 r
.get_identifier (m_loc
),
4456 r
.get_identifier (m_func
),
4461 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4463 /* The constructor for recording::call_through_ptr. */
4465 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
4466 recording::location
*loc
,
4467 recording::rvalue
*fn_ptr
,
4470 : rvalue (ctxt
, loc
,
4471 fn_ptr
->get_type ()->dereference ()
4472 ->as_a_function_type ()->get_return_type ()),
4476 for (int i
= 0; i
< numargs
; i
++)
4477 m_args
.safe_push (args
[i
]);
4480 /* Implementation of pure virtual hook recording::memento::replay_into
4481 for recording::call_through_ptr. */
4484 recording::call_through_ptr::replay_into (replayer
*r
)
4486 auto_vec
<playback::rvalue
*> playback_args
;
4487 playback_args
.create (m_args
.length ());
4488 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4489 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
4491 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
4492 m_fn_ptr
->playback_rvalue (),
4496 /* Implementation of pure virtual hook recording::rvalue::visit_children
4497 for recording::call_through_ptr. */
4500 recording::call_through_ptr::visit_children (rvalue_visitor
*v
)
4502 v
->visit (m_fn_ptr
);
4503 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4504 v
->visit (m_args
[i
]);
4507 /* Implementation of recording::memento::make_debug_string for
4508 calls through function ptrs. */
4511 recording::call_through_ptr::make_debug_string ()
4513 /* First, build a buffer for the arguments. */
4514 /* Calculate length of said buffer. */
4515 size_t sz
= 1; /* nil terminator */
4516 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4518 sz
+= strlen (m_args
[i
]->get_debug_string ());
4519 sz
+= 2; /* ", " separator */
4522 /* Now allocate and populate the buffer. */
4523 char *argbuf
= new char[sz
];
4526 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4528 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string ());
4529 len
+= strlen (m_args
[i
]->get_debug_string ());
4530 if (i
+ 1 < m_args
.length ())
4532 strcpy (argbuf
+ len
, ", ");
4538 /* ...and use it to get the string for the call as a whole. */
4539 string
*result
= string::from_printf (m_ctxt
,
4541 m_fn_ptr
->get_debug_string (),
4549 /* Implementation of recording::memento::write_reproducer for
4550 call_through_ptr. */
4553 recording::call_through_ptr::write_reproducer (reproducer
&r
)
4555 const char *id
= r
.make_identifier (this, "call");
4556 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
4557 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4560 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4561 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
4563 r
.write (" gcc_jit_rvalue *%s =\n"
4564 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
4565 " %s, /* gcc_jit_location *loc */\n"
4566 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
4567 " %i, /* int numargs */ \n"
4568 " %s); /* gcc_jit_rvalue **args*/\n",
4570 r
.get_identifier (get_context ()),
4571 r
.get_identifier (m_loc
),
4572 r
.get_identifier_as_rvalue (m_fn_ptr
),
4577 /* The implementation of class gcc::jit::recording::array_access. */
4579 /* Implementation of pure virtual hook recording::memento::replay_into
4580 for recording::array_access. */
4583 recording::array_access::replay_into (replayer
*r
)
4586 r
->new_array_access (playback_location (r
, m_loc
),
4587 m_ptr
->playback_rvalue (),
4588 m_index
->playback_rvalue ()));
4591 /* Implementation of pure virtual hook recording::rvalue::visit_children
4592 for recording::array_access. */
4595 recording::array_access::visit_children (rvalue_visitor
*v
)
4601 /* Implementation of recording::memento::make_debug_string for
4605 recording::array_access::make_debug_string ()
4607 return string::from_printf (m_ctxt
,
4609 m_ptr
->get_debug_string (),
4610 m_index
->get_debug_string ());
4613 /* Implementation of recording::memento::write_reproducer for
4617 recording::array_access::write_reproducer (reproducer
&r
)
4619 const char *id
= r
.make_identifier (this, "lvalue");
4620 r
.write (" gcc_jit_lvalue *%s = \n"
4621 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
4622 " %s, /*gcc_jit_location *loc */\n"
4623 " %s, /* gcc_jit_rvalue *ptr */\n"
4624 " %s); /* gcc_jit_rvalue *index */\n",
4626 r
.get_identifier (get_context ()),
4627 r
.get_identifier (m_loc
),
4628 r
.get_identifier_as_rvalue (m_ptr
),
4629 r
.get_identifier_as_rvalue (m_index
));
4632 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
4634 /* Implementation of pure virtual hook recording::memento::replay_into
4635 for recording::access_field_of_lvalue. */
4638 recording::access_field_of_lvalue::replay_into (replayer
*r
)
4641 m_lvalue
->playback_lvalue ()
4642 ->access_field (playback_location (r
, m_loc
),
4643 m_field
->playback_field ()));
4647 /* Implementation of pure virtual hook recording::rvalue::visit_children
4648 for recording::access_field_of_lvalue. */
4651 recording::access_field_of_lvalue::visit_children (rvalue_visitor
*v
)
4653 v
->visit (m_lvalue
);
4656 /* Implementation of recording::memento::make_debug_string for
4657 accessing a field of an lvalue. */
4660 recording::access_field_of_lvalue::make_debug_string ()
4662 return string::from_printf (m_ctxt
,
4664 m_lvalue
->get_debug_string (),
4665 m_field
->get_debug_string ());
4668 /* Implementation of recording::memento::write_reproducer for
4669 access_field_of_lvalue. */
4672 recording::access_field_of_lvalue::write_reproducer (reproducer
&r
)
4674 const char *id
= r
.make_identifier (this, "lvalue");
4675 r
.write (" gcc_jit_lvalue *%s = \n"
4676 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
4677 " %s, /*gcc_jit_location *loc */\n"
4680 r
.get_identifier_as_lvalue (m_lvalue
),
4681 r
.get_identifier (m_loc
),
4682 r
.get_identifier (m_field
));
4685 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
4687 /* Implementation of pure virtual hook recording::memento::replay_into
4688 for recording::access_field_rvalue. */
4691 recording::access_field_rvalue::replay_into (replayer
*r
)
4694 m_rvalue
->playback_rvalue ()
4695 ->access_field (playback_location (r
, m_loc
),
4696 m_field
->playback_field ()));
4699 /* Implementation of pure virtual hook recording::rvalue::visit_children
4700 for recording::access_field_rvalue. */
4703 recording::access_field_rvalue::visit_children (rvalue_visitor
*v
)
4705 v
->visit (m_rvalue
);
4708 /* Implementation of recording::memento::make_debug_string for
4709 accessing a field of an rvalue. */
4712 recording::access_field_rvalue::make_debug_string ()
4714 return string::from_printf (m_ctxt
,
4716 m_rvalue
->get_debug_string (),
4717 m_field
->get_debug_string ());
4720 /* Implementation of recording::memento::write_reproducer for
4721 access_field_rvalue. */
4724 recording::access_field_rvalue::write_reproducer (reproducer
&r
)
4726 const char *id
= r
.make_identifier (this, "rvalue");
4727 r
.write (" gcc_jit_rvalue *%s = \n"
4728 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
4729 " %s, /*gcc_jit_location *loc */\n"
4732 r
.get_identifier_as_rvalue (m_rvalue
),
4733 r
.get_identifier (m_loc
),
4734 r
.get_identifier (m_field
));
4737 /* The implementation of class
4738 gcc::jit::recording::dereference_field_rvalue. */
4740 /* Implementation of pure virtual hook recording::memento::replay_into
4741 for recording::dereference_field_rvalue. */
4744 recording::dereference_field_rvalue::replay_into (replayer
*r
)
4747 m_rvalue
->playback_rvalue ()->
4748 dereference_field (playback_location (r
, m_loc
),
4749 m_field
->playback_field ()));
4752 /* Implementation of pure virtual hook recording::rvalue::visit_children
4753 for recording::dereference_field_rvalue. */
4756 recording::dereference_field_rvalue::visit_children (rvalue_visitor
*v
)
4758 v
->visit (m_rvalue
);
4761 /* Implementation of recording::memento::make_debug_string for
4762 dereferencing a field of an rvalue. */
4765 recording::dereference_field_rvalue::make_debug_string ()
4767 return string::from_printf (m_ctxt
,
4769 m_rvalue
->get_debug_string (),
4770 m_field
->get_debug_string ());
4773 /* Implementation of recording::memento::write_reproducer for
4774 dereference_field_rvalue. */
4777 recording::dereference_field_rvalue::write_reproducer (reproducer
&r
)
4779 const char *id
= r
.make_identifier (this, "lvalue");
4780 r
.write (" gcc_jit_lvalue *%s=\n"
4781 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
4782 " %s, /* gcc_jit_location *loc */\n"
4783 " %s); /* gcc_jit_field *field */\n",
4785 r
.get_identifier_as_rvalue (m_rvalue
),
4786 r
.get_identifier (m_loc
),
4787 r
.get_identifier (m_field
));
4790 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
4792 /* Implementation of pure virtual hook recording::memento::replay_into
4793 for recording::dereference_rvalue. */
4796 recording::dereference_rvalue::replay_into (replayer
*r
)
4799 m_rvalue
->playback_rvalue ()->
4800 dereference (playback_location (r
, m_loc
)));
4803 /* Implementation of pure virtual hook recording::rvalue::visit_children
4804 for recording::dereference_rvalue. */
4807 recording::dereference_rvalue::visit_children (rvalue_visitor
*v
)
4809 v
->visit (m_rvalue
);
4812 /* Implementation of recording::memento::make_debug_string for
4813 dereferencing an rvalue. */
4816 recording::dereference_rvalue::make_debug_string ()
4818 return string::from_printf (m_ctxt
,
4820 m_rvalue
->get_debug_string ());
4823 /* Implementation of recording::memento::write_reproducer for
4824 dereference_rvalue. */
4827 recording::dereference_rvalue::write_reproducer (reproducer
&r
)
4829 const char *id
= r
.make_identifier (this, "dereference");
4830 r
.write (" gcc_jit_lvalue *%s =\n"
4831 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
4832 " %s); /* gcc_jit_location *loc */\n",
4834 r
.get_identifier_as_rvalue (m_rvalue
),
4835 r
.get_identifier (m_loc
));
4838 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
4840 /* Implementation of pure virtual hook recording::memento::replay_into
4841 for recording::get_address_of_lvalue. */
4844 recording::get_address_of_lvalue::replay_into (replayer
*r
)
4847 m_lvalue
->playback_lvalue ()->
4848 get_address (playback_location (r
, m_loc
)));
4851 /* Implementation of pure virtual hook recording::rvalue::visit_children
4852 for recording::get_address_of_lvalue. */
4855 recording::get_address_of_lvalue::visit_children (rvalue_visitor
*v
)
4857 v
->visit (m_lvalue
);
4860 /* Implementation of recording::memento::make_debug_string for
4861 getting the address of an lvalue. */
4864 recording::get_address_of_lvalue::make_debug_string ()
4866 return string::from_printf (m_ctxt
,
4868 m_lvalue
->get_debug_string ());
4871 /* Implementation of recording::memento::write_reproducer for
4872 get_address_of_lvalue. */
4875 recording::get_address_of_lvalue::write_reproducer (reproducer
&r
)
4877 const char *id
= r
.make_identifier (this, "address_of");
4878 r
.write (" gcc_jit_rvalue *%s =\n"
4879 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
4880 " %s); /* gcc_jit_location *loc */\n",
4882 r
.get_identifier_as_lvalue (m_lvalue
),
4883 r
.get_identifier (m_loc
));
4886 /* The implementation of class gcc::jit::recording::local. */
4888 /* Implementation of pure virtual hook recording::memento::replay_into
4889 for recording::local. */
4892 recording::local::replay_into (replayer
*r
)
4895 m_func
->playback_function ()
4896 ->new_local (playback_location (r
, m_loc
),
4897 m_type
->playback_type (),
4898 playback_string (m_name
)));
4901 /* Override the default implementation of
4902 recording::memento::write_to_dump for locals by writing
4904 for use at the top of the function body as if it were a
4908 recording::local::write_to_dump (dump
&d
)
4910 if (d
.update_locations ())
4911 m_loc
= d
.make_location ();
4912 d
.write(" %s %s;\n",
4913 m_type
->get_debug_string (),
4914 get_debug_string ());
4918 recording::local::write_reproducer (reproducer
&r
)
4920 const char *id
= r
.make_identifier (this, "local");
4921 r
.write (" gcc_jit_lvalue *%s =\n"
4922 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
4923 " %s, /* gcc_jit_location *loc */\n"
4924 " %s, /* gcc_jit_type *type */\n"
4925 " %s); /* const char *name */\n",
4927 r
.get_identifier (m_func
),
4928 r
.get_identifier (m_loc
),
4929 r
.get_identifier_as_type (m_type
),
4930 m_name
->get_debug_string ());
4933 /* The implementation of class gcc::jit::recording::statement. */
4935 /* We poison the default implementation of
4936 gcc::jit::recording::statement::get_successor_blocks
4937 since this vfunc must only ever be called on terminator
4941 recording::statement::get_successor_blocks (block
**/
*out_next1*/
,
4942 block
**/
*out_next2*/
) const
4944 /* The base class implementation is for non-terminating statements,
4945 and thus should never be called. */
4950 /* Extend the default implementation of
4951 recording::memento::write_to_dump for statements by (if requested)
4952 updating the location of the statement to the current location in
4956 recording::statement::write_to_dump (dump
&d
)
4958 memento::write_to_dump (d
);
4959 if (d
.update_locations ())
4960 m_loc
= d
.make_location ();
4963 /* The implementation of class gcc::jit::recording::eval. */
4965 /* Implementation of pure virtual hook recording::memento::replay_into
4966 for recording::eval. */
4969 recording::eval::replay_into (replayer
*r
)
4971 playback_block (get_block ())
4972 ->add_eval (playback_location (r
),
4973 m_rvalue
->playback_rvalue ());
4976 /* Implementation of recording::memento::make_debug_string for
4977 an eval statement. */
4980 recording::eval::make_debug_string ()
4982 return string::from_printf (m_ctxt
,
4984 m_rvalue
->get_debug_string ());
4987 /* Implementation of recording::memento::write_reproducer for
4991 recording::eval::write_reproducer (reproducer
&r
)
4993 r
.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
4994 " %s, /* gcc_jit_location *loc */\n"
4995 " %s); /* gcc_jit_rvalue *rvalue */\n",
4996 r
.get_identifier (get_block ()),
4997 r
.get_identifier (get_loc ()),
4998 r
.get_identifier_as_rvalue (m_rvalue
));
5001 /* The implementation of class gcc::jit::recording::assignment. */
5003 /* Implementation of pure virtual hook recording::memento::replay_into
5004 for recording::assignment. */
5007 recording::assignment::replay_into (replayer
*r
)
5009 playback_block (get_block ())
5010 ->add_assignment (playback_location (r
),
5011 m_lvalue
->playback_lvalue (),
5012 m_rvalue
->playback_rvalue ());
5015 /* Implementation of recording::memento::make_debug_string for
5016 an assignment statement. */
5019 recording::assignment::make_debug_string ()
5021 return string::from_printf (m_ctxt
,
5023 m_lvalue
->get_debug_string (),
5024 m_rvalue
->get_debug_string ());
5027 /* Implementation of recording::memento::write_reproducer for
5028 assignment statements. */
5031 recording::assignment::write_reproducer (reproducer
&r
)
5033 r
.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5034 " %s, /* gcc_jit_location *loc */\n"
5035 " %s, /* gcc_jit_lvalue *lvalue */\n"
5036 " %s); /* gcc_jit_rvalue *rvalue */\n",
5037 r
.get_identifier (get_block ()),
5038 r
.get_identifier (get_loc ()),
5039 r
.get_identifier_as_lvalue (m_lvalue
),
5040 r
.get_identifier_as_rvalue (m_rvalue
));
5043 /* The implementation of class gcc::jit::recording::assignment_op. */
5045 /* Implementation of pure virtual hook recording::memento::replay_into
5046 for recording::assignment_op. */
5049 recording::assignment_op::replay_into (replayer
*r
)
5051 playback::type
*result_type
=
5052 m_lvalue
->playback_lvalue ()->get_type ();
5054 playback::rvalue
*binary_op
=
5055 r
->new_binary_op (playback_location (r
),
5058 m_lvalue
->playback_rvalue (),
5059 m_rvalue
->playback_rvalue ());
5061 playback_block (get_block ())
5062 ->add_assignment (playback_location (r
),
5063 m_lvalue
->playback_lvalue (),
5067 /* Implementation of recording::memento::make_debug_string for
5068 an assignment_op statement. */
5071 recording::assignment_op::make_debug_string ()
5073 return string::from_printf (m_ctxt
,
5075 m_lvalue
->get_debug_string (),
5076 binary_op_strings
[m_op
],
5077 m_rvalue
->get_debug_string ());
5080 /* Implementation of recording::memento::write_reproducer for
5081 assignment_op statements. */
5084 recording::assignment_op::write_reproducer (reproducer
&r
)
5086 r
.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5087 " %s, /* gcc_jit_location *loc */\n"
5088 " %s, /* gcc_jit_lvalue *lvalue */\n"
5089 " %s, /* enum gcc_jit_binary_op op */\n"
5090 " %s); /* gcc_jit_rvalue *rvalue */\n",
5091 r
.get_identifier (get_block ()),
5092 r
.get_identifier (get_loc ()),
5093 r
.get_identifier_as_lvalue (m_lvalue
),
5094 binary_op_reproducer_strings
[m_op
],
5095 r
.get_identifier_as_rvalue (m_rvalue
));
5098 /* The implementation of class gcc::jit::recording::comment. */
5100 /* Implementation of pure virtual hook recording::memento::replay_into
5101 for recording::comment. */
5104 recording::comment::replay_into (replayer
*r
)
5106 playback_block (get_block ())
5107 ->add_comment (playback_location (r
),
5111 /* Implementation of recording::memento::make_debug_string for
5112 a comment "statement". */
5115 recording::comment::make_debug_string ()
5117 return string::from_printf (m_ctxt
,
5122 /* Implementation of recording::memento::write_reproducer for
5126 recording::comment::write_reproducer (reproducer
&r
)
5128 r
.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5129 " %s, /* gcc_jit_location *loc */\n"
5130 " %s); /* const char *text */\n",
5131 r
.get_identifier (get_block ()),
5132 r
.get_identifier (get_loc ()),
5133 m_text
->get_debug_string ());
5136 /* The implementation of class gcc::jit::recording::conditional. */
5138 /* Implementation of pure virtual hook recording::memento::replay_into
5139 for recording::conditional. */
5142 recording::conditional::replay_into (replayer
*r
)
5144 playback_block (get_block ())
5145 ->add_conditional (playback_location (r
),
5146 m_boolval
->playback_rvalue (),
5147 playback_block (m_on_true
),
5148 playback_block (m_on_false
));
5151 /* Override the poisoned default implementation of
5152 gcc::jit::recording::statement::get_successor_blocks
5154 A conditional jump has 2 successor blocks. */
5157 recording::conditional::get_successor_blocks (block
**out_next1
,
5158 block
**out_next2
) const
5160 *out_next1
= m_on_true
;
5161 *out_next2
= m_on_false
;
5165 /* Implementation of recording::memento::make_debug_string for
5166 a conditional jump statement. */
5169 recording::conditional::make_debug_string ()
5172 return string::from_printf (m_ctxt
,
5173 "if (%s) goto %s; else goto %s;",
5174 m_boolval
->get_debug_string (),
5175 m_on_true
->get_debug_string (),
5176 m_on_false
->get_debug_string ());
5178 return string::from_printf (m_ctxt
,
5180 m_boolval
->get_debug_string (),
5181 m_on_true
->get_debug_string ());
5184 /* Implementation of recording::memento::write_reproducer for
5185 conditional statements. */
5188 recording::conditional::write_reproducer (reproducer
&r
)
5190 r
.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5191 " %s, /* gcc_jit_location *loc */\n"
5192 " %s, /* gcc_jit_rvalue *boolval */\n"
5193 " %s, /* gcc_jit_block *on_true */\n"
5194 " %s); /* gcc_jit_block *on_false */\n",
5195 r
.get_identifier (get_block ()),
5196 r
.get_identifier (get_loc ()),
5197 r
.get_identifier_as_rvalue (m_boolval
),
5198 r
.get_identifier (m_on_true
),
5199 r
.get_identifier (m_on_false
));
5202 /* The implementation of class gcc::jit::recording::jump. */
5204 /* Implementation of pure virtual hook recording::memento::replay_into
5205 for recording::jump. */
5208 recording::jump::replay_into (replayer
*r
)
5210 playback_block (get_block ())
5211 ->add_jump (playback_location (r
),
5212 m_target
->playback_block ());
5215 /* Override the poisoned default implementation of
5216 gcc::jit::recording::statement::get_successor_blocks
5218 An unconditional jump has 1 successor block. */
5221 recording::jump::get_successor_blocks (block
**out_next1
,
5222 block
**/
*out_next2*/
) const
5224 *out_next1
= m_target
;
5228 /* Implementation of recording::memento::make_debug_string for
5229 a unconditional jump statement. */
5232 recording::jump::make_debug_string ()
5234 return string::from_printf (m_ctxt
,
5236 m_target
->get_debug_string ());
5239 /* Implementation of recording::memento::write_reproducer for
5243 recording::jump::write_reproducer (reproducer
&r
)
5245 r
.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5246 " %s, /* gcc_jit_location *loc */\n"
5247 " %s); /* gcc_jit_block *target */\n",
5248 r
.get_identifier (get_block ()),
5249 r
.get_identifier (get_loc ()),
5250 r
.get_identifier (m_target
));
5253 /* The implementation of class gcc::jit::recording::return_. */
5255 /* Implementation of pure virtual hook recording::memento::replay_into
5256 for recording::return_. */
5259 recording::return_::replay_into (replayer
*r
)
5261 playback_block (get_block ())
5262 ->add_return (playback_location (r
),
5263 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
5266 /* Override the poisoned default implementation of
5267 gcc::jit::recording::statement::get_successor_blocks
5269 A return statement has no successor block. */
5272 recording::return_::get_successor_blocks (block
**/
*out_next1*/
,
5273 block
**/
*out_next2*/
) const
5278 /* Implementation of recording::memento::make_debug_string for
5279 a return statement (covers both those with and without rvalues). */
5282 recording::return_::make_debug_string ()
5285 return string::from_printf (m_ctxt
,
5287 m_rvalue
->get_debug_string ());
5289 return string::from_printf (m_ctxt
,
5293 /* Implementation of recording::memento::write_reproducer for
5294 return statements. */
5297 recording::return_::write_reproducer (reproducer
&r
)
5300 r
.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5301 " %s, /* gcc_jit_location *loc */\n"
5302 " %s); /* gcc_jit_rvalue *rvalue */\n",
5303 r
.get_identifier (get_block ()),
5304 r
.get_identifier (get_loc ()),
5305 r
.get_identifier_as_rvalue (m_rvalue
));
5307 r
.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5308 " %s); /* gcc_jit_location *loc */\n",
5309 r
.get_identifier (get_block ()),
5310 r
.get_identifier (get_loc ()));
5313 } // namespace gcc::jit