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 memcpy (m_inner_bool_options
,
493 parent_ctxt
->m_inner_bool_options
,
494 sizeof (m_inner_bool_options
));
495 set_logger (parent_ctxt
->get_logger ());
499 memset (m_str_options
, 0, sizeof (m_str_options
));
500 memset (m_int_options
, 0, sizeof (m_int_options
));
501 memset (m_bool_options
, 0, sizeof (m_bool_options
));
502 memset (m_inner_bool_options
, 0, sizeof (m_inner_bool_options
));
505 memset (m_basic_types
, 0, sizeof (m_basic_types
));
508 /* The destructor for gcc::jit::recording::context, implicitly used by
509 gcc_jit_context_release. */
511 recording::context::~context ()
513 JIT_LOG_SCOPE (get_logger ());
516 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
521 for (i
= 0; i
< GCC_JIT_NUM_STR_OPTIONS
; ++i
)
522 free (m_str_options
[i
]);
525 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
528 if (m_builtins_manager
)
529 delete m_builtins_manager
;
531 if (m_owns_first_error_str
)
532 free (m_first_error_str
);
534 if (m_owns_last_error_str
)
535 if (m_last_error_str
!= m_first_error_str
)
536 free (m_last_error_str
);
539 /* Add the given mememto to the list of those tracked by this
540 gcc::jit::recording::context, so that e.g. it can be deleted
541 when this context is released. */
544 recording::context::record (memento
*m
)
548 m_mementos
.safe_push (m
);
551 /* Replay this context (and any parents) into the given replayer. */
554 recording::context::replay_into (replayer
*r
)
556 JIT_LOG_SCOPE (get_logger ());
560 /* If we have a parent context, we must replay it. This will
561 recursively walk backwards up the historical tree, then replay things
562 forwards "in historical order", starting with the ultimate parent
563 context, until we reach the "this" context.
565 Note that we fully replay the parent, then fully replay the child,
566 which means that inter-context references can only exist from child
567 to parent, not the other way around.
569 All of this replaying is suboptimal - it would be better to do the
570 work for the parent context *once*, rather than replaying the parent
571 every time we replay each child. However, fixing this requires deep
572 surgery to lifetime-management: we'd need every context family tree
573 to have its own GC heap, and to initialize the GCC code to use that
574 heap (with a mutex on such a heap). */
576 m_parent_ctxt
->replay_into (r
);
578 if (r
->errors_occurred ())
581 /* Replay this context's saved operations into r. */
582 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
584 /* Disabled low-level debugging, here if we need it: print what
586 Note that the calls to get_debug_string might lead to more
587 mementos being created for the strings.
588 This can also be used to exercise the debug_string
591 printf ("context %p replaying (%p): %s\n",
592 (void *)this, (void *)m
, m
->get_debug_string ());
596 if (r
->errors_occurred ())
601 /* During a playback, we associate objects from the recording with
602 their counterparts during this playback.
604 For simplicity, we store this within the recording objects.
606 The following method cleans away these associations, to ensure that
607 we never have out-of-date associations lingering on subsequent
608 playbacks (the objects pointed to are GC-managed, but the
609 recording objects don't own refs to them). */
612 recording::context::disassociate_from_playback ()
614 JIT_LOG_SCOPE (get_logger ());
619 m_parent_ctxt
->disassociate_from_playback ();
621 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
623 m
->set_playback_obj (NULL
);
627 /* Create a recording::string instance and add it to this context's list
630 This creates a fresh copy of the given 0-terminated buffer. */
633 recording::context::new_string (const char *text
)
638 recording::string
*result
= new string (this, text
);
643 /* Create a recording::location instance and add it to this context's
646 Implements the post-error-checking part of
647 gcc_jit_context_new_location. */
649 recording::location
*
650 recording::context::new_location (const char *filename
,
653 bool created_by_user
)
655 recording::location
*result
=
656 new recording::location (this,
657 new_string (filename
),
664 /* If we haven't seen this enum value yet, create a recording::type
665 instance and add it to this context's list of mementos.
667 If we have seen it before, reuse our cached value, so that repeated
668 calls on the context give the same object.
670 If we have a parent context, the cache is within the ultimate
673 Implements the post-error-checking part of
674 gcc_jit_context_get_type. */
677 recording::context::get_type (enum gcc_jit_types kind
)
679 if (!m_basic_types
[kind
])
682 m_basic_types
[kind
] = m_parent_ctxt
->get_type (kind
);
685 recording::type
*result
= new memento_of_get_type (this, kind
);
687 m_basic_types
[kind
] = result
;
691 return m_basic_types
[kind
];
694 /* Get a recording::type instance for the given size and signedness.
695 This is implemented in terms of recording::context::get_type
698 Implements the post-error-checking part of
699 gcc_jit_context_get_int_type. */
702 recording::context::get_int_type (int num_bytes
, int is_signed
)
704 /* We can't use a switch here since some of the values are macros affected
705 by options; e.g. i386.h has
706 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
707 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
708 are in bits, rather than bytes.
710 const int num_bits
= num_bytes
* 8;
711 if (num_bits
== INT_TYPE_SIZE
)
712 return get_type (is_signed
714 : GCC_JIT_TYPE_UNSIGNED_INT
);
715 if (num_bits
== CHAR_TYPE_SIZE
)
716 return get_type (is_signed
717 ? GCC_JIT_TYPE_SIGNED_CHAR
718 : GCC_JIT_TYPE_UNSIGNED_CHAR
);
719 if (num_bits
== SHORT_TYPE_SIZE
)
720 return get_type (is_signed
722 : GCC_JIT_TYPE_UNSIGNED_SHORT
);
723 if (num_bits
== LONG_TYPE_SIZE
)
724 return get_type (is_signed
726 : GCC_JIT_TYPE_UNSIGNED_LONG
);
727 if (num_bits
== LONG_LONG_TYPE_SIZE
)
728 return get_type (is_signed
729 ? GCC_JIT_TYPE_LONG_LONG
730 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
732 /* Some other size, not corresponding to the C int types. */
733 /* To be written: support arbitrary other sizes, sharing by
734 memoizing at the recording::context level? */
738 /* Create a recording::type instance and add it to this context's list
741 Implements the post-error-checking part of
742 gcc_jit_context_new_array_type. */
745 recording::context::new_array_type (recording::location
*loc
,
746 recording::type
*element_type
,
749 if (struct_
*s
= element_type
->dyn_cast_struct ())
750 if (!s
->get_fields ())
753 "cannot create an array of type %s"
754 " until the fields have been set",
755 s
->get_name ()->c_str ());
758 recording::type
*result
=
759 new recording::array_type (this, loc
, element_type
, num_elements
);
764 /* Create a recording::field instance and add it to this context's list
767 Implements the post-error-checking part of
768 gcc_jit_context_new_field. */
771 recording::context::new_field (recording::location
*loc
,
772 recording::type
*type
,
775 recording::field
*result
=
776 new recording::field (this, loc
, type
, new_string (name
));
781 /* Create a recording::struct_ instance and add it to this context's
782 list of mementos and list of compound types.
784 Implements the post-error-checking part of
785 gcc_jit_context_new_struct_type. */
788 recording::context::new_struct_type (recording::location
*loc
,
791 recording::struct_
*result
= new struct_ (this, loc
, new_string (name
));
793 m_compound_types
.safe_push (result
);
797 /* Create a recording::union_ instance and add it to this context's
798 list of mementos and list of compound types.
800 Implements the first post-error-checking part of
801 gcc_jit_context_new_union_type. */
804 recording::context::new_union_type (recording::location
*loc
,
807 recording::union_
*result
= new union_ (this, loc
, new_string (name
));
809 m_compound_types
.safe_push (result
);
813 /* Create a recording::function_type instance and add it to this context's
816 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
818 recording::function_type
*
819 recording::context::new_function_type (recording::type
*return_type
,
821 recording::type
**param_types
,
824 recording::function_type
*fn_type
825 = new function_type (this,
834 /* Create a recording::type instance and add it to this context's list
837 Implements the post-error-checking part of
838 gcc_jit_context_new_function_ptr_type. */
841 recording::context::new_function_ptr_type (recording::location
*, /* unused loc */
842 recording::type
*return_type
,
844 recording::type
**param_types
,
847 recording::function_type
*fn_type
848 = new_function_type (return_type
,
853 /* Return a pointer-type to the the function type. */
854 return fn_type
->get_pointer ();
857 /* Create a recording::param instance and add it to this context's list
860 Implements the post-error-checking part of
861 gcc_jit_context_new_param. */
864 recording::context::new_param (recording::location
*loc
,
865 recording::type
*type
,
868 recording::param
*result
= new recording::param (this, loc
, type
, new_string (name
));
873 /* Create a recording::function instance and add it to this context's list
874 of mementos and list of functions.
876 Implements the post-error-checking part of
877 gcc_jit_context_new_function. */
879 recording::function
*
880 recording::context::new_function (recording::location
*loc
,
881 enum gcc_jit_function_kind kind
,
882 recording::type
*return_type
,
885 recording::param
**params
,
887 enum built_in_function builtin_id
)
889 recording::function
*result
=
890 new recording::function (this,
891 loc
, kind
, return_type
,
893 num_params
, params
, is_variadic
,
896 m_functions
.safe_push (result
);
901 /* Locate the builtins_manager (if any) for this family of contexts,
902 creating it if it doesn't exist already.
904 All of the recording contexts in a family share one builtins_manager:
905 if we have a child context, follow the parent links to get the
906 ultimate ancestor context, and look for it/store it there. */
909 recording::context::get_builtins_manager ()
912 return m_parent_ctxt
->get_builtins_manager ();
914 if (!m_builtins_manager
)
915 m_builtins_manager
= new builtins_manager (this);
917 return m_builtins_manager
;
920 /* Get a recording::function instance, which is lazily-created and added
921 to the context's lists of mementos.
923 Implements the post-error-checking part of
924 gcc_jit_context_get_builtin_function. */
926 recording::function
*
927 recording::context::get_builtin_function (const char *name
)
929 builtins_manager
*bm
= get_builtins_manager ();
930 return bm
->get_builtin_function (name
);
933 /* Create a recording::global instance and add it to this context's list
936 Implements the post-error-checking part of
937 gcc_jit_context_new_global. */
940 recording::context::new_global (recording::location
*loc
,
941 enum gcc_jit_global_kind kind
,
942 recording::type
*type
,
945 recording::global
*result
=
946 new recording::global (this, loc
, kind
, type
, new_string (name
));
948 m_globals
.safe_push (result
);
953 /* Create a recording::memento_of_new_string_literal instance and add it
954 to this context's list of mementos.
956 Implements the post-error-checking part of
957 gcc_jit_context_new_string_literal. */
960 recording::context::new_string_literal (const char *value
)
962 recording::rvalue
*result
=
963 new memento_of_new_string_literal (this, NULL
, new_string (value
));
968 /* Create a recording::unary_op instance and add it to this context's
971 Implements the post-error-checking part of
972 gcc_jit_context_new_unary_op. */
975 recording::context::new_unary_op (recording::location
*loc
,
976 enum gcc_jit_unary_op op
,
977 recording::type
*result_type
,
978 recording::rvalue
*a
)
980 recording::rvalue
*result
=
981 new unary_op (this, loc
, op
, result_type
, a
);
986 /* Create a recording::binary_op instance and add it to this context's
989 Implements the post-error-checking part of
990 gcc_jit_context_new_binary_op. */
993 recording::context::new_binary_op (recording::location
*loc
,
994 enum gcc_jit_binary_op op
,
995 recording::type
*result_type
,
996 recording::rvalue
*a
,
997 recording::rvalue
*b
)
999 recording::rvalue
*result
=
1000 new binary_op (this, loc
, op
, result_type
, a
, b
);
1005 /* Create a recording::comparison instance and add it to this context's
1008 Implements the post-error-checking part of
1009 gcc_jit_context_new_comparison. */
1012 recording::context::new_comparison (recording::location
*loc
,
1013 enum gcc_jit_comparison op
,
1014 recording::rvalue
*a
,
1015 recording::rvalue
*b
)
1017 recording::rvalue
*result
= new comparison (this, loc
, op
, a
, b
);
1022 /* Create a recording::cast instance and add it to this context's list
1025 Implements the post-error-checking part of
1026 gcc_jit_context_new_cast. */
1029 recording::context::new_cast (recording::location
*loc
,
1030 recording::rvalue
*expr
,
1031 recording::type
*type_
)
1033 recording::rvalue
*result
= new cast (this, loc
, expr
, type_
);
1038 /* Create a recording::call instance and add it to this context's list
1041 Implements the post-error-checking part of
1042 gcc_jit_context_new_call. */
1045 recording::context::new_call (recording::location
*loc
,
1047 int numargs
, recording::rvalue
**args
)
1049 recording::rvalue
*result
= new call (this, loc
, func
, numargs
, args
);
1054 /* Create a recording::call_through_ptr instance and add it to this
1055 context's list of mementos.
1057 Implements the post-error-checking part of
1058 gcc_jit_context_new_call_through_ptr. */
1061 recording::context::new_call_through_ptr (recording::location
*loc
,
1062 recording::rvalue
*fn_ptr
,
1064 recording::rvalue
**args
)
1066 recording::rvalue
*result
= new call_through_ptr (this, loc
, fn_ptr
, numargs
, args
);
1071 /* Create a recording::array_access instance and add it to this context's list
1074 Implements the post-error-checking part of
1075 gcc_jit_context_new_array_access. */
1078 recording::context::new_array_access (recording::location
*loc
,
1079 recording::rvalue
*ptr
,
1080 recording::rvalue
*index
)
1082 recording::lvalue
*result
= new array_access (this, loc
, ptr
, index
);
1087 /* Set the given string option for this context, or add an error if
1088 it's not recognized.
1090 Implements the post-error-checking part of
1091 gcc_jit_context_set_str_option. */
1094 recording::context::set_str_option (enum gcc_jit_str_option opt
,
1097 if (opt
< 0 || opt
>= GCC_JIT_NUM_STR_OPTIONS
)
1100 "unrecognized (enum gcc_jit_str_option) value: %i", opt
);
1103 free (m_str_options
[opt
]);
1104 m_str_options
[opt
] = value
? xstrdup (value
) : NULL
;
1105 log_str_option (opt
);
1108 /* Set the given integer option for this context, or add an error if
1109 it's not recognized.
1111 Implements the post-error-checking part of
1112 gcc_jit_context_set_int_option. */
1115 recording::context::set_int_option (enum gcc_jit_int_option opt
,
1118 if (opt
< 0 || opt
>= GCC_JIT_NUM_INT_OPTIONS
)
1121 "unrecognized (enum gcc_jit_int_option) value: %i", opt
);
1124 m_int_options
[opt
] = value
;
1125 log_int_option (opt
);
1128 /* Set the given boolean option for this context, or add an error if
1129 it's not recognized.
1131 Implements the post-error-checking part of
1132 gcc_jit_context_set_bool_option. */
1135 recording::context::set_bool_option (enum gcc_jit_bool_option opt
,
1138 if (opt
< 0 || opt
>= GCC_JIT_NUM_BOOL_OPTIONS
)
1141 "unrecognized (enum gcc_jit_bool_option) value: %i", opt
);
1144 m_bool_options
[opt
] = value
? true : false;
1145 log_bool_option (opt
);
1149 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt
,
1152 gcc_assert (inner_opt
>= 0 && inner_opt
< NUM_INNER_BOOL_OPTIONS
);
1153 m_inner_bool_options
[inner_opt
] = value
? true : false;
1154 log_inner_bool_option (inner_opt
);
1158 /* Add the given optname to this context's list of extra options.
1160 Implements the post-error-checking part of
1161 gcc_jit_context_add_command_line_option. */
1164 recording::context::add_command_line_option (const char *optname
)
1166 m_command_line_options
.safe_push (xstrdup (optname
));
1169 /* Add any user-provided extra options, starting with any from
1171 Called by playback::context::make_fake_args. */
1174 recording::context::append_command_line_options (vec
<char *> *argvec
)
1177 m_parent_ctxt
->append_command_line_options (argvec
);
1181 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1182 argvec
->safe_push (xstrdup (optname
));
1185 /* Add the given dumpname/out_ptr pair to this context's list of requested
1188 Implements the post-error-checking part of
1189 gcc_jit_context_enable_dump. */
1192 recording::context::enable_dump (const char *dumpname
,
1196 gcc_assert (dumpname
);
1197 gcc_assert (out_ptr
);
1199 d
.m_dumpname
= dumpname
;
1200 d
.m_out_ptr
= out_ptr
;
1202 m_requested_dumps
.safe_push (d
);
1205 /* Validate this context, and if it passes, compile it to memory
1208 Implements the post-error-checking part of
1209 gcc_jit_context_compile. */
1212 recording::context::compile ()
1214 JIT_LOG_SCOPE (get_logger ());
1220 if (errors_occurred ())
1223 /* Set up a compile_to_memory playback context. */
1224 ::gcc::jit::playback::compile_to_memory
replayer (this);
1227 replayer
.compile ();
1229 /* Get the jit::result (or NULL) from the
1230 compile_to_memory playback context. */
1231 return replayer
.get_result_obj ();
1234 /* Validate this context, and if it passes, compile it to a file
1237 Implements the post-error-checking part of
1238 gcc_jit_context_compile_to_file. */
1241 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind
,
1242 const char *output_path
)
1244 JIT_LOG_SCOPE (get_logger ());
1250 if (errors_occurred ())
1253 /* Set up a compile_to_file playback context. */
1254 ::gcc::jit::playback::compile_to_file
replayer (this,
1259 replayer
.compile ();
1262 /* Format the given error using printf's conventions, print
1263 it to stderr, and add it to the context. */
1266 recording::context::add_error (location
*loc
, const char *fmt
, ...)
1270 add_error_va (loc
, fmt
, ap
);
1274 /* Format the given error using printf's conventions, print
1275 it to stderr, and add it to the context. */
1278 recording::context::add_error_va (location
*loc
, const char *fmt
, va_list ap
)
1285 JIT_LOG_SCOPE (get_logger ());
1287 len
= vasprintf (&malloced_msg
, fmt
, ap
);
1288 if (malloced_msg
== NULL
|| len
< 0)
1290 errmsg
= "out of memory generating error message";
1291 has_ownership
= false;
1295 errmsg
= malloced_msg
;
1296 has_ownership
= true;
1299 get_logger ()->log ("error %i: %s", m_error_count
, errmsg
);
1301 const char *ctxt_progname
=
1302 get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
1304 ctxt_progname
= "libgccjit.so";
1307 fprintf (stderr
, "%s: %s: error: %s\n",
1309 loc
->get_debug_string (),
1312 fprintf (stderr
, "%s: error: %s\n",
1318 m_first_error_str
= const_cast <char *> (errmsg
);
1319 m_owns_first_error_str
= has_ownership
;
1322 if (m_owns_last_error_str
)
1323 if (m_last_error_str
!= m_first_error_str
)
1324 free (m_last_error_str
);
1325 m_last_error_str
= const_cast <char *> (errmsg
);
1326 m_owns_last_error_str
= has_ownership
;
1331 /* Get the message for the first error that occurred on this context, or
1332 NULL if no errors have occurred on it.
1334 Implements the post-error-checking part of
1335 gcc_jit_context_get_first_error. */
1338 recording::context::get_first_error () const
1340 return m_first_error_str
;
1343 /* Get the message for the last error that occurred on this context, or
1344 NULL if no errors have occurred on it.
1346 Implements the post-error-checking part of
1347 gcc_jit_context_get_last_error. */
1350 recording::context::get_last_error () const
1352 return m_last_error_str
;
1355 /* Lazily generate and record a recording::type representing an opaque
1356 struct named "FILE".
1358 For use if client code tries to dereference the result of
1359 get_type (GCC_JIT_TYPE_FILE_PTR). */
1362 recording::context::get_opaque_FILE_type ()
1365 m_FILE_type
= new_struct_type (NULL
, "FILE");
1369 /* Dump a C-like representation of the given context to the given path.
1370 If UPDATE_LOCATIONS is true, update the locations within the
1371 context's mementos to point to the dumpfile.
1373 Implements the post-error-checking part of
1374 gcc_jit_context_dump_to_file. */
1377 recording::context::dump_to_file (const char *path
, bool update_locations
)
1380 dump
d (*this, path
, update_locations
);
1382 /* Forward declaration of structs and unions. */
1384 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1386 d
.write ("%s;\n\n", st
->get_debug_string ());
1389 /* Content of structs, where set. */
1390 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1391 if (st
->get_fields ())
1393 st
->get_fields ()->write_to_dump (d
);
1399 FOR_EACH_VEC_ELT (m_globals
, i
, g
)
1401 g
->write_to_dump (d
);
1403 if (!m_globals
.is_empty ())
1407 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1409 fn
->write_to_dump (d
);
1413 static const char * const
1414 str_option_reproducer_strings
[GCC_JIT_NUM_STR_OPTIONS
] = {
1415 "GCC_JIT_STR_OPTION_PROGNAME"
1418 static const char * const
1419 int_option_reproducer_strings
[GCC_JIT_NUM_INT_OPTIONS
] = {
1420 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1423 static const char * const
1424 bool_option_reproducer_strings
[GCC_JIT_NUM_BOOL_OPTIONS
] = {
1425 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1426 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1427 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1428 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1429 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1430 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1431 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1432 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1435 static const char * const
1436 inner_bool_option_reproducer_strings
[NUM_INNER_BOOL_OPTIONS
] = {
1437 "gcc_jit_context_set_bool_allow_unreachable_blocks"
1440 /* Write the current value of all options to the log file (if any). */
1443 recording::context::log_all_options () const
1450 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1451 log_str_option ((enum gcc_jit_str_option
)opt_idx
);
1453 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1454 log_int_option ((enum gcc_jit_int_option
)opt_idx
);
1456 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1457 log_bool_option ((enum gcc_jit_bool_option
)opt_idx
);
1458 for (opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1459 log_inner_bool_option ((enum inner_bool_option
)opt_idx
);
1462 /* Write the current value of the given string option to the
1463 log file (if any). */
1466 recording::context::log_str_option (enum gcc_jit_str_option opt
) const
1468 gcc_assert (opt
< GCC_JIT_NUM_STR_OPTIONS
);
1471 if (m_str_options
[opt
])
1473 str_option_reproducer_strings
[opt
],
1474 m_str_options
[opt
]);
1477 str_option_reproducer_strings
[opt
]);
1481 /* Write the current value of the given int option to the
1482 log file (if any). */
1485 recording::context::log_int_option (enum gcc_jit_int_option opt
) const
1487 gcc_assert (opt
< GCC_JIT_NUM_INT_OPTIONS
);
1490 int_option_reproducer_strings
[opt
],
1491 m_int_options
[opt
]);
1494 /* Write the current value of the given bool option to the
1495 log file (if any). */
1498 recording::context::log_bool_option (enum gcc_jit_bool_option opt
) const
1500 gcc_assert (opt
< GCC_JIT_NUM_BOOL_OPTIONS
);
1503 bool_option_reproducer_strings
[opt
],
1504 m_bool_options
[opt
] ? "true" : "false");
1507 /* Write the current value of the given "inner" bool option to the
1508 log file (if any). */
1511 recording::context::log_inner_bool_option (enum inner_bool_option opt
) const
1513 gcc_assert (opt
< NUM_INNER_BOOL_OPTIONS
);
1516 inner_bool_option_reproducer_strings
[opt
],
1517 m_inner_bool_options
[opt
] ? "true" : "false");
1520 /* Write C source code to PATH that attempts to replay the API
1521 calls made to this context (and its parents), for use in
1522 minimizing test cases for libgccjit.
1524 Implements the post-error-checking part of
1525 gcc_jit_context_dump_reproducer_to_file. */
1528 recording::context::dump_reproducer_to_file (const char *path
)
1530 JIT_LOG_SCOPE (get_logger ());
1531 reproducer
r (*this, path
);
1533 /* Generate the "ancestry" of this context, as a list. */
1534 auto_vec
<context
*> ascending_contexts
;
1535 for (context
*ctxt
= this; ctxt
; ctxt
= ctxt
->m_parent_ctxt
)
1536 ascending_contexts
.safe_push (ctxt
);
1538 /* Reverse the list, giving a list of contexts from
1539 top-most parent context down through to youngest child context.
1540 We will use this list as the parameters of the functions in
1541 our generated file. */
1542 unsigned num_ctxts
= ascending_contexts
.length ();
1543 auto_vec
<context
*> contexts (num_ctxts
);
1544 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1545 contexts
.safe_push (ascending_contexts
[num_ctxts
- (i
+ 1)]);
1547 /* contexts[0] should be the top-level context. */
1548 gcc_assert (contexts
[0]);
1549 gcc_assert (contexts
[0]->m_toplevel_ctxt
== contexts
[0]);
1551 /* The final element in contexts should be "this". */
1552 gcc_assert (contexts
[contexts
.length () - 1] == this);
1553 gcc_assert (contexts
[contexts
.length () - 1]->m_toplevel_ctxt
1556 r
.write ("/* This code was autogenerated by"
1557 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1558 print_version (r
.get_file (), " ", false);
1560 r
.write ("#include <libgccjit.h>\n\n");
1561 r
.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1562 r
.write ("static void\nset_options (");
1563 r
.write_params (contexts
);
1565 r
.write ("static void\ncreate_code (");
1566 r
.write_params (contexts
);
1568 r
.write ("int\nmain (int argc, const char **argv)\n");
1570 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1571 r
.write (" gcc_jit_context *%s;\n",
1572 r
.get_identifier (contexts
[i
]));
1573 r
.write (" gcc_jit_result *result;\n"
1576 /* Create the contexts.
1577 The top-level context is acquired from a clean slate, the others as
1578 children of the prior context. */
1579 r
.write (" %s = gcc_jit_context_acquire ();\n",
1580 r
.get_identifier (contexts
[0]));
1581 for (unsigned i
= 1; i
< num_ctxts
; i
++)
1582 r
.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1583 r
.get_identifier (contexts
[i
]),
1584 r
.get_identifier (contexts
[i
- 1]));
1585 r
.write (" set_options (");
1586 r
.write_args (contexts
);
1588 r
.write (" create_code (");
1589 r
.write_args (contexts
);
1592 r
.write (" result = gcc_jit_context_compile (%s);\n",
1593 r
.get_identifier (this));
1595 for (unsigned i
= num_ctxts
; i
> 0; i
--)
1596 r
.write (" gcc_jit_context_release (%s);\n",
1597 r
.get_identifier (contexts
[i
- 1]));
1599 r
.write (" gcc_jit_result_release (result);\n"
1603 /* Define (char *) variables for use in calls to
1604 gcc_jit_context_enable_dump. */
1605 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1607 if (m_requested_dumps
.length ())
1609 r
.write ("/* Requested dumps for %s. */\n",
1610 r
.get_identifier (contexts
[ctxt_idx
]));
1611 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1612 r
.write ("static char *dump_%p;\n",
1613 (void *)&m_requested_dumps
[i
]);
1618 /* Write out values of options. */
1619 r
.write ("static void\nset_options (");
1620 r
.write_params (contexts
);
1622 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1627 r
.write (" /* Set options for %s. */\n",
1628 r
.get_identifier (contexts
[ctxt_idx
]));
1630 r
.write (" /* String options. */\n");
1631 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1633 r
.write (" gcc_jit_context_set_str_option (%s,\n"
1635 r
.get_identifier (contexts
[ctxt_idx
]),
1636 str_option_reproducer_strings
[opt_idx
]);
1637 if (m_str_options
[opt_idx
])
1638 r
.write (" \"%s\");\n",
1639 m_str_options
[opt_idx
]);
1641 r
.write (" NULL);\n");
1643 r
.write (" /* Int options. */\n");
1644 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1645 r
.write (" gcc_jit_context_set_int_option (%s,\n"
1648 r
.get_identifier (contexts
[ctxt_idx
]),
1649 int_option_reproducer_strings
[opt_idx
],
1650 m_int_options
[opt_idx
]);
1651 r
.write (" /* Boolean options. */\n");
1652 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1653 r
.write (" gcc_jit_context_set_bool_option (%s,\n"
1656 r
.get_identifier (contexts
[ctxt_idx
]),
1657 bool_option_reproducer_strings
[opt_idx
],
1658 m_bool_options
[opt_idx
]);
1659 for (int opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1660 r
.write (" %s (%s, %i);\n",
1661 inner_bool_option_reproducer_strings
[opt_idx
],
1662 r
.get_identifier (contexts
[ctxt_idx
]),
1663 m_inner_bool_options
[opt_idx
]);
1665 if (!m_command_line_options
.is_empty ())
1669 r
.write (" /* User-provided command-line options. */\n");
1670 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1671 r
.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1672 r
.get_identifier (contexts
[ctxt_idx
]),
1676 if (m_requested_dumps
.length ())
1678 r
.write (" /* Requested dumps. */\n");
1679 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1680 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1682 r
.write (" gcc_jit_context_enable_dump (%s,\n"
1685 r
.get_identifier (contexts
[ctxt_idx
]),
1686 m_requested_dumps
[i
].m_dumpname
,
1687 (void *)&m_requested_dumps
[i
]);
1693 r
.write ("static void\ncreate_code (");
1694 r
.write_params (contexts
);
1697 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1704 r
.write (" /* Replay of API calls for %s. */\n",
1705 r
.get_identifier (contexts
[ctxt_idx
]));
1706 FOR_EACH_VEC_ELT (contexts
[ctxt_idx
]->m_mementos
, i
, m
)
1707 m
->write_reproducer (r
);
1712 /* Copy the requested dumps within this context and all ancestors into
1716 recording::context::get_all_requested_dumps (vec
<recording::requested_dump
> *out
)
1719 m_parent_ctxt
->get_all_requested_dumps (out
);
1721 out
->reserve (m_requested_dumps
.length ());
1722 out
->splice (m_requested_dumps
);
1725 /* This is a pre-compilation check for the context (and any parents).
1727 Detect errors within the context, adding errors if any are found. */
1730 recording::context::validate ()
1732 JIT_LOG_SCOPE (get_logger ());
1735 m_parent_ctxt
->validate ();
1739 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1743 /* The implementation of class gcc::jit::recording::memento. */
1745 /* Get a (const char *) debug description of the given memento, by
1746 calling the pure-virtual make_debug_string hook, caching the
1749 It is intended that this should only be called in debugging and
1750 error-handling paths, so this doesn't need to be particularly
1754 recording::memento::get_debug_string ()
1756 if (!m_debug_string
)
1757 m_debug_string
= make_debug_string ();
1758 return m_debug_string
->c_str ();
1761 /* Default implementation of recording::memento::write_to_dump, writing
1762 an indented form of the memento's debug string to the dump. */
1765 recording::memento::write_to_dump (dump
&d
)
1767 d
.write(" %s\n", get_debug_string ());
1770 /* The implementation of class gcc::jit::recording::string. */
1772 /* Constructor for gcc::jit::recording::string::string, allocating a
1773 copy of the given text using new char[]. */
1775 recording::string::string (context
*ctxt
, const char *text
)
1778 m_len
= strlen (text
);
1779 m_buffer
= new char[m_len
+ 1];
1780 strcpy (m_buffer
, text
);
1783 /* Destructor for gcc::jit::recording::string::string. */
1785 recording::string::~string ()
1790 /* Function for making gcc::jit::recording::string instances on a
1791 context via printf-style formatting.
1793 It is intended that this should only be called in debugging and
1794 error-handling paths, so this doesn't need to be particularly
1795 optimized, hence the double-copy of the string is acceptable. */
1798 recording::string::from_printf (context
*ctxt
, const char *fmt
, ...)
1803 recording::string
*result
;
1806 len
= vasprintf (&buf
, fmt
, ap
);
1809 if (buf
== NULL
|| len
< 0)
1811 ctxt
->add_error (NULL
, "malloc failure");
1815 result
= ctxt
->new_string (buf
);
1820 /* Implementation of recording::memento::make_debug_string for strings,
1821 wrapping the given string in quotes and escaping as necessary. */
1824 recording::string::make_debug_string ()
1826 /* Hack to avoid infinite recursion into strings when logging all
1827 mementos: don't re-escape strings: */
1828 if (m_buffer
[0] == '"')
1831 /* Wrap in quotes and do escaping etc */
1833 size_t sz
= (1 /* opening quote */
1834 + (m_len
* 2) /* each char might get escaped */
1835 + 1 /* closing quote */
1836 + 1); /* nil termintator */
1837 char *tmp
= new char[sz
];
1840 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1841 APPEND('"'); /* opening quote */
1842 for (size_t i
= 0; i
< m_len
; i
++)
1844 char ch
= m_buffer
[i
];
1845 if (ch
== '\t' || ch
== '\n' || ch
== '\\' || ch
== '"')
1849 APPEND('"'); /* closing quote */
1851 tmp
[len
] = '\0'; /* nil termintator */
1853 string
*result
= m_ctxt
->new_string (tmp
);
1859 /* Implementation of recording::memento::write_reproducer for strings. */
1862 recording::string::write_reproducer (reproducer
&)
1867 /* The implementation of class gcc::jit::recording::location. */
1869 /* Implementation of recording::memento::replay_into for locations.
1871 Create a new playback::location and store it into the
1872 recording::location's m_playback_obj field. */
1875 recording::location::replay_into (replayer
*r
)
1877 m_playback_obj
= r
->new_location (this,
1878 m_filename
->c_str (),
1883 /* Implementation of recording::memento::make_debug_string for locations,
1884 turning them into the usual form:
1885 FILENAME:LINE:COLUMN
1886 like we do when emitting diagnostics. */
1889 recording::location::make_debug_string ()
1891 return string::from_printf (m_ctxt
,
1893 m_filename
->c_str (), m_line
, m_column
);
1896 /* Implementation of recording::memento::write_reproducer for locations. */
1899 recording::location::write_reproducer (reproducer
&r
)
1901 const char *id
= r
.make_identifier (this, "loc");
1902 r
.write (" gcc_jit_location *%s =\n"
1903 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1904 " %s, /* const char *filename */\n"
1905 " %i, /* int line */\n"
1906 " %i);/* int column */\n",
1908 r
.get_identifier (get_context ()),
1909 m_filename
->get_debug_string (),
1913 /* The implementation of class gcc::jit::recording::type. */
1915 /* Given a type T, get the type T*.
1917 If this doesn't already exist, generate a new memento_of_get_pointer
1918 instance and add it to this type's context's list of mementos.
1920 Otherwise, use the cached type.
1922 Implements the post-error-checking part of
1923 gcc_jit_type_get_pointer. */
1926 recording::type::get_pointer ()
1928 if (!m_pointer_to_this_type
)
1930 m_pointer_to_this_type
= new memento_of_get_pointer (this);
1931 m_ctxt
->record (m_pointer_to_this_type
);
1933 return m_pointer_to_this_type
;
1936 /* Given a type T, get the type const T.
1938 Implements the post-error-checking part of
1939 gcc_jit_type_get_const. */
1942 recording::type::get_const ()
1944 recording::type
*result
= new memento_of_get_const (this);
1945 m_ctxt
->record (result
);
1949 /* Given a type T, get the type volatile T.
1951 Implements the post-error-checking part of
1952 gcc_jit_type_get_volatile. */
1955 recording::type::get_volatile ()
1957 recording::type
*result
= new memento_of_get_volatile (this);
1958 m_ctxt
->record (result
);
1963 recording::type::access_as_type (reproducer
&r
)
1965 return r
.get_identifier (this);
1968 /* Implementation of pure virtual hook recording::type::dereference for
1969 recording::memento_of_get_type. */
1972 recording::memento_of_get_type::dereference ()
1976 default: gcc_unreachable ();
1978 case GCC_JIT_TYPE_VOID
:
1981 case GCC_JIT_TYPE_VOID_PTR
:
1982 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
1984 case GCC_JIT_TYPE_BOOL
:
1985 case GCC_JIT_TYPE_CHAR
:
1986 case GCC_JIT_TYPE_SIGNED_CHAR
:
1987 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1988 case GCC_JIT_TYPE_SHORT
:
1989 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1990 case GCC_JIT_TYPE_INT
:
1991 case GCC_JIT_TYPE_UNSIGNED_INT
:
1992 case GCC_JIT_TYPE_LONG
:
1993 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1994 case GCC_JIT_TYPE_LONG_LONG
:
1995 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1996 case GCC_JIT_TYPE_FLOAT
:
1997 case GCC_JIT_TYPE_DOUBLE
:
1998 case GCC_JIT_TYPE_LONG_DOUBLE
:
1999 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2000 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2001 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2002 /* Not a pointer: */
2005 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2006 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
2008 case GCC_JIT_TYPE_SIZE_T
:
2009 /* Not a pointer: */
2012 case GCC_JIT_TYPE_FILE_PTR
:
2013 /* Give the client code back an opaque "struct FILE". */
2014 return m_ctxt
->get_opaque_FILE_type ();
2018 /* Implementation of pure virtual hook recording::type::is_int for
2019 recording::memento_of_get_type. */
2022 recording::memento_of_get_type::is_int () const
2026 default: gcc_unreachable ();
2028 case GCC_JIT_TYPE_VOID
:
2031 case GCC_JIT_TYPE_VOID_PTR
:
2034 case GCC_JIT_TYPE_BOOL
:
2037 case GCC_JIT_TYPE_CHAR
:
2038 case GCC_JIT_TYPE_SIGNED_CHAR
:
2039 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2040 case GCC_JIT_TYPE_SHORT
:
2041 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2042 case GCC_JIT_TYPE_INT
:
2043 case GCC_JIT_TYPE_UNSIGNED_INT
:
2044 case GCC_JIT_TYPE_LONG
:
2045 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2046 case GCC_JIT_TYPE_LONG_LONG
:
2047 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2050 case GCC_JIT_TYPE_FLOAT
:
2051 case GCC_JIT_TYPE_DOUBLE
:
2052 case GCC_JIT_TYPE_LONG_DOUBLE
:
2055 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2058 case GCC_JIT_TYPE_SIZE_T
:
2061 case GCC_JIT_TYPE_FILE_PTR
:
2064 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2065 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2066 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2071 /* Implementation of pure virtual hook recording::type::is_float for
2072 recording::memento_of_get_type. */
2075 recording::memento_of_get_type::is_float () const
2079 default: gcc_unreachable ();
2081 case GCC_JIT_TYPE_VOID
:
2084 case GCC_JIT_TYPE_VOID_PTR
:
2087 case GCC_JIT_TYPE_BOOL
:
2090 case GCC_JIT_TYPE_CHAR
:
2091 case GCC_JIT_TYPE_SIGNED_CHAR
:
2092 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2093 case GCC_JIT_TYPE_SHORT
:
2094 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2095 case GCC_JIT_TYPE_INT
:
2096 case GCC_JIT_TYPE_UNSIGNED_INT
:
2097 case GCC_JIT_TYPE_LONG
:
2098 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2099 case GCC_JIT_TYPE_LONG_LONG
:
2100 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2103 case GCC_JIT_TYPE_FLOAT
:
2104 case GCC_JIT_TYPE_DOUBLE
:
2105 case GCC_JIT_TYPE_LONG_DOUBLE
:
2108 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2111 case GCC_JIT_TYPE_SIZE_T
:
2114 case GCC_JIT_TYPE_FILE_PTR
:
2117 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2118 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2119 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2124 /* Implementation of pure virtual hook recording::type::is_bool for
2125 recording::memento_of_get_type. */
2128 recording::memento_of_get_type::is_bool () const
2132 default: gcc_unreachable ();
2134 case GCC_JIT_TYPE_VOID
:
2137 case GCC_JIT_TYPE_VOID_PTR
:
2140 case GCC_JIT_TYPE_BOOL
:
2143 case GCC_JIT_TYPE_CHAR
:
2144 case GCC_JIT_TYPE_SIGNED_CHAR
:
2145 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2146 case GCC_JIT_TYPE_SHORT
:
2147 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2148 case GCC_JIT_TYPE_INT
:
2149 case GCC_JIT_TYPE_UNSIGNED_INT
:
2150 case GCC_JIT_TYPE_LONG
:
2151 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2152 case GCC_JIT_TYPE_LONG_LONG
:
2153 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2156 case GCC_JIT_TYPE_FLOAT
:
2157 case GCC_JIT_TYPE_DOUBLE
:
2158 case GCC_JIT_TYPE_LONG_DOUBLE
:
2161 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2164 case GCC_JIT_TYPE_SIZE_T
:
2167 case GCC_JIT_TYPE_FILE_PTR
:
2170 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2171 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2172 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2177 /* Implementation of pure virtual hook recording::memento::replay_into
2178 for recording::memento_of_get_type. */
2181 recording::memento_of_get_type::replay_into (replayer
*r
)
2183 set_playback_obj (r
->get_type (m_kind
));
2186 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2188 /* Descriptive strings for each of enum gcc_jit_types. */
2190 static const char * const get_type_strings
[] = {
2191 "void", /* GCC_JIT_TYPE_VOID */
2192 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2194 "bool", /* GCC_JIT_TYPE_BOOL */
2196 "char", /* GCC_JIT_TYPE_CHAR */
2197 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2198 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2200 "short", /* GCC_JIT_TYPE_SHORT */
2201 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2203 "int", /* GCC_JIT_TYPE_INT */
2204 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2206 "long", /* GCC_JIT_TYPE_LONG */
2207 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2209 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2210 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2212 "float", /* GCC_JIT_TYPE_FLOAT */
2213 "double", /* GCC_JIT_TYPE_DOUBLE */
2214 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2216 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2218 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2220 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2222 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2223 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2224 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2228 /* Implementation of recording::memento::make_debug_string for
2229 results of get_type, using a simple table of type names. */
2232 recording::memento_of_get_type::make_debug_string ()
2234 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
2237 static const char * const get_type_enum_strings
[] = {
2238 "GCC_JIT_TYPE_VOID",
2239 "GCC_JIT_TYPE_VOID_PTR",
2240 "GCC_JIT_TYPE_BOOL",
2241 "GCC_JIT_TYPE_CHAR",
2242 "GCC_JIT_TYPE_SIGNED_CHAR",
2243 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2244 "GCC_JIT_TYPE_SHORT",
2245 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2247 "GCC_JIT_TYPE_UNSIGNED_INT",
2248 "GCC_JIT_TYPE_LONG",
2249 "GCC_JIT_TYPE_UNSIGNED_LONG",
2250 "GCC_JIT_TYPE_LONG_LONG",
2251 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2252 "GCC_JIT_TYPE_FLOAT",
2253 "GCC_JIT_TYPE_DOUBLE",
2254 "GCC_JIT_TYPE_LONG_DOUBLE",
2255 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2256 "GCC_JIT_TYPE_SIZE_T",
2257 "GCC_JIT_TYPE_FILE_PTR",
2258 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2259 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2260 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2264 recording::memento_of_get_type::write_reproducer (reproducer
&r
)
2266 const char *id
= r
.make_identifier (this, "type");
2267 r
.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2269 r
.get_identifier (get_context ()),
2270 get_type_enum_strings
[m_kind
]);
2273 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2275 /* Override of default implementation of
2276 recording::type::accepts_writes_from for get_pointer.
2278 Require a pointer type, and allowing writes to
2279 (const T *) from a (T*), but not the other way around. */
2282 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
2284 /* Must be a pointer type: */
2285 type
*rtype_points_to
= rtype
->is_pointer ();
2286 if (!rtype_points_to
)
2289 /* It's OK to assign to a (const T *) from a (T *). */
2290 return m_other_type
->unqualified ()
2291 ->accepts_writes_from (rtype_points_to
);
2294 /* Implementation of pure virtual hook recording::memento::replay_into
2295 for recording::memento_of_get_pointer. */
2298 recording::memento_of_get_pointer::replay_into (replayer
*)
2300 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
2303 /* Implementation of recording::memento::make_debug_string for
2304 results of get_pointer, adding " *" to the underlying type,
2305 with special-casing to handle function pointer types. */
2308 recording::memento_of_get_pointer::make_debug_string ()
2310 /* Special-case function pointer types, to put the "*" in parens between
2311 the return type and the params (for one level of dereferencing, at
2313 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2314 return fn_type
->make_debug_string_with_ptr ();
2316 return string::from_printf (m_ctxt
,
2317 "%s *", m_other_type
->get_debug_string ());
2320 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2323 recording::memento_of_get_pointer::write_reproducer (reproducer
&r
)
2325 /* We need to special-case function pointer types; see the notes in
2326 recording::function_type::write_deferred_reproducer. */
2327 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2329 fn_type
->write_deferred_reproducer (r
, this);
2333 const char *id
= r
.make_identifier (this, "type");
2334 r
.write (" gcc_jit_type *%s =\n"
2335 " gcc_jit_type_get_pointer (%s);\n",
2337 r
.get_identifier_as_type (m_other_type
));
2340 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2342 /* Implementation of pure virtual hook recording::memento::replay_into
2343 for recording::memento_of_get_const. */
2346 recording::memento_of_get_const::replay_into (replayer
*)
2348 set_playback_obj (m_other_type
->playback_type ()->get_const ());
2351 /* Implementation of recording::memento::make_debug_string for
2352 results of get_const, prepending "const ". */
2355 recording::memento_of_get_const::make_debug_string ()
2357 return string::from_printf (m_ctxt
,
2358 "const %s", m_other_type
->get_debug_string ());
2361 /* Implementation of recording::memento::write_reproducer for const types. */
2364 recording::memento_of_get_const::write_reproducer (reproducer
&r
)
2366 const char *id
= r
.make_identifier (this, "type");
2367 r
.write (" gcc_jit_type *%s =\n"
2368 " gcc_jit_type_get_const (%s);\n",
2370 r
.get_identifier_as_type (m_other_type
));
2373 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2375 /* Implementation of pure virtual hook recording::memento::replay_into
2376 for recording::memento_of_get_volatile. */
2379 recording::memento_of_get_volatile::replay_into (replayer
*)
2381 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
2384 /* Implementation of recording::memento::make_debug_string for
2385 results of get_volatile, prepending "volatile ". */
2388 recording::memento_of_get_volatile::make_debug_string ()
2390 return string::from_printf (m_ctxt
,
2391 "volatile %s", m_other_type
->get_debug_string ());
2394 /* Implementation of recording::memento::write_reproducer for volatile
2398 recording::memento_of_get_volatile::write_reproducer (reproducer
&r
)
2400 const char *id
= r
.make_identifier (this, "type");
2401 r
.write (" gcc_jit_type *%s =\n"
2402 " gcc_jit_type_get_volatile (%s);\n",
2404 r
.get_identifier_as_type (m_other_type
));
2407 /* The implementation of class gcc::jit::recording::array_type */
2409 /* Implementation of pure virtual hook recording::type::dereference for
2410 recording::array_type. */
2413 recording::array_type::dereference ()
2415 return m_element_type
;
2418 /* Implementation of pure virtual hook recording::memento::replay_into
2419 for recording::array_type. */
2422 recording::array_type::replay_into (replayer
*r
)
2424 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
2425 m_element_type
->playback_type (),
2429 /* Implementation of recording::memento::make_debug_string for
2430 results of new_array_type. */
2433 recording::array_type::make_debug_string ()
2435 return string::from_printf (m_ctxt
,
2437 m_element_type
->get_debug_string (),
2441 /* Implementation of recording::memento::write_reproducer for array
2445 recording::array_type::write_reproducer (reproducer
&r
)
2447 const char *id
= r
.make_identifier (this, "array_type");
2448 r
.write (" gcc_jit_type *%s =\n"
2449 " gcc_jit_context_new_array_type (%s,\n"
2450 " %s, /* gcc_jit_location *loc */\n"
2451 " %s, /* gcc_jit_type *element_type */\n"
2452 " %i); /* int num_elements */\n",
2454 r
.get_identifier (get_context ()),
2455 r
.get_identifier (m_loc
),
2456 r
.get_identifier_as_type (m_element_type
),
2460 /* The implementation of class gcc::jit::recording::function_type */
2462 /* Constructor for gcc::jit::recording::function_type. */
2464 recording::function_type::function_type (context
*ctxt
,
2470 m_return_type (return_type
),
2472 m_is_variadic (is_variadic
)
2474 for (int i
= 0; i
< num_params
; i
++)
2475 m_param_types
.safe_push (param_types
[i
]);
2478 /* Implementation of pure virtual hook recording::type::dereference for
2479 recording::function_type. */
2482 recording::function_type::dereference ()
2487 /* Implementation of pure virtual hook recording::memento::replay_into
2488 for recording::function_type. */
2491 recording::function_type::replay_into (replayer
*r
)
2493 /* Convert m_param_types to a vec of playback type. */
2494 auto_vec
<playback::type
*> param_types
;
2496 recording::type
*type
;
2497 param_types
.create (m_param_types
.length ());
2498 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
2499 param_types
.safe_push (type
->playback_type ());
2501 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
2506 /* Special-casing for make_debug_string for get_pointer results for
2507 handling (one level) of pointers to functions. */
2510 recording::function_type::make_debug_string_with_ptr ()
2512 return make_debug_string_with ("(*) ");
2515 /* Implementation of recording::memento::make_debug_string for
2516 results of new_function_type. */
2519 recording::function_type::make_debug_string ()
2521 return make_debug_string_with ("");
2524 /* Build a debug string representation of the form:
2526 RESULT_TYPE INSERT (PARAM_TYPES)
2528 for use when handling 0 and 1 level of indirection to this
2532 recording::function_type::make_debug_string_with (const char *insert
)
2534 /* First, build a buffer for the arguments. */
2535 /* Calculate length of said buffer. */
2536 size_t sz
= 1; /* nil terminator */
2537 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2539 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
2540 sz
+= 2; /* ", " separator */
2543 sz
+= 5; /* ", ..." separator and ellipsis */
2545 /* Now allocate and populate the buffer. */
2546 char *argbuf
= new char[sz
];
2549 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2551 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
2552 len
+= strlen (m_param_types
[i
]->get_debug_string ());
2553 if (i
+ 1 < m_param_types
.length ())
2555 strcpy (argbuf
+ len
, ", ");
2561 if (m_param_types
.length ())
2563 strcpy (argbuf
+ len
, ", ");
2566 strcpy (argbuf
+ len
, "...");
2571 /* ...and use it to get the string for the call as a whole. */
2572 string
*result
= string::from_printf (m_ctxt
,
2574 m_return_type
->get_debug_string (),
2583 /* Implementation of recording::memento::write_reproducer for function
2587 recording::function_type::write_reproducer (reproducer
&)
2589 /* see notes below. */
2592 /* There's a get_pointer within context::new_function_ptr_type:
2593 the type received by client code isn't the memento for the
2594 function_type, but instead the result of get_pointer on it.
2596 Hence we can't directly write a reproducer that gives function_type.
2597 Instead we special-case things within get_pointer, detecting this
2598 case, calling the following function. */
2601 recording::function_type::write_deferred_reproducer (reproducer
&r
,
2604 gcc_assert (ptr_type
);
2605 r
.make_identifier (this, "function_type");
2606 const char *ptr_id
= r
.make_identifier (ptr_type
, "ptr_to");
2607 const char *param_types_id
= r
.make_tmp_identifier ("params_for", this);
2608 r
.write (" gcc_jit_type *%s[%i] = {\n",
2610 m_param_types
.length ());
2613 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
2614 r
.write (" %s,\n", r
.get_identifier_as_type (param_type
));
2616 r
.write (" gcc_jit_type *%s =\n"
2617 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2618 " %s, /* gcc_jit_location *loc */\n"
2619 " %s, /* gcc_jit_type *return_type */\n"
2620 " %i, /* int num_params */\n"
2621 " %s, /* gcc_jit_type **param_types */\n"
2622 " %i); /* int is_variadic */\n",
2624 r
.get_identifier (get_context ()),
2625 "NULL", /* location is not stored */
2626 r
.get_identifier_as_type (m_return_type
),
2627 m_param_types
.length (),
2632 /* The implementation of class gcc::jit::recording::field. */
2634 /* Implementation of pure virtual hook recording::memento::replay_into
2635 for recording::field. */
2638 recording::field::replay_into (replayer
*r
)
2640 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
2641 m_type
->playback_type (),
2642 playback_string (m_name
)));
2645 /* Override the default implementation of
2646 recording::memento::write_to_dump. Dump each field
2647 by dumping a line of the form:
2649 so that we can build up a struct/union field-byfield. */
2652 recording::field::write_to_dump (dump
&d
)
2654 d
.write (" %s %s;\n",
2655 m_type
->get_debug_string (),
2659 /* Implementation of recording::memento::make_debug_string for
2660 results of new_field. */
2663 recording::field::make_debug_string ()
2668 /* Implementation of recording::memento::write_reproducer for fields. */
2671 recording::field::write_reproducer (reproducer
&r
)
2673 const char *id
= r
.make_identifier (this, "field");
2674 r
.write(" gcc_jit_field *%s =\n"
2675 " gcc_jit_context_new_field (%s,\n"
2676 " %s, /* gcc_jit_location *loc */\n"
2677 " %s, /* gcc_jit_type *type, */\n"
2678 " %s); /* const char *name */\n",
2680 r
.get_identifier (get_context ()),
2681 r
.get_identifier (m_loc
),
2682 r
.get_identifier_as_type (m_type
),
2683 m_name
->get_debug_string ());
2686 /* The implementation of class gcc::jit::recording::compound_type */
2688 /* The constructor for gcc::jit::recording::compound_type. */
2690 recording::compound_type::compound_type (context
*ctxt
,
2700 /* Set the fields of a compound type.
2702 Implements the post-error-checking part of
2703 gcc_jit_struct_set_fields, and is also used by
2704 gcc_jit_context_new_union_type. */
2707 recording::compound_type::set_fields (location
*loc
,
2709 field
**field_array
)
2712 gcc_assert (NULL
== m_fields
);
2714 m_fields
= new fields (this, num_fields
, field_array
);
2715 m_ctxt
->record (m_fields
);
2718 /* Implementation of pure virtual hook recording::type::dereference for
2719 recording::compound_type. */
2722 recording::compound_type::dereference ()
2724 return NULL
; /* not a pointer */
2727 /* The implementation of class gcc::jit::recording::struct_. */
2729 /* The constructor for gcc::jit::recording::struct_. */
2731 recording::struct_::struct_ (context
*ctxt
,
2734 : compound_type (ctxt
, loc
, name
)
2738 /* Implementation of pure virtual hook recording::memento::replay_into
2739 for recording::struct_. */
2742 recording::struct_::replay_into (replayer
*r
)
2745 r
->new_compound_type (playback_location (r
, get_loc ()),
2746 get_name ()->c_str (),
2747 true /* is_struct */));
2751 recording::struct_::access_as_type (reproducer
&r
)
2753 return r
.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2754 r
.get_identifier (this));
2757 /* Implementation of recording::memento::make_debug_string for
2761 recording::struct_::make_debug_string ()
2763 return string::from_printf (m_ctxt
,
2764 "struct %s", get_name ()->c_str ());
2768 recording::struct_::write_reproducer (reproducer
&r
)
2770 const char *id
= r
.make_identifier (this, "struct");
2771 r
.write (" gcc_jit_struct *%s =\n"
2772 " gcc_jit_context_new_opaque_struct (%s,\n"
2773 " %s, /* gcc_jit_location *loc */\n"
2774 " %s); /* const char *name */\n",
2776 r
.get_identifier (get_context ()),
2777 r
.get_identifier (get_loc ()),
2778 get_name ()->get_debug_string ());
2781 /* The implementation of class gcc::jit::recording::union_. */
2783 /* The constructor for gcc::jit::recording::union_. */
2785 recording::union_::union_ (context
*ctxt
,
2788 : compound_type (ctxt
, loc
, name
)
2792 /* Implementation of pure virtual hook recording::memento::replay_into
2793 for recording::union_. */
2796 recording::union_::replay_into (replayer
*r
)
2799 r
->new_compound_type (playback_location (r
, get_loc ()),
2800 get_name ()->c_str (),
2801 false /* is_struct */));
2804 /* Implementation of recording::memento::make_debug_string for
2808 recording::union_::make_debug_string ()
2810 return string::from_printf (m_ctxt
,
2811 "union %s", get_name ()->c_str ());
2814 /* Implementation of recording::memento::write_reproducer for unions. */
2817 recording::union_::write_reproducer (reproducer
&r
)
2819 const char *id
= r
.make_identifier (this, "union");
2821 const char *fields_id
= r
.make_tmp_identifier ("fields_for", this);
2822 r
.write (" gcc_jit_field *%s[%i] = {\n",
2824 get_fields ()->length ());
2825 for (int i
= 0; i
< get_fields ()->length (); i
++)
2826 r
.write (" %s,\n", r
.get_identifier (get_fields ()->get_field (i
)));
2829 r
.write (" gcc_jit_type *%s =\n"
2830 " gcc_jit_context_new_union_type (%s,\n"
2831 " %s, /* gcc_jit_location *loc */\n"
2832 " %s, /* const char *name */\n"
2833 " %i, /* int num_fields */\n"
2834 " %s); /* gcc_jit_field **fields */\n",
2836 r
.get_identifier (get_context ()),
2837 r
.get_identifier (get_loc ()),
2838 get_name ()->get_debug_string (),
2839 get_fields ()->length (),
2843 /* The implementation of class gcc::jit::recording::fields. */
2845 /* The constructor for gcc::jit::recording::fields. */
2847 recording::fields::fields (compound_type
*struct_or_union
,
2850 : memento (struct_or_union
->m_ctxt
),
2851 m_struct_or_union (struct_or_union
),
2854 for (int i
= 0; i
< num_fields
; i
++)
2856 gcc_assert (fields
[i
]->get_container () == NULL
);
2857 fields
[i
]->set_container (m_struct_or_union
);
2858 m_fields
.safe_push (fields
[i
]);
2862 /* Implementation of pure virtual hook recording::memento::replay_into
2863 for recording::fields. */
2866 recording::fields::replay_into (replayer
*)
2868 auto_vec
<playback::field
*> playback_fields
;
2869 playback_fields
.create (m_fields
.length ());
2870 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
2871 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
2872 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
2875 /* Override the default implementation of
2876 recording::memento::write_to_dump by writing a union/struct
2877 declaration of this form:
2889 recording::fields::write_to_dump (dump
&d
)
2894 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
2895 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
2896 f
->write_to_dump (d
);
2900 /* Implementation of recording::memento::write_reproducer for the fields
2904 recording::fields::write_reproducer (reproducer
&r
)
2906 if (m_struct_or_union
)
2907 if (NULL
== m_struct_or_union
->dyn_cast_struct ())
2908 /* We have a union; the fields have already been written by
2909 union::write_reproducer. */
2912 const char *fields_id
= r
.make_identifier (this, "fields");
2913 r
.write (" gcc_jit_field *%s[%i] = {\n",
2915 m_fields
.length ());
2918 FOR_EACH_VEC_ELT (m_fields
, i
, field
)
2919 r
.write (" %s,\n", r
.get_identifier (field
));
2922 r
.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
2923 " %s, /* gcc_jit_location *loc */\n"
2924 " %i, /* int num_fields */\n"
2925 " %s); /* gcc_jit_field **fields */\n",
2926 r
.get_identifier (m_struct_or_union
),
2927 r
.get_identifier ((memento
*)NULL
),
2932 /* Implementation of recording::memento::make_debug_string for
2936 recording::fields::make_debug_string ()
2938 return string::from_printf (m_ctxt
,
2942 /* The implementation of class gcc::jit::recording::rvalue. */
2944 /* Create a recording::access_field_rvalue instance and add it to
2945 the rvalue's context's list of mementos.
2947 Implements the post-error-checking part of
2948 gcc_jit_rvalue_access_field. */
2951 recording::rvalue::access_field (recording::location
*loc
,
2954 recording::rvalue
*result
=
2955 new access_field_rvalue (m_ctxt
, loc
, this, field
);
2956 m_ctxt
->record (result
);
2960 /* Create a recording::dereference_field_rvalue instance and add it to
2961 the rvalue's context's list of mementos.
2963 Implements the post-error-checking part of
2964 gcc_jit_rvalue_dereference_field. */
2967 recording::rvalue::dereference_field (recording::location
*loc
,
2970 recording::lvalue
*result
=
2971 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
2972 m_ctxt
->record (result
);
2976 /* Create a recording::dereference_rvalue instance and add it to the
2977 rvalue's context's list of mementos.
2979 Implements the post-error-checking part of
2980 gcc_jit_rvalue_dereference. */
2983 recording::rvalue::dereference (recording::location
*loc
)
2985 recording::lvalue
*result
=
2986 new dereference_rvalue (m_ctxt
, loc
, this);
2987 m_ctxt
->record (result
);
2991 /* An rvalue visitor, for validating that every rvalue within an expression
2992 trees within "STMT" has the correct scope (e.g. no access to locals
2993 of a different function). */
2995 class rvalue_usage_validator
: public recording::rvalue_visitor
2998 rvalue_usage_validator (const char *api_funcname
,
2999 recording::context
*ctxt
,
3000 recording::statement
*stmt
);
3003 visit (recording::rvalue
*rvalue
);
3006 const char *m_api_funcname
;
3007 recording::context
*m_ctxt
;
3008 recording::statement
*m_stmt
;
3011 /* The trivial constructor for rvalue_usage_validator. */
3013 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname
,
3014 recording::context
*ctxt
,
3015 recording::statement
*stmt
)
3016 : m_api_funcname (api_funcname
),
3022 /* Verify that the given rvalue is in the correct scope. */
3025 rvalue_usage_validator::visit (recording::rvalue
*rvalue
)
3027 gcc_assert (m_stmt
->get_block ());
3028 recording::function
*stmt_scope
= m_stmt
->get_block ()->get_function ();
3030 /* Most rvalues don't have a scope (only locals and params). */
3031 if (rvalue
->get_scope ())
3033 if (rvalue
->get_scope () != stmt_scope
)
3035 (rvalue
->get_loc (),
3037 " rvalue %s (type: %s)"
3038 " has scope limited to function %s"
3039 " but was used within function %s"
3040 " (in statement: %s)",
3042 rvalue
->get_debug_string (),
3043 rvalue
->get_type ()->get_debug_string (),
3044 rvalue
->get_scope ()->get_debug_string (),
3045 stmt_scope
->get_debug_string (),
3046 m_stmt
->get_debug_string ());
3050 if (rvalue
->dyn_cast_param ())
3052 (rvalue
->get_loc (),
3054 " param %s (type: %s)"
3055 " was used within function %s"
3056 " (in statement: %s)"
3057 " but is not associated with any function",
3059 rvalue
->get_debug_string (),
3060 rvalue
->get_type ()->get_debug_string (),
3061 stmt_scope
->get_debug_string (),
3062 m_stmt
->get_debug_string ());
3066 /* Verify that it's valid to use this rvalue (and all expressions
3067 in the tree below it) within the given statement.
3069 For example, we must reject attempts to use a local from one
3070 function within a different function here, or we'll get
3071 an ICE deep inside toplev::main. */
3074 recording::rvalue::verify_valid_within_stmt (const char *api_funcname
, statement
*s
)
3076 rvalue_usage_validator
v (api_funcname
,
3080 /* Verify that it's OK to use this rvalue within s. */
3083 /* Traverse the expression tree below "this", verifying all rvalues
3085 visit_children (&v
);
3088 /* Set the scope of this rvalue to be the given function. This can only
3089 be done once on a given rvalue. */
3092 recording::rvalue::set_scope (function
*scope
)
3095 gcc_assert (NULL
== m_scope
);
3100 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3102 Instances of rvalue don't need an upcast call. */
3105 recording::rvalue::access_as_rvalue (reproducer
&r
)
3107 return r
.get_identifier (this);
3110 /* Return a debug string for the given rvalue, wrapping it in parentheses
3111 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3112 stronger precedence that this rvalue's precedence.
3126 since MULT has strong precedence than PLUS and MINUS, whereas for:
3138 since PLUS has weaker precedence than MULT and DIVIDE. */
3141 recording::rvalue::get_debug_string_parens (enum precedence outer_prec
)
3143 enum precedence this_prec
= get_precedence ();
3145 /* If this_prec has stronger precedence than outer_prec, we don't
3146 need to wrap this in parens within the outer debug string.
3147 Stronger precedences occur earlier than weaker within the enum,
3148 so this is a less than test. Equal precedences don't need
3150 if (this_prec
<= outer_prec
)
3151 return get_debug_string();
3153 /* Otherwise, we need parentheses. */
3155 /* Lazily-build and cache m_parenthesized_string. */
3156 if (!m_parenthesized_string
)
3158 const char *debug_string
= get_debug_string ();
3159 m_parenthesized_string
= string::from_printf (get_context (),
3163 gcc_assert (m_parenthesized_string
);
3164 return m_parenthesized_string
->c_str ();
3168 /* The implementation of class gcc::jit::recording::lvalue. */
3170 /* Create a recording::new_access_field_of_lvalue instance and add it to
3171 the lvalue's context's list of mementos.
3173 Implements the post-error-checking part of
3174 gcc_jit_lvalue_access_field. */
3177 recording::lvalue::access_field (recording::location
*loc
,
3180 recording::lvalue
*result
=
3181 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
3182 m_ctxt
->record (result
);
3186 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3187 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3191 recording::lvalue::access_as_rvalue (reproducer
&r
)
3193 return r
.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3194 r
.get_identifier (this));
3197 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3198 Instances of lvalue don't need to be upcast. */
3201 recording::lvalue::access_as_lvalue (reproducer
&r
)
3203 return r
.get_identifier (this);
3206 /* Create a recording::get_address_of_lvalue instance and add it to
3207 the lvalue's context's list of mementos.
3209 Implements the post-error-checking part of
3210 gcc_jit_lvalue_get_address. */
3213 recording::lvalue::get_address (recording::location
*loc
)
3215 recording::rvalue
*result
=
3216 new get_address_of_lvalue (m_ctxt
, loc
, this);
3217 m_ctxt
->record (result
);
3221 /* The implementation of class gcc::jit::recording::param. */
3223 /* Implementation of pure virtual hook recording::memento::replay_into
3224 for recording::param. */
3227 recording::param::replay_into (replayer
*r
)
3229 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
3230 m_type
->playback_type (),
3234 /* Implementation of recording::rvalue::access_as_rvalue for params.
3235 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3239 recording::param::access_as_rvalue (reproducer
&r
)
3241 return r
.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3242 r
.get_identifier (this));
3245 /* Implementation of recording::lvalue::access_as_lvalue for params.
3246 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3250 recording::param::access_as_lvalue (reproducer
&r
)
3252 return r
.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3253 r
.get_identifier (this));
3256 /* Implementation of recording::memento::write_reproducer for params. */
3259 recording::param::write_reproducer (reproducer
&r
)
3261 const char *id
= r
.make_identifier (this, "param");
3262 r
.write (" gcc_jit_param *%s =\n"
3263 " gcc_jit_context_new_param (%s,\n"
3264 " %s, /* gcc_jit_location *loc */\n"
3265 " %s, /*gcc_jit_type *type */\n"
3266 " %s); /* const char *name */\n",
3268 r
.get_identifier (get_context ()),
3269 r
.get_identifier (m_loc
),
3270 r
.get_identifier_as_type (m_type
),
3271 m_name
->get_debug_string ());
3274 /* The implementation of class gcc::jit::recording::function. */
3276 /* gcc::jit::recording::function's constructor. */
3278 recording::function::function (context
*ctxt
,
3279 recording::location
*loc
,
3280 enum gcc_jit_function_kind kind
,
3282 recording::string
*name
,
3284 recording::param
**params
,
3286 enum built_in_function builtin_id
)
3290 m_return_type (return_type
),
3293 m_is_variadic (is_variadic
),
3294 m_builtin_id (builtin_id
),
3298 for (int i
= 0; i
< num_params
; i
++)
3300 param
*param
= params
[i
];
3303 /* Associate each param with this function.
3305 Verify that the param doesn't already have a function. */
3306 if (param
->get_scope ())
3308 /* We've already rejected attempts to reuse a param between
3309 different functions (within gcc_jit_context_new_function), so
3310 if the param *does* already have a function, it must be being
3311 reused within the params array for this function. We must
3312 produce an error for this reuse (blocking the compile), since
3313 otherwise we'd have an ICE later on. */
3314 gcc_assert (this == param
->get_scope ());
3317 "gcc_jit_context_new_function:"
3318 " parameter %s (type: %s)"
3319 " is used more than once when creating function %s",
3320 param
->get_debug_string (),
3321 param
->get_type ()->get_debug_string (),
3326 /* The normal, non-error case: associate this function with the
3328 param
->set_scope (this);
3331 m_params
.safe_push (param
);
3335 /* Implementation of pure virtual hook recording::memento::replay_into
3336 for recording::function. */
3339 recording::function::replay_into (replayer
*r
)
3341 /* Convert m_params to a vec of playback param. */
3342 auto_vec
<playback::param
*> params
;
3344 recording::param
*param
;
3345 params
.create (m_params
.length ());
3346 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3347 params
.safe_push (param
->playback_param ());
3349 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
3351 m_return_type
->playback_type (),
3358 /* Create a recording::local instance and add it to
3359 the functions's context's list of mementos, and to the function's
3362 Implements the post-error-checking part of
3363 gcc_jit_function_new_local. */
3366 recording::function::new_local (recording::location
*loc
,
3370 local
*result
= new local (this, loc
, type
, new_string (name
));
3371 m_ctxt
->record (result
);
3372 m_locals
.safe_push (result
);
3376 /* Create a recording::block instance and add it to
3377 the functions's context's list of mementos, and to the function's
3380 Implements the post-error-checking part of
3381 gcc_jit_function_new_block. */
3384 recording::function::new_block (const char *name
)
3386 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
3388 recording::block
*result
=
3389 new recording::block (this, m_blocks
.length (), new_string (name
));
3390 m_ctxt
->record (result
);
3391 m_blocks
.safe_push (result
);
3395 /* Override the default implementation of
3396 recording::memento::write_to_dump by dumping a C-like
3397 representation of the function; either like a prototype
3398 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3399 all other kinds of function. */
3402 recording::function::write_to_dump (dump
&d
)
3406 default: gcc_unreachable ();
3407 case GCC_JIT_FUNCTION_EXPORTED
:
3408 case GCC_JIT_FUNCTION_IMPORTED
:
3409 d
.write ("extern ");
3411 case GCC_JIT_FUNCTION_INTERNAL
:
3412 d
.write ("static ");
3414 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
3415 d
.write ("static inline ");
3418 d
.write ("%s\n", m_return_type
->get_debug_string ());
3420 if (d
.update_locations ())
3421 m_loc
= d
.make_location ();
3423 d
.write ("%s (", get_debug_string ());
3426 recording::param
*param
;
3427 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3432 param
->get_type ()->get_debug_string (),
3433 param
->get_debug_string ());
3436 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
3438 d
.write ("; /* (imported) */\n\n");
3448 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
3449 var
->write_to_dump (d
);
3450 if (m_locals
.length ())
3453 /* Write each block: */
3454 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3458 b
->write_to_dump (d
);
3465 /* Pre-compilation validation of a function, for those things we can't
3466 check until the context is (supposedly) fully-populated. */
3469 recording::function::validate ()
3471 /* Complain about empty functions with non-void return type. */
3472 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
3473 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
3474 if (0 == m_blocks
.length ())
3475 m_ctxt
->add_error (m_loc
,
3476 "function %s returns non-void (type: %s)"
3477 " but has no blocks",
3478 get_debug_string (),
3479 m_return_type
->get_debug_string ());
3481 /* Check that all blocks are terminated. */
3482 int num_invalid_blocks
= 0;
3487 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3488 if (!b
->validate ())
3489 num_invalid_blocks
++;
3492 /* Check that all blocks are reachable. */
3493 if (!m_ctxt
->get_inner_bool_option
3494 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS
)
3495 && m_blocks
.length () > 0 && 0 == num_invalid_blocks
)
3497 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3498 flag, starting at the initial block. */
3499 auto_vec
<block
*> worklist (m_blocks
.length ());
3500 worklist
.safe_push (m_blocks
[0]);
3501 while (worklist
.length () > 0)
3503 block
*b
= worklist
.pop ();
3504 b
->m_is_reachable
= true;
3506 /* Add successor blocks that aren't yet marked to the worklist. */
3507 /* We checked that each block has a terminating statement above . */
3508 block
*next1
, *next2
;
3509 int n
= b
->get_successor_blocks (&next1
, &next2
);
3515 if (!next2
->m_is_reachable
)
3516 worklist
.safe_push (next2
);
3519 if (!next1
->m_is_reachable
)
3520 worklist
.safe_push (next1
);
3527 /* Now complain about any blocks that haven't been marked. */
3531 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3532 if (!b
->m_is_reachable
)
3533 m_ctxt
->add_error (b
->get_loc (),
3534 "unreachable block: %s",
3535 b
->get_debug_string ());
3540 /* Implements the post-error-checking part of
3541 gcc_jit_function_dump_to_dot. */
3544 recording::function::dump_to_dot (const char *path
)
3546 FILE *fp
= fopen (path
, "w");
3550 pretty_printer the_pp
;
3551 the_pp
.buffer
->stream
= fp
;
3553 pretty_printer
*pp
= &the_pp
;
3556 "digraph %s {\n", get_debug_string ());
3562 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3563 b
->dump_to_dot (pp
);
3570 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3571 b
->dump_edges_to_dot (pp
);
3574 pp_printf (pp
, "}\n");
3579 /* Implementation of recording::memento::make_debug_string for
3583 recording::function::make_debug_string ()
3588 /* A table of enum gcc_jit_function_kind values expressed in string
3591 static const char * const names_of_function_kinds
[] = {
3592 "GCC_JIT_FUNCTION_EXPORTED",
3593 "GCC_JIT_FUNCTION_INTERNAL",
3594 "GCC_JIT_FUNCTION_IMPORTED",
3595 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3598 /* Implementation of recording::memento::write_reproducer for functions. */
3601 recording::function::write_reproducer (reproducer
&r
)
3603 const char *id
= r
.make_identifier (this, "func");
3607 r
.write (" gcc_jit_function *%s =\n"
3608 " gcc_jit_context_get_builtin_function (%s,\n"
3611 r
.get_identifier (get_context ()),
3612 m_name
->get_debug_string ());
3615 const char *params_id
= r
.make_tmp_identifier ("params_for", this);
3616 r
.write (" gcc_jit_param *%s[%i] = {\n",
3618 m_params
.length ());
3621 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3622 r
.write (" %s,\n", r
.get_identifier (param
));
3624 r
.write (" gcc_jit_function *%s =\n"
3625 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3626 " %s, /* gcc_jit_location *loc */\n"
3627 " %s, /* enum gcc_jit_function_kind kind */\n"
3628 " %s, /* gcc_jit_type *return_type */\n"
3629 " %s, /* const char *name */\n"
3630 " %i, /* int num_params */\n"
3631 " %s, /* gcc_jit_param **params */\n"
3632 " %i); /* int is_variadic */\n",
3634 r
.get_identifier (get_context ()),
3635 r
.get_identifier (m_loc
),
3636 names_of_function_kinds
[m_kind
],
3637 r
.get_identifier_as_type (m_return_type
),
3638 m_name
->get_debug_string (),
3645 /* The implementation of class gcc::jit::recording::block. */
3647 /* Create a recording::eval instance and add it to
3648 the block's context's list of mementos, and to the block's
3651 Implements the heart of gcc_jit_block_add_eval. */
3653 recording::statement
*
3654 recording::block::add_eval (recording::location
*loc
,
3655 recording::rvalue
*rvalue
)
3657 statement
*result
= new eval (this, loc
, rvalue
);
3658 m_ctxt
->record (result
);
3659 m_statements
.safe_push (result
);
3663 /* Create a recording::assignment instance and add it to
3664 the block's context's list of mementos, and to the block's
3667 Implements the heart of gcc_jit_block_add_assignment. */
3669 recording::statement
*
3670 recording::block::add_assignment (recording::location
*loc
,
3671 recording::lvalue
*lvalue
,
3672 recording::rvalue
*rvalue
)
3674 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
3675 m_ctxt
->record (result
);
3676 m_statements
.safe_push (result
);
3680 /* Create a recording::assignment_op instance and add it to
3681 the block's context's list of mementos, and to the block's
3684 Implements the heart of gcc_jit_block_add_assignment_op. */
3686 recording::statement
*
3687 recording::block::add_assignment_op (recording::location
*loc
,
3688 recording::lvalue
*lvalue
,
3689 enum gcc_jit_binary_op op
,
3690 recording::rvalue
*rvalue
)
3692 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
3693 m_ctxt
->record (result
);
3694 m_statements
.safe_push (result
);
3698 /* Create a recording::comment instance and add it to
3699 the block's context's list of mementos, and to the block's
3702 Implements the heart of gcc_jit_block_add_comment. */
3704 recording::statement
*
3705 recording::block::add_comment (recording::location
*loc
,
3708 statement
*result
= new comment (this, loc
, new_string (text
));
3709 m_ctxt
->record (result
);
3710 m_statements
.safe_push (result
);
3714 /* Create a recording::end_with_conditional instance and add it to
3715 the block's context's list of mementos, and to the block's
3718 Implements the heart of gcc_jit_block_end_with_conditional. */
3720 recording::statement
*
3721 recording::block::end_with_conditional (recording::location
*loc
,
3722 recording::rvalue
*boolval
,
3723 recording::block
*on_true
,
3724 recording::block
*on_false
)
3726 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
3727 m_ctxt
->record (result
);
3728 m_statements
.safe_push (result
);
3729 m_has_been_terminated
= true;
3733 /* Create a recording::end_with_jump instance and add it to
3734 the block's context's list of mementos, and to the block's
3737 Implements the heart of gcc_jit_block_end_with_jump. */
3739 recording::statement
*
3740 recording::block::end_with_jump (recording::location
*loc
,
3741 recording::block
*target
)
3743 statement
*result
= new jump (this, loc
, target
);
3744 m_ctxt
->record (result
);
3745 m_statements
.safe_push (result
);
3746 m_has_been_terminated
= true;
3750 /* Create a recording::end_with_return instance and add it to
3751 the block's context's list of mementos, and to the block's
3754 Implements the post-error-checking parts of
3755 gcc_jit_block_end_with_return and
3756 gcc_jit_block_end_with_void_return. */
3758 recording::statement
*
3759 recording::block::end_with_return (recording::location
*loc
,
3760 recording::rvalue
*rvalue
)
3762 /* This is used by both gcc_jit_function_add_return and
3763 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3764 the former and NULL for the latter. */
3765 statement
*result
= new return_ (this, loc
, rvalue
);
3766 m_ctxt
->record (result
);
3767 m_statements
.safe_push (result
);
3768 m_has_been_terminated
= true;
3772 /* Override the default implementation of
3773 recording::memento::write_to_dump for blocks by writing
3774 an unindented block name as a label, followed by the indented
3784 recording::block::write_to_dump (dump
&d
)
3786 d
.write ("%s:\n", get_debug_string ());
3790 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
3791 s
->write_to_dump (d
);
3794 /* Validate a block by ensuring that it has been terminated. */
3797 recording::block::validate ()
3799 /* Check for termination. */
3800 if (!has_been_terminated ())
3802 statement
*stmt
= get_last_statement ();
3803 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
3804 m_func
->get_context ()->add_error (loc
,
3805 "unterminated block in %s: %s",
3806 m_func
->get_debug_string (),
3807 get_debug_string ());
3814 /* Get the source-location of a block by using that of the first
3815 statement within it, if any. */
3817 recording::location
*
3818 recording::block::get_loc () const
3820 recording::statement
*stmt
= get_first_statement ();
3822 return stmt
->get_loc ();
3827 /* Get the first statement within a block, if any. */
3829 recording::statement
*
3830 recording::block::get_first_statement () const
3832 if (m_statements
.length ())
3833 return m_statements
[0];
3838 /* Get the last statement within a block, if any. */
3840 recording::statement
*
3841 recording::block::get_last_statement () const
3843 if (m_statements
.length ())
3844 return m_statements
[m_statements
.length () - 1];
3849 /* Assuming that this block has been terminated, get the number of
3850 successor blocks, which will be 0, 1 or 2, for return, unconditional
3851 jump, and conditional jump respectively.
3852 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
3853 is written to NEXT1, and the second (if any) to NEXT2.
3855 Used when validating functions, and when dumping dot representations
3859 recording::block::get_successor_blocks (block
**next1
, block
**next2
) const
3861 gcc_assert (m_has_been_terminated
);
3864 statement
*last_statement
= get_last_statement ();
3865 gcc_assert (last_statement
);
3866 return last_statement
->get_successor_blocks (next1
, next2
);
3869 /* Implementation of pure virtual hook recording::memento::replay_into
3870 for recording::block. */
3873 recording::block::replay_into (replayer
*)
3875 set_playback_obj (m_func
->playback_function ()
3876 ->new_block (playback_string (m_name
)));
3879 /* Implementation of recording::memento::make_debug_string for
3883 recording::block::make_debug_string ()
3888 return string::from_printf (m_ctxt
,
3889 "<UNNAMED BLOCK %p>",
3893 /* Implementation of recording::memento::write_reproducer for blocks. */
3896 recording::block::write_reproducer (reproducer
&r
)
3898 const char *id
= r
.make_identifier (this, "block");
3899 r
.write (" gcc_jit_block *%s =\n"
3900 " gcc_jit_function_new_block (%s, %s);\n",
3902 r
.get_identifier (m_func
),
3903 m_name
? m_name
->get_debug_string () : "NULL");
3906 /* Dump a block in graphviz form into PP, capturing the block name (if
3907 any) and the statements. */
3910 recording::block::dump_to_dot (pretty_printer
*pp
)
3914 "[shape=record,style=filled,fillcolor=white,label=\"{"),
3916 pp_write_text_to_stream (pp
);
3919 pp_string (pp
, m_name
->c_str ());
3920 pp_string (pp
, ":");
3922 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
3927 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
3929 pp_string (pp
, s
->get_debug_string ());
3931 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
3939 /* Dump the out-edges of the block in graphviz form into PP. */
3942 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
3945 int num_succs
= get_successor_blocks (&next
[0], &next
[1]);
3946 for (int i
= 0; i
< num_succs
; i
++)
3948 "\tblock_%d:s -> block_%d:n;\n",
3949 m_index
, next
[i
]->m_index
);
3952 /* The implementation of class gcc::jit::recording::global. */
3954 /* Implementation of pure virtual hook recording::memento::replay_into
3955 for recording::global. */
3958 recording::global::replay_into (replayer
*r
)
3960 set_playback_obj (r
->new_global (playback_location (r
, m_loc
),
3962 m_type
->playback_type (),
3963 playback_string (m_name
)));
3966 /* Override the default implementation of
3967 recording::memento::write_to_dump for globals.
3968 This will be of the form:
3970 GCC_JIT_GLOBAL_EXPORTED:
3974 GCC_JIT_GLOBAL_INTERNAL:
3976 e.g. "static int foo;"
3978 GCC_JIT_GLOBAL_IMPORTED:
3980 e.g. "extern int foo;"
3982 These are written to the top of the dump by
3983 recording::context::dump_to_file. */
3986 recording::global::write_to_dump (dump
&d
)
3988 if (d
.update_locations ())
3989 m_loc
= d
.make_location ();
3996 case GCC_JIT_GLOBAL_EXPORTED
:
3999 case GCC_JIT_GLOBAL_INTERNAL
:
4000 d
.write ("static ");
4003 case GCC_JIT_GLOBAL_IMPORTED
:
4004 d
.write ("extern ");
4007 d
.write ("%s %s;\n",
4008 m_type
->get_debug_string (),
4009 get_debug_string ());
4012 /* A table of enum gcc_jit_global_kind values expressed in string
4015 static const char * const global_kind_reproducer_strings
[] = {
4016 "GCC_JIT_GLOBAL_EXPORTED",
4017 "GCC_JIT_GLOBAL_INTERNAL",
4018 "GCC_JIT_GLOBAL_IMPORTED"
4021 /* Implementation of recording::memento::write_reproducer for globals. */
4024 recording::global::write_reproducer (reproducer
&r
)
4026 const char *id
= r
.make_identifier (this, "block");
4027 r
.write (" gcc_jit_lvalue *%s =\n"
4028 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4029 " %s, /* gcc_jit_location *loc */\n"
4030 " %s, /* enum gcc_jit_global_kind kind */\n"
4031 " %s, /* gcc_jit_type *type */\n"
4032 " %s); /* const char *name */\n",
4034 r
.get_identifier (get_context ()),
4035 r
.get_identifier (m_loc
),
4036 global_kind_reproducer_strings
[m_kind
],
4037 r
.get_identifier_as_type (get_type ()),
4038 m_name
->get_debug_string ());
4041 /* The implementation of the various const-handling classes:
4042 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4044 /* Explicit specialization of the various mementos we're interested in. */
4045 template class recording::memento_of_new_rvalue_from_const
<int>;
4046 template class recording::memento_of_new_rvalue_from_const
<long>;
4047 template class recording::memento_of_new_rvalue_from_const
<double>;
4048 template class recording::memento_of_new_rvalue_from_const
<void *>;
4050 /* Implementation of the pure virtual hook recording::memento::replay_into
4051 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4053 template <typename HOST_TYPE
>
4056 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
4059 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
4063 /* The make_debug_string and write_reproducer methods vary between the
4065 memento_of_new_rvalue_from_const <HOST_TYPE>
4066 classes, so we explicitly write specializations of them.
4068 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4069 namespaces are written out explicitly, which is why most of this file
4070 doesn't abbreviate things by entering the "recording" namespace.
4072 However, these specializations are required to be in the same namespace
4073 as the template, hence we now have to enter the gcc::jit::recording
4079 /* The make_debug_string specialization for <int>, which renders it as
4080 (TARGET_TYPE)LITERAL
4086 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
4088 return string::from_printf (m_ctxt
,
4090 m_type
->get_debug_string (),
4094 /* The write_reproducer specialization for <int>. */
4098 memento_of_new_rvalue_from_const
<int>::write_reproducer (reproducer
&r
)
4100 const char *id
= r
.make_identifier (this, "rvalue");
4101 r
.write (" gcc_jit_rvalue *%s =\n"
4102 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4103 " %s, /* gcc_jit_type *numeric_type */\n"
4104 " %i); /* int value */\n",
4106 r
.get_identifier (get_context ()),
4107 r
.get_identifier_as_type (m_type
),
4111 /* The make_debug_string specialization for <long>, rendering it as
4112 (TARGET_TYPE)LITERAL
4118 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
4120 return string::from_printf (m_ctxt
,
4122 m_type
->get_debug_string (),
4126 /* The write_reproducer specialization for <long>. */
4130 recording::memento_of_new_rvalue_from_const
<long>::write_reproducer (reproducer
&r
)
4132 const char *id
= r
.make_identifier (this, "rvalue");
4134 /* We have to special-case LONG_MIN, since e.g.
4135 -9223372036854775808L
4137 -(9223372036854775808L)
4139 error: integer constant is so large that it is unsigned [-Werror]
4140 Workaround this by writing (LONG_MIN + 1) - 1. */
4141 if (m_value
== LONG_MIN
)
4143 r
.write (" gcc_jit_rvalue *%s =\n"
4144 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4145 " %s, /* gcc_jit_type *numeric_type */\n"
4146 " %ldL - 1); /* long value */\n",
4148 r
.get_identifier (get_context ()),
4149 r
.get_identifier_as_type (m_type
),
4154 r
.write (" gcc_jit_rvalue *%s =\n"
4155 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4156 " %s, /* gcc_jit_type *numeric_type */\n"
4157 " %ldL); /* long value */\n",
4159 r
.get_identifier (get_context ()),
4160 r
.get_identifier_as_type (m_type
),
4164 /* The make_debug_string specialization for <double>, rendering it as
4165 (TARGET_TYPE)LITERAL
4171 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
4173 return string::from_printf (m_ctxt
,
4175 m_type
->get_debug_string (),
4179 /* The write_reproducer specialization for <double>. */
4183 recording::memento_of_new_rvalue_from_const
<double>::write_reproducer (reproducer
&r
)
4185 const char *id
= r
.make_identifier (this, "rvalue");
4186 r
.write (" gcc_jit_rvalue *%s =\n"
4187 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4188 " %s, /* gcc_jit_type *numeric_type */\n"
4189 " %f); /* double value */\n",
4191 r
.get_identifier (get_context ()),
4192 r
.get_identifier_as_type (m_type
),
4196 /* The make_debug_string specialization for <void *>, rendering it as
4201 Zero is rendered as NULL e.g.
4206 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
4208 if (m_value
!= NULL
)
4209 return string::from_printf (m_ctxt
,
4211 m_type
->get_debug_string (), m_value
);
4213 return string::from_printf (m_ctxt
,
4215 m_type
->get_debug_string ());
4218 /* Implementation of recording::memento::write_reproducer for <void *>
4223 memento_of_new_rvalue_from_const
<void *>::write_reproducer (reproducer
&r
)
4225 const char *id
= r
.make_identifier (this, "rvalue");
4227 r
.write (" gcc_jit_rvalue *%s =\n"
4228 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4229 " %s, /* gcc_jit_type *pointer_type */\n"
4230 " (void *)%p); /* void *value */\n",
4232 r
.get_identifier (get_context ()),
4233 r
.get_identifier_as_type (m_type
),
4236 r
.write (" gcc_jit_rvalue *%s =\n"
4237 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4238 " %s); /* gcc_jit_type *pointer_type */\n",
4240 r
.get_identifier (get_context ()),
4241 r
.get_identifier_as_type (m_type
));
4244 /* We're done specializing make_debug_string and write_reproducer, so we
4245 can exit the gcc::jit::recording namespace. */
4247 } // namespace recording
4249 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4251 /* Implementation of pure virtual hook recording::memento::replay_into
4252 for recording::memento_of_new_string_literal. */
4255 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
4257 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
4260 /* Implementation of recording::memento::make_debug_string for
4264 recording::memento_of_new_string_literal::make_debug_string ()
4266 return string::from_printf (m_ctxt
,
4268 m_value
->get_debug_string ());
4271 /* Implementation of recording::memento::write_reproducer for string literal
4275 recording::memento_of_new_string_literal::write_reproducer (reproducer
&r
)
4277 const char *id
= r
.make_identifier (this, "rvalue");
4278 r
.write (" gcc_jit_rvalue *%s =\n"
4279 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4280 " %s); /* const char *value */\n",
4282 r
.get_identifier (get_context ()),
4283 m_value
->get_debug_string ());
4286 /* The implementation of class gcc::jit::recording::unary_op. */
4288 /* Implementation of pure virtual hook recording::memento::replay_into
4289 for recording::unary_op. */
4292 recording::unary_op::replay_into (replayer
*r
)
4294 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
4296 get_type ()->playback_type (),
4297 m_a
->playback_rvalue ()));
4300 /* Implementation of pure virtual hook recording::rvalue::visit_children
4301 for recording::unary_op. */
4303 recording::unary_op::visit_children (rvalue_visitor
*v
)
4308 /* Implementation of recording::memento::make_debug_string for
4311 static const char * const unary_op_strings
[] = {
4312 "-", /* GCC_JIT_UNARY_OP_MINUS */
4313 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4314 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4315 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4319 recording::unary_op::make_debug_string ()
4321 return string::from_printf (m_ctxt
,
4323 unary_op_strings
[m_op
],
4324 m_a
->get_debug_string ());
4327 static const char * const unary_op_reproducer_strings
[] = {
4328 "GCC_JIT_UNARY_OP_MINUS",
4329 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4330 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4331 "GCC_JIT_UNARY_OP_ABS"
4334 /* Implementation of recording::memento::write_reproducer for unary ops. */
4337 recording::unary_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_unary_op (%s,\n"
4342 " %s, /* gcc_jit_location *loc */\n"
4343 " %s, /* enum gcc_jit_unary_op op */\n"
4344 " %s, /* gcc_jit_type *result_type */\n"
4345 " %s); /* gcc_jit_rvalue *a */\n",
4347 r
.get_identifier (get_context ()),
4348 r
.get_identifier (m_loc
),
4349 unary_op_reproducer_strings
[m_op
],
4350 r
.get_identifier_as_type (get_type ()),
4351 r
.get_identifier_as_rvalue (m_a
));
4354 /* The implementation of class gcc::jit::recording::binary_op. */
4356 /* Implementation of pure virtual hook recording::memento::replay_into
4357 for recording::binary_op. */
4360 recording::binary_op::replay_into (replayer
*r
)
4362 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
4364 get_type ()->playback_type (),
4365 m_a
->playback_rvalue (),
4366 m_b
->playback_rvalue ()));
4369 /* Implementation of pure virtual hook recording::rvalue::visit_children
4370 for recording::binary_op. */
4372 recording::binary_op::visit_children (rvalue_visitor
*v
)
4378 /* Implementation of recording::memento::make_debug_string for
4381 static const char * const binary_op_strings
[] = {
4382 "+", /* GCC_JIT_BINARY_OP_PLUS */
4383 "-", /* GCC_JIT_BINARY_OP_MINUS */
4384 "*", /* GCC_JIT_BINARY_OP_MULT */
4385 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4386 "%", /* GCC_JIT_BINARY_OP_MODULO */
4387 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4388 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4389 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4390 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4391 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4392 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4393 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4397 recording::binary_op::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 binary_op_strings
[m_op
],
4404 m_b
->get_debug_string_parens (prec
));
4407 static const char * const binary_op_reproducer_strings
[] = {
4408 "GCC_JIT_BINARY_OP_PLUS",
4409 "GCC_JIT_BINARY_OP_MINUS",
4410 "GCC_JIT_BINARY_OP_MULT",
4411 "GCC_JIT_BINARY_OP_DIVIDE",
4412 "GCC_JIT_BINARY_OP_MODULO",
4413 "GCC_JIT_BINARY_OP_BITWISE_AND",
4414 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4415 "GCC_JIT_BINARY_OP_BITWISE_OR",
4416 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4417 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4418 "GCC_JIT_BINARY_OP_LSHIFT",
4419 "GCC_JIT_BINARY_OP_RSHIFT"
4422 /* Implementation of recording::memento::write_reproducer for binary ops. */
4425 recording::binary_op::write_reproducer (reproducer
&r
)
4427 const char *id
= r
.make_identifier (this, "rvalue");
4428 r
.write (" gcc_jit_rvalue *%s =\n"
4429 " gcc_jit_context_new_binary_op (%s,\n"
4430 " %s, /* gcc_jit_location *loc */\n"
4431 " %s, /* enum gcc_jit_binary_op op */\n"
4432 " %s, /* gcc_jit_type *result_type */\n"
4433 " %s, /* gcc_jit_rvalue *a */\n"
4434 " %s); /* gcc_jit_rvalue *b */\n",
4436 r
.get_identifier (get_context ()),
4437 r
.get_identifier (m_loc
),
4438 binary_op_reproducer_strings
[m_op
],
4439 r
.get_identifier_as_type (get_type ()),
4440 r
.get_identifier_as_rvalue (m_a
),
4441 r
.get_identifier_as_rvalue (m_b
));
4444 namespace recording
{
4445 static const enum precedence binary_op_precedence
[] = {
4446 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_PLUS */
4447 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_MINUS */
4449 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MULT */
4450 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_DIVIDE */
4451 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MODULO */
4453 PRECEDENCE_BITWISE_AND
, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4454 PRECEDENCE_BITWISE_XOR
, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4455 PRECEDENCE_BITWISE_IOR
, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4456 PRECEDENCE_LOGICAL_AND
, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4457 PRECEDENCE_LOGICAL_OR
, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4458 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_LSHIFT */
4459 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_RSHIFT */
4461 } /* namespace recording */
4463 enum recording::precedence
4464 recording::binary_op::get_precedence () const
4466 return binary_op_precedence
[m_op
];
4469 /* The implementation of class gcc::jit::recording::comparison. */
4471 /* Implementation of recording::memento::make_debug_string for
4474 static const char * const comparison_strings
[] =
4476 "==", /* GCC_JIT_COMPARISON_EQ */
4477 "!=", /* GCC_JIT_COMPARISON_NE */
4478 "<", /* GCC_JIT_COMPARISON_LT */
4479 "<=", /* GCC_JIT_COMPARISON_LE */
4480 ">", /* GCC_JIT_COMPARISON_GT */
4481 ">=", /* GCC_JIT_COMPARISON_GE */
4485 recording::comparison::make_debug_string ()
4487 enum precedence prec
= get_precedence ();
4488 return string::from_printf (m_ctxt
,
4490 m_a
->get_debug_string_parens (prec
),
4491 comparison_strings
[m_op
],
4492 m_b
->get_debug_string_parens (prec
));
4495 /* A table of enum gcc_jit_comparison values expressed in string
4498 static const char * const comparison_reproducer_strings
[] =
4500 "GCC_JIT_COMPARISON_EQ",
4501 "GCC_JIT_COMPARISON_NE",
4502 "GCC_JIT_COMPARISON_LT",
4503 "GCC_JIT_COMPARISON_LE",
4504 "GCC_JIT_COMPARISON_GT",
4505 "GCC_JIT_COMPARISON_GE"
4508 /* Implementation of recording::memento::write_reproducer for comparisons. */
4511 recording::comparison::write_reproducer (reproducer
&r
)
4513 const char *id
= r
.make_identifier (this, "rvalue");
4514 r
.write (" gcc_jit_rvalue *%s =\n"
4515 " gcc_jit_context_new_comparison (%s,\n"
4516 " %s, /* gcc_jit_location *loc */\n"
4517 " %s, /* enum gcc_jit_comparison op */\n"
4518 " %s, /* gcc_jit_rvalue *a */\n"
4519 " %s); /* gcc_jit_rvalue *b */\n",
4521 r
.get_identifier (get_context ()),
4522 r
.get_identifier (m_loc
),
4523 comparison_reproducer_strings
[m_op
],
4524 r
.get_identifier_as_rvalue (m_a
),
4525 r
.get_identifier_as_rvalue (m_b
));
4528 /* Implementation of pure virtual hook recording::memento::replay_into
4529 for recording::comparison. */
4532 recording::comparison::replay_into (replayer
*r
)
4534 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
4536 m_a
->playback_rvalue (),
4537 m_b
->playback_rvalue ()));
4540 /* Implementation of pure virtual hook recording::rvalue::visit_children
4541 for recording::comparison. */
4544 recording::comparison::visit_children (rvalue_visitor
*v
)
4550 namespace recording
{
4551 static const enum precedence comparison_precedence
[] =
4553 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_EQ */
4554 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_NE */
4556 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LT */
4557 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LE */
4558 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GT */
4559 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GE */
4561 } /* namespace recording */
4563 enum recording::precedence
4564 recording::comparison::get_precedence () const
4566 return comparison_precedence
[m_op
];
4569 /* Implementation of pure virtual hook recording::memento::replay_into
4570 for recording::cast. */
4573 recording::cast::replay_into (replayer
*r
)
4575 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
4576 m_rvalue
->playback_rvalue (),
4577 get_type ()->playback_type ()));
4580 /* Implementation of pure virtual hook recording::rvalue::visit_children
4581 for recording::cast. */
4583 recording::cast::visit_children (rvalue_visitor
*v
)
4585 v
->visit (m_rvalue
);
4588 /* Implementation of recording::memento::make_debug_string for
4592 recording::cast::make_debug_string ()
4594 enum precedence prec
= get_precedence ();
4595 return string::from_printf (m_ctxt
,
4597 get_type ()->get_debug_string (),
4598 m_rvalue
->get_debug_string_parens (prec
));
4601 /* Implementation of recording::memento::write_reproducer for casts. */
4604 recording::cast::write_reproducer (reproducer
&r
)
4606 const char *id
= r
.make_identifier (this, "rvalue");
4607 r
.write (" gcc_jit_rvalue *%s =\n"
4608 " gcc_jit_context_new_cast (%s,\n"
4609 " %s, /* gcc_jit_location *loc */\n"
4610 " %s, /* gcc_jit_rvalue *rvalue */\n"
4611 " %s); /* gcc_jit_type *type */\n",
4613 r
.get_identifier (get_context ()),
4614 r
.get_identifier (m_loc
),
4615 r
.get_identifier_as_rvalue (m_rvalue
),
4616 r
.get_identifier_as_type (get_type ()));
4619 /* The implementation of class gcc::jit::recording::call. */
4621 /* The constructor for gcc::jit::recording::call. */
4623 recording::call::call (recording::context
*ctxt
,
4624 recording::location
*loc
,
4625 recording::function
*func
,
4628 : rvalue (ctxt
, loc
, func
->get_return_type ()),
4632 for (int i
= 0; i
< numargs
; i
++)
4633 m_args
.safe_push (args
[i
]);
4636 /* Implementation of pure virtual hook recording::memento::replay_into
4637 for recording::call. */
4640 recording::call::replay_into (replayer
*r
)
4642 auto_vec
<playback::rvalue
*> playback_args
;
4643 playback_args
.create (m_args
.length ());
4644 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4645 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
4647 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
4648 m_func
->playback_function (),
4652 /* Implementation of pure virtual hook recording::rvalue::visit_children
4653 for recording::call. */
4656 recording::call::visit_children (rvalue_visitor
*v
)
4658 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4659 v
->visit (m_args
[i
]);
4662 /* Implementation of recording::memento::make_debug_string for
4666 recording::call::make_debug_string ()
4668 enum precedence prec
= get_precedence ();
4669 /* First, build a buffer for the arguments. */
4670 /* Calculate length of said buffer. */
4671 size_t sz
= 1; /* nil terminator */
4672 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4674 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4675 sz
+= 2; /* ", " separator */
4678 /* Now allocate and populate the buffer. */
4679 char *argbuf
= new char[sz
];
4682 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4684 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
4685 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4686 if (i
+ 1 < m_args
.length ())
4688 strcpy (argbuf
+ len
, ", ");
4694 /* ...and use it to get the string for the call as a whole. */
4695 string
*result
= string::from_printf (m_ctxt
,
4697 m_func
->get_debug_string (),
4706 recording::call::write_reproducer (reproducer
&r
)
4708 const char *id
= r
.make_identifier (this, "call");
4709 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
4710 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4713 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4714 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
4716 r
.write (" gcc_jit_rvalue *%s =\n"
4717 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4718 " %s, /* gcc_jit_location *loc */\n"
4719 " %s, /* gcc_jit_function *func */\n"
4720 " %i, /* int numargs */ \n"
4721 " %s); /* gcc_jit_rvalue **args*/\n",
4723 r
.get_identifier (get_context ()),
4724 r
.get_identifier (m_loc
),
4725 r
.get_identifier (m_func
),
4730 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4732 /* The constructor for recording::call_through_ptr. */
4734 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
4735 recording::location
*loc
,
4736 recording::rvalue
*fn_ptr
,
4739 : rvalue (ctxt
, loc
,
4740 fn_ptr
->get_type ()->dereference ()
4741 ->as_a_function_type ()->get_return_type ()),
4745 for (int i
= 0; i
< numargs
; i
++)
4746 m_args
.safe_push (args
[i
]);
4749 /* Implementation of pure virtual hook recording::memento::replay_into
4750 for recording::call_through_ptr. */
4753 recording::call_through_ptr::replay_into (replayer
*r
)
4755 auto_vec
<playback::rvalue
*> playback_args
;
4756 playback_args
.create (m_args
.length ());
4757 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4758 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
4760 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
4761 m_fn_ptr
->playback_rvalue (),
4765 /* Implementation of pure virtual hook recording::rvalue::visit_children
4766 for recording::call_through_ptr. */
4769 recording::call_through_ptr::visit_children (rvalue_visitor
*v
)
4771 v
->visit (m_fn_ptr
);
4772 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4773 v
->visit (m_args
[i
]);
4776 /* Implementation of recording::memento::make_debug_string for
4777 calls through function ptrs. */
4780 recording::call_through_ptr::make_debug_string ()
4782 enum precedence prec
= get_precedence ();
4783 /* First, build a buffer for the arguments. */
4784 /* Calculate length of said buffer. */
4785 size_t sz
= 1; /* nil terminator */
4786 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4788 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4789 sz
+= 2; /* ", " separator */
4792 /* Now allocate and populate the buffer. */
4793 char *argbuf
= new char[sz
];
4796 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4798 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
4799 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4800 if (i
+ 1 < m_args
.length ())
4802 strcpy (argbuf
+ len
, ", ");
4808 /* ...and use it to get the string for the call as a whole. */
4809 string
*result
= string::from_printf (m_ctxt
,
4811 m_fn_ptr
->get_debug_string_parens (prec
),
4819 /* Implementation of recording::memento::write_reproducer for
4820 call_through_ptr. */
4823 recording::call_through_ptr::write_reproducer (reproducer
&r
)
4825 const char *id
= r
.make_identifier (this, "call");
4826 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
4827 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4830 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4831 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
4833 r
.write (" gcc_jit_rvalue *%s =\n"
4834 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
4835 " %s, /* gcc_jit_location *loc */\n"
4836 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
4837 " %i, /* int numargs */ \n"
4838 " %s); /* gcc_jit_rvalue **args*/\n",
4840 r
.get_identifier (get_context ()),
4841 r
.get_identifier (m_loc
),
4842 r
.get_identifier_as_rvalue (m_fn_ptr
),
4847 /* The implementation of class gcc::jit::recording::array_access. */
4849 /* Implementation of pure virtual hook recording::memento::replay_into
4850 for recording::array_access. */
4853 recording::array_access::replay_into (replayer
*r
)
4856 r
->new_array_access (playback_location (r
, m_loc
),
4857 m_ptr
->playback_rvalue (),
4858 m_index
->playback_rvalue ()));
4861 /* Implementation of pure virtual hook recording::rvalue::visit_children
4862 for recording::array_access. */
4865 recording::array_access::visit_children (rvalue_visitor
*v
)
4871 /* Implementation of recording::memento::make_debug_string for
4875 recording::array_access::make_debug_string ()
4877 enum precedence prec
= get_precedence ();
4878 return string::from_printf (m_ctxt
,
4880 m_ptr
->get_debug_string_parens (prec
),
4881 m_index
->get_debug_string_parens (prec
));
4884 /* Implementation of recording::memento::write_reproducer for
4888 recording::array_access::write_reproducer (reproducer
&r
)
4890 const char *id
= r
.make_identifier (this, "lvalue");
4891 r
.write (" gcc_jit_lvalue *%s = \n"
4892 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
4893 " %s, /*gcc_jit_location *loc */\n"
4894 " %s, /* gcc_jit_rvalue *ptr */\n"
4895 " %s); /* gcc_jit_rvalue *index */\n",
4897 r
.get_identifier (get_context ()),
4898 r
.get_identifier (m_loc
),
4899 r
.get_identifier_as_rvalue (m_ptr
),
4900 r
.get_identifier_as_rvalue (m_index
));
4903 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
4905 /* Implementation of pure virtual hook recording::memento::replay_into
4906 for recording::access_field_of_lvalue. */
4909 recording::access_field_of_lvalue::replay_into (replayer
*r
)
4912 m_lvalue
->playback_lvalue ()
4913 ->access_field (playback_location (r
, m_loc
),
4914 m_field
->playback_field ()));
4918 /* Implementation of pure virtual hook recording::rvalue::visit_children
4919 for recording::access_field_of_lvalue. */
4922 recording::access_field_of_lvalue::visit_children (rvalue_visitor
*v
)
4924 v
->visit (m_lvalue
);
4927 /* Implementation of recording::memento::make_debug_string for
4928 accessing a field of an lvalue. */
4931 recording::access_field_of_lvalue::make_debug_string ()
4933 enum precedence prec
= get_precedence ();
4934 return string::from_printf (m_ctxt
,
4936 m_lvalue
->get_debug_string_parens (prec
),
4937 m_field
->get_debug_string ());
4940 /* Implementation of recording::memento::write_reproducer for
4941 access_field_of_lvalue. */
4944 recording::access_field_of_lvalue::write_reproducer (reproducer
&r
)
4946 const char *id
= r
.make_identifier (this, "lvalue");
4947 r
.write (" gcc_jit_lvalue *%s = \n"
4948 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
4949 " %s, /*gcc_jit_location *loc */\n"
4952 r
.get_identifier_as_lvalue (m_lvalue
),
4953 r
.get_identifier (m_loc
),
4954 r
.get_identifier (m_field
));
4957 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
4959 /* Implementation of pure virtual hook recording::memento::replay_into
4960 for recording::access_field_rvalue. */
4963 recording::access_field_rvalue::replay_into (replayer
*r
)
4966 m_rvalue
->playback_rvalue ()
4967 ->access_field (playback_location (r
, m_loc
),
4968 m_field
->playback_field ()));
4971 /* Implementation of pure virtual hook recording::rvalue::visit_children
4972 for recording::access_field_rvalue. */
4975 recording::access_field_rvalue::visit_children (rvalue_visitor
*v
)
4977 v
->visit (m_rvalue
);
4980 /* Implementation of recording::memento::make_debug_string for
4981 accessing a field of an rvalue. */
4984 recording::access_field_rvalue::make_debug_string ()
4986 enum precedence prec
= get_precedence ();
4987 return string::from_printf (m_ctxt
,
4989 m_rvalue
->get_debug_string_parens (prec
),
4990 m_field
->get_debug_string ());
4993 /* Implementation of recording::memento::write_reproducer for
4994 access_field_rvalue. */
4997 recording::access_field_rvalue::write_reproducer (reproducer
&r
)
4999 const char *id
= r
.make_identifier (this, "rvalue");
5000 r
.write (" gcc_jit_rvalue *%s = \n"
5001 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5002 " %s, /*gcc_jit_location *loc */\n"
5005 r
.get_identifier_as_rvalue (m_rvalue
),
5006 r
.get_identifier (m_loc
),
5007 r
.get_identifier (m_field
));
5010 /* The implementation of class
5011 gcc::jit::recording::dereference_field_rvalue. */
5013 /* Implementation of pure virtual hook recording::memento::replay_into
5014 for recording::dereference_field_rvalue. */
5017 recording::dereference_field_rvalue::replay_into (replayer
*r
)
5020 m_rvalue
->playback_rvalue ()->
5021 dereference_field (playback_location (r
, m_loc
),
5022 m_field
->playback_field ()));
5025 /* Implementation of pure virtual hook recording::rvalue::visit_children
5026 for recording::dereference_field_rvalue. */
5029 recording::dereference_field_rvalue::visit_children (rvalue_visitor
*v
)
5031 v
->visit (m_rvalue
);
5034 /* Implementation of recording::memento::make_debug_string for
5035 dereferencing a field of an rvalue. */
5038 recording::dereference_field_rvalue::make_debug_string ()
5040 enum precedence prec
= get_precedence ();
5041 return string::from_printf (m_ctxt
,
5043 m_rvalue
->get_debug_string_parens (prec
),
5044 m_field
->get_debug_string ());
5047 /* Implementation of recording::memento::write_reproducer for
5048 dereference_field_rvalue. */
5051 recording::dereference_field_rvalue::write_reproducer (reproducer
&r
)
5053 const char *id
= r
.make_identifier (this, "lvalue");
5054 r
.write (" gcc_jit_lvalue *%s=\n"
5055 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5056 " %s, /* gcc_jit_location *loc */\n"
5057 " %s); /* gcc_jit_field *field */\n",
5059 r
.get_identifier_as_rvalue (m_rvalue
),
5060 r
.get_identifier (m_loc
),
5061 r
.get_identifier (m_field
));
5064 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5066 /* Implementation of pure virtual hook recording::memento::replay_into
5067 for recording::dereference_rvalue. */
5070 recording::dereference_rvalue::replay_into (replayer
*r
)
5073 m_rvalue
->playback_rvalue ()->
5074 dereference (playback_location (r
, m_loc
)));
5077 /* Implementation of pure virtual hook recording::rvalue::visit_children
5078 for recording::dereference_rvalue. */
5081 recording::dereference_rvalue::visit_children (rvalue_visitor
*v
)
5083 v
->visit (m_rvalue
);
5086 /* Implementation of recording::memento::make_debug_string for
5087 dereferencing an rvalue. */
5090 recording::dereference_rvalue::make_debug_string ()
5092 enum precedence prec
= get_precedence ();
5093 return string::from_printf (m_ctxt
,
5095 m_rvalue
->get_debug_string_parens (prec
));
5098 /* Implementation of recording::memento::write_reproducer for
5099 dereference_rvalue. */
5102 recording::dereference_rvalue::write_reproducer (reproducer
&r
)
5104 const char *id
= r
.make_identifier (this, "dereference");
5105 r
.write (" gcc_jit_lvalue *%s =\n"
5106 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5107 " %s); /* gcc_jit_location *loc */\n",
5109 r
.get_identifier_as_rvalue (m_rvalue
),
5110 r
.get_identifier (m_loc
));
5113 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5115 /* Implementation of pure virtual hook recording::memento::replay_into
5116 for recording::get_address_of_lvalue. */
5119 recording::get_address_of_lvalue::replay_into (replayer
*r
)
5122 m_lvalue
->playback_lvalue ()->
5123 get_address (playback_location (r
, m_loc
)));
5126 /* Implementation of pure virtual hook recording::rvalue::visit_children
5127 for recording::get_address_of_lvalue. */
5130 recording::get_address_of_lvalue::visit_children (rvalue_visitor
*v
)
5132 v
->visit (m_lvalue
);
5135 /* Implementation of recording::memento::make_debug_string for
5136 getting the address of an lvalue. */
5139 recording::get_address_of_lvalue::make_debug_string ()
5141 enum precedence prec
= get_precedence ();
5142 return string::from_printf (m_ctxt
,
5144 m_lvalue
->get_debug_string_parens (prec
));
5147 /* Implementation of recording::memento::write_reproducer for
5148 get_address_of_lvalue. */
5151 recording::get_address_of_lvalue::write_reproducer (reproducer
&r
)
5153 const char *id
= r
.make_identifier (this, "address_of");
5154 r
.write (" gcc_jit_rvalue *%s =\n"
5155 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5156 " %s); /* gcc_jit_location *loc */\n",
5158 r
.get_identifier_as_lvalue (m_lvalue
),
5159 r
.get_identifier (m_loc
));
5162 /* The implementation of class gcc::jit::recording::local. */
5164 /* Implementation of pure virtual hook recording::memento::replay_into
5165 for recording::local. */
5168 recording::local::replay_into (replayer
*r
)
5171 m_func
->playback_function ()
5172 ->new_local (playback_location (r
, m_loc
),
5173 m_type
->playback_type (),
5174 playback_string (m_name
)));
5177 /* Override the default implementation of
5178 recording::memento::write_to_dump for locals by writing
5180 for use at the top of the function body as if it were a
5184 recording::local::write_to_dump (dump
&d
)
5186 if (d
.update_locations ())
5187 m_loc
= d
.make_location ();
5188 d
.write(" %s %s;\n",
5189 m_type
->get_debug_string (),
5190 get_debug_string ());
5194 recording::local::write_reproducer (reproducer
&r
)
5196 const char *id
= r
.make_identifier (this, "local");
5197 r
.write (" gcc_jit_lvalue *%s =\n"
5198 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5199 " %s, /* gcc_jit_location *loc */\n"
5200 " %s, /* gcc_jit_type *type */\n"
5201 " %s); /* const char *name */\n",
5203 r
.get_identifier (m_func
),
5204 r
.get_identifier (m_loc
),
5205 r
.get_identifier_as_type (m_type
),
5206 m_name
->get_debug_string ());
5209 /* The implementation of class gcc::jit::recording::statement. */
5211 /* We poison the default implementation of
5212 gcc::jit::recording::statement::get_successor_blocks
5213 since this vfunc must only ever be called on terminator
5217 recording::statement::get_successor_blocks (block
**/
*out_next1*/
,
5218 block
**/
*out_next2*/
) const
5220 /* The base class implementation is for non-terminating statements,
5221 and thus should never be called. */
5226 /* Extend the default implementation of
5227 recording::memento::write_to_dump for statements by (if requested)
5228 updating the location of the statement to the current location in
5232 recording::statement::write_to_dump (dump
&d
)
5234 memento::write_to_dump (d
);
5235 if (d
.update_locations ())
5236 m_loc
= d
.make_location ();
5239 /* The implementation of class gcc::jit::recording::eval. */
5241 /* Implementation of pure virtual hook recording::memento::replay_into
5242 for recording::eval. */
5245 recording::eval::replay_into (replayer
*r
)
5247 playback_block (get_block ())
5248 ->add_eval (playback_location (r
),
5249 m_rvalue
->playback_rvalue ());
5252 /* Implementation of recording::memento::make_debug_string for
5253 an eval statement. */
5256 recording::eval::make_debug_string ()
5258 return string::from_printf (m_ctxt
,
5260 m_rvalue
->get_debug_string ());
5263 /* Implementation of recording::memento::write_reproducer for
5267 recording::eval::write_reproducer (reproducer
&r
)
5269 r
.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5270 " %s, /* gcc_jit_location *loc */\n"
5271 " %s); /* gcc_jit_rvalue *rvalue */\n",
5272 r
.get_identifier (get_block ()),
5273 r
.get_identifier (get_loc ()),
5274 r
.get_identifier_as_rvalue (m_rvalue
));
5277 /* The implementation of class gcc::jit::recording::assignment. */
5279 /* Implementation of pure virtual hook recording::memento::replay_into
5280 for recording::assignment. */
5283 recording::assignment::replay_into (replayer
*r
)
5285 playback_block (get_block ())
5286 ->add_assignment (playback_location (r
),
5287 m_lvalue
->playback_lvalue (),
5288 m_rvalue
->playback_rvalue ());
5291 /* Implementation of recording::memento::make_debug_string for
5292 an assignment statement. */
5295 recording::assignment::make_debug_string ()
5297 return string::from_printf (m_ctxt
,
5299 m_lvalue
->get_debug_string (),
5300 m_rvalue
->get_debug_string ());
5303 /* Implementation of recording::memento::write_reproducer for
5304 assignment statements. */
5307 recording::assignment::write_reproducer (reproducer
&r
)
5309 r
.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5310 " %s, /* gcc_jit_location *loc */\n"
5311 " %s, /* gcc_jit_lvalue *lvalue */\n"
5312 " %s); /* gcc_jit_rvalue *rvalue */\n",
5313 r
.get_identifier (get_block ()),
5314 r
.get_identifier (get_loc ()),
5315 r
.get_identifier_as_lvalue (m_lvalue
),
5316 r
.get_identifier_as_rvalue (m_rvalue
));
5319 /* The implementation of class gcc::jit::recording::assignment_op. */
5321 /* Implementation of pure virtual hook recording::memento::replay_into
5322 for recording::assignment_op. */
5325 recording::assignment_op::replay_into (replayer
*r
)
5327 playback::type
*result_type
=
5328 m_lvalue
->playback_lvalue ()->get_type ();
5330 playback::rvalue
*binary_op
=
5331 r
->new_binary_op (playback_location (r
),
5334 m_lvalue
->playback_rvalue (),
5335 m_rvalue
->playback_rvalue ());
5337 playback_block (get_block ())
5338 ->add_assignment (playback_location (r
),
5339 m_lvalue
->playback_lvalue (),
5343 /* Implementation of recording::memento::make_debug_string for
5344 an assignment_op statement. */
5347 recording::assignment_op::make_debug_string ()
5349 return string::from_printf (m_ctxt
,
5351 m_lvalue
->get_debug_string (),
5352 binary_op_strings
[m_op
],
5353 m_rvalue
->get_debug_string ());
5356 /* Implementation of recording::memento::write_reproducer for
5357 assignment_op statements. */
5360 recording::assignment_op::write_reproducer (reproducer
&r
)
5362 r
.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5363 " %s, /* gcc_jit_location *loc */\n"
5364 " %s, /* gcc_jit_lvalue *lvalue */\n"
5365 " %s, /* enum gcc_jit_binary_op op */\n"
5366 " %s); /* gcc_jit_rvalue *rvalue */\n",
5367 r
.get_identifier (get_block ()),
5368 r
.get_identifier (get_loc ()),
5369 r
.get_identifier_as_lvalue (m_lvalue
),
5370 binary_op_reproducer_strings
[m_op
],
5371 r
.get_identifier_as_rvalue (m_rvalue
));
5374 /* The implementation of class gcc::jit::recording::comment. */
5376 /* Implementation of pure virtual hook recording::memento::replay_into
5377 for recording::comment. */
5380 recording::comment::replay_into (replayer
*r
)
5382 playback_block (get_block ())
5383 ->add_comment (playback_location (r
),
5387 /* Implementation of recording::memento::make_debug_string for
5388 a comment "statement". */
5391 recording::comment::make_debug_string ()
5393 return string::from_printf (m_ctxt
,
5398 /* Implementation of recording::memento::write_reproducer for
5402 recording::comment::write_reproducer (reproducer
&r
)
5404 r
.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5405 " %s, /* gcc_jit_location *loc */\n"
5406 " %s); /* const char *text */\n",
5407 r
.get_identifier (get_block ()),
5408 r
.get_identifier (get_loc ()),
5409 m_text
->get_debug_string ());
5412 /* The implementation of class gcc::jit::recording::conditional. */
5414 /* Implementation of pure virtual hook recording::memento::replay_into
5415 for recording::conditional. */
5418 recording::conditional::replay_into (replayer
*r
)
5420 playback_block (get_block ())
5421 ->add_conditional (playback_location (r
),
5422 m_boolval
->playback_rvalue (),
5423 playback_block (m_on_true
),
5424 playback_block (m_on_false
));
5427 /* Override the poisoned default implementation of
5428 gcc::jit::recording::statement::get_successor_blocks
5430 A conditional jump has 2 successor blocks. */
5433 recording::conditional::get_successor_blocks (block
**out_next1
,
5434 block
**out_next2
) const
5436 *out_next1
= m_on_true
;
5437 *out_next2
= m_on_false
;
5441 /* Implementation of recording::memento::make_debug_string for
5442 a conditional jump statement. */
5445 recording::conditional::make_debug_string ()
5448 return string::from_printf (m_ctxt
,
5449 "if (%s) goto %s; else goto %s;",
5450 m_boolval
->get_debug_string (),
5451 m_on_true
->get_debug_string (),
5452 m_on_false
->get_debug_string ());
5454 return string::from_printf (m_ctxt
,
5456 m_boolval
->get_debug_string (),
5457 m_on_true
->get_debug_string ());
5460 /* Implementation of recording::memento::write_reproducer for
5461 conditional statements. */
5464 recording::conditional::write_reproducer (reproducer
&r
)
5466 r
.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5467 " %s, /* gcc_jit_location *loc */\n"
5468 " %s, /* gcc_jit_rvalue *boolval */\n"
5469 " %s, /* gcc_jit_block *on_true */\n"
5470 " %s); /* gcc_jit_block *on_false */\n",
5471 r
.get_identifier (get_block ()),
5472 r
.get_identifier (get_loc ()),
5473 r
.get_identifier_as_rvalue (m_boolval
),
5474 r
.get_identifier (m_on_true
),
5475 r
.get_identifier (m_on_false
));
5478 /* The implementation of class gcc::jit::recording::jump. */
5480 /* Implementation of pure virtual hook recording::memento::replay_into
5481 for recording::jump. */
5484 recording::jump::replay_into (replayer
*r
)
5486 playback_block (get_block ())
5487 ->add_jump (playback_location (r
),
5488 m_target
->playback_block ());
5491 /* Override the poisoned default implementation of
5492 gcc::jit::recording::statement::get_successor_blocks
5494 An unconditional jump has 1 successor block. */
5497 recording::jump::get_successor_blocks (block
**out_next1
,
5498 block
**/
*out_next2*/
) const
5500 *out_next1
= m_target
;
5504 /* Implementation of recording::memento::make_debug_string for
5505 a unconditional jump statement. */
5508 recording::jump::make_debug_string ()
5510 return string::from_printf (m_ctxt
,
5512 m_target
->get_debug_string ());
5515 /* Implementation of recording::memento::write_reproducer for
5519 recording::jump::write_reproducer (reproducer
&r
)
5521 r
.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5522 " %s, /* gcc_jit_location *loc */\n"
5523 " %s); /* gcc_jit_block *target */\n",
5524 r
.get_identifier (get_block ()),
5525 r
.get_identifier (get_loc ()),
5526 r
.get_identifier (m_target
));
5529 /* The implementation of class gcc::jit::recording::return_. */
5531 /* Implementation of pure virtual hook recording::memento::replay_into
5532 for recording::return_. */
5535 recording::return_::replay_into (replayer
*r
)
5537 playback_block (get_block ())
5538 ->add_return (playback_location (r
),
5539 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
5542 /* Override the poisoned default implementation of
5543 gcc::jit::recording::statement::get_successor_blocks
5545 A return statement has no successor block. */
5548 recording::return_::get_successor_blocks (block
**/
*out_next1*/
,
5549 block
**/
*out_next2*/
) const
5554 /* Implementation of recording::memento::make_debug_string for
5555 a return statement (covers both those with and without rvalues). */
5558 recording::return_::make_debug_string ()
5561 return string::from_printf (m_ctxt
,
5563 m_rvalue
->get_debug_string ());
5565 return string::from_printf (m_ctxt
,
5569 /* Implementation of recording::memento::write_reproducer for
5570 return statements. */
5573 recording::return_::write_reproducer (reproducer
&r
)
5576 r
.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5577 " %s, /* gcc_jit_location *loc */\n"
5578 " %s); /* gcc_jit_rvalue *rvalue */\n",
5579 r
.get_identifier (get_block ()),
5580 r
.get_identifier (get_loc ()),
5581 r
.get_identifier_as_rvalue (m_rvalue
));
5583 r
.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5584 " %s); /* gcc_jit_location *loc */\n",
5585 r
.get_identifier (get_block ()),
5586 r
.get_identifier (get_loc ()));
5589 } // namespace gcc::jit