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
, ...)
84 /* If there was an error opening the file, we've already reported it.
85 Don't attempt further work. */
90 len
= vasprintf (&buf
, fmt
, ap
);
93 if (buf
== NULL
|| len
< 0)
95 m_ctxt
.add_error (NULL
, "malloc failure writing to dumpfile %s",
100 if (fwrite (buf
, strlen (buf
), 1, m_file
) != 1)
101 m_ctxt
.add_error (NULL
, "error writing to dump file %s",
104 /* Flush after each line, to ease debugging crashes. */
107 /* Update line/column: */
108 for (const char *ptr
= buf
; *ptr
; ptr
++)
122 /* Construct a gcc::jit::recording::location instance for the current
123 location within the dump. */
125 recording::location
*
126 dump::make_location () const
128 return m_ctxt
.new_location (m_filename
, m_line
, m_column
,
129 /* We need to flag such locations as *not*
130 created by the user, so that
131 reproducer::get_identifier can cope with
132 them appearing *after* the memento that
137 /* A collection of allocations, all of which can be released together, to
138 avoid needing to track and release them individually. */
146 xstrdup_printf (const char *, ...)
147 ATTRIBUTE_RETURNS_NONNULL
151 xstrdup_printf_va (const char *, va_list ap
)
152 ATTRIBUTE_RETURNS_NONNULL
156 auto_vec
<void *> m_buffers
;
159 /* allocator's destructor. Call "free" on all of the allocations. */
161 allocator::~allocator ()
165 FOR_EACH_VEC_ELT (m_buffers
, i
, buffer
)
169 /* Formatted printing, allocating to a buffer (or exiting the process if
170 the allocation fails).
172 The buffer exists until the allocator is cleaned up, and is freed at
173 that point, so the caller doesn't need to track the result. */
176 allocator::xstrdup_printf (const char *fmt
, ...)
181 result
= xstrdup_printf_va (fmt
, ap
);
186 /* Formatted printing, allocating to a buffer (or exiting the process if
187 the allocation fails).
189 The buffer exists until the allocator is cleaned up, and is freed at
190 that point, so the caller doesn't need to track the result. */
193 allocator::xstrdup_printf_va (const char *fmt
, va_list ap
)
195 char *result
= xvasprintf (fmt
, ap
);
196 m_buffers
.safe_push (result
);
200 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
201 implementing gcc_jit_context_dump_reproducer_to_file. */
203 class reproducer
: public dump
206 reproducer (recording::context
&ctxt
,
207 const char *filename
);
210 write_params (const vec
<recording::context
*> &contexts
);
213 write_args (const vec
<recording::context
*> &contexts
);
216 make_identifier (recording::memento
*m
, const char *prefix
);
219 make_tmp_identifier (const char *prefix
, recording::memento
*m
);
222 get_identifier (recording::context
*ctxt
);
225 get_identifier (recording::memento
*m
);
228 get_identifier_as_rvalue (recording::rvalue
*m
);
231 get_identifier_as_lvalue (recording::lvalue
*m
);
234 get_identifier_as_type (recording::type
*m
);
237 xstrdup_printf (const char *, ...)
238 ATTRIBUTE_RETURNS_NONNULL
242 hash_map
<recording::memento
*, const char *> m_identifiers
;
243 allocator m_allocator
;
246 /* gcc::jit::reproducer's constructor. */
248 reproducer::reproducer (recording::context
&ctxt
,
249 const char *filename
) :
250 dump (ctxt
, filename
, 0),
256 /* Write out a list of contexts as a set of parameters within a
257 C function declaration. */
260 reproducer::write_params (const vec
<recording::context
*> &contexts
)
263 recording::context
*ctxt
;
264 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
266 write ("gcc_jit_context *%s",
267 get_identifier (ctxt
));
268 if (i
< contexts
.length () - 1)
274 /* Write out a list of contexts as a set of arguments within a call
278 reproducer::write_args (const vec
<recording::context
*> &contexts
)
281 recording::context
*ctxt
;
282 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
285 get_identifier (ctxt
));
286 if (i
< contexts
.length () - 1)
292 /* Generate a C identifier for the given memento, associating the generated
293 buffer with the memento (for future calls to get_identifier et al).
295 The reproducer will eventually clean up the buffer in its dtor. */
297 reproducer::make_identifier (recording::memento
*m
, const char *prefix
)
300 if (strlen (m
->get_debug_string ()) < 100)
302 result
= m_allocator
.xstrdup_printf ("%s_%s_%p",
304 m
->get_debug_string (),
306 for (char *p
= result
; *p
; p
++)
311 result
= m_allocator
.xstrdup_printf ("%s_%p",
313 m_identifiers
.put (m
, result
);
317 /* Generate a C identifier for a temporary variable.
318 The reproducer will eventually clean up the buffer in its dtor. */
321 reproducer::make_tmp_identifier (const char *prefix
, recording::memento
*m
)
323 return m_allocator
.xstrdup_printf ("%s_%s",
324 prefix
, get_identifier (m
));
327 /* Generate a C identifier for the given context.
328 The reproducer will eventually clean up the buffer in its dtor. */
331 reproducer::get_identifier (recording::context
*ctxt
)
333 return m_allocator
.xstrdup_printf ("ctxt_%p",
337 /* Locate the C identifier for the given memento, which is assumed to
338 have already been created via make_identifier. */
341 reproducer::get_identifier (recording::memento
*m
)
346 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
347 and hence these locations appear in the context's memento list
348 out-of-order: they appear in the context's memento list *after*
349 the memento that refers to them. For this case, it's simplest to
350 pretend that they're NULL when writing out the code to recreate the
351 memento that uses them. */
352 if (recording::location
*loc
= m
->dyn_cast_location ())
353 if (!loc
->created_by_user ())
356 const char **slot
= m_identifiers
.get (m
);
359 get_context ().add_error (NULL
,
360 "unable to find identifier for %p: %s",
362 m
->get_debug_string ());
368 /* Locate the C identifier for the given rvalue, wrapping it within
369 a gcc_*_as_rvalue upcast if necessary. */
372 reproducer::get_identifier_as_rvalue (recording::rvalue
*m
)
374 return m
->access_as_rvalue (*this);
377 /* Locate the C identifier for the given lvalue, wrapping it within
378 a gcc_*_as_lvalue upcast if necessary. */
381 reproducer::get_identifier_as_lvalue (recording::lvalue
*m
)
383 return m
->access_as_lvalue (*this);
386 /* Locate the C identifier for the given type, wrapping it within
387 a gcc_*_as_type upcast if necessary. */
390 reproducer::get_identifier_as_type (recording::type
*m
)
392 return m
->access_as_type (*this);
395 /* Formatted printing, allocating to a buffer (or exiting the process if
396 the allocation fails).
398 The buffer exists until the allocator is cleaned up, and is freed at
399 that point, so the caller doesn't need to track the result.
401 Note that we can't use ggc_printf since we're not within the compiler
402 proper (when within gcc_jit_context_dump_reproducer_to_file). */
405 reproducer::xstrdup_printf (const char *fmt
, ...)
410 result
= m_allocator
.xstrdup_printf_va (fmt
, ap
);
415 /**********************************************************************
417 **********************************************************************/
419 /* Get the playback::location for the given recording::location,
420 handling a NULL input with a NULL output. */
423 recording::playback_location (replayer
*r
, recording::location
*loc
)
426 return loc
->playback_location (r
);
431 /* Get a const char * for the given recording::string
432 handling a NULL input with a NULL output. */
435 recording::playback_string (recording::string
*str
)
438 return str
->c_str ();
443 /* Get the playback::block for the given recording::block,
444 handling a NULL input with a NULL output. */
447 recording::playback_block (recording::block
*b
)
450 return b
->playback_block ();
455 /* Methods of cc::jit::recording::context. */
457 /* The constructor for gcc::jit::recording::context, used by
458 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
460 recording::context::context (context
*parent_ctxt
)
462 m_parent_ctxt (parent_ctxt
),
463 m_toplevel_ctxt (m_parent_ctxt
? m_parent_ctxt
->m_toplevel_ctxt
: this),
465 m_first_error_str (NULL
),
466 m_owns_first_error_str (false),
467 m_last_error_str (NULL
),
468 m_owns_last_error_str (false),
474 m_builtins_manager(NULL
)
478 /* Inherit options from parent. */
480 i
< sizeof (m_str_options
) / sizeof (m_str_options
[0]);
483 const char *parent_opt
= parent_ctxt
->m_str_options
[i
];
484 m_str_options
[i
] = parent_opt
? xstrdup (parent_opt
) : NULL
;
486 memcpy (m_int_options
,
487 parent_ctxt
->m_int_options
,
488 sizeof (m_int_options
));
489 memcpy (m_bool_options
,
490 parent_ctxt
->m_bool_options
,
491 sizeof (m_bool_options
));
492 set_logger (parent_ctxt
->get_logger ());
496 memset (m_str_options
, 0, sizeof (m_str_options
));
497 memset (m_int_options
, 0, sizeof (m_int_options
));
498 memset (m_bool_options
, 0, sizeof (m_bool_options
));
501 memset (m_basic_types
, 0, sizeof (m_basic_types
));
504 /* The destructor for gcc::jit::recording::context, implicitly used by
505 gcc_jit_context_release. */
507 recording::context::~context ()
509 JIT_LOG_SCOPE (get_logger ());
512 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
517 for (i
= 0; i
< GCC_JIT_NUM_STR_OPTIONS
; ++i
)
518 free (m_str_options
[i
]);
520 if (m_builtins_manager
)
521 delete m_builtins_manager
;
523 if (m_owns_first_error_str
)
524 free (m_first_error_str
);
526 if (m_owns_last_error_str
)
527 if (m_last_error_str
!= m_first_error_str
)
528 free (m_last_error_str
);
531 /* Add the given mememto to the list of those tracked by this
532 gcc::jit::recording::context, so that e.g. it can be deleted
533 when this context is released. */
536 recording::context::record (memento
*m
)
540 m_mementos
.safe_push (m
);
543 /* Replay this context (and any parents) into the given replayer. */
546 recording::context::replay_into (replayer
*r
)
548 JIT_LOG_SCOPE (get_logger ());
552 /* If we have a parent context, we must replay it. This will
553 recursively walk backwards up the historical tree, then replay things
554 forwards "in historical order", starting with the ultimate parent
555 context, until we reach the "this" context.
557 Note that we fully replay the parent, then fully replay the child,
558 which means that inter-context references can only exist from child
559 to parent, not the other way around.
561 All of this replaying is suboptimal - it would be better to do the
562 work for the parent context *once*, rather than replaying the parent
563 every time we replay each child. However, fixing this requires deep
564 surgery to lifetime-management: we'd need every context family tree
565 to have its own GC heap, and to initialize the GCC code to use that
566 heap (with a mutex on such a heap). */
568 m_parent_ctxt
->replay_into (r
);
570 if (r
->errors_occurred ())
573 /* Replay this context's saved operations into r. */
574 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
576 /* Disabled low-level debugging, here if we need it: print what
578 Note that the calls to get_debug_string might lead to more
579 mementos being created for the strings.
580 This can also be used to exercise the debug_string
583 printf ("context %p replaying (%p): %s\n",
584 (void *)this, (void *)m
, m
->get_debug_string ());
588 if (r
->errors_occurred ())
593 /* During a playback, we associate objects from the recording with
594 their counterparts during this playback.
596 For simplicity, we store this within the recording objects.
598 The following method cleans away these associations, to ensure that
599 we never have out-of-date associations lingering on subsequent
600 playbacks (the objects pointed to are GC-managed, but the
601 recording objects don't own refs to them). */
604 recording::context::disassociate_from_playback ()
606 JIT_LOG_SCOPE (get_logger ());
611 m_parent_ctxt
->disassociate_from_playback ();
613 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
615 m
->set_playback_obj (NULL
);
619 /* Create a recording::string instance and add it to this context's list
622 This creates a fresh copy of the given 0-terminated buffer. */
625 recording::context::new_string (const char *text
)
630 recording::string
*result
= new string (this, text
);
635 /* Create a recording::location instance and add it to this context's
638 Implements the post-error-checking part of
639 gcc_jit_context_new_location. */
641 recording::location
*
642 recording::context::new_location (const char *filename
,
645 bool created_by_user
)
647 recording::location
*result
=
648 new recording::location (this,
649 new_string (filename
),
656 /* If we haven't seen this enum value yet, create a recording::type
657 instance and add it to this context's list of mementos.
659 If we have seen it before, reuse our cached value, so that repeated
660 calls on the context give the same object.
662 If we have a parent context, the cache is within the ultimate
665 Implements the post-error-checking part of
666 gcc_jit_context_get_type. */
669 recording::context::get_type (enum gcc_jit_types kind
)
671 if (!m_basic_types
[kind
])
674 m_basic_types
[kind
] = m_parent_ctxt
->get_type (kind
);
677 recording::type
*result
= new memento_of_get_type (this, kind
);
679 m_basic_types
[kind
] = result
;
683 return m_basic_types
[kind
];
686 /* Get a recording::type instance for the given size and signedness.
687 This is implemented in terms of recording::context::get_type
690 Implements the post-error-checking part of
691 gcc_jit_context_get_int_type. */
694 recording::context::get_int_type (int num_bytes
, int is_signed
)
696 /* We can't use a switch here since some of the values are macros affected
697 by options; e.g. i386.h has
698 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
699 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
700 are in bits, rather than bytes.
702 const int num_bits
= num_bytes
* 8;
703 if (num_bits
== INT_TYPE_SIZE
)
704 return get_type (is_signed
706 : GCC_JIT_TYPE_UNSIGNED_INT
);
707 if (num_bits
== CHAR_TYPE_SIZE
)
708 return get_type (is_signed
709 ? GCC_JIT_TYPE_SIGNED_CHAR
710 : GCC_JIT_TYPE_UNSIGNED_CHAR
);
711 if (num_bits
== SHORT_TYPE_SIZE
)
712 return get_type (is_signed
714 : GCC_JIT_TYPE_UNSIGNED_SHORT
);
715 if (num_bits
== LONG_TYPE_SIZE
)
716 return get_type (is_signed
718 : GCC_JIT_TYPE_UNSIGNED_LONG
);
719 if (num_bits
== LONG_LONG_TYPE_SIZE
)
720 return get_type (is_signed
721 ? GCC_JIT_TYPE_LONG_LONG
722 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
724 /* Some other size, not corresponding to the C int types. */
725 /* To be written: support arbitrary other sizes, sharing by
726 memoizing at the recording::context level? */
730 /* Create a recording::type instance and add it to this context's list
733 Implements the post-error-checking part of
734 gcc_jit_context_new_array_type. */
737 recording::context::new_array_type (recording::location
*loc
,
738 recording::type
*element_type
,
741 if (struct_
*s
= element_type
->dyn_cast_struct ())
742 if (!s
->get_fields ())
745 "cannot create an array of type %s"
746 " until the fields have been set",
747 s
->get_name ()->c_str ());
750 recording::type
*result
=
751 new recording::array_type (this, loc
, element_type
, num_elements
);
756 /* Create a recording::field instance and add it to this context's list
759 Implements the post-error-checking part of
760 gcc_jit_context_new_field. */
763 recording::context::new_field (recording::location
*loc
,
764 recording::type
*type
,
767 recording::field
*result
=
768 new recording::field (this, loc
, type
, new_string (name
));
773 /* Create a recording::struct_ instance and add it to this context's
774 list of mementos and list of compound types.
776 Implements the post-error-checking part of
777 gcc_jit_context_new_struct_type. */
780 recording::context::new_struct_type (recording::location
*loc
,
783 recording::struct_
*result
= new struct_ (this, loc
, new_string (name
));
785 m_compound_types
.safe_push (result
);
789 /* Create a recording::union_ instance and add it to this context's
790 list of mementos and list of compound types.
792 Implements the first post-error-checking part of
793 gcc_jit_context_new_union_type. */
796 recording::context::new_union_type (recording::location
*loc
,
799 recording::union_
*result
= new union_ (this, loc
, new_string (name
));
801 m_compound_types
.safe_push (result
);
805 /* Create a recording::function_type instance and add it to this context's
808 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
810 recording::function_type
*
811 recording::context::new_function_type (recording::type
*return_type
,
813 recording::type
**param_types
,
816 recording::function_type
*fn_type
817 = new function_type (this,
826 /* Create a recording::type instance and add it to this context's list
829 Implements the post-error-checking part of
830 gcc_jit_context_new_function_ptr_type. */
833 recording::context::new_function_ptr_type (recording::location
*, /* unused loc */
834 recording::type
*return_type
,
836 recording::type
**param_types
,
839 recording::function_type
*fn_type
840 = new_function_type (return_type
,
845 /* Return a pointer-type to the the function type. */
846 return fn_type
->get_pointer ();
849 /* Create a recording::param instance and add it to this context's list
852 Implements the post-error-checking part of
853 gcc_jit_context_new_param. */
856 recording::context::new_param (recording::location
*loc
,
857 recording::type
*type
,
860 recording::param
*result
= new recording::param (this, loc
, type
, new_string (name
));
865 /* Create a recording::function instance and add it to this context's list
866 of mementos and list of functions.
868 Implements the post-error-checking part of
869 gcc_jit_context_new_function. */
871 recording::function
*
872 recording::context::new_function (recording::location
*loc
,
873 enum gcc_jit_function_kind kind
,
874 recording::type
*return_type
,
877 recording::param
**params
,
879 enum built_in_function builtin_id
)
881 recording::function
*result
=
882 new recording::function (this,
883 loc
, kind
, return_type
,
885 num_params
, params
, is_variadic
,
888 m_functions
.safe_push (result
);
893 /* Locate the builtins_manager (if any) for this family of contexts,
894 creating it if it doesn't exist already.
896 All of the recording contexts in a family share one builtins_manager:
897 if we have a child context, follow the parent links to get the
898 ultimate ancestor context, and look for it/store it there. */
901 recording::context::get_builtins_manager ()
904 return m_parent_ctxt
->get_builtins_manager ();
906 if (!m_builtins_manager
)
907 m_builtins_manager
= new builtins_manager (this);
909 return m_builtins_manager
;
912 /* Get a recording::function instance, which is lazily-created and added
913 to the context's lists of mementos.
915 Implements the post-error-checking part of
916 gcc_jit_context_get_builtin_function. */
918 recording::function
*
919 recording::context::get_builtin_function (const char *name
)
921 builtins_manager
*bm
= get_builtins_manager ();
922 return bm
->get_builtin_function (name
);
925 /* Create a recording::global instance and add it to this context's list
928 Implements the post-error-checking part of
929 gcc_jit_context_new_global. */
932 recording::context::new_global (recording::location
*loc
,
933 enum gcc_jit_global_kind kind
,
934 recording::type
*type
,
937 recording::global
*result
=
938 new recording::global (this, loc
, kind
, type
, new_string (name
));
940 m_globals
.safe_push (result
);
945 /* Create a recording::memento_of_new_string_literal instance and add it
946 to this context's list of mementos.
948 Implements the post-error-checking part of
949 gcc_jit_context_new_string_literal. */
952 recording::context::new_string_literal (const char *value
)
954 recording::rvalue
*result
=
955 new memento_of_new_string_literal (this, NULL
, new_string (value
));
960 /* Create a recording::unary_op instance and add it to this context's
963 Implements the post-error-checking part of
964 gcc_jit_context_new_unary_op. */
967 recording::context::new_unary_op (recording::location
*loc
,
968 enum gcc_jit_unary_op op
,
969 recording::type
*result_type
,
970 recording::rvalue
*a
)
972 recording::rvalue
*result
=
973 new unary_op (this, loc
, op
, result_type
, a
);
978 /* Create a recording::binary_op instance and add it to this context's
981 Implements the post-error-checking part of
982 gcc_jit_context_new_binary_op. */
985 recording::context::new_binary_op (recording::location
*loc
,
986 enum gcc_jit_binary_op op
,
987 recording::type
*result_type
,
988 recording::rvalue
*a
,
989 recording::rvalue
*b
)
991 recording::rvalue
*result
=
992 new binary_op (this, loc
, op
, result_type
, a
, b
);
997 /* Create a recording::comparison instance and add it to this context's
1000 Implements the post-error-checking part of
1001 gcc_jit_context_new_comparison. */
1004 recording::context::new_comparison (recording::location
*loc
,
1005 enum gcc_jit_comparison op
,
1006 recording::rvalue
*a
,
1007 recording::rvalue
*b
)
1009 recording::rvalue
*result
= new comparison (this, loc
, op
, a
, b
);
1014 /* Create a recording::cast instance and add it to this context's list
1017 Implements the post-error-checking part of
1018 gcc_jit_context_new_cast. */
1021 recording::context::new_cast (recording::location
*loc
,
1022 recording::rvalue
*expr
,
1023 recording::type
*type_
)
1025 recording::rvalue
*result
= new cast (this, loc
, expr
, type_
);
1030 /* Create a recording::call instance and add it to this context's list
1033 Implements the post-error-checking part of
1034 gcc_jit_context_new_call. */
1037 recording::context::new_call (recording::location
*loc
,
1039 int numargs
, recording::rvalue
**args
)
1041 recording::rvalue
*result
= new call (this, loc
, func
, numargs
, args
);
1046 /* Create a recording::call_through_ptr instance and add it to this
1047 context's list of mementos.
1049 Implements the post-error-checking part of
1050 gcc_jit_context_new_call_through_ptr. */
1053 recording::context::new_call_through_ptr (recording::location
*loc
,
1054 recording::rvalue
*fn_ptr
,
1056 recording::rvalue
**args
)
1058 recording::rvalue
*result
= new call_through_ptr (this, loc
, fn_ptr
, numargs
, args
);
1063 /* Create a recording::array_access instance and add it to this context's list
1066 Implements the post-error-checking part of
1067 gcc_jit_context_new_array_access. */
1070 recording::context::new_array_access (recording::location
*loc
,
1071 recording::rvalue
*ptr
,
1072 recording::rvalue
*index
)
1074 recording::lvalue
*result
= new array_access (this, loc
, ptr
, index
);
1079 /* Set the given string option for this context, or add an error if
1080 it's not recognized.
1082 Implements the post-error-checking part of
1083 gcc_jit_context_set_str_option. */
1086 recording::context::set_str_option (enum gcc_jit_str_option opt
,
1089 if (opt
< 0 || opt
>= GCC_JIT_NUM_STR_OPTIONS
)
1092 "unrecognized (enum gcc_jit_str_option) value: %i", opt
);
1095 free (m_str_options
[opt
]);
1096 m_str_options
[opt
] = value
? xstrdup (value
) : NULL
;
1097 log_str_option (opt
);
1100 /* Set the given integer option for this context, or add an error if
1101 it's not recognized.
1103 Implements the post-error-checking part of
1104 gcc_jit_context_set_int_option. */
1107 recording::context::set_int_option (enum gcc_jit_int_option opt
,
1110 if (opt
< 0 || opt
>= GCC_JIT_NUM_INT_OPTIONS
)
1113 "unrecognized (enum gcc_jit_int_option) value: %i", opt
);
1116 m_int_options
[opt
] = value
;
1117 log_int_option (opt
);
1120 /* Set the given boolean option for this context, or add an error if
1121 it's not recognized.
1123 Implements the post-error-checking part of
1124 gcc_jit_context_set_bool_option. */
1127 recording::context::set_bool_option (enum gcc_jit_bool_option opt
,
1130 if (opt
< 0 || opt
>= GCC_JIT_NUM_BOOL_OPTIONS
)
1133 "unrecognized (enum gcc_jit_bool_option) value: %i", opt
);
1136 m_bool_options
[opt
] = value
? true : false;
1137 log_bool_option (opt
);
1140 /* Add the given dumpname/out_ptr pair to this context's list of requested
1143 Implements the post-error-checking part of
1144 gcc_jit_context_enable_dump. */
1147 recording::context::enable_dump (const char *dumpname
,
1151 gcc_assert (dumpname
);
1152 gcc_assert (out_ptr
);
1154 d
.m_dumpname
= dumpname
;
1155 d
.m_out_ptr
= out_ptr
;
1157 m_requested_dumps
.safe_push (d
);
1160 /* Validate this context, and if it passes, compile it to memory
1163 Implements the post-error-checking part of
1164 gcc_jit_context_compile. */
1167 recording::context::compile ()
1169 JIT_LOG_SCOPE (get_logger ());
1175 if (errors_occurred ())
1178 /* Set up a compile_to_memory playback context. */
1179 ::gcc::jit::playback::compile_to_memory
replayer (this);
1182 replayer
.compile ();
1184 /* Get the jit::result (or NULL) from the
1185 compile_to_memory playback context. */
1186 return replayer
.get_result_obj ();
1189 /* Validate this context, and if it passes, compile it to a file
1192 Implements the post-error-checking part of
1193 gcc_jit_context_compile_to_file. */
1196 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind
,
1197 const char *output_path
)
1199 JIT_LOG_SCOPE (get_logger ());
1205 if (errors_occurred ())
1208 /* Set up a compile_to_file playback context. */
1209 ::gcc::jit::playback::compile_to_file
replayer (this,
1214 replayer
.compile ();
1217 /* Format the given error using printf's conventions, print
1218 it to stderr, and add it to the context. */
1221 recording::context::add_error (location
*loc
, const char *fmt
, ...)
1225 add_error_va (loc
, fmt
, ap
);
1229 /* Format the given error using printf's conventions, print
1230 it to stderr, and add it to the context. */
1233 recording::context::add_error_va (location
*loc
, const char *fmt
, va_list ap
)
1240 JIT_LOG_SCOPE (get_logger ());
1242 len
= vasprintf (&malloced_msg
, fmt
, ap
);
1243 if (malloced_msg
== NULL
|| len
< 0)
1245 errmsg
= "out of memory generating error message";
1246 has_ownership
= false;
1250 errmsg
= malloced_msg
;
1251 has_ownership
= true;
1254 get_logger ()->log ("error %i: %s", m_error_count
, errmsg
);
1256 const char *ctxt_progname
=
1257 get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
1259 ctxt_progname
= "libgccjit.so";
1262 fprintf (stderr
, "%s: %s: error: %s\n",
1264 loc
->get_debug_string (),
1267 fprintf (stderr
, "%s: error: %s\n",
1273 m_first_error_str
= const_cast <char *> (errmsg
);
1274 m_owns_first_error_str
= has_ownership
;
1277 if (m_owns_last_error_str
)
1278 if (m_last_error_str
!= m_first_error_str
)
1279 free (m_last_error_str
);
1280 m_last_error_str
= const_cast <char *> (errmsg
);
1281 m_owns_last_error_str
= has_ownership
;
1286 /* Get the message for the first error that occurred on this context, or
1287 NULL if no errors have occurred on it.
1289 Implements the post-error-checking part of
1290 gcc_jit_context_get_first_error. */
1293 recording::context::get_first_error () const
1295 return m_first_error_str
;
1298 /* Get the message for the last error that occurred on this context, or
1299 NULL if no errors have occurred on it.
1301 Implements the post-error-checking part of
1302 gcc_jit_context_get_last_error. */
1305 recording::context::get_last_error () const
1307 return m_last_error_str
;
1310 /* Lazily generate and record a recording::type representing an opaque
1311 struct named "FILE".
1313 For use if client code tries to dereference the result of
1314 get_type (GCC_JIT_TYPE_FILE_PTR). */
1317 recording::context::get_opaque_FILE_type ()
1320 m_FILE_type
= new_struct_type (NULL
, "FILE");
1324 /* Dump a C-like representation of the given context to the given path.
1325 If UPDATE_LOCATIONS is true, update the locations within the
1326 context's mementos to point to the dumpfile.
1328 Implements the post-error-checking part of
1329 gcc_jit_context_dump_to_file. */
1332 recording::context::dump_to_file (const char *path
, bool update_locations
)
1335 dump
d (*this, path
, update_locations
);
1337 /* Forward declaration of structs and unions. */
1339 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1341 d
.write ("%s;\n\n", st
->get_debug_string ());
1344 /* Content of structs, where set. */
1345 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1346 if (st
->get_fields ())
1348 st
->get_fields ()->write_to_dump (d
);
1354 FOR_EACH_VEC_ELT (m_globals
, i
, g
)
1356 g
->write_to_dump (d
);
1358 if (!m_globals
.is_empty ())
1362 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1364 fn
->write_to_dump (d
);
1368 static const char * const
1369 str_option_reproducer_strings
[GCC_JIT_NUM_STR_OPTIONS
] = {
1370 "GCC_JIT_STR_OPTION_PROGNAME"
1373 static const char * const
1374 int_option_reproducer_strings
[GCC_JIT_NUM_INT_OPTIONS
] = {
1375 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1378 static const char * const
1379 bool_option_reproducer_strings
[GCC_JIT_NUM_BOOL_OPTIONS
] = {
1380 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1381 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1382 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1383 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1384 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1385 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1386 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1387 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1391 /* Write the current value of all options to the log file (if any). */
1394 recording::context::log_all_options () const
1401 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1402 log_str_option ((enum gcc_jit_str_option
)opt_idx
);
1404 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1405 log_int_option ((enum gcc_jit_int_option
)opt_idx
);
1407 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1408 log_bool_option ((enum gcc_jit_bool_option
)opt_idx
);
1411 /* Write the current value of the given string option to the
1412 log file (if any). */
1415 recording::context::log_str_option (enum gcc_jit_str_option opt
) const
1417 gcc_assert (opt
< GCC_JIT_NUM_STR_OPTIONS
);
1420 if (m_str_options
[opt
])
1422 str_option_reproducer_strings
[opt
],
1423 m_str_options
[opt
]);
1426 str_option_reproducer_strings
[opt
]);
1430 /* Write the current value of the given int option to the
1431 log file (if any). */
1434 recording::context::log_int_option (enum gcc_jit_int_option opt
) const
1436 gcc_assert (opt
< GCC_JIT_NUM_INT_OPTIONS
);
1439 int_option_reproducer_strings
[opt
],
1440 m_int_options
[opt
]);
1443 /* Write the current value of the given bool option to the
1444 log file (if any). */
1447 recording::context::log_bool_option (enum gcc_jit_bool_option opt
) const
1449 gcc_assert (opt
< GCC_JIT_NUM_BOOL_OPTIONS
);
1452 bool_option_reproducer_strings
[opt
],
1453 m_bool_options
[opt
] ? "true" : "false");
1456 /* Write C source code to PATH that attempts to replay the API
1457 calls made to this context (and its parents), for use in
1458 minimizing test cases for libgccjit.
1460 Implements the post-error-checking part of
1461 gcc_jit_context_dump_reproducer_to_file. */
1464 recording::context::dump_reproducer_to_file (const char *path
)
1466 JIT_LOG_SCOPE (get_logger ());
1467 reproducer
r (*this, path
);
1469 /* Generate the "ancestry" of this context, as a list. */
1470 auto_vec
<context
*> ascending_contexts
;
1471 for (context
*ctxt
= this; ctxt
; ctxt
= ctxt
->m_parent_ctxt
)
1472 ascending_contexts
.safe_push (ctxt
);
1474 /* Reverse the list, giving a list of contexts from
1475 top-most parent context down through to youngest child context.
1476 We will use this list as the parameters of the functions in
1477 our generated file. */
1478 unsigned num_ctxts
= ascending_contexts
.length ();
1479 auto_vec
<context
*> contexts (num_ctxts
);
1480 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1481 contexts
.safe_push (ascending_contexts
[num_ctxts
- (i
+ 1)]);
1483 /* contexts[0] should be the top-level context. */
1484 gcc_assert (contexts
[0]);
1485 gcc_assert (contexts
[0]->m_toplevel_ctxt
== contexts
[0]);
1487 /* The final element in contexts should be "this". */
1488 gcc_assert (contexts
[contexts
.length () - 1] == this);
1489 gcc_assert (contexts
[contexts
.length () - 1]->m_toplevel_ctxt
1492 r
.write ("/* This code was autogenerated by"
1493 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1494 print_version (r
.get_file (), " ", false);
1496 r
.write ("#include <libgccjit.h>\n\n");
1497 r
.write ("static void\nset_options (");
1498 r
.write_params (contexts
);
1500 r
.write ("static void\ncreate_code (");
1501 r
.write_params (contexts
);
1503 r
.write ("int\nmain (int argc, const char **argv)\n");
1505 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1506 r
.write (" gcc_jit_context *%s;\n",
1507 r
.get_identifier (contexts
[i
]));
1508 r
.write (" gcc_jit_result *result;\n"
1511 /* Create the contexts.
1512 The top-level context is acquired from a clean slate, the others as
1513 children of the prior context. */
1514 r
.write (" %s = gcc_jit_context_acquire ();\n",
1515 r
.get_identifier (contexts
[0]));
1516 for (unsigned i
= 1; i
< num_ctxts
; i
++)
1517 r
.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1518 r
.get_identifier (contexts
[i
]),
1519 r
.get_identifier (contexts
[i
- 1]));
1520 r
.write (" set_options (");
1521 r
.write_args (contexts
);
1523 r
.write (" create_code (");
1524 r
.write_args (contexts
);
1527 r
.write (" result = gcc_jit_context_compile (%s);\n",
1528 r
.get_identifier (this));
1530 for (unsigned i
= num_ctxts
; i
> 0; i
--)
1531 r
.write (" gcc_jit_context_release (%s);\n",
1532 r
.get_identifier (contexts
[i
- 1]));
1534 r
.write (" gcc_jit_result_release (result);\n"
1538 /* Define (char *) variables for use in calls to
1539 gcc_jit_context_enable_dump. */
1540 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1542 if (m_requested_dumps
.length ())
1544 r
.write ("/* Requested dumps for %s. */\n",
1545 r
.get_identifier (contexts
[ctxt_idx
]));
1546 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1547 r
.write ("static char *dump_%p;\n",
1548 (void *)&m_requested_dumps
[i
]);
1553 /* Write out values of options. */
1554 r
.write ("static void\nset_options (");
1555 r
.write_params (contexts
);
1557 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1562 r
.write (" /* Set options for %s. */\n",
1563 r
.get_identifier (contexts
[ctxt_idx
]));
1565 r
.write (" /* String options. */\n");
1566 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1567 r
.write (" gcc_jit_context_set_str_option (%s,\n"
1570 r
.get_identifier (contexts
[ctxt_idx
]),
1571 str_option_reproducer_strings
[opt_idx
],
1572 m_str_options
[opt_idx
] ? m_str_options
[opt_idx
] : "NULL");
1573 r
.write (" /* Int options. */\n");
1574 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1575 r
.write (" gcc_jit_context_set_int_option (%s,\n"
1578 r
.get_identifier (contexts
[ctxt_idx
]),
1579 int_option_reproducer_strings
[opt_idx
],
1580 m_int_options
[opt_idx
]);
1581 r
.write (" /* Boolean options. */\n");
1582 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1583 r
.write (" gcc_jit_context_set_bool_option (%s,\n"
1586 r
.get_identifier (contexts
[ctxt_idx
]),
1587 bool_option_reproducer_strings
[opt_idx
],
1588 m_bool_options
[opt_idx
]);
1590 if (m_requested_dumps
.length ())
1592 r
.write (" /* Requested dumps. */\n");
1593 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1594 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1596 r
.write (" gcc_jit_context_enable_dump (%s,\n"
1599 r
.get_identifier (contexts
[ctxt_idx
]),
1600 m_requested_dumps
[i
].m_dumpname
,
1601 (void *)&m_requested_dumps
[i
]);
1607 r
.write ("static void\ncreate_code (");
1608 r
.write_params (contexts
);
1611 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1618 r
.write (" /* Replay of API calls for %s. */\n",
1619 r
.get_identifier (contexts
[ctxt_idx
]));
1620 FOR_EACH_VEC_ELT (contexts
[ctxt_idx
]->m_mementos
, i
, m
)
1621 m
->write_reproducer (r
);
1626 /* Copy the requested dumps within this context and all ancestors into
1630 recording::context::get_all_requested_dumps (vec
<recording::requested_dump
> *out
)
1633 m_parent_ctxt
->get_all_requested_dumps (out
);
1635 out
->reserve (m_requested_dumps
.length ());
1636 out
->splice (m_requested_dumps
);
1639 /* This is a pre-compilation check for the context (and any parents).
1641 Detect errors within the context, adding errors if any are found. */
1644 recording::context::validate ()
1646 JIT_LOG_SCOPE (get_logger ());
1649 m_parent_ctxt
->validate ();
1653 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1657 /* The implementation of class gcc::jit::recording::memento. */
1659 /* Get a (const char *) debug description of the given memento, by
1660 calling the pure-virtual make_debug_string hook, caching the
1663 It is intended that this should only be called in debugging and
1664 error-handling paths, so this doesn't need to be particularly
1668 recording::memento::get_debug_string ()
1670 if (!m_debug_string
)
1671 m_debug_string
= make_debug_string ();
1672 return m_debug_string
->c_str ();
1675 /* Default implementation of recording::memento::write_to_dump, writing
1676 an indented form of the memento's debug string to the dump. */
1679 recording::memento::write_to_dump (dump
&d
)
1681 d
.write(" %s\n", get_debug_string ());
1684 /* The implementation of class gcc::jit::recording::string. */
1686 /* Constructor for gcc::jit::recording::string::string, allocating a
1687 copy of the given text using new char[]. */
1689 recording::string::string (context
*ctxt
, const char *text
)
1692 m_len
= strlen (text
);
1693 m_buffer
= new char[m_len
+ 1];
1694 strcpy (m_buffer
, text
);
1697 /* Destructor for gcc::jit::recording::string::string. */
1699 recording::string::~string ()
1704 /* Function for making gcc::jit::recording::string instances on a
1705 context via printf-style formatting.
1707 It is intended that this should only be called in debugging and
1708 error-handling paths, so this doesn't need to be particularly
1709 optimized, hence the double-copy of the string is acceptable. */
1712 recording::string::from_printf (context
*ctxt
, const char *fmt
, ...)
1717 recording::string
*result
;
1720 len
= vasprintf (&buf
, fmt
, ap
);
1723 if (buf
== NULL
|| len
< 0)
1725 ctxt
->add_error (NULL
, "malloc failure");
1729 result
= ctxt
->new_string (buf
);
1734 /* Implementation of recording::memento::make_debug_string for strings,
1735 wrapping the given string in quotes and escaping as necessary. */
1738 recording::string::make_debug_string ()
1740 /* Hack to avoid infinite recursion into strings when logging all
1741 mementos: don't re-escape strings: */
1742 if (m_buffer
[0] == '"')
1745 /* Wrap in quotes and do escaping etc */
1747 size_t sz
= (1 /* opening quote */
1748 + (m_len
* 2) /* each char might get escaped */
1749 + 1 /* closing quote */
1750 + 1); /* nil termintator */
1751 char *tmp
= new char[sz
];
1754 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1755 APPEND('"'); /* opening quote */
1756 for (size_t i
= 0; i
< m_len
; i
++)
1758 char ch
= m_buffer
[i
];
1759 if (ch
== '\t' || ch
== '\n' || ch
== '\\' || ch
== '"')
1763 APPEND('"'); /* closing quote */
1765 tmp
[len
] = '\0'; /* nil termintator */
1767 string
*result
= m_ctxt
->new_string (tmp
);
1773 /* Implementation of recording::memento::write_reproducer for strings. */
1776 recording::string::write_reproducer (reproducer
&)
1781 /* The implementation of class gcc::jit::recording::location. */
1783 /* Implementation of recording::memento::replay_into for locations.
1785 Create a new playback::location and store it into the
1786 recording::location's m_playback_obj field. */
1789 recording::location::replay_into (replayer
*r
)
1791 m_playback_obj
= r
->new_location (this,
1792 m_filename
->c_str (),
1797 /* Implementation of recording::memento::make_debug_string for locations,
1798 turning them into the usual form:
1799 FILENAME:LINE:COLUMN
1800 like we do when emitting diagnostics. */
1803 recording::location::make_debug_string ()
1805 return string::from_printf (m_ctxt
,
1807 m_filename
->c_str (), m_line
, m_column
);
1810 /* Implementation of recording::memento::write_reproducer for locations. */
1813 recording::location::write_reproducer (reproducer
&r
)
1815 const char *id
= r
.make_identifier (this, "loc");
1816 r
.write (" gcc_jit_location *%s =\n"
1817 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1818 " %s, /* const char *filename */\n"
1819 " %i, /* int line */\n"
1820 " %i);/* int column */\n",
1822 r
.get_identifier (get_context ()),
1823 m_filename
->get_debug_string (),
1827 /* The implementation of class gcc::jit::recording::type. */
1829 /* Given a type T, get the type T*.
1831 If this doesn't already exist, generate a new memento_of_get_pointer
1832 instance and add it to this type's context's list of mementos.
1834 Otherwise, use the cached type.
1836 Implements the post-error-checking part of
1837 gcc_jit_type_get_pointer. */
1840 recording::type::get_pointer ()
1842 if (!m_pointer_to_this_type
)
1844 m_pointer_to_this_type
= new memento_of_get_pointer (this);
1845 m_ctxt
->record (m_pointer_to_this_type
);
1847 return m_pointer_to_this_type
;
1850 /* Given a type T, get the type const T.
1852 Implements the post-error-checking part of
1853 gcc_jit_type_get_const. */
1856 recording::type::get_const ()
1858 recording::type
*result
= new memento_of_get_const (this);
1859 m_ctxt
->record (result
);
1863 /* Given a type T, get the type volatile T.
1865 Implements the post-error-checking part of
1866 gcc_jit_type_get_volatile. */
1869 recording::type::get_volatile ()
1871 recording::type
*result
= new memento_of_get_volatile (this);
1872 m_ctxt
->record (result
);
1877 recording::type::access_as_type (reproducer
&r
)
1879 return r
.get_identifier (this);
1882 /* Implementation of pure virtual hook recording::type::dereference for
1883 recording::memento_of_get_type. */
1886 recording::memento_of_get_type::dereference ()
1890 default: gcc_unreachable ();
1892 case GCC_JIT_TYPE_VOID
:
1895 case GCC_JIT_TYPE_VOID_PTR
:
1896 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
1898 case GCC_JIT_TYPE_BOOL
:
1899 case GCC_JIT_TYPE_CHAR
:
1900 case GCC_JIT_TYPE_SIGNED_CHAR
:
1901 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1902 case GCC_JIT_TYPE_SHORT
:
1903 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1904 case GCC_JIT_TYPE_INT
:
1905 case GCC_JIT_TYPE_UNSIGNED_INT
:
1906 case GCC_JIT_TYPE_LONG
:
1907 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1908 case GCC_JIT_TYPE_LONG_LONG
:
1909 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1910 case GCC_JIT_TYPE_FLOAT
:
1911 case GCC_JIT_TYPE_DOUBLE
:
1912 case GCC_JIT_TYPE_LONG_DOUBLE
:
1913 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1914 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1915 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1916 /* Not a pointer: */
1919 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1920 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
1922 case GCC_JIT_TYPE_SIZE_T
:
1923 /* Not a pointer: */
1926 case GCC_JIT_TYPE_FILE_PTR
:
1927 /* Give the client code back an opaque "struct FILE". */
1928 return m_ctxt
->get_opaque_FILE_type ();
1932 /* Implementation of pure virtual hook recording::type::is_int for
1933 recording::memento_of_get_type. */
1936 recording::memento_of_get_type::is_int () const
1940 default: gcc_unreachable ();
1942 case GCC_JIT_TYPE_VOID
:
1945 case GCC_JIT_TYPE_VOID_PTR
:
1948 case GCC_JIT_TYPE_BOOL
:
1951 case GCC_JIT_TYPE_CHAR
:
1952 case GCC_JIT_TYPE_SIGNED_CHAR
:
1953 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1954 case GCC_JIT_TYPE_SHORT
:
1955 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1956 case GCC_JIT_TYPE_INT
:
1957 case GCC_JIT_TYPE_UNSIGNED_INT
:
1958 case GCC_JIT_TYPE_LONG
:
1959 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1960 case GCC_JIT_TYPE_LONG_LONG
:
1961 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1964 case GCC_JIT_TYPE_FLOAT
:
1965 case GCC_JIT_TYPE_DOUBLE
:
1966 case GCC_JIT_TYPE_LONG_DOUBLE
:
1969 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1972 case GCC_JIT_TYPE_SIZE_T
:
1975 case GCC_JIT_TYPE_FILE_PTR
:
1978 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1979 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1980 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1985 /* Implementation of pure virtual hook recording::type::is_float for
1986 recording::memento_of_get_type. */
1989 recording::memento_of_get_type::is_float () const
1993 default: gcc_unreachable ();
1995 case GCC_JIT_TYPE_VOID
:
1998 case GCC_JIT_TYPE_VOID_PTR
:
2001 case GCC_JIT_TYPE_BOOL
:
2004 case GCC_JIT_TYPE_CHAR
:
2005 case GCC_JIT_TYPE_SIGNED_CHAR
:
2006 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2007 case GCC_JIT_TYPE_SHORT
:
2008 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2009 case GCC_JIT_TYPE_INT
:
2010 case GCC_JIT_TYPE_UNSIGNED_INT
:
2011 case GCC_JIT_TYPE_LONG
:
2012 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2013 case GCC_JIT_TYPE_LONG_LONG
:
2014 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2017 case GCC_JIT_TYPE_FLOAT
:
2018 case GCC_JIT_TYPE_DOUBLE
:
2019 case GCC_JIT_TYPE_LONG_DOUBLE
:
2022 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2025 case GCC_JIT_TYPE_SIZE_T
:
2028 case GCC_JIT_TYPE_FILE_PTR
:
2031 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2032 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2033 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2038 /* Implementation of pure virtual hook recording::type::is_bool for
2039 recording::memento_of_get_type. */
2042 recording::memento_of_get_type::is_bool () const
2046 default: gcc_unreachable ();
2048 case GCC_JIT_TYPE_VOID
:
2051 case GCC_JIT_TYPE_VOID_PTR
:
2054 case GCC_JIT_TYPE_BOOL
:
2057 case GCC_JIT_TYPE_CHAR
:
2058 case GCC_JIT_TYPE_SIGNED_CHAR
:
2059 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2060 case GCC_JIT_TYPE_SHORT
:
2061 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2062 case GCC_JIT_TYPE_INT
:
2063 case GCC_JIT_TYPE_UNSIGNED_INT
:
2064 case GCC_JIT_TYPE_LONG
:
2065 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2066 case GCC_JIT_TYPE_LONG_LONG
:
2067 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2070 case GCC_JIT_TYPE_FLOAT
:
2071 case GCC_JIT_TYPE_DOUBLE
:
2072 case GCC_JIT_TYPE_LONG_DOUBLE
:
2075 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2078 case GCC_JIT_TYPE_SIZE_T
:
2081 case GCC_JIT_TYPE_FILE_PTR
:
2084 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2085 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2086 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2091 /* Implementation of pure virtual hook recording::memento::replay_into
2092 for recording::memento_of_get_type. */
2095 recording::memento_of_get_type::replay_into (replayer
*r
)
2097 set_playback_obj (r
->get_type (m_kind
));
2100 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2102 /* Descriptive strings for each of enum gcc_jit_types. */
2104 static const char * const get_type_strings
[] = {
2105 "void", /* GCC_JIT_TYPE_VOID */
2106 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2108 "bool", /* GCC_JIT_TYPE_BOOL */
2110 "char", /* GCC_JIT_TYPE_CHAR */
2111 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2112 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2114 "short", /* GCC_JIT_TYPE_SHORT */
2115 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2117 "int", /* GCC_JIT_TYPE_INT */
2118 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2120 "long", /* GCC_JIT_TYPE_LONG */
2121 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2123 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2124 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2126 "float", /* GCC_JIT_TYPE_FLOAT */
2127 "double", /* GCC_JIT_TYPE_DOUBLE */
2128 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2130 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2132 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2134 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2136 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2137 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2138 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2142 /* Implementation of recording::memento::make_debug_string for
2143 results of get_type, using a simple table of type names. */
2146 recording::memento_of_get_type::make_debug_string ()
2148 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
2151 static const char * const get_type_enum_strings
[] = {
2152 "GCC_JIT_TYPE_VOID",
2153 "GCC_JIT_TYPE_VOID_PTR",
2154 "GCC_JIT_TYPE_BOOL",
2155 "GCC_JIT_TYPE_CHAR",
2156 "GCC_JIT_TYPE_SIGNED_CHAR",
2157 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2158 "GCC_JIT_TYPE_SHORT",
2159 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2161 "GCC_JIT_TYPE_UNSIGNED_INT",
2162 "GCC_JIT_TYPE_LONG",
2163 "GCC_JIT_TYPE_UNSIGNED_LONG",
2164 "GCC_JIT_TYPE_LONG_LONG",
2165 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2166 "GCC_JIT_TYPE_FLOAT",
2167 "GCC_JIT_TYPE_DOUBLE",
2168 "GCC_JIT_TYPE_LONG_DOUBLE",
2169 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2170 "GCC_JIT_TYPE_SIZE_T",
2171 "GCC_JIT_TYPE_FILE_PTR",
2172 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2173 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2174 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2178 recording::memento_of_get_type::write_reproducer (reproducer
&r
)
2180 const char *id
= r
.make_identifier (this, "type");
2181 r
.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2183 r
.get_identifier (get_context ()),
2184 get_type_enum_strings
[m_kind
]);
2187 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2189 /* Override of default implementation of
2190 recording::type::accepts_writes_from for get_pointer.
2192 Require a pointer type, and allowing writes to
2193 (const T *) from a (T*), but not the other way around. */
2196 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
2198 /* Must be a pointer type: */
2199 type
*rtype_points_to
= rtype
->is_pointer ();
2200 if (!rtype_points_to
)
2203 /* It's OK to assign to a (const T *) from a (T *). */
2204 return m_other_type
->unqualified ()
2205 ->accepts_writes_from (rtype_points_to
);
2208 /* Implementation of pure virtual hook recording::memento::replay_into
2209 for recording::memento_of_get_pointer. */
2212 recording::memento_of_get_pointer::replay_into (replayer
*)
2214 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
2217 /* Implementation of recording::memento::make_debug_string for
2218 results of get_pointer, adding " *" to the underlying type,
2219 with special-casing to handle function pointer types. */
2222 recording::memento_of_get_pointer::make_debug_string ()
2224 /* Special-case function pointer types, to put the "*" in parens between
2225 the return type and the params (for one level of dereferencing, at
2227 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2228 return fn_type
->make_debug_string_with_ptr ();
2230 return string::from_printf (m_ctxt
,
2231 "%s *", m_other_type
->get_debug_string ());
2234 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2237 recording::memento_of_get_pointer::write_reproducer (reproducer
&r
)
2239 /* We need to special-case function pointer types; see the notes in
2240 recording::function_type::write_deferred_reproducer. */
2241 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2243 fn_type
->write_deferred_reproducer (r
, this);
2247 const char *id
= r
.make_identifier (this, "type");
2248 r
.write (" gcc_jit_type *%s =\n"
2249 " gcc_jit_type_get_pointer (%s);\n",
2251 r
.get_identifier_as_type (m_other_type
));
2254 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2256 /* Implementation of pure virtual hook recording::memento::replay_into
2257 for recording::memento_of_get_const. */
2260 recording::memento_of_get_const::replay_into (replayer
*)
2262 set_playback_obj (m_other_type
->playback_type ()->get_const ());
2265 /* Implementation of recording::memento::make_debug_string for
2266 results of get_const, prepending "const ". */
2269 recording::memento_of_get_const::make_debug_string ()
2271 return string::from_printf (m_ctxt
,
2272 "const %s", m_other_type
->get_debug_string ());
2275 /* Implementation of recording::memento::write_reproducer for const types. */
2278 recording::memento_of_get_const::write_reproducer (reproducer
&r
)
2280 const char *id
= r
.make_identifier (this, "type");
2281 r
.write (" gcc_jit_type *%s =\n"
2282 " gcc_jit_type_get_const (%s);\n",
2284 r
.get_identifier_as_type (m_other_type
));
2287 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2289 /* Implementation of pure virtual hook recording::memento::replay_into
2290 for recording::memento_of_get_volatile. */
2293 recording::memento_of_get_volatile::replay_into (replayer
*)
2295 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
2298 /* Implementation of recording::memento::make_debug_string for
2299 results of get_volatile, prepending "volatile ". */
2302 recording::memento_of_get_volatile::make_debug_string ()
2304 return string::from_printf (m_ctxt
,
2305 "volatile %s", m_other_type
->get_debug_string ());
2308 /* Implementation of recording::memento::write_reproducer for volatile
2312 recording::memento_of_get_volatile::write_reproducer (reproducer
&r
)
2314 const char *id
= r
.make_identifier (this, "type");
2315 r
.write (" gcc_jit_type *%s =\n"
2316 " gcc_jit_type_get_volatile (%s);\n",
2318 r
.get_identifier_as_type (m_other_type
));
2321 /* The implementation of class gcc::jit::recording::array_type */
2323 /* Implementation of pure virtual hook recording::type::dereference for
2324 recording::array_type. */
2327 recording::array_type::dereference ()
2329 return m_element_type
;
2332 /* Implementation of pure virtual hook recording::memento::replay_into
2333 for recording::array_type. */
2336 recording::array_type::replay_into (replayer
*r
)
2338 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
2339 m_element_type
->playback_type (),
2343 /* Implementation of recording::memento::make_debug_string for
2344 results of new_array_type. */
2347 recording::array_type::make_debug_string ()
2349 return string::from_printf (m_ctxt
,
2351 m_element_type
->get_debug_string (),
2355 /* Implementation of recording::memento::write_reproducer for array
2359 recording::array_type::write_reproducer (reproducer
&r
)
2361 const char *id
= r
.make_identifier (this, "array_type");
2362 r
.write (" gcc_jit_type *%s =\n"
2363 " gcc_jit_context_new_array_type (%s,\n"
2364 " %s, /* gcc_jit_location *loc */\n"
2365 " %s, /* gcc_jit_type *element_type */\n"
2366 " %i); /* int num_elements */\n",
2368 r
.get_identifier (get_context ()),
2369 r
.get_identifier (m_loc
),
2370 r
.get_identifier_as_type (m_element_type
),
2374 /* The implementation of class gcc::jit::recording::function_type */
2376 /* Constructor for gcc::jit::recording::function_type. */
2378 recording::function_type::function_type (context
*ctxt
,
2384 m_return_type (return_type
),
2386 m_is_variadic (is_variadic
)
2388 for (int i
= 0; i
< num_params
; i
++)
2389 m_param_types
.safe_push (param_types
[i
]);
2392 /* Implementation of pure virtual hook recording::type::dereference for
2393 recording::function_type. */
2396 recording::function_type::dereference ()
2401 /* Implementation of pure virtual hook recording::memento::replay_into
2402 for recording::function_type. */
2405 recording::function_type::replay_into (replayer
*r
)
2407 /* Convert m_param_types to a vec of playback type. */
2408 auto_vec
<playback::type
*> param_types
;
2410 recording::type
*type
;
2411 param_types
.create (m_param_types
.length ());
2412 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
2413 param_types
.safe_push (type
->playback_type ());
2415 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
2420 /* Special-casing for make_debug_string for get_pointer results for
2421 handling (one level) of pointers to functions. */
2424 recording::function_type::make_debug_string_with_ptr ()
2426 return make_debug_string_with ("(*) ");
2429 /* Implementation of recording::memento::make_debug_string for
2430 results of new_function_type. */
2433 recording::function_type::make_debug_string ()
2435 return make_debug_string_with ("");
2438 /* Build a debug string representation of the form:
2440 RESULT_TYPE INSERT (PARAM_TYPES)
2442 for use when handling 0 and 1 level of indirection to this
2446 recording::function_type::make_debug_string_with (const char *insert
)
2448 /* First, build a buffer for the arguments. */
2449 /* Calculate length of said buffer. */
2450 size_t sz
= 1; /* nil terminator */
2451 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2453 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
2454 sz
+= 2; /* ", " separator */
2457 sz
+= 5; /* ", ..." separator and ellipsis */
2459 /* Now allocate and populate the buffer. */
2460 char *argbuf
= new char[sz
];
2463 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2465 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
2466 len
+= strlen (m_param_types
[i
]->get_debug_string ());
2467 if (i
+ 1 < m_param_types
.length ())
2469 strcpy (argbuf
+ len
, ", ");
2475 if (m_param_types
.length ())
2477 strcpy (argbuf
+ len
, ", ");
2480 strcpy (argbuf
+ len
, "...");
2485 /* ...and use it to get the string for the call as a whole. */
2486 string
*result
= string::from_printf (m_ctxt
,
2488 m_return_type
->get_debug_string (),
2497 /* Implementation of recording::memento::write_reproducer for function
2501 recording::function_type::write_reproducer (reproducer
&)
2503 /* see notes below. */
2506 /* There's a get_pointer within context::new_function_ptr_type:
2507 the type received by client code isn't the memento for the
2508 function_type, but instead the result of get_pointer on it.
2510 Hence we can't directly write a reproducer that gives function_type.
2511 Instead we special-case things within get_pointer, detecting this
2512 case, calling the following function. */
2515 recording::function_type::write_deferred_reproducer (reproducer
&r
,
2518 gcc_assert (ptr_type
);
2519 r
.make_identifier (this, "function_type");
2520 const char *ptr_id
= r
.make_identifier (ptr_type
, "ptr_to");
2521 const char *param_types_id
= r
.make_tmp_identifier ("params_for", this);
2522 r
.write (" gcc_jit_type *%s[%i] = {\n",
2524 m_param_types
.length ());
2527 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
2528 r
.write (" %s,\n", r
.get_identifier_as_type (param_type
));
2530 r
.write (" gcc_jit_type *%s =\n"
2531 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2532 " %s, /* gcc_jit_location *loc */\n"
2533 " %s, /* gcc_jit_type *return_type */\n"
2534 " %i, /* int num_params */\n"
2535 " %s, /* gcc_jit_type **param_types */\n"
2536 " %i); /* int is_variadic */\n",
2538 r
.get_identifier (get_context ()),
2539 "NULL", /* location is not stored */
2540 r
.get_identifier_as_type (m_return_type
),
2541 m_param_types
.length (),
2546 /* The implementation of class gcc::jit::recording::field. */
2548 /* Implementation of pure virtual hook recording::memento::replay_into
2549 for recording::field. */
2552 recording::field::replay_into (replayer
*r
)
2554 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
2555 m_type
->playback_type (),
2556 playback_string (m_name
)));
2559 /* Override the default implementation of
2560 recording::memento::write_to_dump. Dump each field
2561 by dumping a line of the form:
2563 so that we can build up a struct/union field-byfield. */
2566 recording::field::write_to_dump (dump
&d
)
2568 d
.write (" %s %s;\n",
2569 m_type
->get_debug_string (),
2573 /* Implementation of recording::memento::make_debug_string for
2574 results of new_field. */
2577 recording::field::make_debug_string ()
2582 /* Implementation of recording::memento::write_reproducer for fields. */
2585 recording::field::write_reproducer (reproducer
&r
)
2587 const char *id
= r
.make_identifier (this, "field");
2588 r
.write(" gcc_jit_field *%s =\n"
2589 " gcc_jit_context_new_field (%s,\n"
2590 " %s, /* gcc_jit_location *loc */\n"
2591 " %s, /* gcc_jit_type *type, */\n"
2592 " %s); /* const char *name */\n",
2594 r
.get_identifier (get_context ()),
2595 r
.get_identifier (m_loc
),
2596 r
.get_identifier_as_type (m_type
),
2597 m_name
->get_debug_string ());
2600 /* The implementation of class gcc::jit::recording::compound_type */
2602 /* The constructor for gcc::jit::recording::compound_type. */
2604 recording::compound_type::compound_type (context
*ctxt
,
2614 /* Set the fields of a compound type.
2616 Implements the post-error-checking part of
2617 gcc_jit_struct_set_fields, and is also used by
2618 gcc_jit_context_new_union_type. */
2621 recording::compound_type::set_fields (location
*loc
,
2623 field
**field_array
)
2626 gcc_assert (NULL
== m_fields
);
2628 m_fields
= new fields (this, num_fields
, field_array
);
2629 m_ctxt
->record (m_fields
);
2632 /* Implementation of pure virtual hook recording::type::dereference for
2633 recording::compound_type. */
2636 recording::compound_type::dereference ()
2638 return NULL
; /* not a pointer */
2641 /* The implementation of class gcc::jit::recording::struct_. */
2643 /* The constructor for gcc::jit::recording::struct_. */
2645 recording::struct_::struct_ (context
*ctxt
,
2648 : compound_type (ctxt
, loc
, name
)
2652 /* Implementation of pure virtual hook recording::memento::replay_into
2653 for recording::struct_. */
2656 recording::struct_::replay_into (replayer
*r
)
2659 r
->new_compound_type (playback_location (r
, get_loc ()),
2660 get_name ()->c_str (),
2661 true /* is_struct */));
2665 recording::struct_::access_as_type (reproducer
&r
)
2667 return r
.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2668 r
.get_identifier (this));
2671 /* Implementation of recording::memento::make_debug_string for
2675 recording::struct_::make_debug_string ()
2677 return string::from_printf (m_ctxt
,
2678 "struct %s", get_name ()->c_str ());
2682 recording::struct_::write_reproducer (reproducer
&r
)
2684 const char *id
= r
.make_identifier (this, "struct");
2685 r
.write (" gcc_jit_struct *%s =\n"
2686 " gcc_jit_context_new_opaque_struct (%s,\n"
2687 " %s, /* gcc_jit_location *loc */\n"
2688 " %s); /* const char *name */\n",
2690 r
.get_identifier (get_context ()),
2691 r
.get_identifier (get_loc ()),
2692 get_name ()->get_debug_string ());
2695 /* The implementation of class gcc::jit::recording::union_. */
2697 /* The constructor for gcc::jit::recording::union_. */
2699 recording::union_::union_ (context
*ctxt
,
2702 : compound_type (ctxt
, loc
, name
)
2706 /* Implementation of pure virtual hook recording::memento::replay_into
2707 for recording::union_. */
2710 recording::union_::replay_into (replayer
*r
)
2713 r
->new_compound_type (playback_location (r
, get_loc ()),
2714 get_name ()->c_str (),
2715 false /* is_struct */));
2718 /* Implementation of recording::memento::make_debug_string for
2722 recording::union_::make_debug_string ()
2724 return string::from_printf (m_ctxt
,
2725 "union %s", get_name ()->c_str ());
2728 /* Implementation of recording::memento::write_reproducer for unions. */
2731 recording::union_::write_reproducer (reproducer
&r
)
2733 const char *id
= r
.make_identifier (this, "union");
2735 const char *fields_id
= r
.make_tmp_identifier ("fields_for", this);
2736 r
.write (" gcc_jit_field *%s[%i] = {\n",
2738 get_fields ()->length ());
2739 for (int i
= 0; i
< get_fields ()->length (); i
++)
2740 r
.write (" %s,\n", r
.get_identifier (get_fields ()->get_field (i
)));
2743 r
.write (" gcc_jit_type *%s =\n"
2744 " gcc_jit_context_new_union_type (%s,\n"
2745 " %s, /* gcc_jit_location *loc */\n"
2746 " %s, /* const char *name */\n"
2747 " %i, /* int num_fields */\n"
2748 " %s); /* gcc_jit_field **fields */\n",
2750 r
.get_identifier (get_context ()),
2751 r
.get_identifier (get_loc ()),
2752 get_name ()->get_debug_string (),
2753 get_fields ()->length (),
2757 /* The implementation of class gcc::jit::recording::fields. */
2759 /* The constructor for gcc::jit::recording::fields. */
2761 recording::fields::fields (compound_type
*struct_or_union
,
2764 : memento (struct_or_union
->m_ctxt
),
2765 m_struct_or_union (struct_or_union
),
2768 for (int i
= 0; i
< num_fields
; i
++)
2770 gcc_assert (fields
[i
]->get_container () == NULL
);
2771 fields
[i
]->set_container (m_struct_or_union
);
2772 m_fields
.safe_push (fields
[i
]);
2776 /* Implementation of pure virtual hook recording::memento::replay_into
2777 for recording::fields. */
2780 recording::fields::replay_into (replayer
*)
2782 auto_vec
<playback::field
*> playback_fields
;
2783 playback_fields
.create (m_fields
.length ());
2784 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
2785 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
2786 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
2789 /* Override the default implementation of
2790 recording::memento::write_to_dump by writing a union/struct
2791 declaration of this form:
2803 recording::fields::write_to_dump (dump
&d
)
2808 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
2809 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
2810 f
->write_to_dump (d
);
2814 /* Implementation of recording::memento::write_reproducer for the fields
2818 recording::fields::write_reproducer (reproducer
&r
)
2820 if (m_struct_or_union
)
2821 if (NULL
== m_struct_or_union
->dyn_cast_struct ())
2822 /* We have a union; the fields have already been written by
2823 union::write_reproducer. */
2826 const char *fields_id
= r
.make_identifier (this, "fields");
2827 r
.write (" gcc_jit_field *%s[%i] = {\n",
2829 m_fields
.length ());
2832 FOR_EACH_VEC_ELT (m_fields
, i
, field
)
2833 r
.write (" %s,\n", r
.get_identifier (field
));
2836 r
.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
2837 " %s, /* gcc_jit_location *loc */\n"
2838 " %i, /* int num_fields */\n"
2839 " %s); /* gcc_jit_field **fields */\n",
2840 r
.get_identifier (m_struct_or_union
),
2841 r
.get_identifier ((memento
*)NULL
),
2846 /* Implementation of recording::memento::make_debug_string for
2850 recording::fields::make_debug_string ()
2852 return string::from_printf (m_ctxt
,
2856 /* The implementation of class gcc::jit::recording::rvalue. */
2858 /* Create a recording::access_field_rvalue instance and add it to
2859 the rvalue's context's list of mementos.
2861 Implements the post-error-checking part of
2862 gcc_jit_rvalue_access_field. */
2865 recording::rvalue::access_field (recording::location
*loc
,
2868 recording::rvalue
*result
=
2869 new access_field_rvalue (m_ctxt
, loc
, this, field
);
2870 m_ctxt
->record (result
);
2874 /* Create a recording::dereference_field_rvalue instance and add it to
2875 the rvalue's context's list of mementos.
2877 Implements the post-error-checking part of
2878 gcc_jit_rvalue_dereference_field. */
2881 recording::rvalue::dereference_field (recording::location
*loc
,
2884 recording::lvalue
*result
=
2885 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
2886 m_ctxt
->record (result
);
2890 /* Create a recording::dereference_rvalue instance and add it to the
2891 rvalue's context's list of mementos.
2893 Implements the post-error-checking part of
2894 gcc_jit_rvalue_dereference. */
2897 recording::rvalue::dereference (recording::location
*loc
)
2899 recording::lvalue
*result
=
2900 new dereference_rvalue (m_ctxt
, loc
, this);
2901 m_ctxt
->record (result
);
2905 /* An rvalue visitor, for validating that every rvalue within an expression
2906 trees within "STMT" has the correct scope (e.g. no access to locals
2907 of a different function). */
2909 class rvalue_usage_validator
: public recording::rvalue_visitor
2912 rvalue_usage_validator (const char *api_funcname
,
2913 recording::context
*ctxt
,
2914 recording::statement
*stmt
);
2917 visit (recording::rvalue
*rvalue
);
2920 const char *m_api_funcname
;
2921 recording::context
*m_ctxt
;
2922 recording::statement
*m_stmt
;
2925 /* The trivial constructor for rvalue_usage_validator. */
2927 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname
,
2928 recording::context
*ctxt
,
2929 recording::statement
*stmt
)
2930 : m_api_funcname (api_funcname
),
2936 /* Verify that the given rvalue is in the correct scope. */
2939 rvalue_usage_validator::visit (recording::rvalue
*rvalue
)
2941 gcc_assert (m_stmt
->get_block ());
2942 recording::function
*stmt_scope
= m_stmt
->get_block ()->get_function ();
2944 /* Most rvalues don't have a scope (only locals and params). */
2945 if (rvalue
->get_scope ())
2947 if (rvalue
->get_scope () != stmt_scope
)
2949 (rvalue
->get_loc (),
2951 " rvalue %s (type: %s)"
2952 " has scope limited to function %s"
2953 " but was used within function %s"
2954 " (in statement: %s)",
2956 rvalue
->get_debug_string (),
2957 rvalue
->get_type ()->get_debug_string (),
2958 rvalue
->get_scope ()->get_debug_string (),
2959 stmt_scope
->get_debug_string (),
2960 m_stmt
->get_debug_string ());
2964 if (rvalue
->dyn_cast_param ())
2966 (rvalue
->get_loc (),
2968 " param %s (type: %s)"
2969 " was used within function %s"
2970 " (in statement: %s)"
2971 " but is not associated with any function",
2973 rvalue
->get_debug_string (),
2974 rvalue
->get_type ()->get_debug_string (),
2975 stmt_scope
->get_debug_string (),
2976 m_stmt
->get_debug_string ());
2980 /* Verify that it's valid to use this rvalue (and all expressions
2981 in the tree below it) within the given statement.
2983 For example, we must reject attempts to use a local from one
2984 function within a different function here, or we'll get
2985 an ICE deep inside toplev::main. */
2988 recording::rvalue::verify_valid_within_stmt (const char *api_funcname
, statement
*s
)
2990 rvalue_usage_validator
v (api_funcname
,
2994 /* Verify that it's OK to use this rvalue within s. */
2997 /* Traverse the expression tree below "this", verifying all rvalues
2999 visit_children (&v
);
3002 /* Set the scope of this rvalue to be the given function. This can only
3003 be done once on a given rvalue. */
3006 recording::rvalue::set_scope (function
*scope
)
3009 gcc_assert (NULL
== m_scope
);
3014 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3016 Instances of rvalue don't need an upcast call. */
3019 recording::rvalue::access_as_rvalue (reproducer
&r
)
3021 return r
.get_identifier (this);
3024 /* Return a debug string for the given rvalue, wrapping it in parentheses
3025 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3026 stronger precedence that this rvalue's precedence.
3040 since MULT has strong precedence than PLUS and MINUS, whereas for:
3052 since PLUS has weaker precedence than MULT and DIVIDE. */
3055 recording::rvalue::get_debug_string_parens (enum precedence outer_prec
)
3057 enum precedence this_prec
= get_precedence ();
3059 /* If this_prec has stronger precedence than outer_prec, we don't
3060 need to wrap this in parens within the outer debug string.
3061 Stronger precedences occur earlier than weaker within the enum,
3062 so this is a less than test. Equal precedences don't need
3064 if (this_prec
<= outer_prec
)
3065 return get_debug_string();
3067 /* Otherwise, we need parentheses. */
3069 /* Lazily-build and cache m_parenthesized_string. */
3070 if (!m_parenthesized_string
)
3072 const char *debug_string
= get_debug_string ();
3073 m_parenthesized_string
= string::from_printf (get_context (),
3077 gcc_assert (m_parenthesized_string
);
3078 return m_parenthesized_string
->c_str ();
3082 /* The implementation of class gcc::jit::recording::lvalue. */
3084 /* Create a recording::new_access_field_of_lvalue instance and add it to
3085 the lvalue's context's list of mementos.
3087 Implements the post-error-checking part of
3088 gcc_jit_lvalue_access_field. */
3091 recording::lvalue::access_field (recording::location
*loc
,
3094 recording::lvalue
*result
=
3095 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
3096 m_ctxt
->record (result
);
3100 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3101 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3105 recording::lvalue::access_as_rvalue (reproducer
&r
)
3107 return r
.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3108 r
.get_identifier (this));
3111 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3112 Instances of lvalue don't need to be upcast. */
3115 recording::lvalue::access_as_lvalue (reproducer
&r
)
3117 return r
.get_identifier (this);
3120 /* Create a recording::get_address_of_lvalue instance and add it to
3121 the lvalue's context's list of mementos.
3123 Implements the post-error-checking part of
3124 gcc_jit_lvalue_get_address. */
3127 recording::lvalue::get_address (recording::location
*loc
)
3129 recording::rvalue
*result
=
3130 new get_address_of_lvalue (m_ctxt
, loc
, this);
3131 m_ctxt
->record (result
);
3135 /* The implementation of class gcc::jit::recording::param. */
3137 /* Implementation of pure virtual hook recording::memento::replay_into
3138 for recording::param. */
3141 recording::param::replay_into (replayer
*r
)
3143 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
3144 m_type
->playback_type (),
3148 /* Implementation of recording::rvalue::access_as_rvalue for params.
3149 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3153 recording::param::access_as_rvalue (reproducer
&r
)
3155 return r
.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3156 r
.get_identifier (this));
3159 /* Implementation of recording::lvalue::access_as_lvalue for params.
3160 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3164 recording::param::access_as_lvalue (reproducer
&r
)
3166 return r
.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3167 r
.get_identifier (this));
3170 /* Implementation of recording::memento::write_reproducer for params. */
3173 recording::param::write_reproducer (reproducer
&r
)
3175 const char *id
= r
.make_identifier (this, "param");
3176 r
.write (" gcc_jit_param *%s =\n"
3177 " gcc_jit_context_new_param (%s,\n"
3178 " %s, /* gcc_jit_location *loc */\n"
3179 " %s, /*gcc_jit_type *type */\n"
3180 " %s); /* const char *name */\n",
3182 r
.get_identifier (get_context ()),
3183 r
.get_identifier (m_loc
),
3184 r
.get_identifier_as_type (m_type
),
3185 m_name
->get_debug_string ());
3188 /* The implementation of class gcc::jit::recording::function. */
3190 /* gcc::jit::recording::function's constructor. */
3192 recording::function::function (context
*ctxt
,
3193 recording::location
*loc
,
3194 enum gcc_jit_function_kind kind
,
3196 recording::string
*name
,
3198 recording::param
**params
,
3200 enum built_in_function builtin_id
)
3204 m_return_type (return_type
),
3207 m_is_variadic (is_variadic
),
3208 m_builtin_id (builtin_id
),
3212 for (int i
= 0; i
< num_params
; i
++)
3214 param
*param
= params
[i
];
3217 /* Associate each param with this function.
3219 Verify that the param doesn't already have a function. */
3220 if (param
->get_scope ())
3222 /* We've already rejected attempts to reuse a param between
3223 different functions (within gcc_jit_context_new_function), so
3224 if the param *does* already have a function, it must be being
3225 reused within the params array for this function. We must
3226 produce an error for this reuse (blocking the compile), since
3227 otherwise we'd have an ICE later on. */
3228 gcc_assert (this == param
->get_scope ());
3231 "gcc_jit_context_new_function:"
3232 " parameter %s (type: %s)"
3233 " is used more than once when creating function %s",
3234 param
->get_debug_string (),
3235 param
->get_type ()->get_debug_string (),
3240 /* The normal, non-error case: associate this function with the
3242 param
->set_scope (this);
3245 m_params
.safe_push (param
);
3249 /* Implementation of pure virtual hook recording::memento::replay_into
3250 for recording::function. */
3253 recording::function::replay_into (replayer
*r
)
3255 /* Convert m_params to a vec of playback param. */
3256 auto_vec
<playback::param
*> params
;
3258 recording::param
*param
;
3259 params
.create (m_params
.length ());
3260 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3261 params
.safe_push (param
->playback_param ());
3263 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
3265 m_return_type
->playback_type (),
3272 /* Create a recording::local instance and add it to
3273 the functions's context's list of mementos, and to the function's
3276 Implements the post-error-checking part of
3277 gcc_jit_function_new_local. */
3280 recording::function::new_local (recording::location
*loc
,
3284 local
*result
= new local (this, loc
, type
, new_string (name
));
3285 m_ctxt
->record (result
);
3286 m_locals
.safe_push (result
);
3290 /* Create a recording::block instance and add it to
3291 the functions's context's list of mementos, and to the function's
3294 Implements the post-error-checking part of
3295 gcc_jit_function_new_block. */
3298 recording::function::new_block (const char *name
)
3300 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
3302 recording::block
*result
=
3303 new recording::block (this, m_blocks
.length (), new_string (name
));
3304 m_ctxt
->record (result
);
3305 m_blocks
.safe_push (result
);
3309 /* Override the default implementation of
3310 recording::memento::write_to_dump by dumping a C-like
3311 representation of the function; either like a prototype
3312 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3313 all other kinds of function. */
3316 recording::function::write_to_dump (dump
&d
)
3320 default: gcc_unreachable ();
3321 case GCC_JIT_FUNCTION_EXPORTED
:
3322 case GCC_JIT_FUNCTION_IMPORTED
:
3323 d
.write ("extern ");
3325 case GCC_JIT_FUNCTION_INTERNAL
:
3326 d
.write ("static ");
3328 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
3329 d
.write ("static inline ");
3332 d
.write ("%s\n", m_return_type
->get_debug_string ());
3334 if (d
.update_locations ())
3335 m_loc
= d
.make_location ();
3337 d
.write ("%s (", get_debug_string ());
3340 recording::param
*param
;
3341 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3346 param
->get_type ()->get_debug_string (),
3347 param
->get_debug_string ());
3350 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
3352 d
.write ("; /* (imported) */\n\n");
3362 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
3363 var
->write_to_dump (d
);
3364 if (m_locals
.length ())
3367 /* Write each block: */
3368 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3372 b
->write_to_dump (d
);
3379 /* Pre-compilation validation of a function, for those things we can't
3380 check until the context is (supposedly) fully-populated. */
3383 recording::function::validate ()
3385 /* Complain about empty functions with non-void return type. */
3386 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
3387 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
3388 if (0 == m_blocks
.length ())
3389 m_ctxt
->add_error (m_loc
,
3390 "function %s returns non-void (type: %s)"
3391 " but has no blocks",
3392 get_debug_string (),
3393 m_return_type
->get_debug_string ());
3395 /* Check that all blocks are terminated. */
3396 int num_invalid_blocks
= 0;
3401 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3402 if (!b
->validate ())
3403 num_invalid_blocks
++;
3406 /* Check that all blocks are reachable. */
3407 if (m_blocks
.length () > 0 && 0 == num_invalid_blocks
)
3409 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3410 flag, starting at the initial block. */
3411 auto_vec
<block
*> worklist (m_blocks
.length ());
3412 worklist
.safe_push (m_blocks
[0]);
3413 while (worklist
.length () > 0)
3415 block
*b
= worklist
.pop ();
3416 b
->m_is_reachable
= true;
3418 /* Add successor blocks that aren't yet marked to the worklist. */
3419 /* We checked that each block has a terminating statement above . */
3420 block
*next1
, *next2
;
3421 int n
= b
->get_successor_blocks (&next1
, &next2
);
3427 if (!next2
->m_is_reachable
)
3428 worklist
.safe_push (next2
);
3431 if (!next1
->m_is_reachable
)
3432 worklist
.safe_push (next1
);
3439 /* Now complain about any blocks that haven't been marked. */
3443 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3444 if (!b
->m_is_reachable
)
3445 m_ctxt
->add_error (b
->get_loc (),
3446 "unreachable block: %s",
3447 b
->get_debug_string ());
3452 /* Implements the post-error-checking part of
3453 gcc_jit_function_dump_to_dot. */
3456 recording::function::dump_to_dot (const char *path
)
3458 FILE *fp
= fopen (path
, "w");
3462 pretty_printer the_pp
;
3463 the_pp
.buffer
->stream
= fp
;
3465 pretty_printer
*pp
= &the_pp
;
3468 "digraph %s {\n", get_debug_string ());
3474 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3475 b
->dump_to_dot (pp
);
3482 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3483 b
->dump_edges_to_dot (pp
);
3486 pp_printf (pp
, "}\n");
3491 /* Implementation of recording::memento::make_debug_string for
3495 recording::function::make_debug_string ()
3500 /* A table of enum gcc_jit_function_kind values expressed in string
3503 static const char * const names_of_function_kinds
[] = {
3504 "GCC_JIT_FUNCTION_EXPORTED",
3505 "GCC_JIT_FUNCTION_INTERNAL",
3506 "GCC_JIT_FUNCTION_IMPORTED",
3507 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3510 /* Implementation of recording::memento::write_reproducer for functions. */
3513 recording::function::write_reproducer (reproducer
&r
)
3515 const char *id
= r
.make_identifier (this, "func");
3519 r
.write (" gcc_jit_function *%s =\n"
3520 " gcc_jit_context_get_builtin_function (%s,\n"
3523 r
.get_identifier (get_context ()),
3524 m_name
->get_debug_string ());
3527 const char *params_id
= r
.make_tmp_identifier ("params_for", this);
3528 r
.write (" gcc_jit_param *%s[%i] = {\n",
3530 m_params
.length ());
3533 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3534 r
.write (" %s,\n", r
.get_identifier (param
));
3536 r
.write (" gcc_jit_function *%s =\n"
3537 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3538 " %s, /* gcc_jit_location *loc */\n"
3539 " %s, /* enum gcc_jit_function_kind kind */\n"
3540 " %s, /* gcc_jit_type *return_type */\n"
3541 " %s, /* const char *name */\n"
3542 " %i, /* int num_params */\n"
3543 " %s, /* gcc_jit_param **params */\n"
3544 " %i); /* int is_variadic */\n",
3546 r
.get_identifier (get_context ()),
3547 r
.get_identifier (m_loc
),
3548 names_of_function_kinds
[m_kind
],
3549 r
.get_identifier_as_type (m_return_type
),
3550 m_name
->get_debug_string (),
3557 /* The implementation of class gcc::jit::recording::block. */
3559 /* Create a recording::eval instance and add it to
3560 the block's context's list of mementos, and to the block's
3563 Implements the heart of gcc_jit_block_add_eval. */
3565 recording::statement
*
3566 recording::block::add_eval (recording::location
*loc
,
3567 recording::rvalue
*rvalue
)
3569 statement
*result
= new eval (this, loc
, rvalue
);
3570 m_ctxt
->record (result
);
3571 m_statements
.safe_push (result
);
3575 /* Create a recording::assignment instance and add it to
3576 the block's context's list of mementos, and to the block's
3579 Implements the heart of gcc_jit_block_add_assignment. */
3581 recording::statement
*
3582 recording::block::add_assignment (recording::location
*loc
,
3583 recording::lvalue
*lvalue
,
3584 recording::rvalue
*rvalue
)
3586 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
3587 m_ctxt
->record (result
);
3588 m_statements
.safe_push (result
);
3592 /* Create a recording::assignment_op instance and add it to
3593 the block's context's list of mementos, and to the block's
3596 Implements the heart of gcc_jit_block_add_assignment_op. */
3598 recording::statement
*
3599 recording::block::add_assignment_op (recording::location
*loc
,
3600 recording::lvalue
*lvalue
,
3601 enum gcc_jit_binary_op op
,
3602 recording::rvalue
*rvalue
)
3604 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
3605 m_ctxt
->record (result
);
3606 m_statements
.safe_push (result
);
3610 /* Create a recording::comment instance and add it to
3611 the block's context's list of mementos, and to the block's
3614 Implements the heart of gcc_jit_block_add_comment. */
3616 recording::statement
*
3617 recording::block::add_comment (recording::location
*loc
,
3620 statement
*result
= new comment (this, loc
, new_string (text
));
3621 m_ctxt
->record (result
);
3622 m_statements
.safe_push (result
);
3626 /* Create a recording::end_with_conditional instance and add it to
3627 the block's context's list of mementos, and to the block's
3630 Implements the heart of gcc_jit_block_end_with_conditional. */
3632 recording::statement
*
3633 recording::block::end_with_conditional (recording::location
*loc
,
3634 recording::rvalue
*boolval
,
3635 recording::block
*on_true
,
3636 recording::block
*on_false
)
3638 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
3639 m_ctxt
->record (result
);
3640 m_statements
.safe_push (result
);
3641 m_has_been_terminated
= true;
3645 /* Create a recording::end_with_jump instance and add it to
3646 the block's context's list of mementos, and to the block's
3649 Implements the heart of gcc_jit_block_end_with_jump. */
3651 recording::statement
*
3652 recording::block::end_with_jump (recording::location
*loc
,
3653 recording::block
*target
)
3655 statement
*result
= new jump (this, loc
, target
);
3656 m_ctxt
->record (result
);
3657 m_statements
.safe_push (result
);
3658 m_has_been_terminated
= true;
3662 /* Create a recording::end_with_return instance and add it to
3663 the block's context's list of mementos, and to the block's
3666 Implements the post-error-checking parts of
3667 gcc_jit_block_end_with_return and
3668 gcc_jit_block_end_with_void_return. */
3670 recording::statement
*
3671 recording::block::end_with_return (recording::location
*loc
,
3672 recording::rvalue
*rvalue
)
3674 /* This is used by both gcc_jit_function_add_return and
3675 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3676 the former and NULL for the latter. */
3677 statement
*result
= new return_ (this, loc
, rvalue
);
3678 m_ctxt
->record (result
);
3679 m_statements
.safe_push (result
);
3680 m_has_been_terminated
= true;
3684 /* Override the default implementation of
3685 recording::memento::write_to_dump for blocks by writing
3686 an unindented block name as a label, followed by the indented
3696 recording::block::write_to_dump (dump
&d
)
3698 d
.write ("%s:\n", get_debug_string ());
3702 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
3703 s
->write_to_dump (d
);
3706 /* Validate a block by ensuring that it has been terminated. */
3709 recording::block::validate ()
3711 /* Check for termination. */
3712 if (!has_been_terminated ())
3714 statement
*stmt
= get_last_statement ();
3715 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
3716 m_func
->get_context ()->add_error (loc
,
3717 "unterminated block in %s: %s",
3718 m_func
->get_debug_string (),
3719 get_debug_string ());
3726 /* Get the source-location of a block by using that of the first
3727 statement within it, if any. */
3729 recording::location
*
3730 recording::block::get_loc () const
3732 recording::statement
*stmt
= get_first_statement ();
3734 return stmt
->get_loc ();
3739 /* Get the first statement within a block, if any. */
3741 recording::statement
*
3742 recording::block::get_first_statement () const
3744 if (m_statements
.length ())
3745 return m_statements
[0];
3750 /* Get the last statement within a block, if any. */
3752 recording::statement
*
3753 recording::block::get_last_statement () const
3755 if (m_statements
.length ())
3756 return m_statements
[m_statements
.length () - 1];
3761 /* Assuming that this block has been terminated, get the number of
3762 successor blocks, which will be 0, 1 or 2, for return, unconditional
3763 jump, and conditional jump respectively.
3764 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
3765 is written to NEXT1, and the second (if any) to NEXT2.
3767 Used when validating functions, and when dumping dot representations
3771 recording::block::get_successor_blocks (block
**next1
, block
**next2
) const
3773 gcc_assert (m_has_been_terminated
);
3776 statement
*last_statement
= get_last_statement ();
3777 gcc_assert (last_statement
);
3778 return last_statement
->get_successor_blocks (next1
, next2
);
3781 /* Implementation of pure virtual hook recording::memento::replay_into
3782 for recording::block. */
3785 recording::block::replay_into (replayer
*)
3787 set_playback_obj (m_func
->playback_function ()
3788 ->new_block (playback_string (m_name
)));
3791 /* Implementation of recording::memento::make_debug_string for
3795 recording::block::make_debug_string ()
3800 return string::from_printf (m_ctxt
,
3801 "<UNNAMED BLOCK %p>",
3805 /* Implementation of recording::memento::write_reproducer for blocks. */
3808 recording::block::write_reproducer (reproducer
&r
)
3810 const char *id
= r
.make_identifier (this, "block");
3811 r
.write (" gcc_jit_block *%s =\n"
3812 " gcc_jit_function_new_block (%s, %s);\n",
3814 r
.get_identifier (m_func
),
3815 m_name
? m_name
->get_debug_string () : "NULL");
3818 /* Dump a block in graphviz form into PP, capturing the block name (if
3819 any) and the statements. */
3822 recording::block::dump_to_dot (pretty_printer
*pp
)
3826 "[shape=record,style=filled,fillcolor=white,label=\"{"),
3828 pp_write_text_to_stream (pp
);
3831 pp_string (pp
, m_name
->c_str ());
3832 pp_string (pp
, ":");
3834 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
3839 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
3841 pp_string (pp
, s
->get_debug_string ());
3843 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
3851 /* Dump the out-edges of the block in graphviz form into PP. */
3854 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
3857 int num_succs
= get_successor_blocks (&next
[0], &next
[1]);
3858 for (int i
= 0; i
< num_succs
; i
++)
3860 "\tblock_%d:s -> block_%d:n;\n",
3861 m_index
, next
[i
]->m_index
);
3864 /* The implementation of class gcc::jit::recording::global. */
3866 /* Implementation of pure virtual hook recording::memento::replay_into
3867 for recording::global. */
3870 recording::global::replay_into (replayer
*r
)
3872 set_playback_obj (r
->new_global (playback_location (r
, m_loc
),
3874 m_type
->playback_type (),
3875 playback_string (m_name
)));
3878 /* Override the default implementation of
3879 recording::memento::write_to_dump for globals.
3880 This will be of the form:
3882 GCC_JIT_GLOBAL_EXPORTED:
3886 GCC_JIT_GLOBAL_INTERNAL:
3888 e.g. "static int foo;"
3890 GCC_JIT_GLOBAL_IMPORTED:
3892 e.g. "extern int foo;"
3894 These are written to the top of the dump by
3895 recording::context::dump_to_file. */
3898 recording::global::write_to_dump (dump
&d
)
3900 if (d
.update_locations ())
3901 m_loc
= d
.make_location ();
3908 case GCC_JIT_GLOBAL_EXPORTED
:
3911 case GCC_JIT_GLOBAL_INTERNAL
:
3912 d
.write ("static ");
3915 case GCC_JIT_GLOBAL_IMPORTED
:
3916 d
.write ("extern ");
3919 d
.write ("%s %s;\n",
3920 m_type
->get_debug_string (),
3921 get_debug_string ());
3924 /* A table of enum gcc_jit_global_kind values expressed in string
3927 static const char * const global_kind_reproducer_strings
[] = {
3928 "GCC_JIT_GLOBAL_EXPORTED",
3929 "GCC_JIT_GLOBAL_INTERNAL",
3930 "GCC_JIT_GLOBAL_IMPORTED"
3933 /* Implementation of recording::memento::write_reproducer for globals. */
3936 recording::global::write_reproducer (reproducer
&r
)
3938 const char *id
= r
.make_identifier (this, "block");
3939 r
.write (" gcc_jit_lvalue *%s =\n"
3940 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
3941 " %s, /* gcc_jit_location *loc */\n"
3942 " %s, /* enum gcc_jit_global_kind kind */\n"
3943 " %s, /* gcc_jit_type *type */\n"
3944 " %s); /* const char *name */\n",
3946 r
.get_identifier (get_context ()),
3947 r
.get_identifier (m_loc
),
3948 global_kind_reproducer_strings
[m_kind
],
3949 r
.get_identifier_as_type (get_type ()),
3950 m_name
->get_debug_string ());
3953 /* The implementation of the various const-handling classes:
3954 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
3956 /* Explicit specialization of the various mementos we're interested in. */
3957 template class recording::memento_of_new_rvalue_from_const
<int>;
3958 template class recording::memento_of_new_rvalue_from_const
<long>;
3959 template class recording::memento_of_new_rvalue_from_const
<double>;
3960 template class recording::memento_of_new_rvalue_from_const
<void *>;
3962 /* Implementation of the pure virtual hook recording::memento::replay_into
3963 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
3965 template <typename HOST_TYPE
>
3968 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
3971 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
3975 /* The make_debug_string and write_reproducer methods vary between the
3977 memento_of_new_rvalue_from_const <HOST_TYPE>
3978 classes, so we explicitly write specializations of them.
3980 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
3981 namespaces are written out explicitly, which is why most of this file
3982 doesn't abbreviate things by entering the "recording" namespace.
3984 However, these specializations are required to be in the same namespace
3985 as the template, hence we now have to enter the gcc::jit::recording
3991 /* The make_debug_string specialization for <int>, which renders it as
3992 (TARGET_TYPE)LITERAL
3998 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
4000 return string::from_printf (m_ctxt
,
4002 m_type
->get_debug_string (),
4006 /* The write_reproducer specialization for <int>. */
4010 memento_of_new_rvalue_from_const
<int>::write_reproducer (reproducer
&r
)
4012 const char *id
= r
.make_identifier (this, "rvalue");
4013 r
.write (" gcc_jit_rvalue *%s =\n"
4014 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4015 " %s, /* gcc_jit_type *numeric_type */\n"
4016 " %i); /* int value */\n",
4018 r
.get_identifier (get_context ()),
4019 r
.get_identifier_as_type (m_type
),
4023 /* The make_debug_string specialization for <long>, rendering it as
4024 (TARGET_TYPE)LITERAL
4030 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
4032 return string::from_printf (m_ctxt
,
4034 m_type
->get_debug_string (),
4038 /* The write_reproducer specialization for <long>. */
4042 recording::memento_of_new_rvalue_from_const
<long>::write_reproducer (reproducer
&r
)
4044 const char *id
= r
.make_identifier (this, "rvalue");
4046 /* We have to special-case LONG_MIN, since e.g.
4047 -9223372036854775808L
4049 -(9223372036854775808L)
4051 error: integer constant is so large that it is unsigned [-Werror]
4052 Workaround this by writing (LONG_MIN + 1) - 1. */
4053 if (m_value
== LONG_MIN
)
4055 r
.write (" gcc_jit_rvalue *%s =\n"
4056 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4057 " %s, /* gcc_jit_type *numeric_type */\n"
4058 " %ldL - 1); /* long value */\n",
4060 r
.get_identifier (get_context ()),
4061 r
.get_identifier_as_type (m_type
),
4066 r
.write (" gcc_jit_rvalue *%s =\n"
4067 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4068 " %s, /* gcc_jit_type *numeric_type */\n"
4069 " %ldL); /* long value */\n",
4071 r
.get_identifier (get_context ()),
4072 r
.get_identifier_as_type (m_type
),
4076 /* The make_debug_string specialization for <double>, rendering it as
4077 (TARGET_TYPE)LITERAL
4083 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
4085 return string::from_printf (m_ctxt
,
4087 m_type
->get_debug_string (),
4091 /* The write_reproducer specialization for <double>. */
4095 recording::memento_of_new_rvalue_from_const
<double>::write_reproducer (reproducer
&r
)
4097 const char *id
= r
.make_identifier (this, "rvalue");
4098 r
.write (" gcc_jit_rvalue *%s =\n"
4099 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4100 " %s, /* gcc_jit_type *numeric_type */\n"
4101 " %f); /* double value */\n",
4103 r
.get_identifier (get_context ()),
4104 r
.get_identifier_as_type (m_type
),
4108 /* The make_debug_string specialization for <void *>, rendering it as
4113 Zero is rendered as NULL e.g.
4118 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
4120 if (m_value
!= NULL
)
4121 return string::from_printf (m_ctxt
,
4123 m_type
->get_debug_string (), m_value
);
4125 return string::from_printf (m_ctxt
,
4127 m_type
->get_debug_string ());
4130 /* Implementation of recording::memento::write_reproducer for <void *>
4135 memento_of_new_rvalue_from_const
<void *>::write_reproducer (reproducer
&r
)
4137 const char *id
= r
.make_identifier (this, "rvalue");
4139 r
.write (" gcc_jit_rvalue *%s =\n"
4140 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4141 " %s, /* gcc_jit_type *pointer_type */\n"
4142 " (void *)%p); /* void *value */\n",
4144 r
.get_identifier (get_context ()),
4145 r
.get_identifier_as_type (m_type
),
4148 r
.write (" gcc_jit_rvalue *%s =\n"
4149 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4150 " %s); /* gcc_jit_type *pointer_type */\n",
4152 r
.get_identifier (get_context ()),
4153 r
.get_identifier_as_type (m_type
));
4156 /* We're done specializing make_debug_string and write_reproducer, so we
4157 can exit the gcc::jit::recording namespace. */
4159 } // namespace recording
4161 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4163 /* Implementation of pure virtual hook recording::memento::replay_into
4164 for recording::memento_of_new_string_literal. */
4167 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
4169 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
4172 /* Implementation of recording::memento::make_debug_string for
4176 recording::memento_of_new_string_literal::make_debug_string ()
4178 return string::from_printf (m_ctxt
,
4180 m_value
->get_debug_string ());
4183 /* Implementation of recording::memento::write_reproducer for string literal
4187 recording::memento_of_new_string_literal::write_reproducer (reproducer
&r
)
4189 const char *id
= r
.make_identifier (this, "rvalue");
4190 r
.write (" gcc_jit_rvalue *%s =\n"
4191 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4192 " %s); /* const char *value */\n",
4194 r
.get_identifier (get_context ()),
4195 m_value
->get_debug_string ());
4198 /* The implementation of class gcc::jit::recording::unary_op. */
4200 /* Implementation of pure virtual hook recording::memento::replay_into
4201 for recording::unary_op. */
4204 recording::unary_op::replay_into (replayer
*r
)
4206 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
4208 get_type ()->playback_type (),
4209 m_a
->playback_rvalue ()));
4212 /* Implementation of pure virtual hook recording::rvalue::visit_children
4213 for recording::unary_op. */
4215 recording::unary_op::visit_children (rvalue_visitor
*v
)
4220 /* Implementation of recording::memento::make_debug_string for
4223 static const char * const unary_op_strings
[] = {
4224 "-", /* GCC_JIT_UNARY_OP_MINUS */
4225 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4226 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4227 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4231 recording::unary_op::make_debug_string ()
4233 return string::from_printf (m_ctxt
,
4235 unary_op_strings
[m_op
],
4236 m_a
->get_debug_string ());
4239 static const char * const unary_op_reproducer_strings
[] = {
4240 "GCC_JIT_UNARY_OP_MINUS",
4241 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4242 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4243 "GCC_JIT_UNARY_OP_ABS"
4246 /* Implementation of recording::memento::write_reproducer for unary ops. */
4249 recording::unary_op::write_reproducer (reproducer
&r
)
4251 const char *id
= r
.make_identifier (this, "rvalue");
4252 r
.write (" gcc_jit_rvalue *%s =\n"
4253 " gcc_jit_context_new_unary_op (%s,\n"
4254 " %s, /* gcc_jit_location *loc */\n"
4255 " %s, /* enum gcc_jit_unary_op op */\n"
4256 " %s, /* gcc_jit_type *result_type */\n"
4257 " %s); /* gcc_jit_rvalue *a */\n",
4259 r
.get_identifier (get_context ()),
4260 r
.get_identifier (m_loc
),
4261 unary_op_reproducer_strings
[m_op
],
4262 r
.get_identifier_as_type (get_type ()),
4263 r
.get_identifier_as_rvalue (m_a
));
4266 /* The implementation of class gcc::jit::recording::binary_op. */
4268 /* Implementation of pure virtual hook recording::memento::replay_into
4269 for recording::binary_op. */
4272 recording::binary_op::replay_into (replayer
*r
)
4274 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
4276 get_type ()->playback_type (),
4277 m_a
->playback_rvalue (),
4278 m_b
->playback_rvalue ()));
4281 /* Implementation of pure virtual hook recording::rvalue::visit_children
4282 for recording::binary_op. */
4284 recording::binary_op::visit_children (rvalue_visitor
*v
)
4290 /* Implementation of recording::memento::make_debug_string for
4293 static const char * const binary_op_strings
[] = {
4294 "+", /* GCC_JIT_BINARY_OP_PLUS */
4295 "-", /* GCC_JIT_BINARY_OP_MINUS */
4296 "*", /* GCC_JIT_BINARY_OP_MULT */
4297 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4298 "%", /* GCC_JIT_BINARY_OP_MODULO */
4299 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4300 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4301 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4302 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4303 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4304 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4305 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4309 recording::binary_op::make_debug_string ()
4311 enum precedence prec
= get_precedence ();
4312 return string::from_printf (m_ctxt
,
4314 m_a
->get_debug_string_parens (prec
),
4315 binary_op_strings
[m_op
],
4316 m_b
->get_debug_string_parens (prec
));
4319 static const char * const binary_op_reproducer_strings
[] = {
4320 "GCC_JIT_BINARY_OP_PLUS",
4321 "GCC_JIT_BINARY_OP_MINUS",
4322 "GCC_JIT_BINARY_OP_MULT",
4323 "GCC_JIT_BINARY_OP_DIVIDE",
4324 "GCC_JIT_BINARY_OP_MODULO",
4325 "GCC_JIT_BINARY_OP_BITWISE_AND",
4326 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4327 "GCC_JIT_BINARY_OP_BITWISE_OR",
4328 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4329 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4330 "GCC_JIT_BINARY_OP_LSHIFT",
4331 "GCC_JIT_BINARY_OP_RSHIFT"
4334 /* Implementation of recording::memento::write_reproducer for binary ops. */
4337 recording::binary_op::write_reproducer (reproducer
&r
)
4339 const char *id
= r
.make_identifier (this, "rvalue");
4340 r
.write (" gcc_jit_rvalue *%s =\n"
4341 " gcc_jit_context_new_binary_op (%s,\n"
4342 " %s, /* gcc_jit_location *loc */\n"
4343 " %s, /* enum gcc_jit_binary_op op */\n"
4344 " %s, /* gcc_jit_type *result_type */\n"
4345 " %s, /* gcc_jit_rvalue *a */\n"
4346 " %s); /* gcc_jit_rvalue *b */\n",
4348 r
.get_identifier (get_context ()),
4349 r
.get_identifier (m_loc
),
4350 binary_op_reproducer_strings
[m_op
],
4351 r
.get_identifier_as_type (get_type ()),
4352 r
.get_identifier_as_rvalue (m_a
),
4353 r
.get_identifier_as_rvalue (m_b
));
4356 namespace recording
{
4357 static const enum precedence binary_op_precedence
[] = {
4358 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_PLUS */
4359 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_MINUS */
4361 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MULT */
4362 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_DIVIDE */
4363 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MODULO */
4365 PRECEDENCE_BITWISE_AND
, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4366 PRECEDENCE_BITWISE_XOR
, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4367 PRECEDENCE_BITWISE_IOR
, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4368 PRECEDENCE_LOGICAL_AND
, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4369 PRECEDENCE_LOGICAL_OR
, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4370 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_LSHIFT */
4371 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_RSHIFT */
4373 } /* namespace recording */
4375 enum recording::precedence
4376 recording::binary_op::get_precedence () const
4378 return binary_op_precedence
[m_op
];
4381 /* The implementation of class gcc::jit::recording::comparison. */
4383 /* Implementation of recording::memento::make_debug_string for
4386 static const char * const comparison_strings
[] =
4388 "==", /* GCC_JIT_COMPARISON_EQ */
4389 "!=", /* GCC_JIT_COMPARISON_NE */
4390 "<", /* GCC_JIT_COMPARISON_LT */
4391 "<=", /* GCC_JIT_COMPARISON_LE */
4392 ">", /* GCC_JIT_COMPARISON_GT */
4393 ">=", /* GCC_JIT_COMPARISON_GE */
4397 recording::comparison::make_debug_string ()
4399 enum precedence prec
= get_precedence ();
4400 return string::from_printf (m_ctxt
,
4402 m_a
->get_debug_string_parens (prec
),
4403 comparison_strings
[m_op
],
4404 m_b
->get_debug_string_parens (prec
));
4407 /* A table of enum gcc_jit_comparison values expressed in string
4410 static const char * const comparison_reproducer_strings
[] =
4412 "GCC_JIT_COMPARISON_EQ",
4413 "GCC_JIT_COMPARISON_NE",
4414 "GCC_JIT_COMPARISON_LT",
4415 "GCC_JIT_COMPARISON_LE",
4416 "GCC_JIT_COMPARISON_GT",
4417 "GCC_JIT_COMPARISON_GE"
4420 /* Implementation of recording::memento::write_reproducer for comparisons. */
4423 recording::comparison::write_reproducer (reproducer
&r
)
4425 const char *id
= r
.make_identifier (this, "rvalue");
4426 r
.write (" gcc_jit_rvalue *%s =\n"
4427 " gcc_jit_context_new_comparison (%s,\n"
4428 " %s, /* gcc_jit_location *loc */\n"
4429 " %s, /* enum gcc_jit_comparison op */\n"
4430 " %s, /* gcc_jit_rvalue *a */\n"
4431 " %s); /* gcc_jit_rvalue *b */\n",
4433 r
.get_identifier (get_context ()),
4434 r
.get_identifier (m_loc
),
4435 comparison_reproducer_strings
[m_op
],
4436 r
.get_identifier_as_rvalue (m_a
),
4437 r
.get_identifier_as_rvalue (m_b
));
4440 /* Implementation of pure virtual hook recording::memento::replay_into
4441 for recording::comparison. */
4444 recording::comparison::replay_into (replayer
*r
)
4446 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
4448 m_a
->playback_rvalue (),
4449 m_b
->playback_rvalue ()));
4452 /* Implementation of pure virtual hook recording::rvalue::visit_children
4453 for recording::comparison. */
4456 recording::comparison::visit_children (rvalue_visitor
*v
)
4462 namespace recording
{
4463 static const enum precedence comparison_precedence
[] =
4465 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_EQ */
4466 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_NE */
4468 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LT */
4469 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LE */
4470 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GT */
4471 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GE */
4473 } /* namespace recording */
4475 enum recording::precedence
4476 recording::comparison::get_precedence () const
4478 return comparison_precedence
[m_op
];
4481 /* Implementation of pure virtual hook recording::memento::replay_into
4482 for recording::cast. */
4485 recording::cast::replay_into (replayer
*r
)
4487 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
4488 m_rvalue
->playback_rvalue (),
4489 get_type ()->playback_type ()));
4492 /* Implementation of pure virtual hook recording::rvalue::visit_children
4493 for recording::cast. */
4495 recording::cast::visit_children (rvalue_visitor
*v
)
4497 v
->visit (m_rvalue
);
4500 /* Implementation of recording::memento::make_debug_string for
4504 recording::cast::make_debug_string ()
4506 enum precedence prec
= get_precedence ();
4507 return string::from_printf (m_ctxt
,
4509 get_type ()->get_debug_string (),
4510 m_rvalue
->get_debug_string_parens (prec
));
4513 /* Implementation of recording::memento::write_reproducer for casts. */
4516 recording::cast::write_reproducer (reproducer
&r
)
4518 const char *id
= r
.make_identifier (this, "rvalue");
4519 r
.write (" gcc_jit_rvalue *%s =\n"
4520 " gcc_jit_context_new_cast (%s,\n"
4521 " %s, /* gcc_jit_location *loc */\n"
4522 " %s, /* gcc_jit_rvalue *rvalue */\n"
4523 " %s); /* gcc_jit_type *type */\n",
4525 r
.get_identifier (get_context ()),
4526 r
.get_identifier (m_loc
),
4527 r
.get_identifier_as_rvalue (m_rvalue
),
4528 r
.get_identifier_as_type (get_type ()));
4531 /* The implementation of class gcc::jit::recording::call. */
4533 /* The constructor for gcc::jit::recording::call. */
4535 recording::call::call (recording::context
*ctxt
,
4536 recording::location
*loc
,
4537 recording::function
*func
,
4540 : rvalue (ctxt
, loc
, func
->get_return_type ()),
4544 for (int i
= 0; i
< numargs
; i
++)
4545 m_args
.safe_push (args
[i
]);
4548 /* Implementation of pure virtual hook recording::memento::replay_into
4549 for recording::call. */
4552 recording::call::replay_into (replayer
*r
)
4554 auto_vec
<playback::rvalue
*> playback_args
;
4555 playback_args
.create (m_args
.length ());
4556 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4557 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
4559 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
4560 m_func
->playback_function (),
4564 /* Implementation of pure virtual hook recording::rvalue::visit_children
4565 for recording::call. */
4568 recording::call::visit_children (rvalue_visitor
*v
)
4570 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4571 v
->visit (m_args
[i
]);
4574 /* Implementation of recording::memento::make_debug_string for
4578 recording::call::make_debug_string ()
4580 enum precedence prec
= get_precedence ();
4581 /* First, build a buffer for the arguments. */
4582 /* Calculate length of said buffer. */
4583 size_t sz
= 1; /* nil terminator */
4584 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4586 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4587 sz
+= 2; /* ", " separator */
4590 /* Now allocate and populate the buffer. */
4591 char *argbuf
= new char[sz
];
4594 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4596 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
4597 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4598 if (i
+ 1 < m_args
.length ())
4600 strcpy (argbuf
+ len
, ", ");
4606 /* ...and use it to get the string for the call as a whole. */
4607 string
*result
= string::from_printf (m_ctxt
,
4609 m_func
->get_debug_string (),
4618 recording::call::write_reproducer (reproducer
&r
)
4620 const char *id
= r
.make_identifier (this, "call");
4621 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
4622 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4625 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4626 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
4628 r
.write (" gcc_jit_rvalue *%s =\n"
4629 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4630 " %s, /* gcc_jit_location *loc */\n"
4631 " %s, /* gcc_jit_function *func */\n"
4632 " %i, /* int numargs */ \n"
4633 " %s); /* gcc_jit_rvalue **args*/\n",
4635 r
.get_identifier (get_context ()),
4636 r
.get_identifier (m_loc
),
4637 r
.get_identifier (m_func
),
4642 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4644 /* The constructor for recording::call_through_ptr. */
4646 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
4647 recording::location
*loc
,
4648 recording::rvalue
*fn_ptr
,
4651 : rvalue (ctxt
, loc
,
4652 fn_ptr
->get_type ()->dereference ()
4653 ->as_a_function_type ()->get_return_type ()),
4657 for (int i
= 0; i
< numargs
; i
++)
4658 m_args
.safe_push (args
[i
]);
4661 /* Implementation of pure virtual hook recording::memento::replay_into
4662 for recording::call_through_ptr. */
4665 recording::call_through_ptr::replay_into (replayer
*r
)
4667 auto_vec
<playback::rvalue
*> playback_args
;
4668 playback_args
.create (m_args
.length ());
4669 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4670 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
4672 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
4673 m_fn_ptr
->playback_rvalue (),
4677 /* Implementation of pure virtual hook recording::rvalue::visit_children
4678 for recording::call_through_ptr. */
4681 recording::call_through_ptr::visit_children (rvalue_visitor
*v
)
4683 v
->visit (m_fn_ptr
);
4684 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4685 v
->visit (m_args
[i
]);
4688 /* Implementation of recording::memento::make_debug_string for
4689 calls through function ptrs. */
4692 recording::call_through_ptr::make_debug_string ()
4694 enum precedence prec
= get_precedence ();
4695 /* First, build a buffer for the arguments. */
4696 /* Calculate length of said buffer. */
4697 size_t sz
= 1; /* nil terminator */
4698 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4700 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4701 sz
+= 2; /* ", " separator */
4704 /* Now allocate and populate the buffer. */
4705 char *argbuf
= new char[sz
];
4708 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4710 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
4711 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4712 if (i
+ 1 < m_args
.length ())
4714 strcpy (argbuf
+ len
, ", ");
4720 /* ...and use it to get the string for the call as a whole. */
4721 string
*result
= string::from_printf (m_ctxt
,
4723 m_fn_ptr
->get_debug_string_parens (prec
),
4731 /* Implementation of recording::memento::write_reproducer for
4732 call_through_ptr. */
4735 recording::call_through_ptr::write_reproducer (reproducer
&r
)
4737 const char *id
= r
.make_identifier (this, "call");
4738 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
4739 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4742 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4743 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
4745 r
.write (" gcc_jit_rvalue *%s =\n"
4746 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
4747 " %s, /* gcc_jit_location *loc */\n"
4748 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
4749 " %i, /* int numargs */ \n"
4750 " %s); /* gcc_jit_rvalue **args*/\n",
4752 r
.get_identifier (get_context ()),
4753 r
.get_identifier (m_loc
),
4754 r
.get_identifier_as_rvalue (m_fn_ptr
),
4759 /* The implementation of class gcc::jit::recording::array_access. */
4761 /* Implementation of pure virtual hook recording::memento::replay_into
4762 for recording::array_access. */
4765 recording::array_access::replay_into (replayer
*r
)
4768 r
->new_array_access (playback_location (r
, m_loc
),
4769 m_ptr
->playback_rvalue (),
4770 m_index
->playback_rvalue ()));
4773 /* Implementation of pure virtual hook recording::rvalue::visit_children
4774 for recording::array_access. */
4777 recording::array_access::visit_children (rvalue_visitor
*v
)
4783 /* Implementation of recording::memento::make_debug_string for
4787 recording::array_access::make_debug_string ()
4789 enum precedence prec
= get_precedence ();
4790 return string::from_printf (m_ctxt
,
4792 m_ptr
->get_debug_string_parens (prec
),
4793 m_index
->get_debug_string_parens (prec
));
4796 /* Implementation of recording::memento::write_reproducer for
4800 recording::array_access::write_reproducer (reproducer
&r
)
4802 const char *id
= r
.make_identifier (this, "lvalue");
4803 r
.write (" gcc_jit_lvalue *%s = \n"
4804 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
4805 " %s, /*gcc_jit_location *loc */\n"
4806 " %s, /* gcc_jit_rvalue *ptr */\n"
4807 " %s); /* gcc_jit_rvalue *index */\n",
4809 r
.get_identifier (get_context ()),
4810 r
.get_identifier (m_loc
),
4811 r
.get_identifier_as_rvalue (m_ptr
),
4812 r
.get_identifier_as_rvalue (m_index
));
4815 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
4817 /* Implementation of pure virtual hook recording::memento::replay_into
4818 for recording::access_field_of_lvalue. */
4821 recording::access_field_of_lvalue::replay_into (replayer
*r
)
4824 m_lvalue
->playback_lvalue ()
4825 ->access_field (playback_location (r
, m_loc
),
4826 m_field
->playback_field ()));
4830 /* Implementation of pure virtual hook recording::rvalue::visit_children
4831 for recording::access_field_of_lvalue. */
4834 recording::access_field_of_lvalue::visit_children (rvalue_visitor
*v
)
4836 v
->visit (m_lvalue
);
4839 /* Implementation of recording::memento::make_debug_string for
4840 accessing a field of an lvalue. */
4843 recording::access_field_of_lvalue::make_debug_string ()
4845 enum precedence prec
= get_precedence ();
4846 return string::from_printf (m_ctxt
,
4848 m_lvalue
->get_debug_string_parens (prec
),
4849 m_field
->get_debug_string ());
4852 /* Implementation of recording::memento::write_reproducer for
4853 access_field_of_lvalue. */
4856 recording::access_field_of_lvalue::write_reproducer (reproducer
&r
)
4858 const char *id
= r
.make_identifier (this, "lvalue");
4859 r
.write (" gcc_jit_lvalue *%s = \n"
4860 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
4861 " %s, /*gcc_jit_location *loc */\n"
4864 r
.get_identifier_as_lvalue (m_lvalue
),
4865 r
.get_identifier (m_loc
),
4866 r
.get_identifier (m_field
));
4869 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
4871 /* Implementation of pure virtual hook recording::memento::replay_into
4872 for recording::access_field_rvalue. */
4875 recording::access_field_rvalue::replay_into (replayer
*r
)
4878 m_rvalue
->playback_rvalue ()
4879 ->access_field (playback_location (r
, m_loc
),
4880 m_field
->playback_field ()));
4883 /* Implementation of pure virtual hook recording::rvalue::visit_children
4884 for recording::access_field_rvalue. */
4887 recording::access_field_rvalue::visit_children (rvalue_visitor
*v
)
4889 v
->visit (m_rvalue
);
4892 /* Implementation of recording::memento::make_debug_string for
4893 accessing a field of an rvalue. */
4896 recording::access_field_rvalue::make_debug_string ()
4898 enum precedence prec
= get_precedence ();
4899 return string::from_printf (m_ctxt
,
4901 m_rvalue
->get_debug_string_parens (prec
),
4902 m_field
->get_debug_string ());
4905 /* Implementation of recording::memento::write_reproducer for
4906 access_field_rvalue. */
4909 recording::access_field_rvalue::write_reproducer (reproducer
&r
)
4911 const char *id
= r
.make_identifier (this, "rvalue");
4912 r
.write (" gcc_jit_rvalue *%s = \n"
4913 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
4914 " %s, /*gcc_jit_location *loc */\n"
4917 r
.get_identifier_as_rvalue (m_rvalue
),
4918 r
.get_identifier (m_loc
),
4919 r
.get_identifier (m_field
));
4922 /* The implementation of class
4923 gcc::jit::recording::dereference_field_rvalue. */
4925 /* Implementation of pure virtual hook recording::memento::replay_into
4926 for recording::dereference_field_rvalue. */
4929 recording::dereference_field_rvalue::replay_into (replayer
*r
)
4932 m_rvalue
->playback_rvalue ()->
4933 dereference_field (playback_location (r
, m_loc
),
4934 m_field
->playback_field ()));
4937 /* Implementation of pure virtual hook recording::rvalue::visit_children
4938 for recording::dereference_field_rvalue. */
4941 recording::dereference_field_rvalue::visit_children (rvalue_visitor
*v
)
4943 v
->visit (m_rvalue
);
4946 /* Implementation of recording::memento::make_debug_string for
4947 dereferencing a field of an rvalue. */
4950 recording::dereference_field_rvalue::make_debug_string ()
4952 enum precedence prec
= get_precedence ();
4953 return string::from_printf (m_ctxt
,
4955 m_rvalue
->get_debug_string_parens (prec
),
4956 m_field
->get_debug_string ());
4959 /* Implementation of recording::memento::write_reproducer for
4960 dereference_field_rvalue. */
4963 recording::dereference_field_rvalue::write_reproducer (reproducer
&r
)
4965 const char *id
= r
.make_identifier (this, "lvalue");
4966 r
.write (" gcc_jit_lvalue *%s=\n"
4967 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
4968 " %s, /* gcc_jit_location *loc */\n"
4969 " %s); /* gcc_jit_field *field */\n",
4971 r
.get_identifier_as_rvalue (m_rvalue
),
4972 r
.get_identifier (m_loc
),
4973 r
.get_identifier (m_field
));
4976 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
4978 /* Implementation of pure virtual hook recording::memento::replay_into
4979 for recording::dereference_rvalue. */
4982 recording::dereference_rvalue::replay_into (replayer
*r
)
4985 m_rvalue
->playback_rvalue ()->
4986 dereference (playback_location (r
, m_loc
)));
4989 /* Implementation of pure virtual hook recording::rvalue::visit_children
4990 for recording::dereference_rvalue. */
4993 recording::dereference_rvalue::visit_children (rvalue_visitor
*v
)
4995 v
->visit (m_rvalue
);
4998 /* Implementation of recording::memento::make_debug_string for
4999 dereferencing an rvalue. */
5002 recording::dereference_rvalue::make_debug_string ()
5004 enum precedence prec
= get_precedence ();
5005 return string::from_printf (m_ctxt
,
5007 m_rvalue
->get_debug_string_parens (prec
));
5010 /* Implementation of recording::memento::write_reproducer for
5011 dereference_rvalue. */
5014 recording::dereference_rvalue::write_reproducer (reproducer
&r
)
5016 const char *id
= r
.make_identifier (this, "dereference");
5017 r
.write (" gcc_jit_lvalue *%s =\n"
5018 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5019 " %s); /* gcc_jit_location *loc */\n",
5021 r
.get_identifier_as_rvalue (m_rvalue
),
5022 r
.get_identifier (m_loc
));
5025 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5027 /* Implementation of pure virtual hook recording::memento::replay_into
5028 for recording::get_address_of_lvalue. */
5031 recording::get_address_of_lvalue::replay_into (replayer
*r
)
5034 m_lvalue
->playback_lvalue ()->
5035 get_address (playback_location (r
, m_loc
)));
5038 /* Implementation of pure virtual hook recording::rvalue::visit_children
5039 for recording::get_address_of_lvalue. */
5042 recording::get_address_of_lvalue::visit_children (rvalue_visitor
*v
)
5044 v
->visit (m_lvalue
);
5047 /* Implementation of recording::memento::make_debug_string for
5048 getting the address of an lvalue. */
5051 recording::get_address_of_lvalue::make_debug_string ()
5053 enum precedence prec
= get_precedence ();
5054 return string::from_printf (m_ctxt
,
5056 m_lvalue
->get_debug_string_parens (prec
));
5059 /* Implementation of recording::memento::write_reproducer for
5060 get_address_of_lvalue. */
5063 recording::get_address_of_lvalue::write_reproducer (reproducer
&r
)
5065 const char *id
= r
.make_identifier (this, "address_of");
5066 r
.write (" gcc_jit_rvalue *%s =\n"
5067 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5068 " %s); /* gcc_jit_location *loc */\n",
5070 r
.get_identifier_as_lvalue (m_lvalue
),
5071 r
.get_identifier (m_loc
));
5074 /* The implementation of class gcc::jit::recording::local. */
5076 /* Implementation of pure virtual hook recording::memento::replay_into
5077 for recording::local. */
5080 recording::local::replay_into (replayer
*r
)
5083 m_func
->playback_function ()
5084 ->new_local (playback_location (r
, m_loc
),
5085 m_type
->playback_type (),
5086 playback_string (m_name
)));
5089 /* Override the default implementation of
5090 recording::memento::write_to_dump for locals by writing
5092 for use at the top of the function body as if it were a
5096 recording::local::write_to_dump (dump
&d
)
5098 if (d
.update_locations ())
5099 m_loc
= d
.make_location ();
5100 d
.write(" %s %s;\n",
5101 m_type
->get_debug_string (),
5102 get_debug_string ());
5106 recording::local::write_reproducer (reproducer
&r
)
5108 const char *id
= r
.make_identifier (this, "local");
5109 r
.write (" gcc_jit_lvalue *%s =\n"
5110 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5111 " %s, /* gcc_jit_location *loc */\n"
5112 " %s, /* gcc_jit_type *type */\n"
5113 " %s); /* const char *name */\n",
5115 r
.get_identifier (m_func
),
5116 r
.get_identifier (m_loc
),
5117 r
.get_identifier_as_type (m_type
),
5118 m_name
->get_debug_string ());
5121 /* The implementation of class gcc::jit::recording::statement. */
5123 /* We poison the default implementation of
5124 gcc::jit::recording::statement::get_successor_blocks
5125 since this vfunc must only ever be called on terminator
5129 recording::statement::get_successor_blocks (block
**/
*out_next1*/
,
5130 block
**/
*out_next2*/
) const
5132 /* The base class implementation is for non-terminating statements,
5133 and thus should never be called. */
5138 /* Extend the default implementation of
5139 recording::memento::write_to_dump for statements by (if requested)
5140 updating the location of the statement to the current location in
5144 recording::statement::write_to_dump (dump
&d
)
5146 memento::write_to_dump (d
);
5147 if (d
.update_locations ())
5148 m_loc
= d
.make_location ();
5151 /* The implementation of class gcc::jit::recording::eval. */
5153 /* Implementation of pure virtual hook recording::memento::replay_into
5154 for recording::eval. */
5157 recording::eval::replay_into (replayer
*r
)
5159 playback_block (get_block ())
5160 ->add_eval (playback_location (r
),
5161 m_rvalue
->playback_rvalue ());
5164 /* Implementation of recording::memento::make_debug_string for
5165 an eval statement. */
5168 recording::eval::make_debug_string ()
5170 return string::from_printf (m_ctxt
,
5172 m_rvalue
->get_debug_string ());
5175 /* Implementation of recording::memento::write_reproducer for
5179 recording::eval::write_reproducer (reproducer
&r
)
5181 r
.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5182 " %s, /* gcc_jit_location *loc */\n"
5183 " %s); /* gcc_jit_rvalue *rvalue */\n",
5184 r
.get_identifier (get_block ()),
5185 r
.get_identifier (get_loc ()),
5186 r
.get_identifier_as_rvalue (m_rvalue
));
5189 /* The implementation of class gcc::jit::recording::assignment. */
5191 /* Implementation of pure virtual hook recording::memento::replay_into
5192 for recording::assignment. */
5195 recording::assignment::replay_into (replayer
*r
)
5197 playback_block (get_block ())
5198 ->add_assignment (playback_location (r
),
5199 m_lvalue
->playback_lvalue (),
5200 m_rvalue
->playback_rvalue ());
5203 /* Implementation of recording::memento::make_debug_string for
5204 an assignment statement. */
5207 recording::assignment::make_debug_string ()
5209 return string::from_printf (m_ctxt
,
5211 m_lvalue
->get_debug_string (),
5212 m_rvalue
->get_debug_string ());
5215 /* Implementation of recording::memento::write_reproducer for
5216 assignment statements. */
5219 recording::assignment::write_reproducer (reproducer
&r
)
5221 r
.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5222 " %s, /* gcc_jit_location *loc */\n"
5223 " %s, /* gcc_jit_lvalue *lvalue */\n"
5224 " %s); /* gcc_jit_rvalue *rvalue */\n",
5225 r
.get_identifier (get_block ()),
5226 r
.get_identifier (get_loc ()),
5227 r
.get_identifier_as_lvalue (m_lvalue
),
5228 r
.get_identifier_as_rvalue (m_rvalue
));
5231 /* The implementation of class gcc::jit::recording::assignment_op. */
5233 /* Implementation of pure virtual hook recording::memento::replay_into
5234 for recording::assignment_op. */
5237 recording::assignment_op::replay_into (replayer
*r
)
5239 playback::type
*result_type
=
5240 m_lvalue
->playback_lvalue ()->get_type ();
5242 playback::rvalue
*binary_op
=
5243 r
->new_binary_op (playback_location (r
),
5246 m_lvalue
->playback_rvalue (),
5247 m_rvalue
->playback_rvalue ());
5249 playback_block (get_block ())
5250 ->add_assignment (playback_location (r
),
5251 m_lvalue
->playback_lvalue (),
5255 /* Implementation of recording::memento::make_debug_string for
5256 an assignment_op statement. */
5259 recording::assignment_op::make_debug_string ()
5261 return string::from_printf (m_ctxt
,
5263 m_lvalue
->get_debug_string (),
5264 binary_op_strings
[m_op
],
5265 m_rvalue
->get_debug_string ());
5268 /* Implementation of recording::memento::write_reproducer for
5269 assignment_op statements. */
5272 recording::assignment_op::write_reproducer (reproducer
&r
)
5274 r
.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5275 " %s, /* gcc_jit_location *loc */\n"
5276 " %s, /* gcc_jit_lvalue *lvalue */\n"
5277 " %s, /* enum gcc_jit_binary_op op */\n"
5278 " %s); /* gcc_jit_rvalue *rvalue */\n",
5279 r
.get_identifier (get_block ()),
5280 r
.get_identifier (get_loc ()),
5281 r
.get_identifier_as_lvalue (m_lvalue
),
5282 binary_op_reproducer_strings
[m_op
],
5283 r
.get_identifier_as_rvalue (m_rvalue
));
5286 /* The implementation of class gcc::jit::recording::comment. */
5288 /* Implementation of pure virtual hook recording::memento::replay_into
5289 for recording::comment. */
5292 recording::comment::replay_into (replayer
*r
)
5294 playback_block (get_block ())
5295 ->add_comment (playback_location (r
),
5299 /* Implementation of recording::memento::make_debug_string for
5300 a comment "statement". */
5303 recording::comment::make_debug_string ()
5305 return string::from_printf (m_ctxt
,
5310 /* Implementation of recording::memento::write_reproducer for
5314 recording::comment::write_reproducer (reproducer
&r
)
5316 r
.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5317 " %s, /* gcc_jit_location *loc */\n"
5318 " %s); /* const char *text */\n",
5319 r
.get_identifier (get_block ()),
5320 r
.get_identifier (get_loc ()),
5321 m_text
->get_debug_string ());
5324 /* The implementation of class gcc::jit::recording::conditional. */
5326 /* Implementation of pure virtual hook recording::memento::replay_into
5327 for recording::conditional. */
5330 recording::conditional::replay_into (replayer
*r
)
5332 playback_block (get_block ())
5333 ->add_conditional (playback_location (r
),
5334 m_boolval
->playback_rvalue (),
5335 playback_block (m_on_true
),
5336 playback_block (m_on_false
));
5339 /* Override the poisoned default implementation of
5340 gcc::jit::recording::statement::get_successor_blocks
5342 A conditional jump has 2 successor blocks. */
5345 recording::conditional::get_successor_blocks (block
**out_next1
,
5346 block
**out_next2
) const
5348 *out_next1
= m_on_true
;
5349 *out_next2
= m_on_false
;
5353 /* Implementation of recording::memento::make_debug_string for
5354 a conditional jump statement. */
5357 recording::conditional::make_debug_string ()
5360 return string::from_printf (m_ctxt
,
5361 "if (%s) goto %s; else goto %s;",
5362 m_boolval
->get_debug_string (),
5363 m_on_true
->get_debug_string (),
5364 m_on_false
->get_debug_string ());
5366 return string::from_printf (m_ctxt
,
5368 m_boolval
->get_debug_string (),
5369 m_on_true
->get_debug_string ());
5372 /* Implementation of recording::memento::write_reproducer for
5373 conditional statements. */
5376 recording::conditional::write_reproducer (reproducer
&r
)
5378 r
.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5379 " %s, /* gcc_jit_location *loc */\n"
5380 " %s, /* gcc_jit_rvalue *boolval */\n"
5381 " %s, /* gcc_jit_block *on_true */\n"
5382 " %s); /* gcc_jit_block *on_false */\n",
5383 r
.get_identifier (get_block ()),
5384 r
.get_identifier (get_loc ()),
5385 r
.get_identifier_as_rvalue (m_boolval
),
5386 r
.get_identifier (m_on_true
),
5387 r
.get_identifier (m_on_false
));
5390 /* The implementation of class gcc::jit::recording::jump. */
5392 /* Implementation of pure virtual hook recording::memento::replay_into
5393 for recording::jump. */
5396 recording::jump::replay_into (replayer
*r
)
5398 playback_block (get_block ())
5399 ->add_jump (playback_location (r
),
5400 m_target
->playback_block ());
5403 /* Override the poisoned default implementation of
5404 gcc::jit::recording::statement::get_successor_blocks
5406 An unconditional jump has 1 successor block. */
5409 recording::jump::get_successor_blocks (block
**out_next1
,
5410 block
**/
*out_next2*/
) const
5412 *out_next1
= m_target
;
5416 /* Implementation of recording::memento::make_debug_string for
5417 a unconditional jump statement. */
5420 recording::jump::make_debug_string ()
5422 return string::from_printf (m_ctxt
,
5424 m_target
->get_debug_string ());
5427 /* Implementation of recording::memento::write_reproducer for
5431 recording::jump::write_reproducer (reproducer
&r
)
5433 r
.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5434 " %s, /* gcc_jit_location *loc */\n"
5435 " %s); /* gcc_jit_block *target */\n",
5436 r
.get_identifier (get_block ()),
5437 r
.get_identifier (get_loc ()),
5438 r
.get_identifier (m_target
));
5441 /* The implementation of class gcc::jit::recording::return_. */
5443 /* Implementation of pure virtual hook recording::memento::replay_into
5444 for recording::return_. */
5447 recording::return_::replay_into (replayer
*r
)
5449 playback_block (get_block ())
5450 ->add_return (playback_location (r
),
5451 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
5454 /* Override the poisoned default implementation of
5455 gcc::jit::recording::statement::get_successor_blocks
5457 A return statement has no successor block. */
5460 recording::return_::get_successor_blocks (block
**/
*out_next1*/
,
5461 block
**/
*out_next2*/
) const
5466 /* Implementation of recording::memento::make_debug_string for
5467 a return statement (covers both those with and without rvalues). */
5470 recording::return_::make_debug_string ()
5473 return string::from_printf (m_ctxt
,
5475 m_rvalue
->get_debug_string ());
5477 return string::from_printf (m_ctxt
,
5481 /* Implementation of recording::memento::write_reproducer for
5482 return statements. */
5485 recording::return_::write_reproducer (reproducer
&r
)
5488 r
.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5489 " %s, /* gcc_jit_location *loc */\n"
5490 " %s); /* gcc_jit_rvalue *rvalue */\n",
5491 r
.get_identifier (get_block ()),
5492 r
.get_identifier (get_loc ()),
5493 r
.get_identifier_as_rvalue (m_rvalue
));
5495 r
.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5496 " %s); /* gcc_jit_location *loc */\n",
5497 r
.get_identifier (get_block ()),
5498 r
.get_identifier (get_loc ()));
5501 } // namespace gcc::jit