1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2017 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
25 #include "pretty-print.h"
30 #include "jit-builtins.h"
31 #include "jit-recording.h"
32 #include "jit-playback.h"
39 dump::dump (recording::context
&ctxt
,
41 bool update_locations
)
43 m_filename (filename
),
44 m_update_locations (update_locations
),
48 m_file
= fopen (filename
, "w");
51 "error opening dump file %s for writing: %s",
60 int err
= fclose (m_file
);
62 m_ctxt
.add_error (NULL
,
63 "error closing dump file %s: %s",
69 /* Write the given message to the dump, using printf-formatting
70 conventions, updating the line/column within the dump.
72 Emit an error on the context if a failure occurs. */
75 dump::write (const char *fmt
, ...)
81 /* If there was an error opening the file, we've already reported it.
82 Don't attempt further work. */
87 len
= vasprintf (&buf
, fmt
, ap
);
90 if (buf
== NULL
|| len
< 0)
92 m_ctxt
.add_error (NULL
, "malloc failure writing to dumpfile %s",
97 if (fwrite (buf
, strlen (buf
), 1, m_file
) != 1)
98 m_ctxt
.add_error (NULL
, "error writing to dump file %s",
101 /* Flush after each line, to ease debugging crashes. */
104 /* Update line/column: */
105 for (const char *ptr
= buf
; *ptr
; ptr
++)
119 /* Construct a gcc::jit::recording::location instance for the current
120 location within the dump. */
122 recording::location
*
123 dump::make_location () const
125 return m_ctxt
.new_location (m_filename
, m_line
, m_column
,
126 /* We need to flag such locations as *not*
127 created by the user, so that
128 reproducer::get_identifier can cope with
129 them appearing *after* the memento that
134 /* A collection of allocations, all of which can be released together, to
135 avoid needing to track and release them individually. */
143 xstrdup_printf (const char *, ...)
144 ATTRIBUTE_RETURNS_NONNULL
148 xstrdup_printf_va (const char *, va_list ap
)
149 ATTRIBUTE_RETURNS_NONNULL
153 auto_vec
<void *> m_buffers
;
156 /* allocator's destructor. Call "free" on all of the allocations. */
158 allocator::~allocator ()
162 FOR_EACH_VEC_ELT (m_buffers
, i
, buffer
)
166 /* Formatted printing, allocating to a buffer (or exiting the process if
167 the allocation fails).
169 The buffer exists until the allocator is cleaned up, and is freed at
170 that point, so the caller doesn't need to track the result. */
173 allocator::xstrdup_printf (const char *fmt
, ...)
178 result
= xstrdup_printf_va (fmt
, ap
);
183 /* Formatted printing, allocating to a buffer (or exiting the process if
184 the allocation fails).
186 The buffer exists until the allocator is cleaned up, and is freed at
187 that point, so the caller doesn't need to track the result. */
190 allocator::xstrdup_printf_va (const char *fmt
, va_list ap
)
192 char *result
= xvasprintf (fmt
, ap
);
193 m_buffers
.safe_push (result
);
197 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
198 implementing gcc_jit_context_dump_reproducer_to_file. */
200 class reproducer
: public dump
203 reproducer (recording::context
&ctxt
,
204 const char *filename
);
207 write_params (const vec
<recording::context
*> &contexts
);
210 write_args (const vec
<recording::context
*> &contexts
);
213 make_identifier (recording::memento
*m
, const char *prefix
);
216 make_tmp_identifier (const char *prefix
, recording::memento
*m
);
219 get_identifier (recording::context
*ctxt
);
222 get_identifier (recording::memento
*m
);
225 get_identifier_as_rvalue (recording::rvalue
*m
);
228 get_identifier_as_lvalue (recording::lvalue
*m
);
231 get_identifier_as_type (recording::type
*m
);
234 xstrdup_printf (const char *, ...)
235 ATTRIBUTE_RETURNS_NONNULL
239 hash_map
<recording::memento
*, const char *> m_identifiers
;
240 allocator m_allocator
;
243 /* gcc::jit::reproducer's constructor. */
245 reproducer::reproducer (recording::context
&ctxt
,
246 const char *filename
) :
247 dump (ctxt
, filename
, 0),
253 /* Write out a list of contexts as a set of parameters within a
254 C function declaration. */
257 reproducer::write_params (const vec
<recording::context
*> &contexts
)
260 recording::context
*ctxt
;
261 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
263 write ("gcc_jit_context *%s",
264 get_identifier (ctxt
));
265 if (i
< contexts
.length () - 1)
271 /* Write out a list of contexts as a set of arguments within a call
275 reproducer::write_args (const vec
<recording::context
*> &contexts
)
278 recording::context
*ctxt
;
279 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
282 get_identifier (ctxt
));
283 if (i
< contexts
.length () - 1)
289 /* Generate a C identifier for the given memento, associating the generated
290 buffer with the memento (for future calls to get_identifier et al).
292 The reproducer will eventually clean up the buffer in its dtor. */
294 reproducer::make_identifier (recording::memento
*m
, const char *prefix
)
297 if (strlen (m
->get_debug_string ()) < 100)
299 result
= m_allocator
.xstrdup_printf ("%s_%s_%p",
301 m
->get_debug_string (),
303 for (char *p
= result
; *p
; p
++)
308 result
= m_allocator
.xstrdup_printf ("%s_%p",
310 m_identifiers
.put (m
, result
);
314 /* Generate a C identifier for a temporary variable.
315 The reproducer will eventually clean up the buffer in its dtor. */
318 reproducer::make_tmp_identifier (const char *prefix
, recording::memento
*m
)
320 return m_allocator
.xstrdup_printf ("%s_%s",
321 prefix
, get_identifier (m
));
324 /* Generate a C identifier for the given context.
325 The reproducer will eventually clean up the buffer in its dtor. */
328 reproducer::get_identifier (recording::context
*ctxt
)
330 return m_allocator
.xstrdup_printf ("ctxt_%p",
334 /* Locate the C identifier for the given memento, which is assumed to
335 have already been created via make_identifier. */
338 reproducer::get_identifier (recording::memento
*m
)
343 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
344 and hence these locations appear in the context's memento list
345 out-of-order: they appear in the context's memento list *after*
346 the memento that refers to them. For this case, it's simplest to
347 pretend that they're NULL when writing out the code to recreate the
348 memento that uses them. */
349 if (recording::location
*loc
= m
->dyn_cast_location ())
350 if (!loc
->created_by_user ())
353 const char **slot
= m_identifiers
.get (m
);
356 get_context ().add_error (NULL
,
357 "unable to find identifier for %p: %s",
359 m
->get_debug_string ());
365 /* Locate the C identifier for the given rvalue, wrapping it within
366 a gcc_*_as_rvalue upcast if necessary. */
369 reproducer::get_identifier_as_rvalue (recording::rvalue
*m
)
371 return m
->access_as_rvalue (*this);
374 /* Locate the C identifier for the given lvalue, wrapping it within
375 a gcc_*_as_lvalue upcast if necessary. */
378 reproducer::get_identifier_as_lvalue (recording::lvalue
*m
)
380 return m
->access_as_lvalue (*this);
383 /* Locate the C identifier for the given type, wrapping it within
384 a gcc_*_as_type upcast if necessary. */
387 reproducer::get_identifier_as_type (recording::type
*m
)
389 return m
->access_as_type (*this);
392 /* Formatted printing, allocating to a buffer (or exiting the process if
393 the allocation fails).
395 The buffer exists until the allocator is cleaned up, and is freed at
396 that point, so the caller doesn't need to track the result.
398 Note that we can't use ggc_printf since we're not within the compiler
399 proper (when within gcc_jit_context_dump_reproducer_to_file). */
402 reproducer::xstrdup_printf (const char *fmt
, ...)
407 result
= m_allocator
.xstrdup_printf_va (fmt
, ap
);
412 /**********************************************************************
414 **********************************************************************/
416 /* Get the playback::location for the given recording::location,
417 handling a NULL input with a NULL output. */
420 recording::playback_location (replayer
*r
, recording::location
*loc
)
423 return loc
->playback_location (r
);
428 /* Get a const char * for the given recording::string
429 handling a NULL input with a NULL output. */
432 recording::playback_string (recording::string
*str
)
435 return str
->c_str ();
440 /* Get the playback::block for the given recording::block,
441 handling a NULL input with a NULL output. */
444 recording::playback_block (recording::block
*b
)
447 return b
->playback_block ();
452 /* Methods of cc::jit::recording::context. */
454 /* The constructor for gcc::jit::recording::context, used by
455 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
457 recording::context::context (context
*parent_ctxt
)
459 m_parent_ctxt (parent_ctxt
),
460 m_toplevel_ctxt (m_parent_ctxt
? m_parent_ctxt
->m_toplevel_ctxt
: this),
463 m_first_error_str (NULL
),
464 m_owns_first_error_str (false),
465 m_last_error_str (NULL
),
466 m_owns_last_error_str (false),
472 m_builtins_manager(NULL
)
476 /* Inherit options from parent. */
478 i
< sizeof (m_str_options
) / sizeof (m_str_options
[0]);
481 const char *parent_opt
= parent_ctxt
->m_str_options
[i
];
482 m_str_options
[i
] = parent_opt
? xstrdup (parent_opt
) : NULL
;
484 memcpy (m_int_options
,
485 parent_ctxt
->m_int_options
,
486 sizeof (m_int_options
));
487 memcpy (m_bool_options
,
488 parent_ctxt
->m_bool_options
,
489 sizeof (m_bool_options
));
490 memcpy (m_inner_bool_options
,
491 parent_ctxt
->m_inner_bool_options
,
492 sizeof (m_inner_bool_options
));
493 set_logger (parent_ctxt
->get_logger ());
497 memset (m_str_options
, 0, sizeof (m_str_options
));
498 memset (m_int_options
, 0, sizeof (m_int_options
));
499 memset (m_bool_options
, 0, sizeof (m_bool_options
));
500 memset (m_inner_bool_options
, 0, sizeof (m_inner_bool_options
));
503 memset (m_basic_types
, 0, sizeof (m_basic_types
));
506 /* The destructor for gcc::jit::recording::context, implicitly used by
507 gcc_jit_context_release. */
509 recording::context::~context ()
511 JIT_LOG_SCOPE (get_logger ());
514 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
519 for (i
= 0; i
< GCC_JIT_NUM_STR_OPTIONS
; ++i
)
520 free (m_str_options
[i
]);
523 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
526 if (m_builtins_manager
)
527 delete m_builtins_manager
;
529 if (m_owns_first_error_str
)
530 free (m_first_error_str
);
532 if (m_owns_last_error_str
)
533 if (m_last_error_str
!= m_first_error_str
)
534 free (m_last_error_str
);
537 /* Add the given mememto to the list of those tracked by this
538 gcc::jit::recording::context, so that e.g. it can be deleted
539 when this context is released. */
542 recording::context::record (memento
*m
)
546 m_mementos
.safe_push (m
);
549 /* Replay this context (and any parents) into the given replayer. */
552 recording::context::replay_into (replayer
*r
)
554 JIT_LOG_SCOPE (get_logger ());
558 /* If we have a parent context, we must replay it. This will
559 recursively walk backwards up the historical tree, then replay things
560 forwards "in historical order", starting with the ultimate parent
561 context, until we reach the "this" context.
563 Note that we fully replay the parent, then fully replay the child,
564 which means that inter-context references can only exist from child
565 to parent, not the other way around.
567 All of this replaying is suboptimal - it would be better to do the
568 work for the parent context *once*, rather than replaying the parent
569 every time we replay each child. However, fixing this requires deep
570 surgery to lifetime-management: we'd need every context family tree
571 to have its own GC heap, and to initialize the GCC code to use that
572 heap (with a mutex on such a heap). */
574 m_parent_ctxt
->replay_into (r
);
576 if (r
->errors_occurred ())
579 /* Replay this context's saved operations into r. */
580 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
582 /* Disabled low-level debugging, here if we need it: print what
584 Note that the calls to get_debug_string might lead to more
585 mementos being created for the strings.
586 This can also be used to exercise the debug_string
589 printf ("context %p replaying (%p): %s\n",
590 (void *)this, (void *)m
, m
->get_debug_string ());
594 if (r
->errors_occurred ())
599 /* During a playback, we associate objects from the recording with
600 their counterparts during this playback.
602 For simplicity, we store this within the recording objects.
604 The following method cleans away these associations, to ensure that
605 we never have out-of-date associations lingering on subsequent
606 playbacks (the objects pointed to are GC-managed, but the
607 recording objects don't own refs to them). */
610 recording::context::disassociate_from_playback ()
612 JIT_LOG_SCOPE (get_logger ());
617 m_parent_ctxt
->disassociate_from_playback ();
619 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
621 m
->set_playback_obj (NULL
);
625 /* Create a recording::string instance and add it to this context's list
628 This creates a fresh copy of the given 0-terminated buffer. */
631 recording::context::new_string (const char *text
)
636 recording::string
*result
= new string (this, text
);
641 /* Create a recording::location instance and add it to this context's
644 Implements the post-error-checking part of
645 gcc_jit_context_new_location. */
647 recording::location
*
648 recording::context::new_location (const char *filename
,
651 bool created_by_user
)
653 recording::location
*result
=
654 new recording::location (this,
655 new_string (filename
),
662 /* If we haven't seen this enum value yet, create a recording::type
663 instance and add it to this context's list of mementos.
665 If we have seen it before, reuse our cached value, so that repeated
666 calls on the context give the same object.
668 If we have a parent context, the cache is within the ultimate
671 Implements the post-error-checking part of
672 gcc_jit_context_get_type. */
675 recording::context::get_type (enum gcc_jit_types kind
)
677 if (!m_basic_types
[kind
])
680 m_basic_types
[kind
] = m_parent_ctxt
->get_type (kind
);
683 recording::type
*result
= new memento_of_get_type (this, kind
);
685 m_basic_types
[kind
] = result
;
689 return m_basic_types
[kind
];
692 /* Get a recording::type instance for the given size and signedness.
693 This is implemented in terms of recording::context::get_type
696 Implements the post-error-checking part of
697 gcc_jit_context_get_int_type. */
700 recording::context::get_int_type (int num_bytes
, int is_signed
)
702 /* We can't use a switch here since some of the values are macros affected
703 by options; e.g. i386.h has
704 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
705 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
706 are in bits, rather than bytes.
708 const int num_bits
= num_bytes
* 8;
709 if (num_bits
== INT_TYPE_SIZE
)
710 return get_type (is_signed
712 : GCC_JIT_TYPE_UNSIGNED_INT
);
713 if (num_bits
== CHAR_TYPE_SIZE
)
714 return get_type (is_signed
715 ? GCC_JIT_TYPE_SIGNED_CHAR
716 : GCC_JIT_TYPE_UNSIGNED_CHAR
);
717 if (num_bits
== SHORT_TYPE_SIZE
)
718 return get_type (is_signed
720 : GCC_JIT_TYPE_UNSIGNED_SHORT
);
721 if (num_bits
== LONG_TYPE_SIZE
)
722 return get_type (is_signed
724 : GCC_JIT_TYPE_UNSIGNED_LONG
);
725 if (num_bits
== LONG_LONG_TYPE_SIZE
)
726 return get_type (is_signed
727 ? GCC_JIT_TYPE_LONG_LONG
728 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
730 /* Some other size, not corresponding to the C int types. */
731 /* To be written: support arbitrary other sizes, sharing by
732 memoizing at the recording::context level? */
736 /* Create a recording::type instance and add it to this context's list
739 Implements the post-error-checking part of
740 gcc_jit_context_new_array_type. */
743 recording::context::new_array_type (recording::location
*loc
,
744 recording::type
*element_type
,
747 if (struct_
*s
= element_type
->dyn_cast_struct ())
748 if (!s
->get_fields ())
751 "cannot create an array of type %s"
752 " until the fields have been set",
753 s
->get_name ()->c_str ());
756 recording::type
*result
=
757 new recording::array_type (this, loc
, element_type
, num_elements
);
762 /* Create a recording::field instance and add it to this context's list
765 Implements the post-error-checking part of
766 gcc_jit_context_new_field. */
769 recording::context::new_field (recording::location
*loc
,
770 recording::type
*type
,
773 recording::field
*result
=
774 new recording::field (this, loc
, type
, new_string (name
));
779 /* Create a recording::struct_ instance and add it to this context's
780 list of mementos and list of compound types.
782 Implements the post-error-checking part of
783 gcc_jit_context_new_struct_type. */
786 recording::context::new_struct_type (recording::location
*loc
,
789 recording::struct_
*result
= new struct_ (this, loc
, new_string (name
));
791 m_compound_types
.safe_push (result
);
795 /* Create a recording::union_ instance and add it to this context's
796 list of mementos and list of compound types.
798 Implements the first post-error-checking part of
799 gcc_jit_context_new_union_type. */
802 recording::context::new_union_type (recording::location
*loc
,
805 recording::union_
*result
= new union_ (this, loc
, new_string (name
));
807 m_compound_types
.safe_push (result
);
811 /* Create a recording::function_type instance and add it to this context's
814 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
816 recording::function_type
*
817 recording::context::new_function_type (recording::type
*return_type
,
819 recording::type
**param_types
,
822 recording::function_type
*fn_type
823 = new function_type (this,
832 /* Create a recording::type instance and add it to this context's list
835 Implements the post-error-checking part of
836 gcc_jit_context_new_function_ptr_type. */
839 recording::context::new_function_ptr_type (recording::location
*, /* unused loc */
840 recording::type
*return_type
,
842 recording::type
**param_types
,
845 recording::function_type
*fn_type
846 = new_function_type (return_type
,
851 /* Return a pointer-type to the function type. */
852 return fn_type
->get_pointer ();
855 /* Create a recording::param instance and add it to this context's list
858 Implements the post-error-checking part of
859 gcc_jit_context_new_param. */
862 recording::context::new_param (recording::location
*loc
,
863 recording::type
*type
,
866 recording::param
*result
= new recording::param (this, loc
, type
, new_string (name
));
871 /* Create a recording::function instance and add it to this context's list
872 of mementos and list of functions.
874 Implements the post-error-checking part of
875 gcc_jit_context_new_function. */
877 recording::function
*
878 recording::context::new_function (recording::location
*loc
,
879 enum gcc_jit_function_kind kind
,
880 recording::type
*return_type
,
883 recording::param
**params
,
885 enum built_in_function builtin_id
)
887 recording::function
*result
=
888 new recording::function (this,
889 loc
, kind
, return_type
,
891 num_params
, params
, is_variadic
,
894 m_functions
.safe_push (result
);
899 /* Locate the builtins_manager (if any) for this family of contexts,
900 creating it if it doesn't exist already.
902 All of the recording contexts in a family share one builtins_manager:
903 if we have a child context, follow the parent links to get the
904 ultimate ancestor context, and look for it/store it there. */
907 recording::context::get_builtins_manager ()
910 return m_parent_ctxt
->get_builtins_manager ();
912 if (!m_builtins_manager
)
913 m_builtins_manager
= new builtins_manager (this);
915 return m_builtins_manager
;
918 /* Get a recording::function instance, which is lazily-created and added
919 to the context's lists of mementos.
921 Implements the post-error-checking part of
922 gcc_jit_context_get_builtin_function. */
924 recording::function
*
925 recording::context::get_builtin_function (const char *name
)
927 builtins_manager
*bm
= get_builtins_manager ();
928 return bm
->get_builtin_function (name
);
931 /* Create a recording::global instance and add it to this context's list
934 Implements the post-error-checking part of
935 gcc_jit_context_new_global. */
938 recording::context::new_global (recording::location
*loc
,
939 enum gcc_jit_global_kind kind
,
940 recording::type
*type
,
943 recording::global
*result
=
944 new recording::global (this, loc
, kind
, type
, new_string (name
));
946 m_globals
.safe_push (result
);
951 /* Create a recording::memento_of_new_string_literal instance and add it
952 to this context's list of mementos.
954 Implements the post-error-checking part of
955 gcc_jit_context_new_string_literal. */
958 recording::context::new_string_literal (const char *value
)
960 recording::rvalue
*result
=
961 new memento_of_new_string_literal (this, NULL
, new_string (value
));
966 /* Create a recording::unary_op instance and add it to this context's
969 Implements the post-error-checking part of
970 gcc_jit_context_new_unary_op. */
973 recording::context::new_unary_op (recording::location
*loc
,
974 enum gcc_jit_unary_op op
,
975 recording::type
*result_type
,
976 recording::rvalue
*a
)
978 recording::rvalue
*result
=
979 new unary_op (this, loc
, op
, result_type
, a
);
984 /* Create a recording::binary_op instance and add it to this context's
987 Implements the post-error-checking part of
988 gcc_jit_context_new_binary_op. */
991 recording::context::new_binary_op (recording::location
*loc
,
992 enum gcc_jit_binary_op op
,
993 recording::type
*result_type
,
994 recording::rvalue
*a
,
995 recording::rvalue
*b
)
997 recording::rvalue
*result
=
998 new binary_op (this, loc
, op
, result_type
, a
, b
);
1003 /* Create a recording::comparison instance and add it to this context's
1006 Implements the post-error-checking part of
1007 gcc_jit_context_new_comparison. */
1010 recording::context::new_comparison (recording::location
*loc
,
1011 enum gcc_jit_comparison op
,
1012 recording::rvalue
*a
,
1013 recording::rvalue
*b
)
1015 recording::rvalue
*result
= new comparison (this, loc
, op
, a
, b
);
1020 /* Create a recording::cast instance and add it to this context's list
1023 Implements the post-error-checking part of
1024 gcc_jit_context_new_cast. */
1027 recording::context::new_cast (recording::location
*loc
,
1028 recording::rvalue
*expr
,
1029 recording::type
*type_
)
1031 recording::rvalue
*result
= new cast (this, loc
, expr
, type_
);
1036 /* Create a recording::call instance and add it to this context's list
1039 Implements the post-error-checking part of
1040 gcc_jit_context_new_call. */
1043 recording::context::new_call (recording::location
*loc
,
1045 int numargs
, recording::rvalue
**args
)
1047 recording::rvalue
*result
= new call (this, loc
, func
, numargs
, args
);
1052 /* Create a recording::call_through_ptr instance and add it to this
1053 context's list of mementos.
1055 Implements the post-error-checking part of
1056 gcc_jit_context_new_call_through_ptr. */
1059 recording::context::new_call_through_ptr (recording::location
*loc
,
1060 recording::rvalue
*fn_ptr
,
1062 recording::rvalue
**args
)
1064 recording::rvalue
*result
= new call_through_ptr (this, loc
, fn_ptr
, numargs
, args
);
1069 /* Create a recording::array_access instance and add it to this context's list
1072 Implements the post-error-checking part of
1073 gcc_jit_context_new_array_access. */
1076 recording::context::new_array_access (recording::location
*loc
,
1077 recording::rvalue
*ptr
,
1078 recording::rvalue
*index
)
1080 recording::lvalue
*result
= new array_access (this, loc
, ptr
, index
);
1085 /* Create a recording::case_ instance and add it to this context's list
1088 Implements the post-error-checking part of
1089 gcc_jit_context_new_case. */
1092 recording::context::new_case (recording::rvalue
*min_value
,
1093 recording::rvalue
*max_value
,
1094 recording::block
*block
)
1096 recording::case_
*result
= new case_ (this, min_value
, max_value
, block
);
1101 /* Set the given string option for this context, or add an error if
1102 it's not recognized.
1104 Implements the post-error-checking part of
1105 gcc_jit_context_set_str_option. */
1108 recording::context::set_str_option (enum gcc_jit_str_option opt
,
1111 if (opt
< 0 || opt
>= GCC_JIT_NUM_STR_OPTIONS
)
1114 "unrecognized (enum gcc_jit_str_option) value: %i", opt
);
1117 free (m_str_options
[opt
]);
1118 m_str_options
[opt
] = value
? xstrdup (value
) : NULL
;
1119 log_str_option (opt
);
1122 /* Set the given integer option for this context, or add an error if
1123 it's not recognized.
1125 Implements the post-error-checking part of
1126 gcc_jit_context_set_int_option. */
1129 recording::context::set_int_option (enum gcc_jit_int_option opt
,
1132 if (opt
< 0 || opt
>= GCC_JIT_NUM_INT_OPTIONS
)
1135 "unrecognized (enum gcc_jit_int_option) value: %i", opt
);
1138 m_int_options
[opt
] = value
;
1139 log_int_option (opt
);
1142 /* Set the given boolean option for this context, or add an error if
1143 it's not recognized.
1145 Implements the post-error-checking part of
1146 gcc_jit_context_set_bool_option. */
1149 recording::context::set_bool_option (enum gcc_jit_bool_option opt
,
1152 if (opt
< 0 || opt
>= GCC_JIT_NUM_BOOL_OPTIONS
)
1155 "unrecognized (enum gcc_jit_bool_option) value: %i", opt
);
1158 m_bool_options
[opt
] = value
? true : false;
1159 log_bool_option (opt
);
1163 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt
,
1166 gcc_assert (inner_opt
>= 0 && inner_opt
< NUM_INNER_BOOL_OPTIONS
);
1167 m_inner_bool_options
[inner_opt
] = value
? true : false;
1168 log_inner_bool_option (inner_opt
);
1172 /* Add the given optname to this context's list of extra options.
1174 Implements the post-error-checking part of
1175 gcc_jit_context_add_command_line_option. */
1178 recording::context::add_command_line_option (const char *optname
)
1180 m_command_line_options
.safe_push (xstrdup (optname
));
1183 /* Add any user-provided extra options, starting with any from
1185 Called by playback::context::make_fake_args. */
1188 recording::context::append_command_line_options (vec
<char *> *argvec
)
1191 m_parent_ctxt
->append_command_line_options (argvec
);
1195 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1196 argvec
->safe_push (xstrdup (optname
));
1199 /* Add the given dumpname/out_ptr pair to this context's list of requested
1202 Implements the post-error-checking part of
1203 gcc_jit_context_enable_dump. */
1206 recording::context::enable_dump (const char *dumpname
,
1210 gcc_assert (dumpname
);
1211 gcc_assert (out_ptr
);
1213 d
.m_dumpname
= dumpname
;
1214 d
.m_out_ptr
= out_ptr
;
1216 m_requested_dumps
.safe_push (d
);
1219 /* Validate this context, and if it passes, compile it to memory
1222 Implements the post-error-checking part of
1223 gcc_jit_context_compile. */
1226 recording::context::compile ()
1228 JIT_LOG_SCOPE (get_logger ());
1234 if (errors_occurred ())
1237 /* Set up a compile_to_memory playback context. */
1238 ::gcc::jit::playback::compile_to_memory
replayer (this);
1241 replayer
.compile ();
1243 /* Get the jit::result (or NULL) from the
1244 compile_to_memory playback context. */
1245 return replayer
.get_result_obj ();
1248 /* Validate this context, and if it passes, compile it to a file
1251 Implements the post-error-checking part of
1252 gcc_jit_context_compile_to_file. */
1255 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind
,
1256 const char *output_path
)
1258 JIT_LOG_SCOPE (get_logger ());
1264 if (errors_occurred ())
1267 /* Set up a compile_to_file playback context. */
1268 ::gcc::jit::playback::compile_to_file
replayer (this,
1273 replayer
.compile ();
1276 /* Format the given error using printf's conventions, print
1277 it to stderr, and add it to the context. */
1280 recording::context::add_error (location
*loc
, const char *fmt
, ...)
1284 add_error_va (loc
, fmt
, ap
);
1288 /* Format the given error using printf's conventions, print
1289 it to stderr, and add it to the context. */
1292 recording::context::add_error_va (location
*loc
, const char *fmt
, va_list ap
)
1299 JIT_LOG_SCOPE (get_logger ());
1301 len
= vasprintf (&malloced_msg
, fmt
, ap
);
1302 if (malloced_msg
== NULL
|| len
< 0)
1304 errmsg
= "out of memory generating error message";
1305 has_ownership
= false;
1309 errmsg
= malloced_msg
;
1310 has_ownership
= true;
1313 get_logger ()->log ("error %i: %s", m_error_count
, errmsg
);
1315 const char *ctxt_progname
=
1316 get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
1318 ctxt_progname
= "libgccjit.so";
1321 fprintf (stderr
, "%s: %s: error: %s\n",
1323 loc
->get_debug_string (),
1326 fprintf (stderr
, "%s: error: %s\n",
1332 m_first_error_str
= const_cast <char *> (errmsg
);
1333 m_owns_first_error_str
= has_ownership
;
1336 if (m_owns_last_error_str
)
1337 if (m_last_error_str
!= m_first_error_str
)
1338 free (m_last_error_str
);
1339 m_last_error_str
= const_cast <char *> (errmsg
);
1340 m_owns_last_error_str
= has_ownership
;
1345 /* Get the message for the first error that occurred on this context, or
1346 NULL if no errors have occurred on it.
1348 Implements the post-error-checking part of
1349 gcc_jit_context_get_first_error. */
1352 recording::context::get_first_error () const
1354 return m_first_error_str
;
1357 /* Get the message for the last error that occurred on this context, or
1358 NULL if no errors have occurred on it.
1360 Implements the post-error-checking part of
1361 gcc_jit_context_get_last_error. */
1364 recording::context::get_last_error () const
1366 return m_last_error_str
;
1369 /* Lazily generate and record a recording::type representing an opaque
1370 struct named "FILE".
1372 For use if client code tries to dereference the result of
1373 get_type (GCC_JIT_TYPE_FILE_PTR). */
1376 recording::context::get_opaque_FILE_type ()
1379 m_FILE_type
= new_struct_type (NULL
, "FILE");
1383 /* Dump a C-like representation of the given context to the given path.
1384 If UPDATE_LOCATIONS is true, update the locations within the
1385 context's mementos to point to the dumpfile.
1387 Implements the post-error-checking part of
1388 gcc_jit_context_dump_to_file. */
1391 recording::context::dump_to_file (const char *path
, bool update_locations
)
1394 dump
d (*this, path
, update_locations
);
1396 /* Forward declaration of structs and unions. */
1398 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1400 d
.write ("%s;\n\n", st
->get_debug_string ());
1403 /* Content of structs, where set. */
1404 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1405 if (st
->get_fields ())
1407 st
->get_fields ()->write_to_dump (d
);
1413 FOR_EACH_VEC_ELT (m_globals
, i
, g
)
1415 g
->write_to_dump (d
);
1417 if (!m_globals
.is_empty ())
1421 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1423 fn
->write_to_dump (d
);
1427 static const char * const
1428 str_option_reproducer_strings
[GCC_JIT_NUM_STR_OPTIONS
] = {
1429 "GCC_JIT_STR_OPTION_PROGNAME"
1432 static const char * const
1433 int_option_reproducer_strings
[GCC_JIT_NUM_INT_OPTIONS
] = {
1434 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1437 static const char * const
1438 bool_option_reproducer_strings
[GCC_JIT_NUM_BOOL_OPTIONS
] = {
1439 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1440 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1441 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1442 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1443 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1444 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1445 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1446 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1449 static const char * const
1450 inner_bool_option_reproducer_strings
[NUM_INNER_BOOL_OPTIONS
] = {
1451 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1452 "gcc_jit_context_set_bool_use_external_driver"
1455 /* Write the current value of all options to the log file (if any). */
1458 recording::context::log_all_options () const
1465 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1466 log_str_option ((enum gcc_jit_str_option
)opt_idx
);
1468 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1469 log_int_option ((enum gcc_jit_int_option
)opt_idx
);
1471 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1472 log_bool_option ((enum gcc_jit_bool_option
)opt_idx
);
1473 for (opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1474 log_inner_bool_option ((enum inner_bool_option
)opt_idx
);
1477 /* Write the current value of the given string option to the
1478 log file (if any). */
1481 recording::context::log_str_option (enum gcc_jit_str_option opt
) const
1483 gcc_assert (opt
< GCC_JIT_NUM_STR_OPTIONS
);
1486 if (m_str_options
[opt
])
1488 str_option_reproducer_strings
[opt
],
1489 m_str_options
[opt
]);
1492 str_option_reproducer_strings
[opt
]);
1496 /* Write the current value of the given int option to the
1497 log file (if any). */
1500 recording::context::log_int_option (enum gcc_jit_int_option opt
) const
1502 gcc_assert (opt
< GCC_JIT_NUM_INT_OPTIONS
);
1505 int_option_reproducer_strings
[opt
],
1506 m_int_options
[opt
]);
1509 /* Write the current value of the given bool option to the
1510 log file (if any). */
1513 recording::context::log_bool_option (enum gcc_jit_bool_option opt
) const
1515 gcc_assert (opt
< GCC_JIT_NUM_BOOL_OPTIONS
);
1518 bool_option_reproducer_strings
[opt
],
1519 m_bool_options
[opt
] ? "true" : "false");
1522 /* Write the current value of the given "inner" bool option to the
1523 log file (if any). */
1526 recording::context::log_inner_bool_option (enum inner_bool_option opt
) const
1528 gcc_assert (opt
< NUM_INNER_BOOL_OPTIONS
);
1531 inner_bool_option_reproducer_strings
[opt
],
1532 m_inner_bool_options
[opt
] ? "true" : "false");
1535 /* Write C source code to PATH that attempts to replay the API
1536 calls made to this context (and its parents), for use in
1537 minimizing test cases for libgccjit.
1539 Implements the post-error-checking part of
1540 gcc_jit_context_dump_reproducer_to_file. */
1543 recording::context::dump_reproducer_to_file (const char *path
)
1545 JIT_LOG_SCOPE (get_logger ());
1546 reproducer
r (*this, path
);
1548 /* Generate the "ancestry" of this context, as a list. */
1549 auto_vec
<context
*> ascending_contexts
;
1550 for (context
*ctxt
= this; ctxt
; ctxt
= ctxt
->m_parent_ctxt
)
1551 ascending_contexts
.safe_push (ctxt
);
1553 /* Reverse the list, giving a list of contexts from
1554 top-most parent context down through to youngest child context.
1555 We will use this list as the parameters of the functions in
1556 our generated file. */
1557 unsigned num_ctxts
= ascending_contexts
.length ();
1558 auto_vec
<context
*> contexts (num_ctxts
);
1559 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1560 contexts
.safe_push (ascending_contexts
[num_ctxts
- (i
+ 1)]);
1562 /* contexts[0] should be the top-level context. */
1563 gcc_assert (contexts
[0]);
1564 gcc_assert (contexts
[0]->m_toplevel_ctxt
== contexts
[0]);
1566 /* The final element in contexts should be "this". */
1567 gcc_assert (contexts
[contexts
.length () - 1] == this);
1568 gcc_assert (contexts
[contexts
.length () - 1]->m_toplevel_ctxt
1571 r
.write ("/* This code was autogenerated by"
1572 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1573 print_version (r
.get_file (), " ", false);
1575 r
.write ("#include <libgccjit.h>\n\n");
1576 r
.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1577 r
.write ("static void\nset_options (");
1578 r
.write_params (contexts
);
1580 r
.write ("static void\ncreate_code (");
1581 r
.write_params (contexts
);
1583 r
.write ("int\nmain (int argc, const char **argv)\n");
1585 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1586 r
.write (" gcc_jit_context *%s;\n",
1587 r
.get_identifier (contexts
[i
]));
1588 r
.write (" gcc_jit_result *result;\n"
1591 /* Create the contexts.
1592 The top-level context is acquired from a clean slate, the others as
1593 children of the prior context. */
1594 r
.write (" %s = gcc_jit_context_acquire ();\n",
1595 r
.get_identifier (contexts
[0]));
1596 for (unsigned i
= 1; i
< num_ctxts
; i
++)
1597 r
.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1598 r
.get_identifier (contexts
[i
]),
1599 r
.get_identifier (contexts
[i
- 1]));
1600 r
.write (" set_options (");
1601 r
.write_args (contexts
);
1603 r
.write (" create_code (");
1604 r
.write_args (contexts
);
1607 r
.write (" result = gcc_jit_context_compile (%s);\n",
1608 r
.get_identifier (this));
1610 for (unsigned i
= num_ctxts
; i
> 0; i
--)
1611 r
.write (" gcc_jit_context_release (%s);\n",
1612 r
.get_identifier (contexts
[i
- 1]));
1614 r
.write (" gcc_jit_result_release (result);\n"
1618 /* Define (char *) variables for use in calls to
1619 gcc_jit_context_enable_dump. */
1620 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1622 if (m_requested_dumps
.length ())
1624 r
.write ("/* Requested dumps for %s. */\n",
1625 r
.get_identifier (contexts
[ctxt_idx
]));
1626 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1627 r
.write ("static char *dump_%p;\n",
1628 (void *)&m_requested_dumps
[i
]);
1633 /* Write out values of options. */
1634 r
.write ("static void\nset_options (");
1635 r
.write_params (contexts
);
1637 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1642 r
.write (" /* Set options for %s. */\n",
1643 r
.get_identifier (contexts
[ctxt_idx
]));
1645 r
.write (" /* String options. */\n");
1646 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1648 r
.write (" gcc_jit_context_set_str_option (%s,\n"
1650 r
.get_identifier (contexts
[ctxt_idx
]),
1651 str_option_reproducer_strings
[opt_idx
]);
1652 if (m_str_options
[opt_idx
])
1653 r
.write (" \"%s\");\n",
1654 m_str_options
[opt_idx
]);
1656 r
.write (" NULL);\n");
1658 r
.write (" /* Int options. */\n");
1659 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1660 r
.write (" gcc_jit_context_set_int_option (%s,\n"
1663 r
.get_identifier (contexts
[ctxt_idx
]),
1664 int_option_reproducer_strings
[opt_idx
],
1665 m_int_options
[opt_idx
]);
1666 r
.write (" /* Boolean options. */\n");
1667 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1668 r
.write (" gcc_jit_context_set_bool_option (%s,\n"
1671 r
.get_identifier (contexts
[ctxt_idx
]),
1672 bool_option_reproducer_strings
[opt_idx
],
1673 m_bool_options
[opt_idx
]);
1674 for (int opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1675 r
.write (" %s (%s, %i);\n",
1676 inner_bool_option_reproducer_strings
[opt_idx
],
1677 r
.get_identifier (contexts
[ctxt_idx
]),
1678 m_inner_bool_options
[opt_idx
]);
1680 if (!m_command_line_options
.is_empty ())
1684 r
.write (" /* User-provided command-line options. */\n");
1685 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1686 r
.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1687 r
.get_identifier (contexts
[ctxt_idx
]),
1691 if (m_requested_dumps
.length ())
1693 r
.write (" /* Requested dumps. */\n");
1694 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1695 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1697 r
.write (" gcc_jit_context_enable_dump (%s,\n"
1700 r
.get_identifier (contexts
[ctxt_idx
]),
1701 m_requested_dumps
[i
].m_dumpname
,
1702 (void *)&m_requested_dumps
[i
]);
1708 r
.write ("static void\ncreate_code (");
1709 r
.write_params (contexts
);
1712 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1719 r
.write (" /* Replay of API calls for %s. */\n",
1720 r
.get_identifier (contexts
[ctxt_idx
]));
1721 FOR_EACH_VEC_ELT (contexts
[ctxt_idx
]->m_mementos
, i
, m
)
1722 m
->write_reproducer (r
);
1727 /* Copy the requested dumps within this context and all ancestors into
1731 recording::context::get_all_requested_dumps (vec
<recording::requested_dump
> *out
)
1734 m_parent_ctxt
->get_all_requested_dumps (out
);
1736 out
->reserve (m_requested_dumps
.length ());
1737 out
->splice (m_requested_dumps
);
1740 /* This is a pre-compilation check for the context (and any parents).
1742 Detect errors within the context, adding errors if any are found. */
1745 recording::context::validate ()
1747 JIT_LOG_SCOPE (get_logger ());
1750 m_parent_ctxt
->validate ();
1754 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1758 /* The implementation of class gcc::jit::recording::memento. */
1760 /* Get a (const char *) debug description of the given memento, by
1761 calling the pure-virtual make_debug_string hook, caching the
1764 It is intended that this should only be called in debugging and
1765 error-handling paths, so this doesn't need to be particularly
1769 recording::memento::get_debug_string ()
1771 if (!m_debug_string
)
1772 m_debug_string
= make_debug_string ();
1773 return m_debug_string
->c_str ();
1776 /* Default implementation of recording::memento::write_to_dump, writing
1777 an indented form of the memento's debug string to the dump. */
1780 recording::memento::write_to_dump (dump
&d
)
1782 d
.write(" %s\n", get_debug_string ());
1785 /* The implementation of class gcc::jit::recording::string. */
1787 /* Constructor for gcc::jit::recording::string::string, allocating a
1788 copy of the given text using new char[]. */
1790 recording::string::string (context
*ctxt
, const char *text
)
1793 m_len
= strlen (text
);
1794 m_buffer
= new char[m_len
+ 1];
1795 strcpy (m_buffer
, text
);
1798 /* Destructor for gcc::jit::recording::string::string. */
1800 recording::string::~string ()
1805 /* Function for making gcc::jit::recording::string instances on a
1806 context via printf-style formatting.
1808 It is intended that this should only be called in debugging and
1809 error-handling paths, so this doesn't need to be particularly
1810 optimized, hence the double-copy of the string is acceptable. */
1813 recording::string::from_printf (context
*ctxt
, const char *fmt
, ...)
1818 recording::string
*result
;
1821 len
= vasprintf (&buf
, fmt
, ap
);
1824 if (buf
== NULL
|| len
< 0)
1826 ctxt
->add_error (NULL
, "malloc failure");
1830 result
= ctxt
->new_string (buf
);
1835 /* Implementation of recording::memento::make_debug_string for strings,
1836 wrapping the given string in quotes and escaping as necessary. */
1839 recording::string::make_debug_string ()
1841 /* Hack to avoid infinite recursion into strings when logging all
1842 mementos: don't re-escape strings: */
1843 if (m_buffer
[0] == '"')
1846 /* Wrap in quotes and do escaping etc */
1848 size_t sz
= (1 /* opening quote */
1849 + (m_len
* 2) /* each char might get escaped */
1850 + 1 /* closing quote */
1851 + 1); /* nil termintator */
1852 char *tmp
= new char[sz
];
1855 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1856 APPEND('"'); /* opening quote */
1857 for (size_t i
= 0; i
< m_len
; i
++)
1859 char ch
= m_buffer
[i
];
1860 if (ch
== '\t' || ch
== '\n' || ch
== '\\' || ch
== '"')
1864 APPEND('"'); /* closing quote */
1866 tmp
[len
] = '\0'; /* nil termintator */
1868 string
*result
= m_ctxt
->new_string (tmp
);
1874 /* Implementation of recording::memento::write_reproducer for strings. */
1877 recording::string::write_reproducer (reproducer
&)
1882 /* The implementation of class gcc::jit::recording::location. */
1884 /* Implementation of recording::memento::replay_into for locations.
1886 Create a new playback::location and store it into the
1887 recording::location's m_playback_obj field. */
1890 recording::location::replay_into (replayer
*r
)
1892 m_playback_obj
= r
->new_location (this,
1893 m_filename
->c_str (),
1898 /* Implementation of recording::memento::make_debug_string for locations,
1899 turning them into the usual form:
1900 FILENAME:LINE:COLUMN
1901 like we do when emitting diagnostics. */
1904 recording::location::make_debug_string ()
1906 return string::from_printf (m_ctxt
,
1908 m_filename
->c_str (), m_line
, m_column
);
1911 /* Implementation of recording::memento::write_reproducer for locations. */
1914 recording::location::write_reproducer (reproducer
&r
)
1916 const char *id
= r
.make_identifier (this, "loc");
1917 r
.write (" gcc_jit_location *%s =\n"
1918 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1919 " %s, /* const char *filename */\n"
1920 " %i, /* int line */\n"
1921 " %i);/* int column */\n",
1923 r
.get_identifier (get_context ()),
1924 m_filename
->get_debug_string (),
1928 /* The implementation of class gcc::jit::recording::type. */
1930 /* Given a type T, get the type T*.
1932 If this doesn't already exist, generate a new memento_of_get_pointer
1933 instance and add it to this type's context's list of mementos.
1935 Otherwise, use the cached type.
1937 Implements the post-error-checking part of
1938 gcc_jit_type_get_pointer. */
1941 recording::type::get_pointer ()
1943 if (!m_pointer_to_this_type
)
1945 m_pointer_to_this_type
= new memento_of_get_pointer (this);
1946 m_ctxt
->record (m_pointer_to_this_type
);
1948 return m_pointer_to_this_type
;
1951 /* Given a type T, get the type const T.
1953 Implements the post-error-checking part of
1954 gcc_jit_type_get_const. */
1957 recording::type::get_const ()
1959 recording::type
*result
= new memento_of_get_const (this);
1960 m_ctxt
->record (result
);
1964 /* Given a type T, get the type volatile T.
1966 Implements the post-error-checking part of
1967 gcc_jit_type_get_volatile. */
1970 recording::type::get_volatile ()
1972 recording::type
*result
= new memento_of_get_volatile (this);
1973 m_ctxt
->record (result
);
1977 /* Given a type, get an aligned version of the type.
1979 Implements the post-error-checking part of
1980 gcc_jit_type_get_aligned. */
1983 recording::type::get_aligned (size_t alignment_in_bytes
)
1985 recording::type
*result
1986 = new memento_of_get_aligned (this, alignment_in_bytes
);
1987 m_ctxt
->record (result
);
1991 /* Given a type, get a vector version of the type.
1993 Implements the post-error-checking part of
1994 gcc_jit_type_get_vector. */
1997 recording::type::get_vector (size_t num_units
)
1999 recording::type
*result
2000 = new memento_of_get_vector (this, num_units
);
2001 m_ctxt
->record (result
);
2006 recording::type::access_as_type (reproducer
&r
)
2008 return r
.get_identifier (this);
2011 /* Implementation of pure virtual hook recording::type::dereference for
2012 recording::memento_of_get_type. */
2015 recording::memento_of_get_type::dereference ()
2019 default: gcc_unreachable ();
2021 case GCC_JIT_TYPE_VOID
:
2024 case GCC_JIT_TYPE_VOID_PTR
:
2025 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
2027 case GCC_JIT_TYPE_BOOL
:
2028 case GCC_JIT_TYPE_CHAR
:
2029 case GCC_JIT_TYPE_SIGNED_CHAR
:
2030 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2031 case GCC_JIT_TYPE_SHORT
:
2032 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2033 case GCC_JIT_TYPE_INT
:
2034 case GCC_JIT_TYPE_UNSIGNED_INT
:
2035 case GCC_JIT_TYPE_LONG
:
2036 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2037 case GCC_JIT_TYPE_LONG_LONG
:
2038 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2039 case GCC_JIT_TYPE_FLOAT
:
2040 case GCC_JIT_TYPE_DOUBLE
:
2041 case GCC_JIT_TYPE_LONG_DOUBLE
:
2042 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2043 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2044 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2045 /* Not a pointer: */
2048 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2049 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
2051 case GCC_JIT_TYPE_SIZE_T
:
2052 /* Not a pointer: */
2055 case GCC_JIT_TYPE_FILE_PTR
:
2056 /* Give the client code back an opaque "struct FILE". */
2057 return m_ctxt
->get_opaque_FILE_type ();
2061 /* Implementation of pure virtual hook recording::type::is_int for
2062 recording::memento_of_get_type. */
2065 recording::memento_of_get_type::is_int () const
2069 default: gcc_unreachable ();
2071 case GCC_JIT_TYPE_VOID
:
2074 case GCC_JIT_TYPE_VOID_PTR
:
2077 case GCC_JIT_TYPE_BOOL
:
2080 case GCC_JIT_TYPE_CHAR
:
2081 case GCC_JIT_TYPE_SIGNED_CHAR
:
2082 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2083 case GCC_JIT_TYPE_SHORT
:
2084 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2085 case GCC_JIT_TYPE_INT
:
2086 case GCC_JIT_TYPE_UNSIGNED_INT
:
2087 case GCC_JIT_TYPE_LONG
:
2088 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2089 case GCC_JIT_TYPE_LONG_LONG
:
2090 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2093 case GCC_JIT_TYPE_FLOAT
:
2094 case GCC_JIT_TYPE_DOUBLE
:
2095 case GCC_JIT_TYPE_LONG_DOUBLE
:
2098 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2101 case GCC_JIT_TYPE_SIZE_T
:
2104 case GCC_JIT_TYPE_FILE_PTR
:
2107 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2108 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2109 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2114 /* Implementation of pure virtual hook recording::type::is_float for
2115 recording::memento_of_get_type. */
2118 recording::memento_of_get_type::is_float () const
2122 default: gcc_unreachable ();
2124 case GCC_JIT_TYPE_VOID
:
2127 case GCC_JIT_TYPE_VOID_PTR
:
2130 case GCC_JIT_TYPE_BOOL
:
2133 case GCC_JIT_TYPE_CHAR
:
2134 case GCC_JIT_TYPE_SIGNED_CHAR
:
2135 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2136 case GCC_JIT_TYPE_SHORT
:
2137 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2138 case GCC_JIT_TYPE_INT
:
2139 case GCC_JIT_TYPE_UNSIGNED_INT
:
2140 case GCC_JIT_TYPE_LONG
:
2141 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2142 case GCC_JIT_TYPE_LONG_LONG
:
2143 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2146 case GCC_JIT_TYPE_FLOAT
:
2147 case GCC_JIT_TYPE_DOUBLE
:
2148 case GCC_JIT_TYPE_LONG_DOUBLE
:
2151 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2154 case GCC_JIT_TYPE_SIZE_T
:
2157 case GCC_JIT_TYPE_FILE_PTR
:
2160 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2161 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2162 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2167 /* Implementation of pure virtual hook recording::type::is_bool for
2168 recording::memento_of_get_type. */
2171 recording::memento_of_get_type::is_bool () const
2175 default: gcc_unreachable ();
2177 case GCC_JIT_TYPE_VOID
:
2180 case GCC_JIT_TYPE_VOID_PTR
:
2183 case GCC_JIT_TYPE_BOOL
:
2186 case GCC_JIT_TYPE_CHAR
:
2187 case GCC_JIT_TYPE_SIGNED_CHAR
:
2188 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2189 case GCC_JIT_TYPE_SHORT
:
2190 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2191 case GCC_JIT_TYPE_INT
:
2192 case GCC_JIT_TYPE_UNSIGNED_INT
:
2193 case GCC_JIT_TYPE_LONG
:
2194 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2195 case GCC_JIT_TYPE_LONG_LONG
:
2196 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2199 case GCC_JIT_TYPE_FLOAT
:
2200 case GCC_JIT_TYPE_DOUBLE
:
2201 case GCC_JIT_TYPE_LONG_DOUBLE
:
2204 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2207 case GCC_JIT_TYPE_SIZE_T
:
2210 case GCC_JIT_TYPE_FILE_PTR
:
2213 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2214 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2215 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2220 /* Implementation of pure virtual hook recording::memento::replay_into
2221 for recording::memento_of_get_type. */
2224 recording::memento_of_get_type::replay_into (replayer
*r
)
2226 set_playback_obj (r
->get_type (m_kind
));
2229 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2231 /* Descriptive strings for each of enum gcc_jit_types. */
2233 static const char * const get_type_strings
[] = {
2234 "void", /* GCC_JIT_TYPE_VOID */
2235 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2237 "bool", /* GCC_JIT_TYPE_BOOL */
2239 "char", /* GCC_JIT_TYPE_CHAR */
2240 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2241 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2243 "short", /* GCC_JIT_TYPE_SHORT */
2244 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2246 "int", /* GCC_JIT_TYPE_INT */
2247 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2249 "long", /* GCC_JIT_TYPE_LONG */
2250 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2252 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2253 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2255 "float", /* GCC_JIT_TYPE_FLOAT */
2256 "double", /* GCC_JIT_TYPE_DOUBLE */
2257 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2259 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2261 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2263 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2265 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2266 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2267 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2271 /* Implementation of recording::memento::make_debug_string for
2272 results of get_type, using a simple table of type names. */
2275 recording::memento_of_get_type::make_debug_string ()
2277 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
2280 static const char * const get_type_enum_strings
[] = {
2281 "GCC_JIT_TYPE_VOID",
2282 "GCC_JIT_TYPE_VOID_PTR",
2283 "GCC_JIT_TYPE_BOOL",
2284 "GCC_JIT_TYPE_CHAR",
2285 "GCC_JIT_TYPE_SIGNED_CHAR",
2286 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2287 "GCC_JIT_TYPE_SHORT",
2288 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2290 "GCC_JIT_TYPE_UNSIGNED_INT",
2291 "GCC_JIT_TYPE_LONG",
2292 "GCC_JIT_TYPE_UNSIGNED_LONG",
2293 "GCC_JIT_TYPE_LONG_LONG",
2294 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2295 "GCC_JIT_TYPE_FLOAT",
2296 "GCC_JIT_TYPE_DOUBLE",
2297 "GCC_JIT_TYPE_LONG_DOUBLE",
2298 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2299 "GCC_JIT_TYPE_SIZE_T",
2300 "GCC_JIT_TYPE_FILE_PTR",
2301 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2302 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2303 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2307 recording::memento_of_get_type::write_reproducer (reproducer
&r
)
2309 const char *id
= r
.make_identifier (this, "type");
2310 r
.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2312 r
.get_identifier (get_context ()),
2313 get_type_enum_strings
[m_kind
]);
2316 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2318 /* Override of default implementation of
2319 recording::type::accepts_writes_from for get_pointer.
2321 Require a pointer type, and allowing writes to
2322 (const T *) from a (T*), but not the other way around. */
2325 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
2327 /* Must be a pointer type: */
2328 type
*rtype_points_to
= rtype
->is_pointer ();
2329 if (!rtype_points_to
)
2332 /* It's OK to assign to a (const T *) from a (T *). */
2333 return m_other_type
->unqualified ()
2334 ->accepts_writes_from (rtype_points_to
);
2337 /* Implementation of pure virtual hook recording::memento::replay_into
2338 for recording::memento_of_get_pointer. */
2341 recording::memento_of_get_pointer::replay_into (replayer
*)
2343 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
2346 /* Implementation of recording::memento::make_debug_string for
2347 results of get_pointer, adding " *" to the underlying type,
2348 with special-casing to handle function pointer types. */
2351 recording::memento_of_get_pointer::make_debug_string ()
2353 /* Special-case function pointer types, to put the "*" in parens between
2354 the return type and the params (for one level of dereferencing, at
2356 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2357 return fn_type
->make_debug_string_with_ptr ();
2359 return string::from_printf (m_ctxt
,
2360 "%s *", m_other_type
->get_debug_string ());
2363 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2366 recording::memento_of_get_pointer::write_reproducer (reproducer
&r
)
2368 /* We need to special-case function pointer types; see the notes in
2369 recording::function_type::write_deferred_reproducer. */
2370 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2372 fn_type
->write_deferred_reproducer (r
, this);
2376 const char *id
= r
.make_identifier (this, "type");
2377 r
.write (" gcc_jit_type *%s =\n"
2378 " gcc_jit_type_get_pointer (%s);\n",
2380 r
.get_identifier_as_type (m_other_type
));
2383 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2385 /* Implementation of pure virtual hook recording::memento::replay_into
2386 for recording::memento_of_get_const. */
2389 recording::memento_of_get_const::replay_into (replayer
*)
2391 set_playback_obj (m_other_type
->playback_type ()->get_const ());
2394 /* Implementation of recording::memento::make_debug_string for
2395 results of get_const, prepending "const ". */
2398 recording::memento_of_get_const::make_debug_string ()
2400 return string::from_printf (m_ctxt
,
2401 "const %s", m_other_type
->get_debug_string ());
2404 /* Implementation of recording::memento::write_reproducer for const types. */
2407 recording::memento_of_get_const::write_reproducer (reproducer
&r
)
2409 const char *id
= r
.make_identifier (this, "type");
2410 r
.write (" gcc_jit_type *%s =\n"
2411 " gcc_jit_type_get_const (%s);\n",
2413 r
.get_identifier_as_type (m_other_type
));
2416 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2418 /* Implementation of pure virtual hook recording::memento::replay_into
2419 for recording::memento_of_get_volatile. */
2422 recording::memento_of_get_volatile::replay_into (replayer
*)
2424 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
2427 /* Implementation of recording::memento::make_debug_string for
2428 results of get_volatile, prepending "volatile ". */
2431 recording::memento_of_get_volatile::make_debug_string ()
2433 return string::from_printf (m_ctxt
,
2434 "volatile %s", m_other_type
->get_debug_string ());
2437 /* Implementation of recording::memento::write_reproducer for volatile
2441 recording::memento_of_get_volatile::write_reproducer (reproducer
&r
)
2443 const char *id
= r
.make_identifier (this, "type");
2444 r
.write (" gcc_jit_type *%s =\n"
2445 " gcc_jit_type_get_volatile (%s);\n",
2447 r
.get_identifier_as_type (m_other_type
));
2450 /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
2452 /* Implementation of pure virtual hook recording::memento::replay_into
2453 for recording::memento_of_get_aligned. */
2456 recording::memento_of_get_aligned::replay_into (replayer
*)
2459 (m_other_type
->playback_type ()->get_aligned (m_alignment_in_bytes
));
2462 /* Implementation of recording::memento::make_debug_string for
2463 results of get_aligned. */
2466 recording::memento_of_get_aligned::make_debug_string ()
2468 return string::from_printf (m_ctxt
,
2469 "%s __attribute__((aligned(%zi)))",
2470 m_other_type
->get_debug_string (),
2471 m_alignment_in_bytes
);
2474 /* Implementation of recording::memento::write_reproducer for aligned
2478 recording::memento_of_get_aligned::write_reproducer (reproducer
&r
)
2480 const char *id
= r
.make_identifier (this, "type");
2481 r
.write (" gcc_jit_type *%s =\n"
2482 " gcc_jit_type_get_aligned (%s, %zi);\n",
2484 r
.get_identifier_as_type (m_other_type
),
2485 m_alignment_in_bytes
);
2488 /* The implementation of class gcc::jit::recording::memento_of_get_vector. */
2490 /* Implementation of pure virtual hook recording::memento::replay_into
2491 for recording::memento_of_get_vector. */
2494 recording::memento_of_get_vector::replay_into (replayer
*)
2497 (m_other_type
->playback_type ()->get_vector (m_num_units
));
2500 /* Implementation of recording::memento::make_debug_string for
2501 results of get_vector. */
2504 recording::memento_of_get_vector::make_debug_string ()
2506 return string::from_printf
2508 "%s __attribute__((vector_size(sizeof (%s) * %zi)))",
2509 m_other_type
->get_debug_string (),
2510 m_other_type
->get_debug_string (),
2514 /* Implementation of recording::memento::write_reproducer for volatile
2518 recording::memento_of_get_vector::write_reproducer (reproducer
&r
)
2520 const char *id
= r
.make_identifier (this, "type");
2521 r
.write (" gcc_jit_type *%s =\n"
2522 " gcc_jit_type_get_vector (%s, %zi);\n",
2524 r
.get_identifier_as_type (m_other_type
),
2528 /* The implementation of class gcc::jit::recording::array_type */
2530 /* Implementation of pure virtual hook recording::type::dereference for
2531 recording::array_type. */
2534 recording::array_type::dereference ()
2536 return m_element_type
;
2539 /* Implementation of pure virtual hook recording::memento::replay_into
2540 for recording::array_type. */
2543 recording::array_type::replay_into (replayer
*r
)
2545 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
2546 m_element_type
->playback_type (),
2550 /* Implementation of recording::memento::make_debug_string for
2551 results of new_array_type. */
2554 recording::array_type::make_debug_string ()
2556 return string::from_printf (m_ctxt
,
2558 m_element_type
->get_debug_string (),
2562 /* Implementation of recording::memento::write_reproducer for array
2566 recording::array_type::write_reproducer (reproducer
&r
)
2568 const char *id
= r
.make_identifier (this, "array_type");
2569 r
.write (" gcc_jit_type *%s =\n"
2570 " gcc_jit_context_new_array_type (%s,\n"
2571 " %s, /* gcc_jit_location *loc */\n"
2572 " %s, /* gcc_jit_type *element_type */\n"
2573 " %i); /* int num_elements */\n",
2575 r
.get_identifier (get_context ()),
2576 r
.get_identifier (m_loc
),
2577 r
.get_identifier_as_type (m_element_type
),
2581 /* The implementation of class gcc::jit::recording::function_type */
2583 /* Constructor for gcc::jit::recording::function_type. */
2585 recording::function_type::function_type (context
*ctxt
,
2591 m_return_type (return_type
),
2593 m_is_variadic (is_variadic
)
2595 for (int i
= 0; i
< num_params
; i
++)
2596 m_param_types
.safe_push (param_types
[i
]);
2599 /* Implementation of pure virtual hook recording::type::dereference for
2600 recording::function_type. */
2603 recording::function_type::dereference ()
2608 /* Implementation of pure virtual hook recording::memento::replay_into
2609 for recording::function_type. */
2612 recording::function_type::replay_into (replayer
*r
)
2614 /* Convert m_param_types to a vec of playback type. */
2615 auto_vec
<playback::type
*> param_types
;
2617 recording::type
*type
;
2618 param_types
.create (m_param_types
.length ());
2619 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
2620 param_types
.safe_push (type
->playback_type ());
2622 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
2627 /* Special-casing for make_debug_string for get_pointer results for
2628 handling (one level) of pointers to functions. */
2631 recording::function_type::make_debug_string_with_ptr ()
2633 return make_debug_string_with ("(*) ");
2636 /* Implementation of recording::memento::make_debug_string for
2637 results of new_function_type. */
2640 recording::function_type::make_debug_string ()
2642 return make_debug_string_with ("");
2645 /* Build a debug string representation of the form:
2647 RESULT_TYPE INSERT (PARAM_TYPES)
2649 for use when handling 0 and 1 level of indirection to this
2653 recording::function_type::make_debug_string_with (const char *insert
)
2655 /* First, build a buffer for the arguments. */
2656 /* Calculate length of said buffer. */
2657 size_t sz
= 1; /* nil terminator */
2658 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2660 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
2661 sz
+= 2; /* ", " separator */
2664 sz
+= 5; /* ", ..." separator and ellipsis */
2666 /* Now allocate and populate the buffer. */
2667 char *argbuf
= new char[sz
];
2670 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2672 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
2673 len
+= strlen (m_param_types
[i
]->get_debug_string ());
2674 if (i
+ 1 < m_param_types
.length ())
2676 strcpy (argbuf
+ len
, ", ");
2682 if (m_param_types
.length ())
2684 strcpy (argbuf
+ len
, ", ");
2687 strcpy (argbuf
+ len
, "...");
2692 /* ...and use it to get the string for the call as a whole. */
2693 string
*result
= string::from_printf (m_ctxt
,
2695 m_return_type
->get_debug_string (),
2704 /* Implementation of recording::memento::write_reproducer for function
2708 recording::function_type::write_reproducer (reproducer
&)
2710 /* see notes below. */
2713 /* There's a get_pointer within context::new_function_ptr_type:
2714 the type received by client code isn't the memento for the
2715 function_type, but instead the result of get_pointer on it.
2717 Hence we can't directly write a reproducer that gives function_type.
2718 Instead we special-case things within get_pointer, detecting this
2719 case, calling the following function. */
2722 recording::function_type::write_deferred_reproducer (reproducer
&r
,
2725 gcc_assert (ptr_type
);
2726 r
.make_identifier (this, "function_type");
2727 const char *ptr_id
= r
.make_identifier (ptr_type
, "ptr_to");
2728 const char *param_types_id
= r
.make_tmp_identifier ("params_for", this);
2729 r
.write (" gcc_jit_type *%s[%i] = {\n",
2731 m_param_types
.length ());
2734 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
2735 r
.write (" %s,\n", r
.get_identifier_as_type (param_type
));
2737 r
.write (" gcc_jit_type *%s =\n"
2738 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2739 " %s, /* gcc_jit_location *loc */\n"
2740 " %s, /* gcc_jit_type *return_type */\n"
2741 " %i, /* int num_params */\n"
2742 " %s, /* gcc_jit_type **param_types */\n"
2743 " %i); /* int is_variadic */\n",
2745 r
.get_identifier (get_context ()),
2746 "NULL", /* location is not stored */
2747 r
.get_identifier_as_type (m_return_type
),
2748 m_param_types
.length (),
2753 /* The implementation of class gcc::jit::recording::field. */
2755 /* Implementation of pure virtual hook recording::memento::replay_into
2756 for recording::field. */
2759 recording::field::replay_into (replayer
*r
)
2761 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
2762 m_type
->playback_type (),
2763 playback_string (m_name
)));
2766 /* Override the default implementation of
2767 recording::memento::write_to_dump. Dump each field
2768 by dumping a line of the form:
2770 so that we can build up a struct/union field-byfield. */
2773 recording::field::write_to_dump (dump
&d
)
2775 d
.write (" %s %s;\n",
2776 m_type
->get_debug_string (),
2780 /* Implementation of recording::memento::make_debug_string for
2781 results of new_field. */
2784 recording::field::make_debug_string ()
2789 /* Implementation of recording::memento::write_reproducer for fields. */
2792 recording::field::write_reproducer (reproducer
&r
)
2794 const char *id
= r
.make_identifier (this, "field");
2795 r
.write(" gcc_jit_field *%s =\n"
2796 " gcc_jit_context_new_field (%s,\n"
2797 " %s, /* gcc_jit_location *loc */\n"
2798 " %s, /* gcc_jit_type *type, */\n"
2799 " %s); /* const char *name */\n",
2801 r
.get_identifier (get_context ()),
2802 r
.get_identifier (m_loc
),
2803 r
.get_identifier_as_type (m_type
),
2804 m_name
->get_debug_string ());
2807 /* The implementation of class gcc::jit::recording::compound_type */
2809 /* The constructor for gcc::jit::recording::compound_type. */
2811 recording::compound_type::compound_type (context
*ctxt
,
2821 /* Set the fields of a compound type.
2823 Implements the post-error-checking part of
2824 gcc_jit_struct_set_fields, and is also used by
2825 gcc_jit_context_new_union_type. */
2828 recording::compound_type::set_fields (location
*loc
,
2830 field
**field_array
)
2833 gcc_assert (NULL
== m_fields
);
2835 m_fields
= new fields (this, num_fields
, field_array
);
2836 m_ctxt
->record (m_fields
);
2839 /* Implementation of pure virtual hook recording::type::dereference for
2840 recording::compound_type. */
2843 recording::compound_type::dereference ()
2845 return NULL
; /* not a pointer */
2848 /* The implementation of class gcc::jit::recording::struct_. */
2850 /* The constructor for gcc::jit::recording::struct_. */
2852 recording::struct_::struct_ (context
*ctxt
,
2855 : compound_type (ctxt
, loc
, name
)
2859 /* Implementation of pure virtual hook recording::memento::replay_into
2860 for recording::struct_. */
2863 recording::struct_::replay_into (replayer
*r
)
2866 r
->new_compound_type (playback_location (r
, get_loc ()),
2867 get_name ()->c_str (),
2868 true /* is_struct */));
2872 recording::struct_::access_as_type (reproducer
&r
)
2874 return r
.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2875 r
.get_identifier (this));
2878 /* Implementation of recording::memento::make_debug_string for
2882 recording::struct_::make_debug_string ()
2884 return string::from_printf (m_ctxt
,
2885 "struct %s", get_name ()->c_str ());
2889 recording::struct_::write_reproducer (reproducer
&r
)
2891 const char *id
= r
.make_identifier (this, "struct");
2892 r
.write (" gcc_jit_struct *%s =\n"
2893 " gcc_jit_context_new_opaque_struct (%s,\n"
2894 " %s, /* gcc_jit_location *loc */\n"
2895 " %s); /* const char *name */\n",
2897 r
.get_identifier (get_context ()),
2898 r
.get_identifier (get_loc ()),
2899 get_name ()->get_debug_string ());
2902 /* The implementation of class gcc::jit::recording::union_. */
2904 /* The constructor for gcc::jit::recording::union_. */
2906 recording::union_::union_ (context
*ctxt
,
2909 : compound_type (ctxt
, loc
, name
)
2913 /* Implementation of pure virtual hook recording::memento::replay_into
2914 for recording::union_. */
2917 recording::union_::replay_into (replayer
*r
)
2920 r
->new_compound_type (playback_location (r
, get_loc ()),
2921 get_name ()->c_str (),
2922 false /* is_struct */));
2925 /* Implementation of recording::memento::make_debug_string for
2929 recording::union_::make_debug_string ()
2931 return string::from_printf (m_ctxt
,
2932 "union %s", get_name ()->c_str ());
2935 /* Implementation of recording::memento::write_reproducer for unions. */
2938 recording::union_::write_reproducer (reproducer
&r
)
2940 const char *id
= r
.make_identifier (this, "union");
2942 const char *fields_id
= r
.make_tmp_identifier ("fields_for", this);
2943 r
.write (" gcc_jit_field *%s[%i] = {\n",
2945 get_fields ()->length ());
2946 for (int i
= 0; i
< get_fields ()->length (); i
++)
2947 r
.write (" %s,\n", r
.get_identifier (get_fields ()->get_field (i
)));
2950 r
.write (" gcc_jit_type *%s =\n"
2951 " gcc_jit_context_new_union_type (%s,\n"
2952 " %s, /* gcc_jit_location *loc */\n"
2953 " %s, /* const char *name */\n"
2954 " %i, /* int num_fields */\n"
2955 " %s); /* gcc_jit_field **fields */\n",
2957 r
.get_identifier (get_context ()),
2958 r
.get_identifier (get_loc ()),
2959 get_name ()->get_debug_string (),
2960 get_fields ()->length (),
2964 /* The implementation of class gcc::jit::recording::fields. */
2966 /* The constructor for gcc::jit::recording::fields. */
2968 recording::fields::fields (compound_type
*struct_or_union
,
2971 : memento (struct_or_union
->m_ctxt
),
2972 m_struct_or_union (struct_or_union
),
2975 for (int i
= 0; i
< num_fields
; i
++)
2977 gcc_assert (fields
[i
]->get_container () == NULL
);
2978 fields
[i
]->set_container (m_struct_or_union
);
2979 m_fields
.safe_push (fields
[i
]);
2983 /* Implementation of pure virtual hook recording::memento::replay_into
2984 for recording::fields. */
2987 recording::fields::replay_into (replayer
*)
2989 auto_vec
<playback::field
*> playback_fields
;
2990 playback_fields
.create (m_fields
.length ());
2991 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
2992 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
2993 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
2996 /* Override the default implementation of
2997 recording::memento::write_to_dump by writing a union/struct
2998 declaration of this form:
3010 recording::fields::write_to_dump (dump
&d
)
3015 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
3016 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
3017 f
->write_to_dump (d
);
3021 /* Implementation of recording::memento::write_reproducer for the fields
3025 recording::fields::write_reproducer (reproducer
&r
)
3027 if (m_struct_or_union
)
3028 if (NULL
== m_struct_or_union
->dyn_cast_struct ())
3029 /* We have a union; the fields have already been written by
3030 union::write_reproducer. */
3033 const char *fields_id
= r
.make_identifier (this, "fields");
3034 r
.write (" gcc_jit_field *%s[%i] = {\n",
3036 m_fields
.length ());
3039 FOR_EACH_VEC_ELT (m_fields
, i
, field
)
3040 r
.write (" %s,\n", r
.get_identifier (field
));
3043 r
.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
3044 " %s, /* gcc_jit_location *loc */\n"
3045 " %i, /* int num_fields */\n"
3046 " %s); /* gcc_jit_field **fields */\n",
3047 r
.get_identifier (m_struct_or_union
),
3048 r
.get_identifier ((memento
*)NULL
),
3053 /* Implementation of recording::memento::make_debug_string for
3057 recording::fields::make_debug_string ()
3059 return string::from_printf (m_ctxt
,
3063 /* The implementation of class gcc::jit::recording::rvalue. */
3065 /* Create a recording::access_field_rvalue instance and add it to
3066 the rvalue's context's list of mementos.
3068 Implements the post-error-checking part of
3069 gcc_jit_rvalue_access_field. */
3072 recording::rvalue::access_field (recording::location
*loc
,
3075 recording::rvalue
*result
=
3076 new access_field_rvalue (m_ctxt
, loc
, this, field
);
3077 m_ctxt
->record (result
);
3081 /* Create a recording::dereference_field_rvalue instance and add it to
3082 the rvalue's context's list of mementos.
3084 Implements the post-error-checking part of
3085 gcc_jit_rvalue_dereference_field. */
3088 recording::rvalue::dereference_field (recording::location
*loc
,
3091 recording::lvalue
*result
=
3092 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
3093 m_ctxt
->record (result
);
3097 /* Create a recording::dereference_rvalue instance and add it to the
3098 rvalue's context's list of mementos.
3100 Implements the post-error-checking part of
3101 gcc_jit_rvalue_dereference. */
3104 recording::rvalue::dereference (recording::location
*loc
)
3106 recording::lvalue
*result
=
3107 new dereference_rvalue (m_ctxt
, loc
, this);
3108 m_ctxt
->record (result
);
3112 /* An rvalue visitor, for validating that every rvalue within an expression
3113 trees within "STMT" has the correct scope (e.g. no access to locals
3114 of a different function). */
3116 class rvalue_usage_validator
: public recording::rvalue_visitor
3119 rvalue_usage_validator (const char *api_funcname
,
3120 recording::context
*ctxt
,
3121 recording::statement
*stmt
);
3124 visit (recording::rvalue
*rvalue
) FINAL OVERRIDE
;
3127 const char *m_api_funcname
;
3128 recording::context
*m_ctxt
;
3129 recording::statement
*m_stmt
;
3132 /* The trivial constructor for rvalue_usage_validator. */
3134 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname
,
3135 recording::context
*ctxt
,
3136 recording::statement
*stmt
)
3137 : m_api_funcname (api_funcname
),
3143 /* Verify that the given rvalue is in the correct scope. */
3146 rvalue_usage_validator::visit (recording::rvalue
*rvalue
)
3148 gcc_assert (m_stmt
->get_block ());
3149 recording::function
*stmt_scope
= m_stmt
->get_block ()->get_function ();
3151 /* Most rvalues don't have a scope (only locals and params). */
3152 if (rvalue
->get_scope ())
3154 if (rvalue
->get_scope () != stmt_scope
)
3156 (rvalue
->get_loc (),
3158 " rvalue %s (type: %s)"
3159 " has scope limited to function %s"
3160 " but was used within function %s"
3161 " (in statement: %s)",
3163 rvalue
->get_debug_string (),
3164 rvalue
->get_type ()->get_debug_string (),
3165 rvalue
->get_scope ()->get_debug_string (),
3166 stmt_scope
->get_debug_string (),
3167 m_stmt
->get_debug_string ());
3171 if (rvalue
->dyn_cast_param ())
3173 (rvalue
->get_loc (),
3175 " param %s (type: %s)"
3176 " was used within function %s"
3177 " (in statement: %s)"
3178 " but is not associated with any function",
3180 rvalue
->get_debug_string (),
3181 rvalue
->get_type ()->get_debug_string (),
3182 stmt_scope
->get_debug_string (),
3183 m_stmt
->get_debug_string ());
3187 /* Verify that it's valid to use this rvalue (and all expressions
3188 in the tree below it) within the given statement.
3190 For example, we must reject attempts to use a local from one
3191 function within a different function here, or we'll get
3192 an ICE deep inside toplev::main. */
3195 recording::rvalue::verify_valid_within_stmt (const char *api_funcname
, statement
*s
)
3197 rvalue_usage_validator
v (api_funcname
,
3201 /* Verify that it's OK to use this rvalue within s. */
3204 /* Traverse the expression tree below "this", verifying all rvalues
3206 visit_children (&v
);
3209 /* Set the scope of this rvalue to be the given function. This can only
3210 be done once on a given rvalue. */
3213 recording::rvalue::set_scope (function
*scope
)
3216 gcc_assert (NULL
== m_scope
);
3221 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3223 Instances of rvalue don't need an upcast call. */
3226 recording::rvalue::access_as_rvalue (reproducer
&r
)
3228 return r
.get_identifier (this);
3231 /* Return a debug string for the given rvalue, wrapping it in parentheses
3232 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3233 stronger precedence that this rvalue's precedence.
3247 since MULT has strong precedence than PLUS and MINUS, whereas for:
3259 since PLUS has weaker precedence than MULT and DIVIDE. */
3262 recording::rvalue::get_debug_string_parens (enum precedence outer_prec
)
3264 enum precedence this_prec
= get_precedence ();
3266 /* If this_prec has stronger precedence than outer_prec, we don't
3267 need to wrap this in parens within the outer debug string.
3268 Stronger precedences occur earlier than weaker within the enum,
3269 so this is a less than test. Equal precedences don't need
3271 if (this_prec
<= outer_prec
)
3272 return get_debug_string();
3274 /* Otherwise, we need parentheses. */
3276 /* Lazily-build and cache m_parenthesized_string. */
3277 if (!m_parenthesized_string
)
3279 const char *debug_string
= get_debug_string ();
3280 m_parenthesized_string
= string::from_printf (get_context (),
3284 gcc_assert (m_parenthesized_string
);
3285 return m_parenthesized_string
->c_str ();
3289 /* The implementation of class gcc::jit::recording::lvalue. */
3291 /* Create a recording::new_access_field_of_lvalue instance and add it to
3292 the lvalue's context's list of mementos.
3294 Implements the post-error-checking part of
3295 gcc_jit_lvalue_access_field. */
3298 recording::lvalue::access_field (recording::location
*loc
,
3301 recording::lvalue
*result
=
3302 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
3303 m_ctxt
->record (result
);
3307 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3308 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3312 recording::lvalue::access_as_rvalue (reproducer
&r
)
3314 return r
.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3315 r
.get_identifier (this));
3318 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3319 Instances of lvalue don't need to be upcast. */
3322 recording::lvalue::access_as_lvalue (reproducer
&r
)
3324 return r
.get_identifier (this);
3327 /* Create a recording::get_address_of_lvalue instance and add it to
3328 the lvalue's context's list of mementos.
3330 Implements the post-error-checking part of
3331 gcc_jit_lvalue_get_address. */
3334 recording::lvalue::get_address (recording::location
*loc
)
3336 recording::rvalue
*result
=
3337 new get_address_of_lvalue (m_ctxt
, loc
, this);
3338 m_ctxt
->record (result
);
3342 /* The implementation of class gcc::jit::recording::param. */
3344 /* Implementation of pure virtual hook recording::memento::replay_into
3345 for recording::param. */
3348 recording::param::replay_into (replayer
*r
)
3350 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
3351 m_type
->playback_type (),
3355 /* Implementation of recording::rvalue::access_as_rvalue for params.
3356 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3360 recording::param::access_as_rvalue (reproducer
&r
)
3362 return r
.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3363 r
.get_identifier (this));
3366 /* Implementation of recording::lvalue::access_as_lvalue for params.
3367 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3371 recording::param::access_as_lvalue (reproducer
&r
)
3373 return r
.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3374 r
.get_identifier (this));
3377 /* Implementation of recording::memento::write_reproducer for params. */
3380 recording::param::write_reproducer (reproducer
&r
)
3382 const char *id
= r
.make_identifier (this, "param");
3383 r
.write (" gcc_jit_param *%s =\n"
3384 " gcc_jit_context_new_param (%s,\n"
3385 " %s, /* gcc_jit_location *loc */\n"
3386 " %s, /*gcc_jit_type *type */\n"
3387 " %s); /* const char *name */\n",
3389 r
.get_identifier (get_context ()),
3390 r
.get_identifier (m_loc
),
3391 r
.get_identifier_as_type (m_type
),
3392 m_name
->get_debug_string ());
3395 /* The implementation of class gcc::jit::recording::function. */
3397 /* gcc::jit::recording::function's constructor. */
3399 recording::function::function (context
*ctxt
,
3400 recording::location
*loc
,
3401 enum gcc_jit_function_kind kind
,
3403 recording::string
*name
,
3405 recording::param
**params
,
3407 enum built_in_function builtin_id
)
3411 m_return_type (return_type
),
3414 m_is_variadic (is_variadic
),
3415 m_builtin_id (builtin_id
),
3419 for (int i
= 0; i
< num_params
; i
++)
3421 param
*param
= params
[i
];
3424 /* Associate each param with this function.
3426 Verify that the param doesn't already have a function. */
3427 if (param
->get_scope ())
3429 /* We've already rejected attempts to reuse a param between
3430 different functions (within gcc_jit_context_new_function), so
3431 if the param *does* already have a function, it must be being
3432 reused within the params array for this function. We must
3433 produce an error for this reuse (blocking the compile), since
3434 otherwise we'd have an ICE later on. */
3435 gcc_assert (this == param
->get_scope ());
3438 "gcc_jit_context_new_function:"
3439 " parameter %s (type: %s)"
3440 " is used more than once when creating function %s",
3441 param
->get_debug_string (),
3442 param
->get_type ()->get_debug_string (),
3447 /* The normal, non-error case: associate this function with the
3449 param
->set_scope (this);
3452 m_params
.safe_push (param
);
3456 /* Implementation of pure virtual hook recording::memento::replay_into
3457 for recording::function. */
3460 recording::function::replay_into (replayer
*r
)
3462 /* Convert m_params to a vec of playback param. */
3463 auto_vec
<playback::param
*> params
;
3465 recording::param
*param
;
3466 params
.create (m_params
.length ());
3467 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3468 params
.safe_push (param
->playback_param ());
3470 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
3472 m_return_type
->playback_type (),
3479 /* Create a recording::local instance and add it to
3480 the functions's context's list of mementos, and to the function's
3483 Implements the post-error-checking part of
3484 gcc_jit_function_new_local. */
3487 recording::function::new_local (recording::location
*loc
,
3491 local
*result
= new local (this, loc
, type
, new_string (name
));
3492 m_ctxt
->record (result
);
3493 m_locals
.safe_push (result
);
3497 /* Create a recording::block instance and add it to
3498 the functions's context's list of mementos, and to the function's
3501 Implements the post-error-checking part of
3502 gcc_jit_function_new_block. */
3505 recording::function::new_block (const char *name
)
3507 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
3509 recording::block
*result
=
3510 new recording::block (this, m_blocks
.length (), new_string (name
));
3511 m_ctxt
->record (result
);
3512 m_blocks
.safe_push (result
);
3516 /* Override the default implementation of
3517 recording::memento::write_to_dump by dumping a C-like
3518 representation of the function; either like a prototype
3519 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3520 all other kinds of function. */
3523 recording::function::write_to_dump (dump
&d
)
3527 default: gcc_unreachable ();
3528 case GCC_JIT_FUNCTION_EXPORTED
:
3529 case GCC_JIT_FUNCTION_IMPORTED
:
3530 d
.write ("extern ");
3532 case GCC_JIT_FUNCTION_INTERNAL
:
3533 d
.write ("static ");
3535 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
3536 d
.write ("static inline ");
3539 d
.write ("%s\n", m_return_type
->get_debug_string ());
3541 if (d
.update_locations ())
3542 m_loc
= d
.make_location ();
3544 d
.write ("%s (", get_debug_string ());
3547 recording::param
*param
;
3548 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3553 param
->get_type ()->get_debug_string (),
3554 param
->get_debug_string ());
3557 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
3559 d
.write ("; /* (imported) */\n\n");
3569 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
3570 var
->write_to_dump (d
);
3571 if (m_locals
.length ())
3574 /* Write each block: */
3575 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3579 b
->write_to_dump (d
);
3586 /* Pre-compilation validation of a function, for those things we can't
3587 check until the context is (supposedly) fully-populated. */
3590 recording::function::validate ()
3592 /* Complain about empty functions with non-void return type. */
3593 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
3594 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
3595 if (0 == m_blocks
.length ())
3596 m_ctxt
->add_error (m_loc
,
3597 "function %s returns non-void (type: %s)"
3598 " but has no blocks",
3599 get_debug_string (),
3600 m_return_type
->get_debug_string ());
3602 /* Check that all blocks are terminated. */
3603 int num_invalid_blocks
= 0;
3608 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3609 if (!b
->validate ())
3610 num_invalid_blocks
++;
3613 /* Check that all blocks are reachable. */
3614 if (!m_ctxt
->get_inner_bool_option
3615 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS
)
3616 && m_blocks
.length () > 0 && 0 == num_invalid_blocks
)
3618 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3619 flag, starting at the initial block. */
3620 auto_vec
<block
*> worklist (m_blocks
.length ());
3621 worklist
.safe_push (m_blocks
[0]);
3622 while (worklist
.length () > 0)
3624 block
*b
= worklist
.pop ();
3625 b
->m_is_reachable
= true;
3627 /* Add successor blocks that aren't yet marked to the worklist. */
3628 /* We checked that each block has a terminating statement above . */
3629 vec
<block
*> successors
= b
->get_successor_blocks ();
3632 FOR_EACH_VEC_ELT (successors
, i
, succ
)
3633 if (!succ
->m_is_reachable
)
3634 worklist
.safe_push (succ
);
3635 successors
.release ();
3638 /* Now complain about any blocks that haven't been marked. */
3642 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3643 if (!b
->m_is_reachable
)
3644 m_ctxt
->add_error (b
->get_loc (),
3645 "unreachable block: %s",
3646 b
->get_debug_string ());
3651 /* Implements the post-error-checking part of
3652 gcc_jit_function_dump_to_dot. */
3655 recording::function::dump_to_dot (const char *path
)
3657 FILE *fp
= fopen (path
, "w");
3661 pretty_printer the_pp
;
3662 the_pp
.buffer
->stream
= fp
;
3664 pretty_printer
*pp
= &the_pp
;
3667 "digraph %s {\n", get_debug_string ());
3673 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3674 b
->dump_to_dot (pp
);
3681 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3682 b
->dump_edges_to_dot (pp
);
3685 pp_printf (pp
, "}\n");
3690 /* Implementation of recording::memento::make_debug_string for
3694 recording::function::make_debug_string ()
3699 /* A table of enum gcc_jit_function_kind values expressed in string
3702 static const char * const names_of_function_kinds
[] = {
3703 "GCC_JIT_FUNCTION_EXPORTED",
3704 "GCC_JIT_FUNCTION_INTERNAL",
3705 "GCC_JIT_FUNCTION_IMPORTED",
3706 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3709 /* Implementation of recording::memento::write_reproducer for functions. */
3712 recording::function::write_reproducer (reproducer
&r
)
3714 const char *id
= r
.make_identifier (this, "func");
3718 r
.write (" gcc_jit_function *%s =\n"
3719 " gcc_jit_context_get_builtin_function (%s,\n"
3722 r
.get_identifier (get_context ()),
3723 m_name
->get_debug_string ());
3726 const char *params_id
= r
.make_tmp_identifier ("params_for", this);
3727 r
.write (" gcc_jit_param *%s[%i] = {\n",
3729 m_params
.length ());
3732 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3733 r
.write (" %s,\n", r
.get_identifier (param
));
3735 r
.write (" gcc_jit_function *%s =\n"
3736 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3737 " %s, /* gcc_jit_location *loc */\n"
3738 " %s, /* enum gcc_jit_function_kind kind */\n"
3739 " %s, /* gcc_jit_type *return_type */\n"
3740 " %s, /* const char *name */\n"
3741 " %i, /* int num_params */\n"
3742 " %s, /* gcc_jit_param **params */\n"
3743 " %i); /* int is_variadic */\n",
3745 r
.get_identifier (get_context ()),
3746 r
.get_identifier (m_loc
),
3747 names_of_function_kinds
[m_kind
],
3748 r
.get_identifier_as_type (m_return_type
),
3749 m_name
->get_debug_string (),
3756 /* The implementation of class gcc::jit::recording::block. */
3758 /* Create a recording::eval instance and add it to
3759 the block's context's list of mementos, and to the block's
3762 Implements the heart of gcc_jit_block_add_eval. */
3764 recording::statement
*
3765 recording::block::add_eval (recording::location
*loc
,
3766 recording::rvalue
*rvalue
)
3768 statement
*result
= new eval (this, loc
, rvalue
);
3769 m_ctxt
->record (result
);
3770 m_statements
.safe_push (result
);
3774 /* Create a recording::assignment instance and add it to
3775 the block's context's list of mementos, and to the block's
3778 Implements the heart of gcc_jit_block_add_assignment. */
3780 recording::statement
*
3781 recording::block::add_assignment (recording::location
*loc
,
3782 recording::lvalue
*lvalue
,
3783 recording::rvalue
*rvalue
)
3785 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
3786 m_ctxt
->record (result
);
3787 m_statements
.safe_push (result
);
3791 /* Create a recording::assignment_op instance and add it to
3792 the block's context's list of mementos, and to the block's
3795 Implements the heart of gcc_jit_block_add_assignment_op. */
3797 recording::statement
*
3798 recording::block::add_assignment_op (recording::location
*loc
,
3799 recording::lvalue
*lvalue
,
3800 enum gcc_jit_binary_op op
,
3801 recording::rvalue
*rvalue
)
3803 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
3804 m_ctxt
->record (result
);
3805 m_statements
.safe_push (result
);
3809 /* Create a recording::comment instance and add it to
3810 the block's context's list of mementos, and to the block's
3813 Implements the heart of gcc_jit_block_add_comment. */
3815 recording::statement
*
3816 recording::block::add_comment (recording::location
*loc
,
3819 statement
*result
= new comment (this, loc
, new_string (text
));
3820 m_ctxt
->record (result
);
3821 m_statements
.safe_push (result
);
3825 /* Create a recording::end_with_conditional instance and add it to
3826 the block's context's list of mementos, and to the block's
3829 Implements the heart of gcc_jit_block_end_with_conditional. */
3831 recording::statement
*
3832 recording::block::end_with_conditional (recording::location
*loc
,
3833 recording::rvalue
*boolval
,
3834 recording::block
*on_true
,
3835 recording::block
*on_false
)
3837 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
3838 m_ctxt
->record (result
);
3839 m_statements
.safe_push (result
);
3840 m_has_been_terminated
= true;
3844 /* Create a recording::end_with_jump instance and add it to
3845 the block's context's list of mementos, and to the block's
3848 Implements the heart of gcc_jit_block_end_with_jump. */
3850 recording::statement
*
3851 recording::block::end_with_jump (recording::location
*loc
,
3852 recording::block
*target
)
3854 statement
*result
= new jump (this, loc
, target
);
3855 m_ctxt
->record (result
);
3856 m_statements
.safe_push (result
);
3857 m_has_been_terminated
= true;
3861 /* Create a recording::end_with_return instance and add it to
3862 the block's context's list of mementos, and to the block's
3865 Implements the post-error-checking parts of
3866 gcc_jit_block_end_with_return and
3867 gcc_jit_block_end_with_void_return. */
3869 recording::statement
*
3870 recording::block::end_with_return (recording::location
*loc
,
3871 recording::rvalue
*rvalue
)
3873 /* This is used by both gcc_jit_function_add_return and
3874 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3875 the former and NULL for the latter. */
3876 statement
*result
= new return_ (this, loc
, rvalue
);
3877 m_ctxt
->record (result
);
3878 m_statements
.safe_push (result
);
3879 m_has_been_terminated
= true;
3883 /* Create a recording::switch_ instance and add it to
3884 the block's context's list of mementos, and to the block's
3887 Implements the heart of gcc_jit_block_end_with_switch. */
3889 recording::statement
*
3890 recording::block::end_with_switch (recording::location
*loc
,
3891 recording::rvalue
*expr
,
3892 recording::block
*default_block
,
3894 recording::case_
**cases
)
3896 statement
*result
= new switch_ (this, loc
,
3901 m_ctxt
->record (result
);
3902 m_statements
.safe_push (result
);
3903 m_has_been_terminated
= true;
3907 /* Override the default implementation of
3908 recording::memento::write_to_dump for blocks by writing
3909 an unindented block name as a label, followed by the indented
3919 recording::block::write_to_dump (dump
&d
)
3921 d
.write ("%s:\n", get_debug_string ());
3925 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
3926 s
->write_to_dump (d
);
3929 /* Validate a block by ensuring that it has been terminated. */
3932 recording::block::validate ()
3934 /* Check for termination. */
3935 if (!has_been_terminated ())
3937 statement
*stmt
= get_last_statement ();
3938 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
3939 m_func
->get_context ()->add_error (loc
,
3940 "unterminated block in %s: %s",
3941 m_func
->get_debug_string (),
3942 get_debug_string ());
3949 /* Get the source-location of a block by using that of the first
3950 statement within it, if any. */
3952 recording::location
*
3953 recording::block::get_loc () const
3955 recording::statement
*stmt
= get_first_statement ();
3957 return stmt
->get_loc ();
3962 /* Get the first statement within a block, if any. */
3964 recording::statement
*
3965 recording::block::get_first_statement () const
3967 if (m_statements
.length ())
3968 return m_statements
[0];
3973 /* Get the last statement within a block, if any. */
3975 recording::statement
*
3976 recording::block::get_last_statement () const
3978 if (m_statements
.length ())
3979 return m_statements
[m_statements
.length () - 1];
3984 /* Assuming that this block has been terminated, get the successor blocks
3985 as a vector. Ownership of the vector transfers to the caller, which
3986 must call its release () method.
3988 Used when validating functions, and when dumping dot representations
3991 vec
<recording::block
*>
3992 recording::block::get_successor_blocks () const
3994 gcc_assert (m_has_been_terminated
);
3995 statement
*last_statement
= get_last_statement ();
3996 gcc_assert (last_statement
);
3997 return last_statement
->get_successor_blocks ();
4000 /* Implementation of pure virtual hook recording::memento::replay_into
4001 for recording::block. */
4004 recording::block::replay_into (replayer
*)
4006 set_playback_obj (m_func
->playback_function ()
4007 ->new_block (playback_string (m_name
)));
4010 /* Implementation of recording::memento::make_debug_string for
4014 recording::block::make_debug_string ()
4019 return string::from_printf (m_ctxt
,
4020 "<UNNAMED BLOCK %p>",
4024 /* Implementation of recording::memento::write_reproducer for blocks. */
4027 recording::block::write_reproducer (reproducer
&r
)
4029 const char *id
= r
.make_identifier (this, "block");
4030 r
.write (" gcc_jit_block *%s =\n"
4031 " gcc_jit_function_new_block (%s, %s);\n",
4033 r
.get_identifier (m_func
),
4034 m_name
? m_name
->get_debug_string () : "NULL");
4037 /* Dump a block in graphviz form into PP, capturing the block name (if
4038 any) and the statements. */
4041 recording::block::dump_to_dot (pretty_printer
*pp
)
4045 "[shape=record,style=filled,fillcolor=white,label=\"{"),
4047 pp_write_text_to_stream (pp
);
4050 pp_string (pp
, m_name
->c_str ());
4051 pp_string (pp
, ":");
4053 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
4058 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
4060 pp_string (pp
, s
->get_debug_string ());
4062 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
4070 /* Dump the out-edges of the block in graphviz form into PP. */
4073 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
4075 vec
<block
*> successors
= get_successor_blocks ();
4078 FOR_EACH_VEC_ELT (successors
, i
, succ
)
4080 "\tblock_%d:s -> block_%d:n;\n",
4081 m_index
, succ
->m_index
);
4082 successors
.release ();
4085 /* The implementation of class gcc::jit::recording::global. */
4087 /* Implementation of pure virtual hook recording::memento::replay_into
4088 for recording::global. */
4091 recording::global::replay_into (replayer
*r
)
4093 set_playback_obj (r
->new_global (playback_location (r
, m_loc
),
4095 m_type
->playback_type (),
4096 playback_string (m_name
)));
4099 /* Override the default implementation of
4100 recording::memento::write_to_dump for globals.
4101 This will be of the form:
4103 GCC_JIT_GLOBAL_EXPORTED:
4107 GCC_JIT_GLOBAL_INTERNAL:
4109 e.g. "static int foo;"
4111 GCC_JIT_GLOBAL_IMPORTED:
4113 e.g. "extern int foo;"
4115 These are written to the top of the dump by
4116 recording::context::dump_to_file. */
4119 recording::global::write_to_dump (dump
&d
)
4121 if (d
.update_locations ())
4122 m_loc
= d
.make_location ();
4129 case GCC_JIT_GLOBAL_EXPORTED
:
4132 case GCC_JIT_GLOBAL_INTERNAL
:
4133 d
.write ("static ");
4136 case GCC_JIT_GLOBAL_IMPORTED
:
4137 d
.write ("extern ");
4140 d
.write ("%s %s;\n",
4141 m_type
->get_debug_string (),
4142 get_debug_string ());
4145 /* A table of enum gcc_jit_global_kind values expressed in string
4148 static const char * const global_kind_reproducer_strings
[] = {
4149 "GCC_JIT_GLOBAL_EXPORTED",
4150 "GCC_JIT_GLOBAL_INTERNAL",
4151 "GCC_JIT_GLOBAL_IMPORTED"
4154 /* Implementation of recording::memento::write_reproducer for globals. */
4157 recording::global::write_reproducer (reproducer
&r
)
4159 const char *id
= r
.make_identifier (this, "block");
4160 r
.write (" gcc_jit_lvalue *%s =\n"
4161 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4162 " %s, /* gcc_jit_location *loc */\n"
4163 " %s, /* enum gcc_jit_global_kind kind */\n"
4164 " %s, /* gcc_jit_type *type */\n"
4165 " %s); /* const char *name */\n",
4167 r
.get_identifier (get_context ()),
4168 r
.get_identifier (m_loc
),
4169 global_kind_reproducer_strings
[m_kind
],
4170 r
.get_identifier_as_type (get_type ()),
4171 m_name
->get_debug_string ());
4174 /* The implementation of the various const-handling classes:
4175 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4177 /* Explicit specialization of the various mementos we're interested in. */
4178 template class recording::memento_of_new_rvalue_from_const
<int>;
4179 template class recording::memento_of_new_rvalue_from_const
<long>;
4180 template class recording::memento_of_new_rvalue_from_const
<double>;
4181 template class recording::memento_of_new_rvalue_from_const
<void *>;
4183 /* Implementation of the pure virtual hook recording::memento::replay_into
4184 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4186 template <typename HOST_TYPE
>
4189 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
4192 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
4196 /* The make_debug_string and write_reproducer methods vary between the
4198 memento_of_new_rvalue_from_const <HOST_TYPE>
4199 classes, so we explicitly write specializations of them.
4201 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4202 namespaces are written out explicitly, which is why most of this file
4203 doesn't abbreviate things by entering the "recording" namespace.
4205 However, these specializations are required to be in the same namespace
4206 as the template, hence we now have to enter the gcc::jit::recording
4212 /* The make_debug_string specialization for <int>, which renders it as
4213 (TARGET_TYPE)LITERAL
4219 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
4221 return string::from_printf (m_ctxt
,
4223 m_type
->get_debug_string (),
4227 /* The get_wide_int specialization for <int>. */
4231 memento_of_new_rvalue_from_const
<int>::get_wide_int (wide_int
*out
) const
4233 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
4237 /* The write_reproducer specialization for <int>. */
4241 memento_of_new_rvalue_from_const
<int>::write_reproducer (reproducer
&r
)
4243 const char *id
= r
.make_identifier (this, "rvalue");
4244 r
.write (" gcc_jit_rvalue *%s =\n"
4245 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4246 " %s, /* gcc_jit_type *numeric_type */\n"
4247 " %i); /* int value */\n",
4249 r
.get_identifier (get_context ()),
4250 r
.get_identifier_as_type (m_type
),
4254 /* The make_debug_string specialization for <long>, rendering it as
4255 (TARGET_TYPE)LITERAL
4261 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
4263 return string::from_printf (m_ctxt
,
4265 m_type
->get_debug_string (),
4269 /* The get_wide_int specialization for <long>. */
4273 memento_of_new_rvalue_from_const
<long>::get_wide_int (wide_int
*out
) const
4275 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
4279 /* The write_reproducer specialization for <long>. */
4283 recording::memento_of_new_rvalue_from_const
<long>::write_reproducer (reproducer
&r
)
4285 const char *id
= r
.make_identifier (this, "rvalue");
4287 /* We have to special-case LONG_MIN, since e.g.
4288 -9223372036854775808L
4290 -(9223372036854775808L)
4292 error: integer constant is so large that it is unsigned [-Werror]
4293 Workaround this by writing (LONG_MIN + 1) - 1. */
4294 if (m_value
== LONG_MIN
)
4296 r
.write (" gcc_jit_rvalue *%s =\n"
4297 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4298 " %s, /* gcc_jit_type *numeric_type */\n"
4299 " %ldL - 1); /* long value */\n",
4301 r
.get_identifier (get_context ()),
4302 r
.get_identifier_as_type (m_type
),
4307 r
.write (" gcc_jit_rvalue *%s =\n"
4308 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4309 " %s, /* gcc_jit_type *numeric_type */\n"
4310 " %ldL); /* long value */\n",
4312 r
.get_identifier (get_context ()),
4313 r
.get_identifier_as_type (m_type
),
4317 /* The make_debug_string specialization for <double>, rendering it as
4318 (TARGET_TYPE)LITERAL
4324 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
4326 return string::from_printf (m_ctxt
,
4328 m_type
->get_debug_string (),
4332 /* The get_wide_int specialization for <double>. */
4336 memento_of_new_rvalue_from_const
<double>::get_wide_int (wide_int
*) const
4341 /* The write_reproducer specialization for <double>. */
4345 recording::memento_of_new_rvalue_from_const
<double>::write_reproducer (reproducer
&r
)
4347 const char *id
= r
.make_identifier (this, "rvalue");
4348 r
.write (" gcc_jit_rvalue *%s =\n"
4349 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4350 " %s, /* gcc_jit_type *numeric_type */\n"
4351 " %f); /* double value */\n",
4353 r
.get_identifier (get_context ()),
4354 r
.get_identifier_as_type (m_type
),
4358 /* The make_debug_string specialization for <void *>, rendering it as
4363 Zero is rendered as NULL e.g.
4368 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
4370 if (m_value
!= NULL
)
4371 return string::from_printf (m_ctxt
,
4373 m_type
->get_debug_string (), m_value
);
4375 return string::from_printf (m_ctxt
,
4377 m_type
->get_debug_string ());
4380 /* The get_wide_int specialization for <void *>. */
4384 memento_of_new_rvalue_from_const
<void *>::get_wide_int (wide_int
*) const
4389 /* Implementation of recording::memento::write_reproducer for <void *>
4394 memento_of_new_rvalue_from_const
<void *>::write_reproducer (reproducer
&r
)
4396 const char *id
= r
.make_identifier (this, "rvalue");
4398 r
.write (" gcc_jit_rvalue *%s =\n"
4399 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4400 " %s, /* gcc_jit_type *pointer_type */\n"
4401 " (void *)%p); /* void *value */\n",
4403 r
.get_identifier (get_context ()),
4404 r
.get_identifier_as_type (m_type
),
4407 r
.write (" gcc_jit_rvalue *%s =\n"
4408 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4409 " %s); /* gcc_jit_type *pointer_type */\n",
4411 r
.get_identifier (get_context ()),
4412 r
.get_identifier_as_type (m_type
));
4415 /* We're done specializing make_debug_string and write_reproducer, so we
4416 can exit the gcc::jit::recording namespace. */
4418 } // namespace recording
4420 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4422 /* Implementation of pure virtual hook recording::memento::replay_into
4423 for recording::memento_of_new_string_literal. */
4426 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
4428 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
4431 /* Implementation of recording::memento::make_debug_string for
4435 recording::memento_of_new_string_literal::make_debug_string ()
4437 return string::from_printf (m_ctxt
,
4439 m_value
->get_debug_string ());
4442 /* Implementation of recording::memento::write_reproducer for string literal
4446 recording::memento_of_new_string_literal::write_reproducer (reproducer
&r
)
4448 const char *id
= r
.make_identifier (this, "rvalue");
4449 r
.write (" gcc_jit_rvalue *%s =\n"
4450 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4451 " %s); /* const char *value */\n",
4453 r
.get_identifier (get_context ()),
4454 m_value
->get_debug_string ());
4457 /* The implementation of class gcc::jit::recording::unary_op. */
4459 /* Implementation of pure virtual hook recording::memento::replay_into
4460 for recording::unary_op. */
4463 recording::unary_op::replay_into (replayer
*r
)
4465 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
4467 get_type ()->playback_type (),
4468 m_a
->playback_rvalue ()));
4471 /* Implementation of pure virtual hook recording::rvalue::visit_children
4472 for recording::unary_op. */
4474 recording::unary_op::visit_children (rvalue_visitor
*v
)
4479 /* Implementation of recording::memento::make_debug_string for
4482 static const char * const unary_op_strings
[] = {
4483 "-", /* GCC_JIT_UNARY_OP_MINUS */
4484 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4485 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4486 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4490 recording::unary_op::make_debug_string ()
4492 return string::from_printf (m_ctxt
,
4494 unary_op_strings
[m_op
],
4495 m_a
->get_debug_string ());
4498 static const char * const unary_op_reproducer_strings
[] = {
4499 "GCC_JIT_UNARY_OP_MINUS",
4500 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4501 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4502 "GCC_JIT_UNARY_OP_ABS"
4505 /* Implementation of recording::memento::write_reproducer for unary ops. */
4508 recording::unary_op::write_reproducer (reproducer
&r
)
4510 const char *id
= r
.make_identifier (this, "rvalue");
4511 r
.write (" gcc_jit_rvalue *%s =\n"
4512 " gcc_jit_context_new_unary_op (%s,\n"
4513 " %s, /* gcc_jit_location *loc */\n"
4514 " %s, /* enum gcc_jit_unary_op op */\n"
4515 " %s, /* gcc_jit_type *result_type */\n"
4516 " %s); /* gcc_jit_rvalue *a */\n",
4518 r
.get_identifier (get_context ()),
4519 r
.get_identifier (m_loc
),
4520 unary_op_reproducer_strings
[m_op
],
4521 r
.get_identifier_as_type (get_type ()),
4522 r
.get_identifier_as_rvalue (m_a
));
4525 /* The implementation of class gcc::jit::recording::binary_op. */
4527 /* Implementation of pure virtual hook recording::memento::replay_into
4528 for recording::binary_op. */
4531 recording::binary_op::replay_into (replayer
*r
)
4533 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
4535 get_type ()->playback_type (),
4536 m_a
->playback_rvalue (),
4537 m_b
->playback_rvalue ()));
4540 /* Implementation of pure virtual hook recording::rvalue::visit_children
4541 for recording::binary_op. */
4543 recording::binary_op::visit_children (rvalue_visitor
*v
)
4549 /* Implementation of recording::memento::make_debug_string for
4552 static const char * const binary_op_strings
[] = {
4553 "+", /* GCC_JIT_BINARY_OP_PLUS */
4554 "-", /* GCC_JIT_BINARY_OP_MINUS */
4555 "*", /* GCC_JIT_BINARY_OP_MULT */
4556 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4557 "%", /* GCC_JIT_BINARY_OP_MODULO */
4558 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4559 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4560 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4561 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4562 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4563 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4564 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4568 recording::binary_op::make_debug_string ()
4570 enum precedence prec
= get_precedence ();
4571 return string::from_printf (m_ctxt
,
4573 m_a
->get_debug_string_parens (prec
),
4574 binary_op_strings
[m_op
],
4575 m_b
->get_debug_string_parens (prec
));
4578 static const char * const binary_op_reproducer_strings
[] = {
4579 "GCC_JIT_BINARY_OP_PLUS",
4580 "GCC_JIT_BINARY_OP_MINUS",
4581 "GCC_JIT_BINARY_OP_MULT",
4582 "GCC_JIT_BINARY_OP_DIVIDE",
4583 "GCC_JIT_BINARY_OP_MODULO",
4584 "GCC_JIT_BINARY_OP_BITWISE_AND",
4585 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4586 "GCC_JIT_BINARY_OP_BITWISE_OR",
4587 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4588 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4589 "GCC_JIT_BINARY_OP_LSHIFT",
4590 "GCC_JIT_BINARY_OP_RSHIFT"
4593 /* Implementation of recording::memento::write_reproducer for binary ops. */
4596 recording::binary_op::write_reproducer (reproducer
&r
)
4598 const char *id
= r
.make_identifier (this, "rvalue");
4599 r
.write (" gcc_jit_rvalue *%s =\n"
4600 " gcc_jit_context_new_binary_op (%s,\n"
4601 " %s, /* gcc_jit_location *loc */\n"
4602 " %s, /* enum gcc_jit_binary_op op */\n"
4603 " %s, /* gcc_jit_type *result_type */\n"
4604 " %s, /* gcc_jit_rvalue *a */\n"
4605 " %s); /* gcc_jit_rvalue *b */\n",
4607 r
.get_identifier (get_context ()),
4608 r
.get_identifier (m_loc
),
4609 binary_op_reproducer_strings
[m_op
],
4610 r
.get_identifier_as_type (get_type ()),
4611 r
.get_identifier_as_rvalue (m_a
),
4612 r
.get_identifier_as_rvalue (m_b
));
4615 namespace recording
{
4616 static const enum precedence binary_op_precedence
[] = {
4617 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_PLUS */
4618 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_MINUS */
4620 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MULT */
4621 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_DIVIDE */
4622 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MODULO */
4624 PRECEDENCE_BITWISE_AND
, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4625 PRECEDENCE_BITWISE_XOR
, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4626 PRECEDENCE_BITWISE_IOR
, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4627 PRECEDENCE_LOGICAL_AND
, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4628 PRECEDENCE_LOGICAL_OR
, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4629 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_LSHIFT */
4630 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_RSHIFT */
4632 } /* namespace recording */
4634 enum recording::precedence
4635 recording::binary_op::get_precedence () const
4637 return binary_op_precedence
[m_op
];
4640 /* The implementation of class gcc::jit::recording::comparison. */
4642 /* Implementation of recording::memento::make_debug_string for
4645 static const char * const comparison_strings
[] =
4647 "==", /* GCC_JIT_COMPARISON_EQ */
4648 "!=", /* GCC_JIT_COMPARISON_NE */
4649 "<", /* GCC_JIT_COMPARISON_LT */
4650 "<=", /* GCC_JIT_COMPARISON_LE */
4651 ">", /* GCC_JIT_COMPARISON_GT */
4652 ">=", /* GCC_JIT_COMPARISON_GE */
4656 recording::comparison::make_debug_string ()
4658 enum precedence prec
= get_precedence ();
4659 return string::from_printf (m_ctxt
,
4661 m_a
->get_debug_string_parens (prec
),
4662 comparison_strings
[m_op
],
4663 m_b
->get_debug_string_parens (prec
));
4666 /* A table of enum gcc_jit_comparison values expressed in string
4669 static const char * const comparison_reproducer_strings
[] =
4671 "GCC_JIT_COMPARISON_EQ",
4672 "GCC_JIT_COMPARISON_NE",
4673 "GCC_JIT_COMPARISON_LT",
4674 "GCC_JIT_COMPARISON_LE",
4675 "GCC_JIT_COMPARISON_GT",
4676 "GCC_JIT_COMPARISON_GE"
4679 /* Implementation of recording::memento::write_reproducer for comparisons. */
4682 recording::comparison::write_reproducer (reproducer
&r
)
4684 const char *id
= r
.make_identifier (this, "rvalue");
4685 r
.write (" gcc_jit_rvalue *%s =\n"
4686 " gcc_jit_context_new_comparison (%s,\n"
4687 " %s, /* gcc_jit_location *loc */\n"
4688 " %s, /* enum gcc_jit_comparison op */\n"
4689 " %s, /* gcc_jit_rvalue *a */\n"
4690 " %s); /* gcc_jit_rvalue *b */\n",
4692 r
.get_identifier (get_context ()),
4693 r
.get_identifier (m_loc
),
4694 comparison_reproducer_strings
[m_op
],
4695 r
.get_identifier_as_rvalue (m_a
),
4696 r
.get_identifier_as_rvalue (m_b
));
4699 /* Implementation of pure virtual hook recording::memento::replay_into
4700 for recording::comparison. */
4703 recording::comparison::replay_into (replayer
*r
)
4705 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
4707 m_a
->playback_rvalue (),
4708 m_b
->playback_rvalue ()));
4711 /* Implementation of pure virtual hook recording::rvalue::visit_children
4712 for recording::comparison. */
4715 recording::comparison::visit_children (rvalue_visitor
*v
)
4721 namespace recording
{
4722 static const enum precedence comparison_precedence
[] =
4724 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_EQ */
4725 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_NE */
4727 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LT */
4728 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LE */
4729 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GT */
4730 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GE */
4732 } /* namespace recording */
4734 enum recording::precedence
4735 recording::comparison::get_precedence () const
4737 return comparison_precedence
[m_op
];
4740 /* Implementation of pure virtual hook recording::memento::replay_into
4741 for recording::cast. */
4744 recording::cast::replay_into (replayer
*r
)
4746 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
4747 m_rvalue
->playback_rvalue (),
4748 get_type ()->playback_type ()));
4751 /* Implementation of pure virtual hook recording::rvalue::visit_children
4752 for recording::cast. */
4754 recording::cast::visit_children (rvalue_visitor
*v
)
4756 v
->visit (m_rvalue
);
4759 /* Implementation of recording::memento::make_debug_string for
4763 recording::cast::make_debug_string ()
4765 enum precedence prec
= get_precedence ();
4766 return string::from_printf (m_ctxt
,
4768 get_type ()->get_debug_string (),
4769 m_rvalue
->get_debug_string_parens (prec
));
4772 /* Implementation of recording::memento::write_reproducer for casts. */
4775 recording::cast::write_reproducer (reproducer
&r
)
4777 const char *id
= r
.make_identifier (this, "rvalue");
4778 r
.write (" gcc_jit_rvalue *%s =\n"
4779 " gcc_jit_context_new_cast (%s,\n"
4780 " %s, /* gcc_jit_location *loc */\n"
4781 " %s, /* gcc_jit_rvalue *rvalue */\n"
4782 " %s); /* gcc_jit_type *type */\n",
4784 r
.get_identifier (get_context ()),
4785 r
.get_identifier (m_loc
),
4786 r
.get_identifier_as_rvalue (m_rvalue
),
4787 r
.get_identifier_as_type (get_type ()));
4790 /* The implementation of class gcc::jit::recording::base_call. */
4792 /* The constructor for gcc::jit::recording::base_call. */
4794 recording::base_call::base_call (context
*ctxt
,
4799 : rvalue (ctxt
, loc
, type_
),
4801 m_require_tail_call (0)
4803 for (int i
= 0; i
< numargs
; i
++)
4804 m_args
.safe_push (args
[i
]);
4807 /* Subroutine for use by call and call_though_ptr's write_reproducer
4811 recording::base_call::write_reproducer_tail_call (reproducer
&r
,
4814 if (m_require_tail_call
)
4816 r
.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
4817 " %i); /* int require_tail_call*/\n",
4823 /* The implementation of class gcc::jit::recording::call. */
4825 /* The constructor for gcc::jit::recording::call. */
4827 recording::call::call (recording::context
*ctxt
,
4828 recording::location
*loc
,
4829 recording::function
*func
,
4832 : base_call (ctxt
, loc
, func
->get_return_type (), numargs
, args
),
4837 /* Implementation of pure virtual hook recording::memento::replay_into
4838 for recording::call. */
4841 recording::call::replay_into (replayer
*r
)
4843 auto_vec
<playback::rvalue
*> playback_args
;
4844 playback_args
.create (m_args
.length ());
4845 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4846 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
4848 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
4849 m_func
->playback_function (),
4851 m_require_tail_call
));
4854 /* Implementation of pure virtual hook recording::rvalue::visit_children
4855 for recording::call. */
4858 recording::call::visit_children (rvalue_visitor
*v
)
4860 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4861 v
->visit (m_args
[i
]);
4864 /* Implementation of recording::memento::make_debug_string for
4868 recording::call::make_debug_string ()
4870 enum precedence prec
= get_precedence ();
4871 /* First, build a buffer for the arguments. */
4872 /* Calculate length of said buffer. */
4873 size_t sz
= 1; /* nil terminator */
4874 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4876 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4877 sz
+= 2; /* ", " separator */
4880 /* Now allocate and populate the buffer. */
4881 char *argbuf
= new char[sz
];
4884 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4886 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
4887 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4888 if (i
+ 1 < m_args
.length ())
4890 strcpy (argbuf
+ len
, ", ");
4896 /* ...and use it to get the string for the call as a whole. */
4897 string
*result
= string::from_printf (m_ctxt
,
4899 m_func
->get_debug_string (),
4908 recording::call::write_reproducer (reproducer
&r
)
4910 const char *id
= r
.make_identifier (this, "call");
4911 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
4912 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4915 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4916 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
4918 r
.write (" gcc_jit_rvalue *%s =\n"
4919 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4920 " %s, /* gcc_jit_location *loc */\n"
4921 " %s, /* gcc_jit_function *func */\n"
4922 " %i, /* int numargs */ \n"
4923 " %s); /* gcc_jit_rvalue **args*/\n",
4925 r
.get_identifier (get_context ()),
4926 r
.get_identifier (m_loc
),
4927 r
.get_identifier (m_func
),
4930 write_reproducer_tail_call (r
, id
);
4933 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4935 /* The constructor for recording::call_through_ptr. */
4937 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
4938 recording::location
*loc
,
4939 recording::rvalue
*fn_ptr
,
4942 : base_call (ctxt
, loc
,
4943 fn_ptr
->get_type ()->dereference ()
4944 ->as_a_function_type ()->get_return_type (),
4950 /* Implementation of pure virtual hook recording::memento::replay_into
4951 for recording::call_through_ptr. */
4954 recording::call_through_ptr::replay_into (replayer
*r
)
4956 auto_vec
<playback::rvalue
*> playback_args
;
4957 playback_args
.create (m_args
.length ());
4958 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4959 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
4961 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
4962 m_fn_ptr
->playback_rvalue (),
4964 m_require_tail_call
));
4967 /* Implementation of pure virtual hook recording::rvalue::visit_children
4968 for recording::call_through_ptr. */
4971 recording::call_through_ptr::visit_children (rvalue_visitor
*v
)
4973 v
->visit (m_fn_ptr
);
4974 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4975 v
->visit (m_args
[i
]);
4978 /* Implementation of recording::memento::make_debug_string for
4979 calls through function ptrs. */
4982 recording::call_through_ptr::make_debug_string ()
4984 enum precedence prec
= get_precedence ();
4985 /* First, build a buffer for the arguments. */
4986 /* Calculate length of said buffer. */
4987 size_t sz
= 1; /* nil terminator */
4988 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4990 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4991 sz
+= 2; /* ", " separator */
4994 /* Now allocate and populate the buffer. */
4995 char *argbuf
= new char[sz
];
4998 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5000 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
5001 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
5002 if (i
+ 1 < m_args
.length ())
5004 strcpy (argbuf
+ len
, ", ");
5010 /* ...and use it to get the string for the call as a whole. */
5011 string
*result
= string::from_printf (m_ctxt
,
5013 m_fn_ptr
->get_debug_string_parens (prec
),
5021 /* Implementation of recording::memento::write_reproducer for
5022 call_through_ptr. */
5025 recording::call_through_ptr::write_reproducer (reproducer
&r
)
5027 const char *id
= r
.make_identifier (this, "call");
5028 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
5029 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
5032 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5033 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
5035 r
.write (" gcc_jit_rvalue *%s =\n"
5036 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
5037 " %s, /* gcc_jit_location *loc */\n"
5038 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
5039 " %i, /* int numargs */ \n"
5040 " %s); /* gcc_jit_rvalue **args*/\n",
5042 r
.get_identifier (get_context ()),
5043 r
.get_identifier (m_loc
),
5044 r
.get_identifier_as_rvalue (m_fn_ptr
),
5047 write_reproducer_tail_call (r
, id
);
5050 /* The implementation of class gcc::jit::recording::array_access. */
5052 /* Implementation of pure virtual hook recording::memento::replay_into
5053 for recording::array_access. */
5056 recording::array_access::replay_into (replayer
*r
)
5059 r
->new_array_access (playback_location (r
, m_loc
),
5060 m_ptr
->playback_rvalue (),
5061 m_index
->playback_rvalue ()));
5064 /* Implementation of pure virtual hook recording::rvalue::visit_children
5065 for recording::array_access. */
5068 recording::array_access::visit_children (rvalue_visitor
*v
)
5074 /* Implementation of recording::memento::make_debug_string for
5078 recording::array_access::make_debug_string ()
5080 enum precedence prec
= get_precedence ();
5081 return string::from_printf (m_ctxt
,
5083 m_ptr
->get_debug_string_parens (prec
),
5084 m_index
->get_debug_string_parens (prec
));
5087 /* Implementation of recording::memento::write_reproducer for
5091 recording::array_access::write_reproducer (reproducer
&r
)
5093 const char *id
= r
.make_identifier (this, "lvalue");
5094 r
.write (" gcc_jit_lvalue *%s = \n"
5095 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
5096 " %s, /*gcc_jit_location *loc */\n"
5097 " %s, /* gcc_jit_rvalue *ptr */\n"
5098 " %s); /* gcc_jit_rvalue *index */\n",
5100 r
.get_identifier (get_context ()),
5101 r
.get_identifier (m_loc
),
5102 r
.get_identifier_as_rvalue (m_ptr
),
5103 r
.get_identifier_as_rvalue (m_index
));
5106 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
5108 /* Implementation of pure virtual hook recording::memento::replay_into
5109 for recording::access_field_of_lvalue. */
5112 recording::access_field_of_lvalue::replay_into (replayer
*r
)
5115 m_lvalue
->playback_lvalue ()
5116 ->access_field (playback_location (r
, m_loc
),
5117 m_field
->playback_field ()));
5121 /* Implementation of pure virtual hook recording::rvalue::visit_children
5122 for recording::access_field_of_lvalue. */
5125 recording::access_field_of_lvalue::visit_children (rvalue_visitor
*v
)
5127 v
->visit (m_lvalue
);
5130 /* Implementation of recording::memento::make_debug_string for
5131 accessing a field of an lvalue. */
5134 recording::access_field_of_lvalue::make_debug_string ()
5136 enum precedence prec
= get_precedence ();
5137 return string::from_printf (m_ctxt
,
5139 m_lvalue
->get_debug_string_parens (prec
),
5140 m_field
->get_debug_string ());
5143 /* Implementation of recording::memento::write_reproducer for
5144 access_field_of_lvalue. */
5147 recording::access_field_of_lvalue::write_reproducer (reproducer
&r
)
5149 const char *id
= r
.make_identifier (this, "lvalue");
5150 r
.write (" gcc_jit_lvalue *%s = \n"
5151 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5152 " %s, /*gcc_jit_location *loc */\n"
5155 r
.get_identifier_as_lvalue (m_lvalue
),
5156 r
.get_identifier (m_loc
),
5157 r
.get_identifier (m_field
));
5160 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
5162 /* Implementation of pure virtual hook recording::memento::replay_into
5163 for recording::access_field_rvalue. */
5166 recording::access_field_rvalue::replay_into (replayer
*r
)
5169 m_rvalue
->playback_rvalue ()
5170 ->access_field (playback_location (r
, m_loc
),
5171 m_field
->playback_field ()));
5174 /* Implementation of pure virtual hook recording::rvalue::visit_children
5175 for recording::access_field_rvalue. */
5178 recording::access_field_rvalue::visit_children (rvalue_visitor
*v
)
5180 v
->visit (m_rvalue
);
5183 /* Implementation of recording::memento::make_debug_string for
5184 accessing a field of an rvalue. */
5187 recording::access_field_rvalue::make_debug_string ()
5189 enum precedence prec
= get_precedence ();
5190 return string::from_printf (m_ctxt
,
5192 m_rvalue
->get_debug_string_parens (prec
),
5193 m_field
->get_debug_string ());
5196 /* Implementation of recording::memento::write_reproducer for
5197 access_field_rvalue. */
5200 recording::access_field_rvalue::write_reproducer (reproducer
&r
)
5202 const char *id
= r
.make_identifier (this, "rvalue");
5203 r
.write (" gcc_jit_rvalue *%s = \n"
5204 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5205 " %s, /*gcc_jit_location *loc */\n"
5208 r
.get_identifier_as_rvalue (m_rvalue
),
5209 r
.get_identifier (m_loc
),
5210 r
.get_identifier (m_field
));
5213 /* The implementation of class
5214 gcc::jit::recording::dereference_field_rvalue. */
5216 /* Implementation of pure virtual hook recording::memento::replay_into
5217 for recording::dereference_field_rvalue. */
5220 recording::dereference_field_rvalue::replay_into (replayer
*r
)
5223 m_rvalue
->playback_rvalue ()->
5224 dereference_field (playback_location (r
, m_loc
),
5225 m_field
->playback_field ()));
5228 /* Implementation of pure virtual hook recording::rvalue::visit_children
5229 for recording::dereference_field_rvalue. */
5232 recording::dereference_field_rvalue::visit_children (rvalue_visitor
*v
)
5234 v
->visit (m_rvalue
);
5237 /* Implementation of recording::memento::make_debug_string for
5238 dereferencing a field of an rvalue. */
5241 recording::dereference_field_rvalue::make_debug_string ()
5243 enum precedence prec
= get_precedence ();
5244 return string::from_printf (m_ctxt
,
5246 m_rvalue
->get_debug_string_parens (prec
),
5247 m_field
->get_debug_string ());
5250 /* Implementation of recording::memento::write_reproducer for
5251 dereference_field_rvalue. */
5254 recording::dereference_field_rvalue::write_reproducer (reproducer
&r
)
5256 const char *id
= r
.make_identifier (this, "lvalue");
5257 r
.write (" gcc_jit_lvalue *%s=\n"
5258 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5259 " %s, /* gcc_jit_location *loc */\n"
5260 " %s); /* gcc_jit_field *field */\n",
5262 r
.get_identifier_as_rvalue (m_rvalue
),
5263 r
.get_identifier (m_loc
),
5264 r
.get_identifier (m_field
));
5267 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5269 /* Implementation of pure virtual hook recording::memento::replay_into
5270 for recording::dereference_rvalue. */
5273 recording::dereference_rvalue::replay_into (replayer
*r
)
5276 m_rvalue
->playback_rvalue ()->
5277 dereference (playback_location (r
, m_loc
)));
5280 /* Implementation of pure virtual hook recording::rvalue::visit_children
5281 for recording::dereference_rvalue. */
5284 recording::dereference_rvalue::visit_children (rvalue_visitor
*v
)
5286 v
->visit (m_rvalue
);
5289 /* Implementation of recording::memento::make_debug_string for
5290 dereferencing an rvalue. */
5293 recording::dereference_rvalue::make_debug_string ()
5295 enum precedence prec
= get_precedence ();
5296 return string::from_printf (m_ctxt
,
5298 m_rvalue
->get_debug_string_parens (prec
));
5301 /* Implementation of recording::memento::write_reproducer for
5302 dereference_rvalue. */
5305 recording::dereference_rvalue::write_reproducer (reproducer
&r
)
5307 const char *id
= r
.make_identifier (this, "dereference");
5308 r
.write (" gcc_jit_lvalue *%s =\n"
5309 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5310 " %s); /* gcc_jit_location *loc */\n",
5312 r
.get_identifier_as_rvalue (m_rvalue
),
5313 r
.get_identifier (m_loc
));
5316 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5318 /* Implementation of pure virtual hook recording::memento::replay_into
5319 for recording::get_address_of_lvalue. */
5322 recording::get_address_of_lvalue::replay_into (replayer
*r
)
5325 m_lvalue
->playback_lvalue ()->
5326 get_address (playback_location (r
, m_loc
)));
5329 /* Implementation of pure virtual hook recording::rvalue::visit_children
5330 for recording::get_address_of_lvalue. */
5333 recording::get_address_of_lvalue::visit_children (rvalue_visitor
*v
)
5335 v
->visit (m_lvalue
);
5338 /* Implementation of recording::memento::make_debug_string for
5339 getting the address of an lvalue. */
5342 recording::get_address_of_lvalue::make_debug_string ()
5344 enum precedence prec
= get_precedence ();
5345 return string::from_printf (m_ctxt
,
5347 m_lvalue
->get_debug_string_parens (prec
));
5350 /* Implementation of recording::memento::write_reproducer for
5351 get_address_of_lvalue. */
5354 recording::get_address_of_lvalue::write_reproducer (reproducer
&r
)
5356 const char *id
= r
.make_identifier (this, "address_of");
5357 r
.write (" gcc_jit_rvalue *%s =\n"
5358 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5359 " %s); /* gcc_jit_location *loc */\n",
5361 r
.get_identifier_as_lvalue (m_lvalue
),
5362 r
.get_identifier (m_loc
));
5365 /* The implementation of class gcc::jit::recording::local. */
5367 /* Implementation of pure virtual hook recording::memento::replay_into
5368 for recording::local. */
5371 recording::local::replay_into (replayer
*r
)
5374 m_func
->playback_function ()
5375 ->new_local (playback_location (r
, m_loc
),
5376 m_type
->playback_type (),
5377 playback_string (m_name
)));
5380 /* Override the default implementation of
5381 recording::memento::write_to_dump for locals by writing
5383 for use at the top of the function body as if it were a
5387 recording::local::write_to_dump (dump
&d
)
5389 if (d
.update_locations ())
5390 m_loc
= d
.make_location ();
5391 d
.write(" %s %s;\n",
5392 m_type
->get_debug_string (),
5393 get_debug_string ());
5397 recording::local::write_reproducer (reproducer
&r
)
5399 const char *id
= r
.make_identifier (this, "local");
5400 r
.write (" gcc_jit_lvalue *%s =\n"
5401 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5402 " %s, /* gcc_jit_location *loc */\n"
5403 " %s, /* gcc_jit_type *type */\n"
5404 " %s); /* const char *name */\n",
5406 r
.get_identifier (m_func
),
5407 r
.get_identifier (m_loc
),
5408 r
.get_identifier_as_type (m_type
),
5409 m_name
->get_debug_string ());
5412 /* The implementation of class gcc::jit::recording::statement. */
5414 /* We poison the default implementation of
5415 gcc::jit::recording::statement::get_successor_blocks
5416 since this vfunc must only ever be called on terminator
5419 vec
<recording::block
*>
5420 recording::statement::get_successor_blocks () const
5422 /* The base class implementation is for non-terminating statements,
5423 and thus should never be called. */
5425 vec
<block
*> result
;
5430 /* Extend the default implementation of
5431 recording::memento::write_to_dump for statements by (if requested)
5432 updating the location of the statement to the current location in
5436 recording::statement::write_to_dump (dump
&d
)
5438 memento::write_to_dump (d
);
5439 if (d
.update_locations ())
5440 m_loc
= d
.make_location ();
5443 /* The implementation of class gcc::jit::recording::eval. */
5445 /* Implementation of pure virtual hook recording::memento::replay_into
5446 for recording::eval. */
5449 recording::eval::replay_into (replayer
*r
)
5451 playback_block (get_block ())
5452 ->add_eval (playback_location (r
),
5453 m_rvalue
->playback_rvalue ());
5456 /* Implementation of recording::memento::make_debug_string for
5457 an eval statement. */
5460 recording::eval::make_debug_string ()
5462 return string::from_printf (m_ctxt
,
5464 m_rvalue
->get_debug_string ());
5467 /* Implementation of recording::memento::write_reproducer for
5471 recording::eval::write_reproducer (reproducer
&r
)
5473 r
.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5474 " %s, /* gcc_jit_location *loc */\n"
5475 " %s); /* gcc_jit_rvalue *rvalue */\n",
5476 r
.get_identifier (get_block ()),
5477 r
.get_identifier (get_loc ()),
5478 r
.get_identifier_as_rvalue (m_rvalue
));
5481 /* The implementation of class gcc::jit::recording::assignment. */
5483 /* Implementation of pure virtual hook recording::memento::replay_into
5484 for recording::assignment. */
5487 recording::assignment::replay_into (replayer
*r
)
5489 playback_block (get_block ())
5490 ->add_assignment (playback_location (r
),
5491 m_lvalue
->playback_lvalue (),
5492 m_rvalue
->playback_rvalue ());
5495 /* Implementation of recording::memento::make_debug_string for
5496 an assignment statement. */
5499 recording::assignment::make_debug_string ()
5501 return string::from_printf (m_ctxt
,
5503 m_lvalue
->get_debug_string (),
5504 m_rvalue
->get_debug_string ());
5507 /* Implementation of recording::memento::write_reproducer for
5508 assignment statements. */
5511 recording::assignment::write_reproducer (reproducer
&r
)
5513 r
.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5514 " %s, /* gcc_jit_location *loc */\n"
5515 " %s, /* gcc_jit_lvalue *lvalue */\n"
5516 " %s); /* gcc_jit_rvalue *rvalue */\n",
5517 r
.get_identifier (get_block ()),
5518 r
.get_identifier (get_loc ()),
5519 r
.get_identifier_as_lvalue (m_lvalue
),
5520 r
.get_identifier_as_rvalue (m_rvalue
));
5523 /* The implementation of class gcc::jit::recording::assignment_op. */
5525 /* Implementation of pure virtual hook recording::memento::replay_into
5526 for recording::assignment_op. */
5529 recording::assignment_op::replay_into (replayer
*r
)
5531 playback::type
*result_type
=
5532 m_lvalue
->playback_lvalue ()->get_type ();
5534 playback::rvalue
*binary_op
=
5535 r
->new_binary_op (playback_location (r
),
5538 m_lvalue
->playback_rvalue (),
5539 m_rvalue
->playback_rvalue ());
5541 playback_block (get_block ())
5542 ->add_assignment (playback_location (r
),
5543 m_lvalue
->playback_lvalue (),
5547 /* Implementation of recording::memento::make_debug_string for
5548 an assignment_op statement. */
5551 recording::assignment_op::make_debug_string ()
5553 return string::from_printf (m_ctxt
,
5555 m_lvalue
->get_debug_string (),
5556 binary_op_strings
[m_op
],
5557 m_rvalue
->get_debug_string ());
5560 /* Implementation of recording::memento::write_reproducer for
5561 assignment_op statements. */
5564 recording::assignment_op::write_reproducer (reproducer
&r
)
5566 r
.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5567 " %s, /* gcc_jit_location *loc */\n"
5568 " %s, /* gcc_jit_lvalue *lvalue */\n"
5569 " %s, /* enum gcc_jit_binary_op op */\n"
5570 " %s); /* gcc_jit_rvalue *rvalue */\n",
5571 r
.get_identifier (get_block ()),
5572 r
.get_identifier (get_loc ()),
5573 r
.get_identifier_as_lvalue (m_lvalue
),
5574 binary_op_reproducer_strings
[m_op
],
5575 r
.get_identifier_as_rvalue (m_rvalue
));
5578 /* The implementation of class gcc::jit::recording::comment. */
5580 /* Implementation of pure virtual hook recording::memento::replay_into
5581 for recording::comment. */
5584 recording::comment::replay_into (replayer
*r
)
5586 playback_block (get_block ())
5587 ->add_comment (playback_location (r
),
5591 /* Implementation of recording::memento::make_debug_string for
5592 a comment "statement". */
5595 recording::comment::make_debug_string ()
5597 return string::from_printf (m_ctxt
,
5602 /* Implementation of recording::memento::write_reproducer for
5606 recording::comment::write_reproducer (reproducer
&r
)
5608 r
.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5609 " %s, /* gcc_jit_location *loc */\n"
5610 " %s); /* const char *text */\n",
5611 r
.get_identifier (get_block ()),
5612 r
.get_identifier (get_loc ()),
5613 m_text
->get_debug_string ());
5616 /* The implementation of class gcc::jit::recording::conditional. */
5618 /* Implementation of pure virtual hook recording::memento::replay_into
5619 for recording::conditional. */
5622 recording::conditional::replay_into (replayer
*r
)
5624 playback_block (get_block ())
5625 ->add_conditional (playback_location (r
),
5626 m_boolval
->playback_rvalue (),
5627 playback_block (m_on_true
),
5628 playback_block (m_on_false
));
5631 /* Override the poisoned default implementation of
5632 gcc::jit::recording::statement::get_successor_blocks
5634 A conditional jump has 2 successor blocks. */
5636 vec
<recording::block
*>
5637 recording::conditional::get_successor_blocks () const
5639 vec
<block
*> result
;
5641 result
.quick_push (m_on_true
);
5642 result
.quick_push (m_on_false
);
5646 /* Implementation of recording::memento::make_debug_string for
5647 a conditional jump statement. */
5650 recording::conditional::make_debug_string ()
5653 return string::from_printf (m_ctxt
,
5654 "if (%s) goto %s; else goto %s;",
5655 m_boolval
->get_debug_string (),
5656 m_on_true
->get_debug_string (),
5657 m_on_false
->get_debug_string ());
5659 return string::from_printf (m_ctxt
,
5661 m_boolval
->get_debug_string (),
5662 m_on_true
->get_debug_string ());
5665 /* Implementation of recording::memento::write_reproducer for
5666 conditional statements. */
5669 recording::conditional::write_reproducer (reproducer
&r
)
5671 r
.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5672 " %s, /* gcc_jit_location *loc */\n"
5673 " %s, /* gcc_jit_rvalue *boolval */\n"
5674 " %s, /* gcc_jit_block *on_true */\n"
5675 " %s); /* gcc_jit_block *on_false */\n",
5676 r
.get_identifier (get_block ()),
5677 r
.get_identifier (get_loc ()),
5678 r
.get_identifier_as_rvalue (m_boolval
),
5679 r
.get_identifier (m_on_true
),
5680 r
.get_identifier (m_on_false
));
5683 /* The implementation of class gcc::jit::recording::jump. */
5685 /* Implementation of pure virtual hook recording::memento::replay_into
5686 for recording::jump. */
5689 recording::jump::replay_into (replayer
*r
)
5691 playback_block (get_block ())
5692 ->add_jump (playback_location (r
),
5693 m_target
->playback_block ());
5696 /* Override the poisoned default implementation of
5697 gcc::jit::recording::statement::get_successor_blocks
5699 An unconditional jump has 1 successor block. */
5701 vec
<recording::block
*>
5702 recording::jump::get_successor_blocks () const
5704 vec
<block
*> result
;
5706 result
.quick_push (m_target
);
5710 /* Implementation of recording::memento::make_debug_string for
5711 a unconditional jump statement. */
5714 recording::jump::make_debug_string ()
5716 return string::from_printf (m_ctxt
,
5718 m_target
->get_debug_string ());
5721 /* Implementation of recording::memento::write_reproducer for
5725 recording::jump::write_reproducer (reproducer
&r
)
5727 r
.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5728 " %s, /* gcc_jit_location *loc */\n"
5729 " %s); /* gcc_jit_block *target */\n",
5730 r
.get_identifier (get_block ()),
5731 r
.get_identifier (get_loc ()),
5732 r
.get_identifier (m_target
));
5735 /* The implementation of class gcc::jit::recording::return_. */
5737 /* Implementation of pure virtual hook recording::memento::replay_into
5738 for recording::return_. */
5741 recording::return_::replay_into (replayer
*r
)
5743 playback_block (get_block ())
5744 ->add_return (playback_location (r
),
5745 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
5748 /* Override the poisoned default implementation of
5749 gcc::jit::recording::statement::get_successor_blocks
5751 A return statement has no successor block. */
5753 vec
<recording::block
*>
5754 recording::return_::get_successor_blocks () const
5756 vec
<block
*> result
;
5761 /* Implementation of recording::memento::make_debug_string for
5762 a return statement (covers both those with and without rvalues). */
5765 recording::return_::make_debug_string ()
5768 return string::from_printf (m_ctxt
,
5770 m_rvalue
->get_debug_string ());
5772 return string::from_printf (m_ctxt
,
5776 /* Implementation of recording::memento::write_reproducer for
5777 return statements. */
5780 recording::return_::write_reproducer (reproducer
&r
)
5783 r
.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5784 " %s, /* gcc_jit_location *loc */\n"
5785 " %s); /* gcc_jit_rvalue *rvalue */\n",
5786 r
.get_identifier (get_block ()),
5787 r
.get_identifier (get_loc ()),
5788 r
.get_identifier_as_rvalue (m_rvalue
));
5790 r
.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5791 " %s); /* gcc_jit_location *loc */\n",
5792 r
.get_identifier (get_block ()),
5793 r
.get_identifier (get_loc ()));
5796 /* The implementation of class gcc::jit::recording::case_. */
5799 recording::case_::write_reproducer (reproducer
&r
)
5801 const char *id
= r
.make_identifier (this, "case");
5803 " gcc_jit_case *%s = \n"
5804 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
5805 " %s, /* gcc_jit_rvalue *min_value */\n"
5806 " %s, /* gcc_jit_rvalue *max_value */\n"
5807 " %s); /* gcc_jit_block *dest_block */\n";
5810 r
.get_identifier (get_context ()),
5811 r
.get_identifier_as_rvalue (m_min_value
),
5812 r
.get_identifier_as_rvalue (m_max_value
),
5813 r
.get_identifier (m_dest_block
));
5817 recording::case_::make_debug_string ()
5819 return string::from_printf (get_context (),
5820 "case %s ... %s: goto %s;",
5821 m_min_value
->get_debug_string (),
5822 m_max_value
->get_debug_string (),
5823 m_dest_block
->get_debug_string ());
5826 /* The implementation of class gcc::jit::recording::switch_. */
5828 /* gcc::jit::recording::switch_'s constructor. */
5830 recording::switch_::switch_ (block
*b
,
5833 block
*default_block
,
5836 : statement (b
, loc
),
5838 m_default_block (default_block
)
5840 m_cases
.reserve_exact (num_cases
);
5841 for (int i
= 0; i
< num_cases
; i
++)
5842 m_cases
.quick_push (cases
[i
]);
5845 /* Implementation of pure virtual hook recording::memento::replay_into
5846 for recording::switch_. */
5849 recording::switch_::replay_into (replayer
*r
)
5851 auto_vec
<playback::case_
> pcases
;
5853 recording::case_
*rcase
;
5854 pcases
.reserve_exact (m_cases
.length ());
5855 FOR_EACH_VEC_ELT (m_cases
, i
, rcase
)
5857 playback::case_
pcase (rcase
->get_min_value ()->playback_rvalue (),
5858 rcase
->get_max_value ()->playback_rvalue (),
5859 rcase
->get_dest_block ()->playback_block ());
5860 pcases
.safe_push (pcase
);
5862 playback_block (get_block ())
5863 ->add_switch (playback_location (r
),
5864 m_expr
->playback_rvalue (),
5865 m_default_block
->playback_block (),
5869 /* Override the poisoned default implementation of
5870 gcc::jit::recording::statement::get_successor_blocks
5872 A switch statement has (NUM_CASES + 1) successor blocks. */
5874 vec
<recording::block
*>
5875 recording::switch_::get_successor_blocks () const
5877 vec
<block
*> result
;
5878 result
.create (m_cases
.length () + 1);
5879 result
.quick_push (m_default_block
);
5882 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
5883 result
.quick_push (c
->get_dest_block ());
5887 /* Implementation of recording::memento::make_debug_string for
5888 a switch statement. */
5891 recording::switch_::make_debug_string ()
5893 auto_vec
<char> cases_str
;
5896 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
5898 size_t len
= strlen (c
->get_debug_string ());
5899 unsigned idx
= cases_str
.length ();
5900 cases_str
.safe_grow (idx
+ 1 + len
);
5901 cases_str
[idx
] = ' ';
5902 memcpy (&(cases_str
[idx
+ 1]),
5903 c
->get_debug_string (),
5906 cases_str
.safe_push ('\0');
5908 return string::from_printf (m_ctxt
,
5909 "switch (%s) {default: goto %s;%s}",
5910 m_expr
->get_debug_string (),
5911 m_default_block
->get_debug_string (),
5915 /* Implementation of recording::memento::write_reproducer for
5916 switch statements. */
5919 recording::switch_::write_reproducer (reproducer
&r
)
5921 r
.make_identifier (this, "switch");
5924 const char *cases_id
=
5925 r
.make_tmp_identifier ("cases_for", this);
5926 r
.write (" gcc_jit_case *%s[%i] = {\n",
5929 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
5930 r
.write (" %s,\n", r
.get_identifier (c
));
5933 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
5934 " %s, /* gcc_jit_location *loc */\n"
5935 " %s, /* gcc_jit_rvalue *expr */\n"
5936 " %s, /* gcc_jit_block *default_block */\n"
5937 " %i, /* int num_cases */\n"
5938 " %s); /* gcc_jit_case **cases */\n";
5940 r
.get_identifier (get_block ()),
5941 r
.get_identifier (get_loc ()),
5942 r
.get_identifier_as_rvalue (m_expr
),
5943 r
.get_identifier (m_default_block
),
5948 } // namespace gcc::jit