1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2015 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
25 #include "pretty-print.h"
32 #include "jit-common.h"
33 #include "jit-builtins.h"
34 #include "jit-logging.h"
35 #include "jit-recording.h"
36 #include "jit-playback.h"
43 dump::dump (recording::context
&ctxt
,
45 bool update_locations
)
47 m_filename (filename
),
48 m_update_locations (update_locations
),
52 m_file
= fopen (filename
, "w");
55 "error opening dump file %s for writing: %s",
64 int err
= fclose (m_file
);
66 m_ctxt
.add_error (NULL
,
67 "error closing dump file %s: %s",
73 /* Write the given message to the dump, using printf-formatting
74 conventions, updating the line/column within the dump.
76 Emit an error on the context if a failure occurs. */
79 dump::write (const char *fmt
, ...)
85 /* If there was an error opening the file, we've already reported it.
86 Don't attempt further work. */
91 len
= vasprintf (&buf
, fmt
, ap
);
94 if (buf
== NULL
|| len
< 0)
96 m_ctxt
.add_error (NULL
, "malloc failure writing to dumpfile %s",
101 if (fwrite (buf
, strlen (buf
), 1, m_file
) != 1)
102 m_ctxt
.add_error (NULL
, "error writing to dump file %s",
105 /* Flush after each line, to ease debugging crashes. */
108 /* Update line/column: */
109 for (const char *ptr
= buf
; *ptr
; ptr
++)
123 /* Construct a gcc::jit::recording::location instance for the current
124 location within the dump. */
126 recording::location
*
127 dump::make_location () const
129 return m_ctxt
.new_location (m_filename
, m_line
, m_column
,
130 /* We need to flag such locations as *not*
131 created by the user, so that
132 reproducer::get_identifier can cope with
133 them appearing *after* the memento that
138 /* A collection of allocations, all of which can be released together, to
139 avoid needing to track and release them individually. */
147 xstrdup_printf (const char *, ...)
148 ATTRIBUTE_RETURNS_NONNULL
152 xstrdup_printf_va (const char *, va_list ap
)
153 ATTRIBUTE_RETURNS_NONNULL
157 auto_vec
<void *> m_buffers
;
160 /* allocator's destructor. Call "free" on all of the allocations. */
162 allocator::~allocator ()
166 FOR_EACH_VEC_ELT (m_buffers
, i
, buffer
)
170 /* Formatted printing, allocating to a buffer (or exiting the process if
171 the allocation fails).
173 The buffer exists until the allocator is cleaned up, and is freed at
174 that point, so the caller doesn't need to track the result. */
177 allocator::xstrdup_printf (const char *fmt
, ...)
182 result
= xstrdup_printf_va (fmt
, ap
);
187 /* Formatted printing, allocating to a buffer (or exiting the process if
188 the allocation fails).
190 The buffer exists until the allocator is cleaned up, and is freed at
191 that point, so the caller doesn't need to track the result. */
194 allocator::xstrdup_printf_va (const char *fmt
, va_list ap
)
196 char *result
= xvasprintf (fmt
, ap
);
197 m_buffers
.safe_push (result
);
201 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
202 implementing gcc_jit_context_dump_reproducer_to_file. */
204 class reproducer
: public dump
207 reproducer (recording::context
&ctxt
,
208 const char *filename
);
211 write_params (const vec
<recording::context
*> &contexts
);
214 write_args (const vec
<recording::context
*> &contexts
);
217 make_identifier (recording::memento
*m
, const char *prefix
);
220 make_tmp_identifier (const char *prefix
, recording::memento
*m
);
223 get_identifier (recording::context
*ctxt
);
226 get_identifier (recording::memento
*m
);
229 get_identifier_as_rvalue (recording::rvalue
*m
);
232 get_identifier_as_lvalue (recording::lvalue
*m
);
235 get_identifier_as_type (recording::type
*m
);
238 xstrdup_printf (const char *, ...)
239 ATTRIBUTE_RETURNS_NONNULL
243 hash_map
<recording::memento
*, const char *> m_identifiers
;
244 allocator m_allocator
;
247 /* gcc::jit::reproducer's constructor. */
249 reproducer::reproducer (recording::context
&ctxt
,
250 const char *filename
) :
251 dump (ctxt
, filename
, 0),
257 /* Write out a list of contexts as a set of parameters within a
258 C function declaration. */
261 reproducer::write_params (const vec
<recording::context
*> &contexts
)
264 recording::context
*ctxt
;
265 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
267 write ("gcc_jit_context *%s",
268 get_identifier (ctxt
));
269 if (i
< contexts
.length () - 1)
275 /* Write out a list of contexts as a set of arguments within a call
279 reproducer::write_args (const vec
<recording::context
*> &contexts
)
282 recording::context
*ctxt
;
283 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
286 get_identifier (ctxt
));
287 if (i
< contexts
.length () - 1)
293 /* Generate a C identifier for the given memento, associating the generated
294 buffer with the memento (for future calls to get_identifier et al).
296 The reproducer will eventually clean up the buffer in its dtor. */
298 reproducer::make_identifier (recording::memento
*m
, const char *prefix
)
301 if (strlen (m
->get_debug_string ()) < 100)
303 result
= m_allocator
.xstrdup_printf ("%s_%s_%p",
305 m
->get_debug_string (),
307 for (char *p
= result
; *p
; p
++)
312 result
= m_allocator
.xstrdup_printf ("%s_%p",
314 m_identifiers
.put (m
, result
);
318 /* Generate a C identifier for a temporary variable.
319 The reproducer will eventually clean up the buffer in its dtor. */
322 reproducer::make_tmp_identifier (const char *prefix
, recording::memento
*m
)
324 return m_allocator
.xstrdup_printf ("%s_%s",
325 prefix
, get_identifier (m
));
328 /* Generate a C identifier for the given context.
329 The reproducer will eventually clean up the buffer in its dtor. */
332 reproducer::get_identifier (recording::context
*ctxt
)
334 return m_allocator
.xstrdup_printf ("ctxt_%p",
338 /* Locate the C identifier for the given memento, which is assumed to
339 have already been created via make_identifier. */
342 reproducer::get_identifier (recording::memento
*m
)
347 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
348 and hence these locations appear in the context's memento list
349 out-of-order: they appear in the context's memento list *after*
350 the memento that refers to them. For this case, it's simplest to
351 pretend that they're NULL when writing out the code to recreate the
352 memento that uses them. */
353 if (recording::location
*loc
= m
->dyn_cast_location ())
354 if (!loc
->created_by_user ())
357 const char **slot
= m_identifiers
.get (m
);
360 get_context ().add_error (NULL
,
361 "unable to find identifier for %p: %s",
363 m
->get_debug_string ());
369 /* Locate the C identifier for the given rvalue, wrapping it within
370 a gcc_*_as_rvalue upcast if necessary. */
373 reproducer::get_identifier_as_rvalue (recording::rvalue
*m
)
375 return m
->access_as_rvalue (*this);
378 /* Locate the C identifier for the given lvalue, wrapping it within
379 a gcc_*_as_lvalue upcast if necessary. */
382 reproducer::get_identifier_as_lvalue (recording::lvalue
*m
)
384 return m
->access_as_lvalue (*this);
387 /* Locate the C identifier for the given type, wrapping it within
388 a gcc_*_as_type upcast if necessary. */
391 reproducer::get_identifier_as_type (recording::type
*m
)
393 return m
->access_as_type (*this);
396 /* Formatted printing, allocating to a buffer (or exiting the process if
397 the allocation fails).
399 The buffer exists until the allocator is cleaned up, and is freed at
400 that point, so the caller doesn't need to track the result.
402 Note that we can't use ggc_printf since we're not within the compiler
403 proper (when within gcc_jit_context_dump_reproducer_to_file). */
406 reproducer::xstrdup_printf (const char *fmt
, ...)
411 result
= m_allocator
.xstrdup_printf_va (fmt
, ap
);
416 /**********************************************************************
418 **********************************************************************/
420 /* Get the playback::location for the given recording::location,
421 handling a NULL input with a NULL output. */
424 recording::playback_location (replayer
*r
, recording::location
*loc
)
427 return loc
->playback_location (r
);
432 /* Get a const char * for the given recording::string
433 handling a NULL input with a NULL output. */
436 recording::playback_string (recording::string
*str
)
439 return str
->c_str ();
444 /* Get the playback::block for the given recording::block,
445 handling a NULL input with a NULL output. */
448 recording::playback_block (recording::block
*b
)
451 return b
->playback_block ();
456 /* Methods of cc::jit::recording::context. */
458 /* The constructor for gcc::jit::recording::context, used by
459 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
461 recording::context::context (context
*parent_ctxt
)
463 m_parent_ctxt (parent_ctxt
),
464 m_toplevel_ctxt (m_parent_ctxt
? m_parent_ctxt
->m_toplevel_ctxt
: this),
467 m_first_error_str (NULL
),
468 m_owns_first_error_str (false),
469 m_last_error_str (NULL
),
470 m_owns_last_error_str (false),
476 m_builtins_manager(NULL
)
480 /* Inherit options from parent. */
482 i
< sizeof (m_str_options
) / sizeof (m_str_options
[0]);
485 const char *parent_opt
= parent_ctxt
->m_str_options
[i
];
486 m_str_options
[i
] = parent_opt
? xstrdup (parent_opt
) : NULL
;
488 memcpy (m_int_options
,
489 parent_ctxt
->m_int_options
,
490 sizeof (m_int_options
));
491 memcpy (m_bool_options
,
492 parent_ctxt
->m_bool_options
,
493 sizeof (m_bool_options
));
494 memcpy (m_inner_bool_options
,
495 parent_ctxt
->m_inner_bool_options
,
496 sizeof (m_inner_bool_options
));
497 set_logger (parent_ctxt
->get_logger ());
501 memset (m_str_options
, 0, sizeof (m_str_options
));
502 memset (m_int_options
, 0, sizeof (m_int_options
));
503 memset (m_bool_options
, 0, sizeof (m_bool_options
));
504 memset (m_inner_bool_options
, 0, sizeof (m_inner_bool_options
));
507 memset (m_basic_types
, 0, sizeof (m_basic_types
));
510 /* The destructor for gcc::jit::recording::context, implicitly used by
511 gcc_jit_context_release. */
513 recording::context::~context ()
515 JIT_LOG_SCOPE (get_logger ());
518 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
523 for (i
= 0; i
< GCC_JIT_NUM_STR_OPTIONS
; ++i
)
524 free (m_str_options
[i
]);
527 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
530 if (m_builtins_manager
)
531 delete m_builtins_manager
;
533 if (m_owns_first_error_str
)
534 free (m_first_error_str
);
536 if (m_owns_last_error_str
)
537 if (m_last_error_str
!= m_first_error_str
)
538 free (m_last_error_str
);
541 /* Add the given mememto to the list of those tracked by this
542 gcc::jit::recording::context, so that e.g. it can be deleted
543 when this context is released. */
546 recording::context::record (memento
*m
)
550 m_mementos
.safe_push (m
);
553 /* Replay this context (and any parents) into the given replayer. */
556 recording::context::replay_into (replayer
*r
)
558 JIT_LOG_SCOPE (get_logger ());
562 /* If we have a parent context, we must replay it. This will
563 recursively walk backwards up the historical tree, then replay things
564 forwards "in historical order", starting with the ultimate parent
565 context, until we reach the "this" context.
567 Note that we fully replay the parent, then fully replay the child,
568 which means that inter-context references can only exist from child
569 to parent, not the other way around.
571 All of this replaying is suboptimal - it would be better to do the
572 work for the parent context *once*, rather than replaying the parent
573 every time we replay each child. However, fixing this requires deep
574 surgery to lifetime-management: we'd need every context family tree
575 to have its own GC heap, and to initialize the GCC code to use that
576 heap (with a mutex on such a heap). */
578 m_parent_ctxt
->replay_into (r
);
580 if (r
->errors_occurred ())
583 /* Replay this context's saved operations into r. */
584 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
586 /* Disabled low-level debugging, here if we need it: print what
588 Note that the calls to get_debug_string might lead to more
589 mementos being created for the strings.
590 This can also be used to exercise the debug_string
593 printf ("context %p replaying (%p): %s\n",
594 (void *)this, (void *)m
, m
->get_debug_string ());
598 if (r
->errors_occurred ())
603 /* During a playback, we associate objects from the recording with
604 their counterparts during this playback.
606 For simplicity, we store this within the recording objects.
608 The following method cleans away these associations, to ensure that
609 we never have out-of-date associations lingering on subsequent
610 playbacks (the objects pointed to are GC-managed, but the
611 recording objects don't own refs to them). */
614 recording::context::disassociate_from_playback ()
616 JIT_LOG_SCOPE (get_logger ());
621 m_parent_ctxt
->disassociate_from_playback ();
623 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
625 m
->set_playback_obj (NULL
);
629 /* Create a recording::string instance and add it to this context's list
632 This creates a fresh copy of the given 0-terminated buffer. */
635 recording::context::new_string (const char *text
)
640 recording::string
*result
= new string (this, text
);
645 /* Create a recording::location instance and add it to this context's
648 Implements the post-error-checking part of
649 gcc_jit_context_new_location. */
651 recording::location
*
652 recording::context::new_location (const char *filename
,
655 bool created_by_user
)
657 recording::location
*result
=
658 new recording::location (this,
659 new_string (filename
),
666 /* If we haven't seen this enum value yet, create a recording::type
667 instance and add it to this context's list of mementos.
669 If we have seen it before, reuse our cached value, so that repeated
670 calls on the context give the same object.
672 If we have a parent context, the cache is within the ultimate
675 Implements the post-error-checking part of
676 gcc_jit_context_get_type. */
679 recording::context::get_type (enum gcc_jit_types kind
)
681 if (!m_basic_types
[kind
])
684 m_basic_types
[kind
] = m_parent_ctxt
->get_type (kind
);
687 recording::type
*result
= new memento_of_get_type (this, kind
);
689 m_basic_types
[kind
] = result
;
693 return m_basic_types
[kind
];
696 /* Get a recording::type instance for the given size and signedness.
697 This is implemented in terms of recording::context::get_type
700 Implements the post-error-checking part of
701 gcc_jit_context_get_int_type. */
704 recording::context::get_int_type (int num_bytes
, int is_signed
)
706 /* We can't use a switch here since some of the values are macros affected
707 by options; e.g. i386.h has
708 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
709 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
710 are in bits, rather than bytes.
712 const int num_bits
= num_bytes
* 8;
713 if (num_bits
== INT_TYPE_SIZE
)
714 return get_type (is_signed
716 : GCC_JIT_TYPE_UNSIGNED_INT
);
717 if (num_bits
== CHAR_TYPE_SIZE
)
718 return get_type (is_signed
719 ? GCC_JIT_TYPE_SIGNED_CHAR
720 : GCC_JIT_TYPE_UNSIGNED_CHAR
);
721 if (num_bits
== SHORT_TYPE_SIZE
)
722 return get_type (is_signed
724 : GCC_JIT_TYPE_UNSIGNED_SHORT
);
725 if (num_bits
== LONG_TYPE_SIZE
)
726 return get_type (is_signed
728 : GCC_JIT_TYPE_UNSIGNED_LONG
);
729 if (num_bits
== LONG_LONG_TYPE_SIZE
)
730 return get_type (is_signed
731 ? GCC_JIT_TYPE_LONG_LONG
732 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
734 /* Some other size, not corresponding to the C int types. */
735 /* To be written: support arbitrary other sizes, sharing by
736 memoizing at the recording::context level? */
740 /* Create a recording::type instance and add it to this context's list
743 Implements the post-error-checking part of
744 gcc_jit_context_new_array_type. */
747 recording::context::new_array_type (recording::location
*loc
,
748 recording::type
*element_type
,
751 if (struct_
*s
= element_type
->dyn_cast_struct ())
752 if (!s
->get_fields ())
755 "cannot create an array of type %s"
756 " until the fields have been set",
757 s
->get_name ()->c_str ());
760 recording::type
*result
=
761 new recording::array_type (this, loc
, element_type
, num_elements
);
766 /* Create a recording::field instance and add it to this context's list
769 Implements the post-error-checking part of
770 gcc_jit_context_new_field. */
773 recording::context::new_field (recording::location
*loc
,
774 recording::type
*type
,
777 recording::field
*result
=
778 new recording::field (this, loc
, type
, new_string (name
));
783 /* Create a recording::struct_ instance and add it to this context's
784 list of mementos and list of compound types.
786 Implements the post-error-checking part of
787 gcc_jit_context_new_struct_type. */
790 recording::context::new_struct_type (recording::location
*loc
,
793 recording::struct_
*result
= new struct_ (this, loc
, new_string (name
));
795 m_compound_types
.safe_push (result
);
799 /* Create a recording::union_ instance and add it to this context's
800 list of mementos and list of compound types.
802 Implements the first post-error-checking part of
803 gcc_jit_context_new_union_type. */
806 recording::context::new_union_type (recording::location
*loc
,
809 recording::union_
*result
= new union_ (this, loc
, new_string (name
));
811 m_compound_types
.safe_push (result
);
815 /* Create a recording::function_type instance and add it to this context's
818 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
820 recording::function_type
*
821 recording::context::new_function_type (recording::type
*return_type
,
823 recording::type
**param_types
,
826 recording::function_type
*fn_type
827 = new function_type (this,
836 /* Create a recording::type instance and add it to this context's list
839 Implements the post-error-checking part of
840 gcc_jit_context_new_function_ptr_type. */
843 recording::context::new_function_ptr_type (recording::location
*, /* unused loc */
844 recording::type
*return_type
,
846 recording::type
**param_types
,
849 recording::function_type
*fn_type
850 = new_function_type (return_type
,
855 /* Return a pointer-type to the function type. */
856 return fn_type
->get_pointer ();
859 /* Create a recording::param instance and add it to this context's list
862 Implements the post-error-checking part of
863 gcc_jit_context_new_param. */
866 recording::context::new_param (recording::location
*loc
,
867 recording::type
*type
,
870 recording::param
*result
= new recording::param (this, loc
, type
, new_string (name
));
875 /* Create a recording::function instance and add it to this context's list
876 of mementos and list of functions.
878 Implements the post-error-checking part of
879 gcc_jit_context_new_function. */
881 recording::function
*
882 recording::context::new_function (recording::location
*loc
,
883 enum gcc_jit_function_kind kind
,
884 recording::type
*return_type
,
887 recording::param
**params
,
889 enum built_in_function builtin_id
)
891 recording::function
*result
=
892 new recording::function (this,
893 loc
, kind
, return_type
,
895 num_params
, params
, is_variadic
,
898 m_functions
.safe_push (result
);
903 /* Locate the builtins_manager (if any) for this family of contexts,
904 creating it if it doesn't exist already.
906 All of the recording contexts in a family share one builtins_manager:
907 if we have a child context, follow the parent links to get the
908 ultimate ancestor context, and look for it/store it there. */
911 recording::context::get_builtins_manager ()
914 return m_parent_ctxt
->get_builtins_manager ();
916 if (!m_builtins_manager
)
917 m_builtins_manager
= new builtins_manager (this);
919 return m_builtins_manager
;
922 /* Get a recording::function instance, which is lazily-created and added
923 to the context's lists of mementos.
925 Implements the post-error-checking part of
926 gcc_jit_context_get_builtin_function. */
928 recording::function
*
929 recording::context::get_builtin_function (const char *name
)
931 builtins_manager
*bm
= get_builtins_manager ();
932 return bm
->get_builtin_function (name
);
935 /* Create a recording::global instance and add it to this context's list
938 Implements the post-error-checking part of
939 gcc_jit_context_new_global. */
942 recording::context::new_global (recording::location
*loc
,
943 enum gcc_jit_global_kind kind
,
944 recording::type
*type
,
947 recording::global
*result
=
948 new recording::global (this, loc
, kind
, type
, new_string (name
));
950 m_globals
.safe_push (result
);
955 /* Create a recording::memento_of_new_string_literal instance and add it
956 to this context's list of mementos.
958 Implements the post-error-checking part of
959 gcc_jit_context_new_string_literal. */
962 recording::context::new_string_literal (const char *value
)
964 recording::rvalue
*result
=
965 new memento_of_new_string_literal (this, NULL
, new_string (value
));
970 /* Create a recording::unary_op instance and add it to this context's
973 Implements the post-error-checking part of
974 gcc_jit_context_new_unary_op. */
977 recording::context::new_unary_op (recording::location
*loc
,
978 enum gcc_jit_unary_op op
,
979 recording::type
*result_type
,
980 recording::rvalue
*a
)
982 recording::rvalue
*result
=
983 new unary_op (this, loc
, op
, result_type
, a
);
988 /* Create a recording::binary_op instance and add it to this context's
991 Implements the post-error-checking part of
992 gcc_jit_context_new_binary_op. */
995 recording::context::new_binary_op (recording::location
*loc
,
996 enum gcc_jit_binary_op op
,
997 recording::type
*result_type
,
998 recording::rvalue
*a
,
999 recording::rvalue
*b
)
1001 recording::rvalue
*result
=
1002 new binary_op (this, loc
, op
, result_type
, a
, b
);
1007 /* Create a recording::comparison instance and add it to this context's
1010 Implements the post-error-checking part of
1011 gcc_jit_context_new_comparison. */
1014 recording::context::new_comparison (recording::location
*loc
,
1015 enum gcc_jit_comparison op
,
1016 recording::rvalue
*a
,
1017 recording::rvalue
*b
)
1019 recording::rvalue
*result
= new comparison (this, loc
, op
, a
, b
);
1024 /* Create a recording::cast instance and add it to this context's list
1027 Implements the post-error-checking part of
1028 gcc_jit_context_new_cast. */
1031 recording::context::new_cast (recording::location
*loc
,
1032 recording::rvalue
*expr
,
1033 recording::type
*type_
)
1035 recording::rvalue
*result
= new cast (this, loc
, expr
, type_
);
1040 /* Create a recording::call instance and add it to this context's list
1043 Implements the post-error-checking part of
1044 gcc_jit_context_new_call. */
1047 recording::context::new_call (recording::location
*loc
,
1049 int numargs
, recording::rvalue
**args
)
1051 recording::rvalue
*result
= new call (this, loc
, func
, numargs
, args
);
1056 /* Create a recording::call_through_ptr instance and add it to this
1057 context's list of mementos.
1059 Implements the post-error-checking part of
1060 gcc_jit_context_new_call_through_ptr. */
1063 recording::context::new_call_through_ptr (recording::location
*loc
,
1064 recording::rvalue
*fn_ptr
,
1066 recording::rvalue
**args
)
1068 recording::rvalue
*result
= new call_through_ptr (this, loc
, fn_ptr
, numargs
, args
);
1073 /* Create a recording::array_access instance and add it to this context's list
1076 Implements the post-error-checking part of
1077 gcc_jit_context_new_array_access. */
1080 recording::context::new_array_access (recording::location
*loc
,
1081 recording::rvalue
*ptr
,
1082 recording::rvalue
*index
)
1084 recording::lvalue
*result
= new array_access (this, loc
, ptr
, index
);
1089 /* Create a recording::case_ instance and add it to this context's list
1092 Implements the post-error-checking part of
1093 gcc_jit_context_new_case. */
1096 recording::context::new_case (recording::rvalue
*min_value
,
1097 recording::rvalue
*max_value
,
1098 recording::block
*block
)
1100 recording::case_
*result
= new case_ (this, min_value
, max_value
, block
);
1105 /* Set the given string option for this context, or add an error if
1106 it's not recognized.
1108 Implements the post-error-checking part of
1109 gcc_jit_context_set_str_option. */
1112 recording::context::set_str_option (enum gcc_jit_str_option opt
,
1115 if (opt
< 0 || opt
>= GCC_JIT_NUM_STR_OPTIONS
)
1118 "unrecognized (enum gcc_jit_str_option) value: %i", opt
);
1121 free (m_str_options
[opt
]);
1122 m_str_options
[opt
] = value
? xstrdup (value
) : NULL
;
1123 log_str_option (opt
);
1126 /* Set the given integer option for this context, or add an error if
1127 it's not recognized.
1129 Implements the post-error-checking part of
1130 gcc_jit_context_set_int_option. */
1133 recording::context::set_int_option (enum gcc_jit_int_option opt
,
1136 if (opt
< 0 || opt
>= GCC_JIT_NUM_INT_OPTIONS
)
1139 "unrecognized (enum gcc_jit_int_option) value: %i", opt
);
1142 m_int_options
[opt
] = value
;
1143 log_int_option (opt
);
1146 /* Set the given boolean option for this context, or add an error if
1147 it's not recognized.
1149 Implements the post-error-checking part of
1150 gcc_jit_context_set_bool_option. */
1153 recording::context::set_bool_option (enum gcc_jit_bool_option opt
,
1156 if (opt
< 0 || opt
>= GCC_JIT_NUM_BOOL_OPTIONS
)
1159 "unrecognized (enum gcc_jit_bool_option) value: %i", opt
);
1162 m_bool_options
[opt
] = value
? true : false;
1163 log_bool_option (opt
);
1167 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt
,
1170 gcc_assert (inner_opt
>= 0 && inner_opt
< NUM_INNER_BOOL_OPTIONS
);
1171 m_inner_bool_options
[inner_opt
] = value
? true : false;
1172 log_inner_bool_option (inner_opt
);
1176 /* Add the given optname to this context's list of extra options.
1178 Implements the post-error-checking part of
1179 gcc_jit_context_add_command_line_option. */
1182 recording::context::add_command_line_option (const char *optname
)
1184 m_command_line_options
.safe_push (xstrdup (optname
));
1187 /* Add any user-provided extra options, starting with any from
1189 Called by playback::context::make_fake_args. */
1192 recording::context::append_command_line_options (vec
<char *> *argvec
)
1195 m_parent_ctxt
->append_command_line_options (argvec
);
1199 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1200 argvec
->safe_push (xstrdup (optname
));
1203 /* Add the given dumpname/out_ptr pair to this context's list of requested
1206 Implements the post-error-checking part of
1207 gcc_jit_context_enable_dump. */
1210 recording::context::enable_dump (const char *dumpname
,
1214 gcc_assert (dumpname
);
1215 gcc_assert (out_ptr
);
1217 d
.m_dumpname
= dumpname
;
1218 d
.m_out_ptr
= out_ptr
;
1220 m_requested_dumps
.safe_push (d
);
1223 /* Validate this context, and if it passes, compile it to memory
1226 Implements the post-error-checking part of
1227 gcc_jit_context_compile. */
1230 recording::context::compile ()
1232 JIT_LOG_SCOPE (get_logger ());
1238 if (errors_occurred ())
1241 /* Set up a compile_to_memory playback context. */
1242 ::gcc::jit::playback::compile_to_memory
replayer (this);
1245 replayer
.compile ();
1247 /* Get the jit::result (or NULL) from the
1248 compile_to_memory playback context. */
1249 return replayer
.get_result_obj ();
1252 /* Validate this context, and if it passes, compile it to a file
1255 Implements the post-error-checking part of
1256 gcc_jit_context_compile_to_file. */
1259 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind
,
1260 const char *output_path
)
1262 JIT_LOG_SCOPE (get_logger ());
1268 if (errors_occurred ())
1271 /* Set up a compile_to_file playback context. */
1272 ::gcc::jit::playback::compile_to_file
replayer (this,
1277 replayer
.compile ();
1280 /* Format the given error using printf's conventions, print
1281 it to stderr, and add it to the context. */
1284 recording::context::add_error (location
*loc
, const char *fmt
, ...)
1288 add_error_va (loc
, fmt
, ap
);
1292 /* Format the given error using printf's conventions, print
1293 it to stderr, and add it to the context. */
1296 recording::context::add_error_va (location
*loc
, const char *fmt
, va_list ap
)
1303 JIT_LOG_SCOPE (get_logger ());
1305 len
= vasprintf (&malloced_msg
, fmt
, ap
);
1306 if (malloced_msg
== NULL
|| len
< 0)
1308 errmsg
= "out of memory generating error message";
1309 has_ownership
= false;
1313 errmsg
= malloced_msg
;
1314 has_ownership
= true;
1317 get_logger ()->log ("error %i: %s", m_error_count
, errmsg
);
1319 const char *ctxt_progname
=
1320 get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
1322 ctxt_progname
= "libgccjit.so";
1325 fprintf (stderr
, "%s: %s: error: %s\n",
1327 loc
->get_debug_string (),
1330 fprintf (stderr
, "%s: error: %s\n",
1336 m_first_error_str
= const_cast <char *> (errmsg
);
1337 m_owns_first_error_str
= has_ownership
;
1340 if (m_owns_last_error_str
)
1341 if (m_last_error_str
!= m_first_error_str
)
1342 free (m_last_error_str
);
1343 m_last_error_str
= const_cast <char *> (errmsg
);
1344 m_owns_last_error_str
= has_ownership
;
1349 /* Get the message for the first error that occurred on this context, or
1350 NULL if no errors have occurred on it.
1352 Implements the post-error-checking part of
1353 gcc_jit_context_get_first_error. */
1356 recording::context::get_first_error () const
1358 return m_first_error_str
;
1361 /* Get the message for the last error that occurred on this context, or
1362 NULL if no errors have occurred on it.
1364 Implements the post-error-checking part of
1365 gcc_jit_context_get_last_error. */
1368 recording::context::get_last_error () const
1370 return m_last_error_str
;
1373 /* Lazily generate and record a recording::type representing an opaque
1374 struct named "FILE".
1376 For use if client code tries to dereference the result of
1377 get_type (GCC_JIT_TYPE_FILE_PTR). */
1380 recording::context::get_opaque_FILE_type ()
1383 m_FILE_type
= new_struct_type (NULL
, "FILE");
1387 /* Dump a C-like representation of the given context to the given path.
1388 If UPDATE_LOCATIONS is true, update the locations within the
1389 context's mementos to point to the dumpfile.
1391 Implements the post-error-checking part of
1392 gcc_jit_context_dump_to_file. */
1395 recording::context::dump_to_file (const char *path
, bool update_locations
)
1398 dump
d (*this, path
, update_locations
);
1400 /* Forward declaration of structs and unions. */
1402 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1404 d
.write ("%s;\n\n", st
->get_debug_string ());
1407 /* Content of structs, where set. */
1408 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1409 if (st
->get_fields ())
1411 st
->get_fields ()->write_to_dump (d
);
1417 FOR_EACH_VEC_ELT (m_globals
, i
, g
)
1419 g
->write_to_dump (d
);
1421 if (!m_globals
.is_empty ())
1425 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1427 fn
->write_to_dump (d
);
1431 static const char * const
1432 str_option_reproducer_strings
[GCC_JIT_NUM_STR_OPTIONS
] = {
1433 "GCC_JIT_STR_OPTION_PROGNAME"
1436 static const char * const
1437 int_option_reproducer_strings
[GCC_JIT_NUM_INT_OPTIONS
] = {
1438 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1441 static const char * const
1442 bool_option_reproducer_strings
[GCC_JIT_NUM_BOOL_OPTIONS
] = {
1443 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1444 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1445 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1446 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1447 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1448 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1449 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1450 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1453 static const char * const
1454 inner_bool_option_reproducer_strings
[NUM_INNER_BOOL_OPTIONS
] = {
1455 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1456 "gcc_jit_context_set_bool_use_external_driver"
1459 /* Write the current value of all options to the log file (if any). */
1462 recording::context::log_all_options () const
1469 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1470 log_str_option ((enum gcc_jit_str_option
)opt_idx
);
1472 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1473 log_int_option ((enum gcc_jit_int_option
)opt_idx
);
1475 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1476 log_bool_option ((enum gcc_jit_bool_option
)opt_idx
);
1477 for (opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1478 log_inner_bool_option ((enum inner_bool_option
)opt_idx
);
1481 /* Write the current value of the given string option to the
1482 log file (if any). */
1485 recording::context::log_str_option (enum gcc_jit_str_option opt
) const
1487 gcc_assert (opt
< GCC_JIT_NUM_STR_OPTIONS
);
1490 if (m_str_options
[opt
])
1492 str_option_reproducer_strings
[opt
],
1493 m_str_options
[opt
]);
1496 str_option_reproducer_strings
[opt
]);
1500 /* Write the current value of the given int option to the
1501 log file (if any). */
1504 recording::context::log_int_option (enum gcc_jit_int_option opt
) const
1506 gcc_assert (opt
< GCC_JIT_NUM_INT_OPTIONS
);
1509 int_option_reproducer_strings
[opt
],
1510 m_int_options
[opt
]);
1513 /* Write the current value of the given bool option to the
1514 log file (if any). */
1517 recording::context::log_bool_option (enum gcc_jit_bool_option opt
) const
1519 gcc_assert (opt
< GCC_JIT_NUM_BOOL_OPTIONS
);
1522 bool_option_reproducer_strings
[opt
],
1523 m_bool_options
[opt
] ? "true" : "false");
1526 /* Write the current value of the given "inner" bool option to the
1527 log file (if any). */
1530 recording::context::log_inner_bool_option (enum inner_bool_option opt
) const
1532 gcc_assert (opt
< NUM_INNER_BOOL_OPTIONS
);
1535 inner_bool_option_reproducer_strings
[opt
],
1536 m_inner_bool_options
[opt
] ? "true" : "false");
1539 /* Write C source code to PATH that attempts to replay the API
1540 calls made to this context (and its parents), for use in
1541 minimizing test cases for libgccjit.
1543 Implements the post-error-checking part of
1544 gcc_jit_context_dump_reproducer_to_file. */
1547 recording::context::dump_reproducer_to_file (const char *path
)
1549 JIT_LOG_SCOPE (get_logger ());
1550 reproducer
r (*this, path
);
1552 /* Generate the "ancestry" of this context, as a list. */
1553 auto_vec
<context
*> ascending_contexts
;
1554 for (context
*ctxt
= this; ctxt
; ctxt
= ctxt
->m_parent_ctxt
)
1555 ascending_contexts
.safe_push (ctxt
);
1557 /* Reverse the list, giving a list of contexts from
1558 top-most parent context down through to youngest child context.
1559 We will use this list as the parameters of the functions in
1560 our generated file. */
1561 unsigned num_ctxts
= ascending_contexts
.length ();
1562 auto_vec
<context
*> contexts (num_ctxts
);
1563 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1564 contexts
.safe_push (ascending_contexts
[num_ctxts
- (i
+ 1)]);
1566 /* contexts[0] should be the top-level context. */
1567 gcc_assert (contexts
[0]);
1568 gcc_assert (contexts
[0]->m_toplevel_ctxt
== contexts
[0]);
1570 /* The final element in contexts should be "this". */
1571 gcc_assert (contexts
[contexts
.length () - 1] == this);
1572 gcc_assert (contexts
[contexts
.length () - 1]->m_toplevel_ctxt
1575 r
.write ("/* This code was autogenerated by"
1576 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1577 print_version (r
.get_file (), " ", false);
1579 r
.write ("#include <libgccjit.h>\n\n");
1580 r
.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1581 r
.write ("static void\nset_options (");
1582 r
.write_params (contexts
);
1584 r
.write ("static void\ncreate_code (");
1585 r
.write_params (contexts
);
1587 r
.write ("int\nmain (int argc, const char **argv)\n");
1589 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1590 r
.write (" gcc_jit_context *%s;\n",
1591 r
.get_identifier (contexts
[i
]));
1592 r
.write (" gcc_jit_result *result;\n"
1595 /* Create the contexts.
1596 The top-level context is acquired from a clean slate, the others as
1597 children of the prior context. */
1598 r
.write (" %s = gcc_jit_context_acquire ();\n",
1599 r
.get_identifier (contexts
[0]));
1600 for (unsigned i
= 1; i
< num_ctxts
; i
++)
1601 r
.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1602 r
.get_identifier (contexts
[i
]),
1603 r
.get_identifier (contexts
[i
- 1]));
1604 r
.write (" set_options (");
1605 r
.write_args (contexts
);
1607 r
.write (" create_code (");
1608 r
.write_args (contexts
);
1611 r
.write (" result = gcc_jit_context_compile (%s);\n",
1612 r
.get_identifier (this));
1614 for (unsigned i
= num_ctxts
; i
> 0; i
--)
1615 r
.write (" gcc_jit_context_release (%s);\n",
1616 r
.get_identifier (contexts
[i
- 1]));
1618 r
.write (" gcc_jit_result_release (result);\n"
1622 /* Define (char *) variables for use in calls to
1623 gcc_jit_context_enable_dump. */
1624 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1626 if (m_requested_dumps
.length ())
1628 r
.write ("/* Requested dumps for %s. */\n",
1629 r
.get_identifier (contexts
[ctxt_idx
]));
1630 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1631 r
.write ("static char *dump_%p;\n",
1632 (void *)&m_requested_dumps
[i
]);
1637 /* Write out values of options. */
1638 r
.write ("static void\nset_options (");
1639 r
.write_params (contexts
);
1641 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1646 r
.write (" /* Set options for %s. */\n",
1647 r
.get_identifier (contexts
[ctxt_idx
]));
1649 r
.write (" /* String options. */\n");
1650 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1652 r
.write (" gcc_jit_context_set_str_option (%s,\n"
1654 r
.get_identifier (contexts
[ctxt_idx
]),
1655 str_option_reproducer_strings
[opt_idx
]);
1656 if (m_str_options
[opt_idx
])
1657 r
.write (" \"%s\");\n",
1658 m_str_options
[opt_idx
]);
1660 r
.write (" NULL);\n");
1662 r
.write (" /* Int options. */\n");
1663 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1664 r
.write (" gcc_jit_context_set_int_option (%s,\n"
1667 r
.get_identifier (contexts
[ctxt_idx
]),
1668 int_option_reproducer_strings
[opt_idx
],
1669 m_int_options
[opt_idx
]);
1670 r
.write (" /* Boolean options. */\n");
1671 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1672 r
.write (" gcc_jit_context_set_bool_option (%s,\n"
1675 r
.get_identifier (contexts
[ctxt_idx
]),
1676 bool_option_reproducer_strings
[opt_idx
],
1677 m_bool_options
[opt_idx
]);
1678 for (int opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1679 r
.write (" %s (%s, %i);\n",
1680 inner_bool_option_reproducer_strings
[opt_idx
],
1681 r
.get_identifier (contexts
[ctxt_idx
]),
1682 m_inner_bool_options
[opt_idx
]);
1684 if (!m_command_line_options
.is_empty ())
1688 r
.write (" /* User-provided command-line options. */\n");
1689 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1690 r
.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1691 r
.get_identifier (contexts
[ctxt_idx
]),
1695 if (m_requested_dumps
.length ())
1697 r
.write (" /* Requested dumps. */\n");
1698 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1699 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1701 r
.write (" gcc_jit_context_enable_dump (%s,\n"
1704 r
.get_identifier (contexts
[ctxt_idx
]),
1705 m_requested_dumps
[i
].m_dumpname
,
1706 (void *)&m_requested_dumps
[i
]);
1712 r
.write ("static void\ncreate_code (");
1713 r
.write_params (contexts
);
1716 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1723 r
.write (" /* Replay of API calls for %s. */\n",
1724 r
.get_identifier (contexts
[ctxt_idx
]));
1725 FOR_EACH_VEC_ELT (contexts
[ctxt_idx
]->m_mementos
, i
, m
)
1726 m
->write_reproducer (r
);
1731 /* Copy the requested dumps within this context and all ancestors into
1735 recording::context::get_all_requested_dumps (vec
<recording::requested_dump
> *out
)
1738 m_parent_ctxt
->get_all_requested_dumps (out
);
1740 out
->reserve (m_requested_dumps
.length ());
1741 out
->splice (m_requested_dumps
);
1744 /* This is a pre-compilation check for the context (and any parents).
1746 Detect errors within the context, adding errors if any are found. */
1749 recording::context::validate ()
1751 JIT_LOG_SCOPE (get_logger ());
1754 m_parent_ctxt
->validate ();
1758 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1762 /* The implementation of class gcc::jit::recording::memento. */
1764 /* Get a (const char *) debug description of the given memento, by
1765 calling the pure-virtual make_debug_string hook, caching the
1768 It is intended that this should only be called in debugging and
1769 error-handling paths, so this doesn't need to be particularly
1773 recording::memento::get_debug_string ()
1775 if (!m_debug_string
)
1776 m_debug_string
= make_debug_string ();
1777 return m_debug_string
->c_str ();
1780 /* Default implementation of recording::memento::write_to_dump, writing
1781 an indented form of the memento's debug string to the dump. */
1784 recording::memento::write_to_dump (dump
&d
)
1786 d
.write(" %s\n", get_debug_string ());
1789 /* The implementation of class gcc::jit::recording::string. */
1791 /* Constructor for gcc::jit::recording::string::string, allocating a
1792 copy of the given text using new char[]. */
1794 recording::string::string (context
*ctxt
, const char *text
)
1797 m_len
= strlen (text
);
1798 m_buffer
= new char[m_len
+ 1];
1799 strcpy (m_buffer
, text
);
1802 /* Destructor for gcc::jit::recording::string::string. */
1804 recording::string::~string ()
1809 /* Function for making gcc::jit::recording::string instances on a
1810 context via printf-style formatting.
1812 It is intended that this should only be called in debugging and
1813 error-handling paths, so this doesn't need to be particularly
1814 optimized, hence the double-copy of the string is acceptable. */
1817 recording::string::from_printf (context
*ctxt
, const char *fmt
, ...)
1822 recording::string
*result
;
1825 len
= vasprintf (&buf
, fmt
, ap
);
1828 if (buf
== NULL
|| len
< 0)
1830 ctxt
->add_error (NULL
, "malloc failure");
1834 result
= ctxt
->new_string (buf
);
1839 /* Implementation of recording::memento::make_debug_string for strings,
1840 wrapping the given string in quotes and escaping as necessary. */
1843 recording::string::make_debug_string ()
1845 /* Hack to avoid infinite recursion into strings when logging all
1846 mementos: don't re-escape strings: */
1847 if (m_buffer
[0] == '"')
1850 /* Wrap in quotes and do escaping etc */
1852 size_t sz
= (1 /* opening quote */
1853 + (m_len
* 2) /* each char might get escaped */
1854 + 1 /* closing quote */
1855 + 1); /* nil termintator */
1856 char *tmp
= new char[sz
];
1859 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1860 APPEND('"'); /* opening quote */
1861 for (size_t i
= 0; i
< m_len
; i
++)
1863 char ch
= m_buffer
[i
];
1864 if (ch
== '\t' || ch
== '\n' || ch
== '\\' || ch
== '"')
1868 APPEND('"'); /* closing quote */
1870 tmp
[len
] = '\0'; /* nil termintator */
1872 string
*result
= m_ctxt
->new_string (tmp
);
1878 /* Implementation of recording::memento::write_reproducer for strings. */
1881 recording::string::write_reproducer (reproducer
&)
1886 /* The implementation of class gcc::jit::recording::location. */
1888 /* Implementation of recording::memento::replay_into for locations.
1890 Create a new playback::location and store it into the
1891 recording::location's m_playback_obj field. */
1894 recording::location::replay_into (replayer
*r
)
1896 m_playback_obj
= r
->new_location (this,
1897 m_filename
->c_str (),
1902 /* Implementation of recording::memento::make_debug_string for locations,
1903 turning them into the usual form:
1904 FILENAME:LINE:COLUMN
1905 like we do when emitting diagnostics. */
1908 recording::location::make_debug_string ()
1910 return string::from_printf (m_ctxt
,
1912 m_filename
->c_str (), m_line
, m_column
);
1915 /* Implementation of recording::memento::write_reproducer for locations. */
1918 recording::location::write_reproducer (reproducer
&r
)
1920 const char *id
= r
.make_identifier (this, "loc");
1921 r
.write (" gcc_jit_location *%s =\n"
1922 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1923 " %s, /* const char *filename */\n"
1924 " %i, /* int line */\n"
1925 " %i);/* int column */\n",
1927 r
.get_identifier (get_context ()),
1928 m_filename
->get_debug_string (),
1932 /* The implementation of class gcc::jit::recording::type. */
1934 /* Given a type T, get the type T*.
1936 If this doesn't already exist, generate a new memento_of_get_pointer
1937 instance and add it to this type's context's list of mementos.
1939 Otherwise, use the cached type.
1941 Implements the post-error-checking part of
1942 gcc_jit_type_get_pointer. */
1945 recording::type::get_pointer ()
1947 if (!m_pointer_to_this_type
)
1949 m_pointer_to_this_type
= new memento_of_get_pointer (this);
1950 m_ctxt
->record (m_pointer_to_this_type
);
1952 return m_pointer_to_this_type
;
1955 /* Given a type T, get the type const T.
1957 Implements the post-error-checking part of
1958 gcc_jit_type_get_const. */
1961 recording::type::get_const ()
1963 recording::type
*result
= new memento_of_get_const (this);
1964 m_ctxt
->record (result
);
1968 /* Given a type T, get the type volatile T.
1970 Implements the post-error-checking part of
1971 gcc_jit_type_get_volatile. */
1974 recording::type::get_volatile ()
1976 recording::type
*result
= new memento_of_get_volatile (this);
1977 m_ctxt
->record (result
);
1982 recording::type::access_as_type (reproducer
&r
)
1984 return r
.get_identifier (this);
1987 /* Implementation of pure virtual hook recording::type::dereference for
1988 recording::memento_of_get_type. */
1991 recording::memento_of_get_type::dereference ()
1995 default: gcc_unreachable ();
1997 case GCC_JIT_TYPE_VOID
:
2000 case GCC_JIT_TYPE_VOID_PTR
:
2001 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
2003 case GCC_JIT_TYPE_BOOL
:
2004 case GCC_JIT_TYPE_CHAR
:
2005 case GCC_JIT_TYPE_SIGNED_CHAR
:
2006 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2007 case GCC_JIT_TYPE_SHORT
:
2008 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2009 case GCC_JIT_TYPE_INT
:
2010 case GCC_JIT_TYPE_UNSIGNED_INT
:
2011 case GCC_JIT_TYPE_LONG
:
2012 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2013 case GCC_JIT_TYPE_LONG_LONG
:
2014 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2015 case GCC_JIT_TYPE_FLOAT
:
2016 case GCC_JIT_TYPE_DOUBLE
:
2017 case GCC_JIT_TYPE_LONG_DOUBLE
:
2018 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2019 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2020 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2021 /* Not a pointer: */
2024 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2025 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
2027 case GCC_JIT_TYPE_SIZE_T
:
2028 /* Not a pointer: */
2031 case GCC_JIT_TYPE_FILE_PTR
:
2032 /* Give the client code back an opaque "struct FILE". */
2033 return m_ctxt
->get_opaque_FILE_type ();
2037 /* Implementation of pure virtual hook recording::type::is_int for
2038 recording::memento_of_get_type. */
2041 recording::memento_of_get_type::is_int () const
2045 default: gcc_unreachable ();
2047 case GCC_JIT_TYPE_VOID
:
2050 case GCC_JIT_TYPE_VOID_PTR
:
2053 case GCC_JIT_TYPE_BOOL
:
2056 case GCC_JIT_TYPE_CHAR
:
2057 case GCC_JIT_TYPE_SIGNED_CHAR
:
2058 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2059 case GCC_JIT_TYPE_SHORT
:
2060 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2061 case GCC_JIT_TYPE_INT
:
2062 case GCC_JIT_TYPE_UNSIGNED_INT
:
2063 case GCC_JIT_TYPE_LONG
:
2064 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2065 case GCC_JIT_TYPE_LONG_LONG
:
2066 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2069 case GCC_JIT_TYPE_FLOAT
:
2070 case GCC_JIT_TYPE_DOUBLE
:
2071 case GCC_JIT_TYPE_LONG_DOUBLE
:
2074 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2077 case GCC_JIT_TYPE_SIZE_T
:
2080 case GCC_JIT_TYPE_FILE_PTR
:
2083 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2084 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2085 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2090 /* Implementation of pure virtual hook recording::type::is_float for
2091 recording::memento_of_get_type. */
2094 recording::memento_of_get_type::is_float () const
2098 default: gcc_unreachable ();
2100 case GCC_JIT_TYPE_VOID
:
2103 case GCC_JIT_TYPE_VOID_PTR
:
2106 case GCC_JIT_TYPE_BOOL
:
2109 case GCC_JIT_TYPE_CHAR
:
2110 case GCC_JIT_TYPE_SIGNED_CHAR
:
2111 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2112 case GCC_JIT_TYPE_SHORT
:
2113 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2114 case GCC_JIT_TYPE_INT
:
2115 case GCC_JIT_TYPE_UNSIGNED_INT
:
2116 case GCC_JIT_TYPE_LONG
:
2117 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2118 case GCC_JIT_TYPE_LONG_LONG
:
2119 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2122 case GCC_JIT_TYPE_FLOAT
:
2123 case GCC_JIT_TYPE_DOUBLE
:
2124 case GCC_JIT_TYPE_LONG_DOUBLE
:
2127 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2130 case GCC_JIT_TYPE_SIZE_T
:
2133 case GCC_JIT_TYPE_FILE_PTR
:
2136 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2137 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2138 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2143 /* Implementation of pure virtual hook recording::type::is_bool for
2144 recording::memento_of_get_type. */
2147 recording::memento_of_get_type::is_bool () const
2151 default: gcc_unreachable ();
2153 case GCC_JIT_TYPE_VOID
:
2156 case GCC_JIT_TYPE_VOID_PTR
:
2159 case GCC_JIT_TYPE_BOOL
:
2162 case GCC_JIT_TYPE_CHAR
:
2163 case GCC_JIT_TYPE_SIGNED_CHAR
:
2164 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2165 case GCC_JIT_TYPE_SHORT
:
2166 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2167 case GCC_JIT_TYPE_INT
:
2168 case GCC_JIT_TYPE_UNSIGNED_INT
:
2169 case GCC_JIT_TYPE_LONG
:
2170 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2171 case GCC_JIT_TYPE_LONG_LONG
:
2172 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2175 case GCC_JIT_TYPE_FLOAT
:
2176 case GCC_JIT_TYPE_DOUBLE
:
2177 case GCC_JIT_TYPE_LONG_DOUBLE
:
2180 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2183 case GCC_JIT_TYPE_SIZE_T
:
2186 case GCC_JIT_TYPE_FILE_PTR
:
2189 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2190 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2191 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2196 /* Implementation of pure virtual hook recording::memento::replay_into
2197 for recording::memento_of_get_type. */
2200 recording::memento_of_get_type::replay_into (replayer
*r
)
2202 set_playback_obj (r
->get_type (m_kind
));
2205 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2207 /* Descriptive strings for each of enum gcc_jit_types. */
2209 static const char * const get_type_strings
[] = {
2210 "void", /* GCC_JIT_TYPE_VOID */
2211 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2213 "bool", /* GCC_JIT_TYPE_BOOL */
2215 "char", /* GCC_JIT_TYPE_CHAR */
2216 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2217 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2219 "short", /* GCC_JIT_TYPE_SHORT */
2220 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2222 "int", /* GCC_JIT_TYPE_INT */
2223 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2225 "long", /* GCC_JIT_TYPE_LONG */
2226 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2228 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2229 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2231 "float", /* GCC_JIT_TYPE_FLOAT */
2232 "double", /* GCC_JIT_TYPE_DOUBLE */
2233 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2235 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2237 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2239 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2241 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2242 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2243 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2247 /* Implementation of recording::memento::make_debug_string for
2248 results of get_type, using a simple table of type names. */
2251 recording::memento_of_get_type::make_debug_string ()
2253 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
2256 static const char * const get_type_enum_strings
[] = {
2257 "GCC_JIT_TYPE_VOID",
2258 "GCC_JIT_TYPE_VOID_PTR",
2259 "GCC_JIT_TYPE_BOOL",
2260 "GCC_JIT_TYPE_CHAR",
2261 "GCC_JIT_TYPE_SIGNED_CHAR",
2262 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2263 "GCC_JIT_TYPE_SHORT",
2264 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2266 "GCC_JIT_TYPE_UNSIGNED_INT",
2267 "GCC_JIT_TYPE_LONG",
2268 "GCC_JIT_TYPE_UNSIGNED_LONG",
2269 "GCC_JIT_TYPE_LONG_LONG",
2270 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2271 "GCC_JIT_TYPE_FLOAT",
2272 "GCC_JIT_TYPE_DOUBLE",
2273 "GCC_JIT_TYPE_LONG_DOUBLE",
2274 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2275 "GCC_JIT_TYPE_SIZE_T",
2276 "GCC_JIT_TYPE_FILE_PTR",
2277 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2278 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2279 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2283 recording::memento_of_get_type::write_reproducer (reproducer
&r
)
2285 const char *id
= r
.make_identifier (this, "type");
2286 r
.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2288 r
.get_identifier (get_context ()),
2289 get_type_enum_strings
[m_kind
]);
2292 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2294 /* Override of default implementation of
2295 recording::type::accepts_writes_from for get_pointer.
2297 Require a pointer type, and allowing writes to
2298 (const T *) from a (T*), but not the other way around. */
2301 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
2303 /* Must be a pointer type: */
2304 type
*rtype_points_to
= rtype
->is_pointer ();
2305 if (!rtype_points_to
)
2308 /* It's OK to assign to a (const T *) from a (T *). */
2309 return m_other_type
->unqualified ()
2310 ->accepts_writes_from (rtype_points_to
);
2313 /* Implementation of pure virtual hook recording::memento::replay_into
2314 for recording::memento_of_get_pointer. */
2317 recording::memento_of_get_pointer::replay_into (replayer
*)
2319 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
2322 /* Implementation of recording::memento::make_debug_string for
2323 results of get_pointer, adding " *" to the underlying type,
2324 with special-casing to handle function pointer types. */
2327 recording::memento_of_get_pointer::make_debug_string ()
2329 /* Special-case function pointer types, to put the "*" in parens between
2330 the return type and the params (for one level of dereferencing, at
2332 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2333 return fn_type
->make_debug_string_with_ptr ();
2335 return string::from_printf (m_ctxt
,
2336 "%s *", m_other_type
->get_debug_string ());
2339 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2342 recording::memento_of_get_pointer::write_reproducer (reproducer
&r
)
2344 /* We need to special-case function pointer types; see the notes in
2345 recording::function_type::write_deferred_reproducer. */
2346 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2348 fn_type
->write_deferred_reproducer (r
, this);
2352 const char *id
= r
.make_identifier (this, "type");
2353 r
.write (" gcc_jit_type *%s =\n"
2354 " gcc_jit_type_get_pointer (%s);\n",
2356 r
.get_identifier_as_type (m_other_type
));
2359 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2361 /* Implementation of pure virtual hook recording::memento::replay_into
2362 for recording::memento_of_get_const. */
2365 recording::memento_of_get_const::replay_into (replayer
*)
2367 set_playback_obj (m_other_type
->playback_type ()->get_const ());
2370 /* Implementation of recording::memento::make_debug_string for
2371 results of get_const, prepending "const ". */
2374 recording::memento_of_get_const::make_debug_string ()
2376 return string::from_printf (m_ctxt
,
2377 "const %s", m_other_type
->get_debug_string ());
2380 /* Implementation of recording::memento::write_reproducer for const types. */
2383 recording::memento_of_get_const::write_reproducer (reproducer
&r
)
2385 const char *id
= r
.make_identifier (this, "type");
2386 r
.write (" gcc_jit_type *%s =\n"
2387 " gcc_jit_type_get_const (%s);\n",
2389 r
.get_identifier_as_type (m_other_type
));
2392 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2394 /* Implementation of pure virtual hook recording::memento::replay_into
2395 for recording::memento_of_get_volatile. */
2398 recording::memento_of_get_volatile::replay_into (replayer
*)
2400 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
2403 /* Implementation of recording::memento::make_debug_string for
2404 results of get_volatile, prepending "volatile ". */
2407 recording::memento_of_get_volatile::make_debug_string ()
2409 return string::from_printf (m_ctxt
,
2410 "volatile %s", m_other_type
->get_debug_string ());
2413 /* Implementation of recording::memento::write_reproducer for volatile
2417 recording::memento_of_get_volatile::write_reproducer (reproducer
&r
)
2419 const char *id
= r
.make_identifier (this, "type");
2420 r
.write (" gcc_jit_type *%s =\n"
2421 " gcc_jit_type_get_volatile (%s);\n",
2423 r
.get_identifier_as_type (m_other_type
));
2426 /* The implementation of class gcc::jit::recording::array_type */
2428 /* Implementation of pure virtual hook recording::type::dereference for
2429 recording::array_type. */
2432 recording::array_type::dereference ()
2434 return m_element_type
;
2437 /* Implementation of pure virtual hook recording::memento::replay_into
2438 for recording::array_type. */
2441 recording::array_type::replay_into (replayer
*r
)
2443 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
2444 m_element_type
->playback_type (),
2448 /* Implementation of recording::memento::make_debug_string for
2449 results of new_array_type. */
2452 recording::array_type::make_debug_string ()
2454 return string::from_printf (m_ctxt
,
2456 m_element_type
->get_debug_string (),
2460 /* Implementation of recording::memento::write_reproducer for array
2464 recording::array_type::write_reproducer (reproducer
&r
)
2466 const char *id
= r
.make_identifier (this, "array_type");
2467 r
.write (" gcc_jit_type *%s =\n"
2468 " gcc_jit_context_new_array_type (%s,\n"
2469 " %s, /* gcc_jit_location *loc */\n"
2470 " %s, /* gcc_jit_type *element_type */\n"
2471 " %i); /* int num_elements */\n",
2473 r
.get_identifier (get_context ()),
2474 r
.get_identifier (m_loc
),
2475 r
.get_identifier_as_type (m_element_type
),
2479 /* The implementation of class gcc::jit::recording::function_type */
2481 /* Constructor for gcc::jit::recording::function_type. */
2483 recording::function_type::function_type (context
*ctxt
,
2489 m_return_type (return_type
),
2491 m_is_variadic (is_variadic
)
2493 for (int i
= 0; i
< num_params
; i
++)
2494 m_param_types
.safe_push (param_types
[i
]);
2497 /* Implementation of pure virtual hook recording::type::dereference for
2498 recording::function_type. */
2501 recording::function_type::dereference ()
2506 /* Implementation of pure virtual hook recording::memento::replay_into
2507 for recording::function_type. */
2510 recording::function_type::replay_into (replayer
*r
)
2512 /* Convert m_param_types to a vec of playback type. */
2513 auto_vec
<playback::type
*> param_types
;
2515 recording::type
*type
;
2516 param_types
.create (m_param_types
.length ());
2517 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
2518 param_types
.safe_push (type
->playback_type ());
2520 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
2525 /* Special-casing for make_debug_string for get_pointer results for
2526 handling (one level) of pointers to functions. */
2529 recording::function_type::make_debug_string_with_ptr ()
2531 return make_debug_string_with ("(*) ");
2534 /* Implementation of recording::memento::make_debug_string for
2535 results of new_function_type. */
2538 recording::function_type::make_debug_string ()
2540 return make_debug_string_with ("");
2543 /* Build a debug string representation of the form:
2545 RESULT_TYPE INSERT (PARAM_TYPES)
2547 for use when handling 0 and 1 level of indirection to this
2551 recording::function_type::make_debug_string_with (const char *insert
)
2553 /* First, build a buffer for the arguments. */
2554 /* Calculate length of said buffer. */
2555 size_t sz
= 1; /* nil terminator */
2556 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2558 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
2559 sz
+= 2; /* ", " separator */
2562 sz
+= 5; /* ", ..." separator and ellipsis */
2564 /* Now allocate and populate the buffer. */
2565 char *argbuf
= new char[sz
];
2568 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2570 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
2571 len
+= strlen (m_param_types
[i
]->get_debug_string ());
2572 if (i
+ 1 < m_param_types
.length ())
2574 strcpy (argbuf
+ len
, ", ");
2580 if (m_param_types
.length ())
2582 strcpy (argbuf
+ len
, ", ");
2585 strcpy (argbuf
+ len
, "...");
2590 /* ...and use it to get the string for the call as a whole. */
2591 string
*result
= string::from_printf (m_ctxt
,
2593 m_return_type
->get_debug_string (),
2602 /* Implementation of recording::memento::write_reproducer for function
2606 recording::function_type::write_reproducer (reproducer
&)
2608 /* see notes below. */
2611 /* There's a get_pointer within context::new_function_ptr_type:
2612 the type received by client code isn't the memento for the
2613 function_type, but instead the result of get_pointer on it.
2615 Hence we can't directly write a reproducer that gives function_type.
2616 Instead we special-case things within get_pointer, detecting this
2617 case, calling the following function. */
2620 recording::function_type::write_deferred_reproducer (reproducer
&r
,
2623 gcc_assert (ptr_type
);
2624 r
.make_identifier (this, "function_type");
2625 const char *ptr_id
= r
.make_identifier (ptr_type
, "ptr_to");
2626 const char *param_types_id
= r
.make_tmp_identifier ("params_for", this);
2627 r
.write (" gcc_jit_type *%s[%i] = {\n",
2629 m_param_types
.length ());
2632 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
2633 r
.write (" %s,\n", r
.get_identifier_as_type (param_type
));
2635 r
.write (" gcc_jit_type *%s =\n"
2636 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2637 " %s, /* gcc_jit_location *loc */\n"
2638 " %s, /* gcc_jit_type *return_type */\n"
2639 " %i, /* int num_params */\n"
2640 " %s, /* gcc_jit_type **param_types */\n"
2641 " %i); /* int is_variadic */\n",
2643 r
.get_identifier (get_context ()),
2644 "NULL", /* location is not stored */
2645 r
.get_identifier_as_type (m_return_type
),
2646 m_param_types
.length (),
2651 /* The implementation of class gcc::jit::recording::field. */
2653 /* Implementation of pure virtual hook recording::memento::replay_into
2654 for recording::field. */
2657 recording::field::replay_into (replayer
*r
)
2659 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
2660 m_type
->playback_type (),
2661 playback_string (m_name
)));
2664 /* Override the default implementation of
2665 recording::memento::write_to_dump. Dump each field
2666 by dumping a line of the form:
2668 so that we can build up a struct/union field-byfield. */
2671 recording::field::write_to_dump (dump
&d
)
2673 d
.write (" %s %s;\n",
2674 m_type
->get_debug_string (),
2678 /* Implementation of recording::memento::make_debug_string for
2679 results of new_field. */
2682 recording::field::make_debug_string ()
2687 /* Implementation of recording::memento::write_reproducer for fields. */
2690 recording::field::write_reproducer (reproducer
&r
)
2692 const char *id
= r
.make_identifier (this, "field");
2693 r
.write(" gcc_jit_field *%s =\n"
2694 " gcc_jit_context_new_field (%s,\n"
2695 " %s, /* gcc_jit_location *loc */\n"
2696 " %s, /* gcc_jit_type *type, */\n"
2697 " %s); /* const char *name */\n",
2699 r
.get_identifier (get_context ()),
2700 r
.get_identifier (m_loc
),
2701 r
.get_identifier_as_type (m_type
),
2702 m_name
->get_debug_string ());
2705 /* The implementation of class gcc::jit::recording::compound_type */
2707 /* The constructor for gcc::jit::recording::compound_type. */
2709 recording::compound_type::compound_type (context
*ctxt
,
2719 /* Set the fields of a compound type.
2721 Implements the post-error-checking part of
2722 gcc_jit_struct_set_fields, and is also used by
2723 gcc_jit_context_new_union_type. */
2726 recording::compound_type::set_fields (location
*loc
,
2728 field
**field_array
)
2731 gcc_assert (NULL
== m_fields
);
2733 m_fields
= new fields (this, num_fields
, field_array
);
2734 m_ctxt
->record (m_fields
);
2737 /* Implementation of pure virtual hook recording::type::dereference for
2738 recording::compound_type. */
2741 recording::compound_type::dereference ()
2743 return NULL
; /* not a pointer */
2746 /* The implementation of class gcc::jit::recording::struct_. */
2748 /* The constructor for gcc::jit::recording::struct_. */
2750 recording::struct_::struct_ (context
*ctxt
,
2753 : compound_type (ctxt
, loc
, name
)
2757 /* Implementation of pure virtual hook recording::memento::replay_into
2758 for recording::struct_. */
2761 recording::struct_::replay_into (replayer
*r
)
2764 r
->new_compound_type (playback_location (r
, get_loc ()),
2765 get_name ()->c_str (),
2766 true /* is_struct */));
2770 recording::struct_::access_as_type (reproducer
&r
)
2772 return r
.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2773 r
.get_identifier (this));
2776 /* Implementation of recording::memento::make_debug_string for
2780 recording::struct_::make_debug_string ()
2782 return string::from_printf (m_ctxt
,
2783 "struct %s", get_name ()->c_str ());
2787 recording::struct_::write_reproducer (reproducer
&r
)
2789 const char *id
= r
.make_identifier (this, "struct");
2790 r
.write (" gcc_jit_struct *%s =\n"
2791 " gcc_jit_context_new_opaque_struct (%s,\n"
2792 " %s, /* gcc_jit_location *loc */\n"
2793 " %s); /* const char *name */\n",
2795 r
.get_identifier (get_context ()),
2796 r
.get_identifier (get_loc ()),
2797 get_name ()->get_debug_string ());
2800 /* The implementation of class gcc::jit::recording::union_. */
2802 /* The constructor for gcc::jit::recording::union_. */
2804 recording::union_::union_ (context
*ctxt
,
2807 : compound_type (ctxt
, loc
, name
)
2811 /* Implementation of pure virtual hook recording::memento::replay_into
2812 for recording::union_. */
2815 recording::union_::replay_into (replayer
*r
)
2818 r
->new_compound_type (playback_location (r
, get_loc ()),
2819 get_name ()->c_str (),
2820 false /* is_struct */));
2823 /* Implementation of recording::memento::make_debug_string for
2827 recording::union_::make_debug_string ()
2829 return string::from_printf (m_ctxt
,
2830 "union %s", get_name ()->c_str ());
2833 /* Implementation of recording::memento::write_reproducer for unions. */
2836 recording::union_::write_reproducer (reproducer
&r
)
2838 const char *id
= r
.make_identifier (this, "union");
2840 const char *fields_id
= r
.make_tmp_identifier ("fields_for", this);
2841 r
.write (" gcc_jit_field *%s[%i] = {\n",
2843 get_fields ()->length ());
2844 for (int i
= 0; i
< get_fields ()->length (); i
++)
2845 r
.write (" %s,\n", r
.get_identifier (get_fields ()->get_field (i
)));
2848 r
.write (" gcc_jit_type *%s =\n"
2849 " gcc_jit_context_new_union_type (%s,\n"
2850 " %s, /* gcc_jit_location *loc */\n"
2851 " %s, /* const char *name */\n"
2852 " %i, /* int num_fields */\n"
2853 " %s); /* gcc_jit_field **fields */\n",
2855 r
.get_identifier (get_context ()),
2856 r
.get_identifier (get_loc ()),
2857 get_name ()->get_debug_string (),
2858 get_fields ()->length (),
2862 /* The implementation of class gcc::jit::recording::fields. */
2864 /* The constructor for gcc::jit::recording::fields. */
2866 recording::fields::fields (compound_type
*struct_or_union
,
2869 : memento (struct_or_union
->m_ctxt
),
2870 m_struct_or_union (struct_or_union
),
2873 for (int i
= 0; i
< num_fields
; i
++)
2875 gcc_assert (fields
[i
]->get_container () == NULL
);
2876 fields
[i
]->set_container (m_struct_or_union
);
2877 m_fields
.safe_push (fields
[i
]);
2881 /* Implementation of pure virtual hook recording::memento::replay_into
2882 for recording::fields. */
2885 recording::fields::replay_into (replayer
*)
2887 auto_vec
<playback::field
*> playback_fields
;
2888 playback_fields
.create (m_fields
.length ());
2889 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
2890 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
2891 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
2894 /* Override the default implementation of
2895 recording::memento::write_to_dump by writing a union/struct
2896 declaration of this form:
2908 recording::fields::write_to_dump (dump
&d
)
2913 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
2914 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
2915 f
->write_to_dump (d
);
2919 /* Implementation of recording::memento::write_reproducer for the fields
2923 recording::fields::write_reproducer (reproducer
&r
)
2925 if (m_struct_or_union
)
2926 if (NULL
== m_struct_or_union
->dyn_cast_struct ())
2927 /* We have a union; the fields have already been written by
2928 union::write_reproducer. */
2931 const char *fields_id
= r
.make_identifier (this, "fields");
2932 r
.write (" gcc_jit_field *%s[%i] = {\n",
2934 m_fields
.length ());
2937 FOR_EACH_VEC_ELT (m_fields
, i
, field
)
2938 r
.write (" %s,\n", r
.get_identifier (field
));
2941 r
.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
2942 " %s, /* gcc_jit_location *loc */\n"
2943 " %i, /* int num_fields */\n"
2944 " %s); /* gcc_jit_field **fields */\n",
2945 r
.get_identifier (m_struct_or_union
),
2946 r
.get_identifier ((memento
*)NULL
),
2951 /* Implementation of recording::memento::make_debug_string for
2955 recording::fields::make_debug_string ()
2957 return string::from_printf (m_ctxt
,
2961 /* The implementation of class gcc::jit::recording::rvalue. */
2963 /* Create a recording::access_field_rvalue instance and add it to
2964 the rvalue's context's list of mementos.
2966 Implements the post-error-checking part of
2967 gcc_jit_rvalue_access_field. */
2970 recording::rvalue::access_field (recording::location
*loc
,
2973 recording::rvalue
*result
=
2974 new access_field_rvalue (m_ctxt
, loc
, this, field
);
2975 m_ctxt
->record (result
);
2979 /* Create a recording::dereference_field_rvalue instance and add it to
2980 the rvalue's context's list of mementos.
2982 Implements the post-error-checking part of
2983 gcc_jit_rvalue_dereference_field. */
2986 recording::rvalue::dereference_field (recording::location
*loc
,
2989 recording::lvalue
*result
=
2990 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
2991 m_ctxt
->record (result
);
2995 /* Create a recording::dereference_rvalue instance and add it to the
2996 rvalue's context's list of mementos.
2998 Implements the post-error-checking part of
2999 gcc_jit_rvalue_dereference. */
3002 recording::rvalue::dereference (recording::location
*loc
)
3004 recording::lvalue
*result
=
3005 new dereference_rvalue (m_ctxt
, loc
, this);
3006 m_ctxt
->record (result
);
3010 /* An rvalue visitor, for validating that every rvalue within an expression
3011 trees within "STMT" has the correct scope (e.g. no access to locals
3012 of a different function). */
3014 class rvalue_usage_validator
: public recording::rvalue_visitor
3017 rvalue_usage_validator (const char *api_funcname
,
3018 recording::context
*ctxt
,
3019 recording::statement
*stmt
);
3022 visit (recording::rvalue
*rvalue
);
3025 const char *m_api_funcname
;
3026 recording::context
*m_ctxt
;
3027 recording::statement
*m_stmt
;
3030 /* The trivial constructor for rvalue_usage_validator. */
3032 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname
,
3033 recording::context
*ctxt
,
3034 recording::statement
*stmt
)
3035 : m_api_funcname (api_funcname
),
3041 /* Verify that the given rvalue is in the correct scope. */
3044 rvalue_usage_validator::visit (recording::rvalue
*rvalue
)
3046 gcc_assert (m_stmt
->get_block ());
3047 recording::function
*stmt_scope
= m_stmt
->get_block ()->get_function ();
3049 /* Most rvalues don't have a scope (only locals and params). */
3050 if (rvalue
->get_scope ())
3052 if (rvalue
->get_scope () != stmt_scope
)
3054 (rvalue
->get_loc (),
3056 " rvalue %s (type: %s)"
3057 " has scope limited to function %s"
3058 " but was used within function %s"
3059 " (in statement: %s)",
3061 rvalue
->get_debug_string (),
3062 rvalue
->get_type ()->get_debug_string (),
3063 rvalue
->get_scope ()->get_debug_string (),
3064 stmt_scope
->get_debug_string (),
3065 m_stmt
->get_debug_string ());
3069 if (rvalue
->dyn_cast_param ())
3071 (rvalue
->get_loc (),
3073 " param %s (type: %s)"
3074 " was used within function %s"
3075 " (in statement: %s)"
3076 " but is not associated with any function",
3078 rvalue
->get_debug_string (),
3079 rvalue
->get_type ()->get_debug_string (),
3080 stmt_scope
->get_debug_string (),
3081 m_stmt
->get_debug_string ());
3085 /* Verify that it's valid to use this rvalue (and all expressions
3086 in the tree below it) within the given statement.
3088 For example, we must reject attempts to use a local from one
3089 function within a different function here, or we'll get
3090 an ICE deep inside toplev::main. */
3093 recording::rvalue::verify_valid_within_stmt (const char *api_funcname
, statement
*s
)
3095 rvalue_usage_validator
v (api_funcname
,
3099 /* Verify that it's OK to use this rvalue within s. */
3102 /* Traverse the expression tree below "this", verifying all rvalues
3104 visit_children (&v
);
3107 /* Set the scope of this rvalue to be the given function. This can only
3108 be done once on a given rvalue. */
3111 recording::rvalue::set_scope (function
*scope
)
3114 gcc_assert (NULL
== m_scope
);
3119 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3121 Instances of rvalue don't need an upcast call. */
3124 recording::rvalue::access_as_rvalue (reproducer
&r
)
3126 return r
.get_identifier (this);
3129 /* Return a debug string for the given rvalue, wrapping it in parentheses
3130 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3131 stronger precedence that this rvalue's precedence.
3145 since MULT has strong precedence than PLUS and MINUS, whereas for:
3157 since PLUS has weaker precedence than MULT and DIVIDE. */
3160 recording::rvalue::get_debug_string_parens (enum precedence outer_prec
)
3162 enum precedence this_prec
= get_precedence ();
3164 /* If this_prec has stronger precedence than outer_prec, we don't
3165 need to wrap this in parens within the outer debug string.
3166 Stronger precedences occur earlier than weaker within the enum,
3167 so this is a less than test. Equal precedences don't need
3169 if (this_prec
<= outer_prec
)
3170 return get_debug_string();
3172 /* Otherwise, we need parentheses. */
3174 /* Lazily-build and cache m_parenthesized_string. */
3175 if (!m_parenthesized_string
)
3177 const char *debug_string
= get_debug_string ();
3178 m_parenthesized_string
= string::from_printf (get_context (),
3182 gcc_assert (m_parenthesized_string
);
3183 return m_parenthesized_string
->c_str ();
3187 /* The implementation of class gcc::jit::recording::lvalue. */
3189 /* Create a recording::new_access_field_of_lvalue instance and add it to
3190 the lvalue's context's list of mementos.
3192 Implements the post-error-checking part of
3193 gcc_jit_lvalue_access_field. */
3196 recording::lvalue::access_field (recording::location
*loc
,
3199 recording::lvalue
*result
=
3200 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
3201 m_ctxt
->record (result
);
3205 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3206 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3210 recording::lvalue::access_as_rvalue (reproducer
&r
)
3212 return r
.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3213 r
.get_identifier (this));
3216 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3217 Instances of lvalue don't need to be upcast. */
3220 recording::lvalue::access_as_lvalue (reproducer
&r
)
3222 return r
.get_identifier (this);
3225 /* Create a recording::get_address_of_lvalue instance and add it to
3226 the lvalue's context's list of mementos.
3228 Implements the post-error-checking part of
3229 gcc_jit_lvalue_get_address. */
3232 recording::lvalue::get_address (recording::location
*loc
)
3234 recording::rvalue
*result
=
3235 new get_address_of_lvalue (m_ctxt
, loc
, this);
3236 m_ctxt
->record (result
);
3240 /* The implementation of class gcc::jit::recording::param. */
3242 /* Implementation of pure virtual hook recording::memento::replay_into
3243 for recording::param. */
3246 recording::param::replay_into (replayer
*r
)
3248 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
3249 m_type
->playback_type (),
3253 /* Implementation of recording::rvalue::access_as_rvalue for params.
3254 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3258 recording::param::access_as_rvalue (reproducer
&r
)
3260 return r
.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3261 r
.get_identifier (this));
3264 /* Implementation of recording::lvalue::access_as_lvalue for params.
3265 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3269 recording::param::access_as_lvalue (reproducer
&r
)
3271 return r
.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3272 r
.get_identifier (this));
3275 /* Implementation of recording::memento::write_reproducer for params. */
3278 recording::param::write_reproducer (reproducer
&r
)
3280 const char *id
= r
.make_identifier (this, "param");
3281 r
.write (" gcc_jit_param *%s =\n"
3282 " gcc_jit_context_new_param (%s,\n"
3283 " %s, /* gcc_jit_location *loc */\n"
3284 " %s, /*gcc_jit_type *type */\n"
3285 " %s); /* const char *name */\n",
3287 r
.get_identifier (get_context ()),
3288 r
.get_identifier (m_loc
),
3289 r
.get_identifier_as_type (m_type
),
3290 m_name
->get_debug_string ());
3293 /* The implementation of class gcc::jit::recording::function. */
3295 /* gcc::jit::recording::function's constructor. */
3297 recording::function::function (context
*ctxt
,
3298 recording::location
*loc
,
3299 enum gcc_jit_function_kind kind
,
3301 recording::string
*name
,
3303 recording::param
**params
,
3305 enum built_in_function builtin_id
)
3309 m_return_type (return_type
),
3312 m_is_variadic (is_variadic
),
3313 m_builtin_id (builtin_id
),
3317 for (int i
= 0; i
< num_params
; i
++)
3319 param
*param
= params
[i
];
3322 /* Associate each param with this function.
3324 Verify that the param doesn't already have a function. */
3325 if (param
->get_scope ())
3327 /* We've already rejected attempts to reuse a param between
3328 different functions (within gcc_jit_context_new_function), so
3329 if the param *does* already have a function, it must be being
3330 reused within the params array for this function. We must
3331 produce an error for this reuse (blocking the compile), since
3332 otherwise we'd have an ICE later on. */
3333 gcc_assert (this == param
->get_scope ());
3336 "gcc_jit_context_new_function:"
3337 " parameter %s (type: %s)"
3338 " is used more than once when creating function %s",
3339 param
->get_debug_string (),
3340 param
->get_type ()->get_debug_string (),
3345 /* The normal, non-error case: associate this function with the
3347 param
->set_scope (this);
3350 m_params
.safe_push (param
);
3354 /* Implementation of pure virtual hook recording::memento::replay_into
3355 for recording::function. */
3358 recording::function::replay_into (replayer
*r
)
3360 /* Convert m_params to a vec of playback param. */
3361 auto_vec
<playback::param
*> params
;
3363 recording::param
*param
;
3364 params
.create (m_params
.length ());
3365 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3366 params
.safe_push (param
->playback_param ());
3368 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
3370 m_return_type
->playback_type (),
3377 /* Create a recording::local instance and add it to
3378 the functions's context's list of mementos, and to the function's
3381 Implements the post-error-checking part of
3382 gcc_jit_function_new_local. */
3385 recording::function::new_local (recording::location
*loc
,
3389 local
*result
= new local (this, loc
, type
, new_string (name
));
3390 m_ctxt
->record (result
);
3391 m_locals
.safe_push (result
);
3395 /* Create a recording::block instance and add it to
3396 the functions's context's list of mementos, and to the function's
3399 Implements the post-error-checking part of
3400 gcc_jit_function_new_block. */
3403 recording::function::new_block (const char *name
)
3405 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
3407 recording::block
*result
=
3408 new recording::block (this, m_blocks
.length (), new_string (name
));
3409 m_ctxt
->record (result
);
3410 m_blocks
.safe_push (result
);
3414 /* Override the default implementation of
3415 recording::memento::write_to_dump by dumping a C-like
3416 representation of the function; either like a prototype
3417 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3418 all other kinds of function. */
3421 recording::function::write_to_dump (dump
&d
)
3425 default: gcc_unreachable ();
3426 case GCC_JIT_FUNCTION_EXPORTED
:
3427 case GCC_JIT_FUNCTION_IMPORTED
:
3428 d
.write ("extern ");
3430 case GCC_JIT_FUNCTION_INTERNAL
:
3431 d
.write ("static ");
3433 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
3434 d
.write ("static inline ");
3437 d
.write ("%s\n", m_return_type
->get_debug_string ());
3439 if (d
.update_locations ())
3440 m_loc
= d
.make_location ();
3442 d
.write ("%s (", get_debug_string ());
3445 recording::param
*param
;
3446 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3451 param
->get_type ()->get_debug_string (),
3452 param
->get_debug_string ());
3455 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
3457 d
.write ("; /* (imported) */\n\n");
3467 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
3468 var
->write_to_dump (d
);
3469 if (m_locals
.length ())
3472 /* Write each block: */
3473 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3477 b
->write_to_dump (d
);
3484 /* Pre-compilation validation of a function, for those things we can't
3485 check until the context is (supposedly) fully-populated. */
3488 recording::function::validate ()
3490 /* Complain about empty functions with non-void return type. */
3491 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
3492 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
3493 if (0 == m_blocks
.length ())
3494 m_ctxt
->add_error (m_loc
,
3495 "function %s returns non-void (type: %s)"
3496 " but has no blocks",
3497 get_debug_string (),
3498 m_return_type
->get_debug_string ());
3500 /* Check that all blocks are terminated. */
3501 int num_invalid_blocks
= 0;
3506 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3507 if (!b
->validate ())
3508 num_invalid_blocks
++;
3511 /* Check that all blocks are reachable. */
3512 if (!m_ctxt
->get_inner_bool_option
3513 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS
)
3514 && m_blocks
.length () > 0 && 0 == num_invalid_blocks
)
3516 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3517 flag, starting at the initial block. */
3518 auto_vec
<block
*> worklist (m_blocks
.length ());
3519 worklist
.safe_push (m_blocks
[0]);
3520 while (worklist
.length () > 0)
3522 block
*b
= worklist
.pop ();
3523 b
->m_is_reachable
= true;
3525 /* Add successor blocks that aren't yet marked to the worklist. */
3526 /* We checked that each block has a terminating statement above . */
3527 vec
<block
*> successors
= b
->get_successor_blocks ();
3530 FOR_EACH_VEC_ELT (successors
, i
, succ
)
3531 if (!succ
->m_is_reachable
)
3532 worklist
.safe_push (succ
);
3533 successors
.release ();
3536 /* Now complain about any blocks that haven't been marked. */
3540 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3541 if (!b
->m_is_reachable
)
3542 m_ctxt
->add_error (b
->get_loc (),
3543 "unreachable block: %s",
3544 b
->get_debug_string ());
3549 /* Implements the post-error-checking part of
3550 gcc_jit_function_dump_to_dot. */
3553 recording::function::dump_to_dot (const char *path
)
3555 FILE *fp
= fopen (path
, "w");
3559 pretty_printer the_pp
;
3560 the_pp
.buffer
->stream
= fp
;
3562 pretty_printer
*pp
= &the_pp
;
3565 "digraph %s {\n", get_debug_string ());
3571 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3572 b
->dump_to_dot (pp
);
3579 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3580 b
->dump_edges_to_dot (pp
);
3583 pp_printf (pp
, "}\n");
3588 /* Implementation of recording::memento::make_debug_string for
3592 recording::function::make_debug_string ()
3597 /* A table of enum gcc_jit_function_kind values expressed in string
3600 static const char * const names_of_function_kinds
[] = {
3601 "GCC_JIT_FUNCTION_EXPORTED",
3602 "GCC_JIT_FUNCTION_INTERNAL",
3603 "GCC_JIT_FUNCTION_IMPORTED",
3604 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3607 /* Implementation of recording::memento::write_reproducer for functions. */
3610 recording::function::write_reproducer (reproducer
&r
)
3612 const char *id
= r
.make_identifier (this, "func");
3616 r
.write (" gcc_jit_function *%s =\n"
3617 " gcc_jit_context_get_builtin_function (%s,\n"
3620 r
.get_identifier (get_context ()),
3621 m_name
->get_debug_string ());
3624 const char *params_id
= r
.make_tmp_identifier ("params_for", this);
3625 r
.write (" gcc_jit_param *%s[%i] = {\n",
3627 m_params
.length ());
3630 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3631 r
.write (" %s,\n", r
.get_identifier (param
));
3633 r
.write (" gcc_jit_function *%s =\n"
3634 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3635 " %s, /* gcc_jit_location *loc */\n"
3636 " %s, /* enum gcc_jit_function_kind kind */\n"
3637 " %s, /* gcc_jit_type *return_type */\n"
3638 " %s, /* const char *name */\n"
3639 " %i, /* int num_params */\n"
3640 " %s, /* gcc_jit_param **params */\n"
3641 " %i); /* int is_variadic */\n",
3643 r
.get_identifier (get_context ()),
3644 r
.get_identifier (m_loc
),
3645 names_of_function_kinds
[m_kind
],
3646 r
.get_identifier_as_type (m_return_type
),
3647 m_name
->get_debug_string (),
3654 /* The implementation of class gcc::jit::recording::block. */
3656 /* Create a recording::eval instance and add it to
3657 the block's context's list of mementos, and to the block's
3660 Implements the heart of gcc_jit_block_add_eval. */
3662 recording::statement
*
3663 recording::block::add_eval (recording::location
*loc
,
3664 recording::rvalue
*rvalue
)
3666 statement
*result
= new eval (this, loc
, rvalue
);
3667 m_ctxt
->record (result
);
3668 m_statements
.safe_push (result
);
3672 /* Create a recording::assignment instance and add it to
3673 the block's context's list of mementos, and to the block's
3676 Implements the heart of gcc_jit_block_add_assignment. */
3678 recording::statement
*
3679 recording::block::add_assignment (recording::location
*loc
,
3680 recording::lvalue
*lvalue
,
3681 recording::rvalue
*rvalue
)
3683 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
3684 m_ctxt
->record (result
);
3685 m_statements
.safe_push (result
);
3689 /* Create a recording::assignment_op instance and add it to
3690 the block's context's list of mementos, and to the block's
3693 Implements the heart of gcc_jit_block_add_assignment_op. */
3695 recording::statement
*
3696 recording::block::add_assignment_op (recording::location
*loc
,
3697 recording::lvalue
*lvalue
,
3698 enum gcc_jit_binary_op op
,
3699 recording::rvalue
*rvalue
)
3701 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
3702 m_ctxt
->record (result
);
3703 m_statements
.safe_push (result
);
3707 /* Create a recording::comment instance and add it to
3708 the block's context's list of mementos, and to the block's
3711 Implements the heart of gcc_jit_block_add_comment. */
3713 recording::statement
*
3714 recording::block::add_comment (recording::location
*loc
,
3717 statement
*result
= new comment (this, loc
, new_string (text
));
3718 m_ctxt
->record (result
);
3719 m_statements
.safe_push (result
);
3723 /* Create a recording::end_with_conditional instance and add it to
3724 the block's context's list of mementos, and to the block's
3727 Implements the heart of gcc_jit_block_end_with_conditional. */
3729 recording::statement
*
3730 recording::block::end_with_conditional (recording::location
*loc
,
3731 recording::rvalue
*boolval
,
3732 recording::block
*on_true
,
3733 recording::block
*on_false
)
3735 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
3736 m_ctxt
->record (result
);
3737 m_statements
.safe_push (result
);
3738 m_has_been_terminated
= true;
3742 /* Create a recording::end_with_jump instance and add it to
3743 the block's context's list of mementos, and to the block's
3746 Implements the heart of gcc_jit_block_end_with_jump. */
3748 recording::statement
*
3749 recording::block::end_with_jump (recording::location
*loc
,
3750 recording::block
*target
)
3752 statement
*result
= new jump (this, loc
, target
);
3753 m_ctxt
->record (result
);
3754 m_statements
.safe_push (result
);
3755 m_has_been_terminated
= true;
3759 /* Create a recording::end_with_return instance and add it to
3760 the block's context's list of mementos, and to the block's
3763 Implements the post-error-checking parts of
3764 gcc_jit_block_end_with_return and
3765 gcc_jit_block_end_with_void_return. */
3767 recording::statement
*
3768 recording::block::end_with_return (recording::location
*loc
,
3769 recording::rvalue
*rvalue
)
3771 /* This is used by both gcc_jit_function_add_return and
3772 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3773 the former and NULL for the latter. */
3774 statement
*result
= new return_ (this, loc
, rvalue
);
3775 m_ctxt
->record (result
);
3776 m_statements
.safe_push (result
);
3777 m_has_been_terminated
= true;
3781 /* Create a recording::switch_ instance and add it to
3782 the block's context's list of mementos, and to the block's
3785 Implements the heart of gcc_jit_block_end_with_switch. */
3787 recording::statement
*
3788 recording::block::end_with_switch (recording::location
*loc
,
3789 recording::rvalue
*expr
,
3790 recording::block
*default_block
,
3792 recording::case_
**cases
)
3794 statement
*result
= new switch_ (this, loc
,
3799 m_ctxt
->record (result
);
3800 m_statements
.safe_push (result
);
3801 m_has_been_terminated
= true;
3805 /* Override the default implementation of
3806 recording::memento::write_to_dump for blocks by writing
3807 an unindented block name as a label, followed by the indented
3817 recording::block::write_to_dump (dump
&d
)
3819 d
.write ("%s:\n", get_debug_string ());
3823 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
3824 s
->write_to_dump (d
);
3827 /* Validate a block by ensuring that it has been terminated. */
3830 recording::block::validate ()
3832 /* Check for termination. */
3833 if (!has_been_terminated ())
3835 statement
*stmt
= get_last_statement ();
3836 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
3837 m_func
->get_context ()->add_error (loc
,
3838 "unterminated block in %s: %s",
3839 m_func
->get_debug_string (),
3840 get_debug_string ());
3847 /* Get the source-location of a block by using that of the first
3848 statement within it, if any. */
3850 recording::location
*
3851 recording::block::get_loc () const
3853 recording::statement
*stmt
= get_first_statement ();
3855 return stmt
->get_loc ();
3860 /* Get the first statement within a block, if any. */
3862 recording::statement
*
3863 recording::block::get_first_statement () const
3865 if (m_statements
.length ())
3866 return m_statements
[0];
3871 /* Get the last statement within a block, if any. */
3873 recording::statement
*
3874 recording::block::get_last_statement () const
3876 if (m_statements
.length ())
3877 return m_statements
[m_statements
.length () - 1];
3882 /* Assuming that this block has been terminated, get the successor blocks
3883 as a vector. Ownership of the vector transfers to the caller, which
3884 must call its release () method.
3886 Used when validating functions, and when dumping dot representations
3889 vec
<recording::block
*>
3890 recording::block::get_successor_blocks () const
3892 gcc_assert (m_has_been_terminated
);
3893 statement
*last_statement
= get_last_statement ();
3894 gcc_assert (last_statement
);
3895 return last_statement
->get_successor_blocks ();
3898 /* Implementation of pure virtual hook recording::memento::replay_into
3899 for recording::block. */
3902 recording::block::replay_into (replayer
*)
3904 set_playback_obj (m_func
->playback_function ()
3905 ->new_block (playback_string (m_name
)));
3908 /* Implementation of recording::memento::make_debug_string for
3912 recording::block::make_debug_string ()
3917 return string::from_printf (m_ctxt
,
3918 "<UNNAMED BLOCK %p>",
3922 /* Implementation of recording::memento::write_reproducer for blocks. */
3925 recording::block::write_reproducer (reproducer
&r
)
3927 const char *id
= r
.make_identifier (this, "block");
3928 r
.write (" gcc_jit_block *%s =\n"
3929 " gcc_jit_function_new_block (%s, %s);\n",
3931 r
.get_identifier (m_func
),
3932 m_name
? m_name
->get_debug_string () : "NULL");
3935 /* Dump a block in graphviz form into PP, capturing the block name (if
3936 any) and the statements. */
3939 recording::block::dump_to_dot (pretty_printer
*pp
)
3943 "[shape=record,style=filled,fillcolor=white,label=\"{"),
3945 pp_write_text_to_stream (pp
);
3948 pp_string (pp
, m_name
->c_str ());
3949 pp_string (pp
, ":");
3951 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
3956 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
3958 pp_string (pp
, s
->get_debug_string ());
3960 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
3968 /* Dump the out-edges of the block in graphviz form into PP. */
3971 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
3973 vec
<block
*> successors
= get_successor_blocks ();
3976 FOR_EACH_VEC_ELT (successors
, i
, succ
)
3978 "\tblock_%d:s -> block_%d:n;\n",
3979 m_index
, succ
->m_index
);
3980 successors
.release ();
3983 /* The implementation of class gcc::jit::recording::global. */
3985 /* Implementation of pure virtual hook recording::memento::replay_into
3986 for recording::global. */
3989 recording::global::replay_into (replayer
*r
)
3991 set_playback_obj (r
->new_global (playback_location (r
, m_loc
),
3993 m_type
->playback_type (),
3994 playback_string (m_name
)));
3997 /* Override the default implementation of
3998 recording::memento::write_to_dump for globals.
3999 This will be of the form:
4001 GCC_JIT_GLOBAL_EXPORTED:
4005 GCC_JIT_GLOBAL_INTERNAL:
4007 e.g. "static int foo;"
4009 GCC_JIT_GLOBAL_IMPORTED:
4011 e.g. "extern int foo;"
4013 These are written to the top of the dump by
4014 recording::context::dump_to_file. */
4017 recording::global::write_to_dump (dump
&d
)
4019 if (d
.update_locations ())
4020 m_loc
= d
.make_location ();
4027 case GCC_JIT_GLOBAL_EXPORTED
:
4030 case GCC_JIT_GLOBAL_INTERNAL
:
4031 d
.write ("static ");
4034 case GCC_JIT_GLOBAL_IMPORTED
:
4035 d
.write ("extern ");
4038 d
.write ("%s %s;\n",
4039 m_type
->get_debug_string (),
4040 get_debug_string ());
4043 /* A table of enum gcc_jit_global_kind values expressed in string
4046 static const char * const global_kind_reproducer_strings
[] = {
4047 "GCC_JIT_GLOBAL_EXPORTED",
4048 "GCC_JIT_GLOBAL_INTERNAL",
4049 "GCC_JIT_GLOBAL_IMPORTED"
4052 /* Implementation of recording::memento::write_reproducer for globals. */
4055 recording::global::write_reproducer (reproducer
&r
)
4057 const char *id
= r
.make_identifier (this, "block");
4058 r
.write (" gcc_jit_lvalue *%s =\n"
4059 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4060 " %s, /* gcc_jit_location *loc */\n"
4061 " %s, /* enum gcc_jit_global_kind kind */\n"
4062 " %s, /* gcc_jit_type *type */\n"
4063 " %s); /* const char *name */\n",
4065 r
.get_identifier (get_context ()),
4066 r
.get_identifier (m_loc
),
4067 global_kind_reproducer_strings
[m_kind
],
4068 r
.get_identifier_as_type (get_type ()),
4069 m_name
->get_debug_string ());
4072 /* The implementation of the various const-handling classes:
4073 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4075 /* Explicit specialization of the various mementos we're interested in. */
4076 template class recording::memento_of_new_rvalue_from_const
<int>;
4077 template class recording::memento_of_new_rvalue_from_const
<long>;
4078 template class recording::memento_of_new_rvalue_from_const
<double>;
4079 template class recording::memento_of_new_rvalue_from_const
<void *>;
4081 /* Implementation of the pure virtual hook recording::memento::replay_into
4082 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4084 template <typename HOST_TYPE
>
4087 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
4090 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
4094 /* The make_debug_string and write_reproducer methods vary between the
4096 memento_of_new_rvalue_from_const <HOST_TYPE>
4097 classes, so we explicitly write specializations of them.
4099 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4100 namespaces are written out explicitly, which is why most of this file
4101 doesn't abbreviate things by entering the "recording" namespace.
4103 However, these specializations are required to be in the same namespace
4104 as the template, hence we now have to enter the gcc::jit::recording
4110 /* The make_debug_string specialization for <int>, which renders it as
4111 (TARGET_TYPE)LITERAL
4117 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
4119 return string::from_printf (m_ctxt
,
4121 m_type
->get_debug_string (),
4125 /* The get_wide_int specialization for <int>. */
4129 memento_of_new_rvalue_from_const
<int>::get_wide_int (wide_int
*out
) const
4131 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
4135 /* The write_reproducer specialization for <int>. */
4139 memento_of_new_rvalue_from_const
<int>::write_reproducer (reproducer
&r
)
4141 const char *id
= r
.make_identifier (this, "rvalue");
4142 r
.write (" gcc_jit_rvalue *%s =\n"
4143 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4144 " %s, /* gcc_jit_type *numeric_type */\n"
4145 " %i); /* int value */\n",
4147 r
.get_identifier (get_context ()),
4148 r
.get_identifier_as_type (m_type
),
4152 /* The make_debug_string specialization for <long>, rendering it as
4153 (TARGET_TYPE)LITERAL
4159 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
4161 return string::from_printf (m_ctxt
,
4163 m_type
->get_debug_string (),
4167 /* The get_wide_int specialization for <long>. */
4171 memento_of_new_rvalue_from_const
<long>::get_wide_int (wide_int
*out
) const
4173 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
4177 /* The write_reproducer specialization for <long>. */
4181 recording::memento_of_new_rvalue_from_const
<long>::write_reproducer (reproducer
&r
)
4183 const char *id
= r
.make_identifier (this, "rvalue");
4185 /* We have to special-case LONG_MIN, since e.g.
4186 -9223372036854775808L
4188 -(9223372036854775808L)
4190 error: integer constant is so large that it is unsigned [-Werror]
4191 Workaround this by writing (LONG_MIN + 1) - 1. */
4192 if (m_value
== LONG_MIN
)
4194 r
.write (" gcc_jit_rvalue *%s =\n"
4195 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4196 " %s, /* gcc_jit_type *numeric_type */\n"
4197 " %ldL - 1); /* long value */\n",
4199 r
.get_identifier (get_context ()),
4200 r
.get_identifier_as_type (m_type
),
4205 r
.write (" gcc_jit_rvalue *%s =\n"
4206 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4207 " %s, /* gcc_jit_type *numeric_type */\n"
4208 " %ldL); /* long value */\n",
4210 r
.get_identifier (get_context ()),
4211 r
.get_identifier_as_type (m_type
),
4215 /* The make_debug_string specialization for <double>, rendering it as
4216 (TARGET_TYPE)LITERAL
4222 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
4224 return string::from_printf (m_ctxt
,
4226 m_type
->get_debug_string (),
4230 /* The get_wide_int specialization for <double>. */
4234 memento_of_new_rvalue_from_const
<double>::get_wide_int (wide_int
*) const
4239 /* The write_reproducer specialization for <double>. */
4243 recording::memento_of_new_rvalue_from_const
<double>::write_reproducer (reproducer
&r
)
4245 const char *id
= r
.make_identifier (this, "rvalue");
4246 r
.write (" gcc_jit_rvalue *%s =\n"
4247 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4248 " %s, /* gcc_jit_type *numeric_type */\n"
4249 " %f); /* double value */\n",
4251 r
.get_identifier (get_context ()),
4252 r
.get_identifier_as_type (m_type
),
4256 /* The make_debug_string specialization for <void *>, rendering it as
4261 Zero is rendered as NULL e.g.
4266 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
4268 if (m_value
!= NULL
)
4269 return string::from_printf (m_ctxt
,
4271 m_type
->get_debug_string (), m_value
);
4273 return string::from_printf (m_ctxt
,
4275 m_type
->get_debug_string ());
4278 /* The get_wide_int specialization for <void *>. */
4282 memento_of_new_rvalue_from_const
<void *>::get_wide_int (wide_int
*) const
4287 /* Implementation of recording::memento::write_reproducer for <void *>
4292 memento_of_new_rvalue_from_const
<void *>::write_reproducer (reproducer
&r
)
4294 const char *id
= r
.make_identifier (this, "rvalue");
4296 r
.write (" gcc_jit_rvalue *%s =\n"
4297 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4298 " %s, /* gcc_jit_type *pointer_type */\n"
4299 " (void *)%p); /* void *value */\n",
4301 r
.get_identifier (get_context ()),
4302 r
.get_identifier_as_type (m_type
),
4305 r
.write (" gcc_jit_rvalue *%s =\n"
4306 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4307 " %s); /* gcc_jit_type *pointer_type */\n",
4309 r
.get_identifier (get_context ()),
4310 r
.get_identifier_as_type (m_type
));
4313 /* We're done specializing make_debug_string and write_reproducer, so we
4314 can exit the gcc::jit::recording namespace. */
4316 } // namespace recording
4318 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4320 /* Implementation of pure virtual hook recording::memento::replay_into
4321 for recording::memento_of_new_string_literal. */
4324 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
4326 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
4329 /* Implementation of recording::memento::make_debug_string for
4333 recording::memento_of_new_string_literal::make_debug_string ()
4335 return string::from_printf (m_ctxt
,
4337 m_value
->get_debug_string ());
4340 /* Implementation of recording::memento::write_reproducer for string literal
4344 recording::memento_of_new_string_literal::write_reproducer (reproducer
&r
)
4346 const char *id
= r
.make_identifier (this, "rvalue");
4347 r
.write (" gcc_jit_rvalue *%s =\n"
4348 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4349 " %s); /* const char *value */\n",
4351 r
.get_identifier (get_context ()),
4352 m_value
->get_debug_string ());
4355 /* The implementation of class gcc::jit::recording::unary_op. */
4357 /* Implementation of pure virtual hook recording::memento::replay_into
4358 for recording::unary_op. */
4361 recording::unary_op::replay_into (replayer
*r
)
4363 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
4365 get_type ()->playback_type (),
4366 m_a
->playback_rvalue ()));
4369 /* Implementation of pure virtual hook recording::rvalue::visit_children
4370 for recording::unary_op. */
4372 recording::unary_op::visit_children (rvalue_visitor
*v
)
4377 /* Implementation of recording::memento::make_debug_string for
4380 static const char * const unary_op_strings
[] = {
4381 "-", /* GCC_JIT_UNARY_OP_MINUS */
4382 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4383 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4384 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4388 recording::unary_op::make_debug_string ()
4390 return string::from_printf (m_ctxt
,
4392 unary_op_strings
[m_op
],
4393 m_a
->get_debug_string ());
4396 static const char * const unary_op_reproducer_strings
[] = {
4397 "GCC_JIT_UNARY_OP_MINUS",
4398 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4399 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4400 "GCC_JIT_UNARY_OP_ABS"
4403 /* Implementation of recording::memento::write_reproducer for unary ops. */
4406 recording::unary_op::write_reproducer (reproducer
&r
)
4408 const char *id
= r
.make_identifier (this, "rvalue");
4409 r
.write (" gcc_jit_rvalue *%s =\n"
4410 " gcc_jit_context_new_unary_op (%s,\n"
4411 " %s, /* gcc_jit_location *loc */\n"
4412 " %s, /* enum gcc_jit_unary_op op */\n"
4413 " %s, /* gcc_jit_type *result_type */\n"
4414 " %s); /* gcc_jit_rvalue *a */\n",
4416 r
.get_identifier (get_context ()),
4417 r
.get_identifier (m_loc
),
4418 unary_op_reproducer_strings
[m_op
],
4419 r
.get_identifier_as_type (get_type ()),
4420 r
.get_identifier_as_rvalue (m_a
));
4423 /* The implementation of class gcc::jit::recording::binary_op. */
4425 /* Implementation of pure virtual hook recording::memento::replay_into
4426 for recording::binary_op. */
4429 recording::binary_op::replay_into (replayer
*r
)
4431 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
4433 get_type ()->playback_type (),
4434 m_a
->playback_rvalue (),
4435 m_b
->playback_rvalue ()));
4438 /* Implementation of pure virtual hook recording::rvalue::visit_children
4439 for recording::binary_op. */
4441 recording::binary_op::visit_children (rvalue_visitor
*v
)
4447 /* Implementation of recording::memento::make_debug_string for
4450 static const char * const binary_op_strings
[] = {
4451 "+", /* GCC_JIT_BINARY_OP_PLUS */
4452 "-", /* GCC_JIT_BINARY_OP_MINUS */
4453 "*", /* GCC_JIT_BINARY_OP_MULT */
4454 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4455 "%", /* GCC_JIT_BINARY_OP_MODULO */
4456 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4457 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4458 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4459 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4460 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4461 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4462 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4466 recording::binary_op::make_debug_string ()
4468 enum precedence prec
= get_precedence ();
4469 return string::from_printf (m_ctxt
,
4471 m_a
->get_debug_string_parens (prec
),
4472 binary_op_strings
[m_op
],
4473 m_b
->get_debug_string_parens (prec
));
4476 static const char * const binary_op_reproducer_strings
[] = {
4477 "GCC_JIT_BINARY_OP_PLUS",
4478 "GCC_JIT_BINARY_OP_MINUS",
4479 "GCC_JIT_BINARY_OP_MULT",
4480 "GCC_JIT_BINARY_OP_DIVIDE",
4481 "GCC_JIT_BINARY_OP_MODULO",
4482 "GCC_JIT_BINARY_OP_BITWISE_AND",
4483 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4484 "GCC_JIT_BINARY_OP_BITWISE_OR",
4485 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4486 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4487 "GCC_JIT_BINARY_OP_LSHIFT",
4488 "GCC_JIT_BINARY_OP_RSHIFT"
4491 /* Implementation of recording::memento::write_reproducer for binary ops. */
4494 recording::binary_op::write_reproducer (reproducer
&r
)
4496 const char *id
= r
.make_identifier (this, "rvalue");
4497 r
.write (" gcc_jit_rvalue *%s =\n"
4498 " gcc_jit_context_new_binary_op (%s,\n"
4499 " %s, /* gcc_jit_location *loc */\n"
4500 " %s, /* enum gcc_jit_binary_op op */\n"
4501 " %s, /* gcc_jit_type *result_type */\n"
4502 " %s, /* gcc_jit_rvalue *a */\n"
4503 " %s); /* gcc_jit_rvalue *b */\n",
4505 r
.get_identifier (get_context ()),
4506 r
.get_identifier (m_loc
),
4507 binary_op_reproducer_strings
[m_op
],
4508 r
.get_identifier_as_type (get_type ()),
4509 r
.get_identifier_as_rvalue (m_a
),
4510 r
.get_identifier_as_rvalue (m_b
));
4513 namespace recording
{
4514 static const enum precedence binary_op_precedence
[] = {
4515 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_PLUS */
4516 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_MINUS */
4518 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MULT */
4519 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_DIVIDE */
4520 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MODULO */
4522 PRECEDENCE_BITWISE_AND
, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4523 PRECEDENCE_BITWISE_XOR
, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4524 PRECEDENCE_BITWISE_IOR
, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4525 PRECEDENCE_LOGICAL_AND
, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4526 PRECEDENCE_LOGICAL_OR
, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4527 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_LSHIFT */
4528 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_RSHIFT */
4530 } /* namespace recording */
4532 enum recording::precedence
4533 recording::binary_op::get_precedence () const
4535 return binary_op_precedence
[m_op
];
4538 /* The implementation of class gcc::jit::recording::comparison. */
4540 /* Implementation of recording::memento::make_debug_string for
4543 static const char * const comparison_strings
[] =
4545 "==", /* GCC_JIT_COMPARISON_EQ */
4546 "!=", /* GCC_JIT_COMPARISON_NE */
4547 "<", /* GCC_JIT_COMPARISON_LT */
4548 "<=", /* GCC_JIT_COMPARISON_LE */
4549 ">", /* GCC_JIT_COMPARISON_GT */
4550 ">=", /* GCC_JIT_COMPARISON_GE */
4554 recording::comparison::make_debug_string ()
4556 enum precedence prec
= get_precedence ();
4557 return string::from_printf (m_ctxt
,
4559 m_a
->get_debug_string_parens (prec
),
4560 comparison_strings
[m_op
],
4561 m_b
->get_debug_string_parens (prec
));
4564 /* A table of enum gcc_jit_comparison values expressed in string
4567 static const char * const comparison_reproducer_strings
[] =
4569 "GCC_JIT_COMPARISON_EQ",
4570 "GCC_JIT_COMPARISON_NE",
4571 "GCC_JIT_COMPARISON_LT",
4572 "GCC_JIT_COMPARISON_LE",
4573 "GCC_JIT_COMPARISON_GT",
4574 "GCC_JIT_COMPARISON_GE"
4577 /* Implementation of recording::memento::write_reproducer for comparisons. */
4580 recording::comparison::write_reproducer (reproducer
&r
)
4582 const char *id
= r
.make_identifier (this, "rvalue");
4583 r
.write (" gcc_jit_rvalue *%s =\n"
4584 " gcc_jit_context_new_comparison (%s,\n"
4585 " %s, /* gcc_jit_location *loc */\n"
4586 " %s, /* enum gcc_jit_comparison op */\n"
4587 " %s, /* gcc_jit_rvalue *a */\n"
4588 " %s); /* gcc_jit_rvalue *b */\n",
4590 r
.get_identifier (get_context ()),
4591 r
.get_identifier (m_loc
),
4592 comparison_reproducer_strings
[m_op
],
4593 r
.get_identifier_as_rvalue (m_a
),
4594 r
.get_identifier_as_rvalue (m_b
));
4597 /* Implementation of pure virtual hook recording::memento::replay_into
4598 for recording::comparison. */
4601 recording::comparison::replay_into (replayer
*r
)
4603 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
4605 m_a
->playback_rvalue (),
4606 m_b
->playback_rvalue ()));
4609 /* Implementation of pure virtual hook recording::rvalue::visit_children
4610 for recording::comparison. */
4613 recording::comparison::visit_children (rvalue_visitor
*v
)
4619 namespace recording
{
4620 static const enum precedence comparison_precedence
[] =
4622 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_EQ */
4623 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_NE */
4625 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LT */
4626 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LE */
4627 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GT */
4628 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GE */
4630 } /* namespace recording */
4632 enum recording::precedence
4633 recording::comparison::get_precedence () const
4635 return comparison_precedence
[m_op
];
4638 /* Implementation of pure virtual hook recording::memento::replay_into
4639 for recording::cast. */
4642 recording::cast::replay_into (replayer
*r
)
4644 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
4645 m_rvalue
->playback_rvalue (),
4646 get_type ()->playback_type ()));
4649 /* Implementation of pure virtual hook recording::rvalue::visit_children
4650 for recording::cast. */
4652 recording::cast::visit_children (rvalue_visitor
*v
)
4654 v
->visit (m_rvalue
);
4657 /* Implementation of recording::memento::make_debug_string for
4661 recording::cast::make_debug_string ()
4663 enum precedence prec
= get_precedence ();
4664 return string::from_printf (m_ctxt
,
4666 get_type ()->get_debug_string (),
4667 m_rvalue
->get_debug_string_parens (prec
));
4670 /* Implementation of recording::memento::write_reproducer for casts. */
4673 recording::cast::write_reproducer (reproducer
&r
)
4675 const char *id
= r
.make_identifier (this, "rvalue");
4676 r
.write (" gcc_jit_rvalue *%s =\n"
4677 " gcc_jit_context_new_cast (%s,\n"
4678 " %s, /* gcc_jit_location *loc */\n"
4679 " %s, /* gcc_jit_rvalue *rvalue */\n"
4680 " %s); /* gcc_jit_type *type */\n",
4682 r
.get_identifier (get_context ()),
4683 r
.get_identifier (m_loc
),
4684 r
.get_identifier_as_rvalue (m_rvalue
),
4685 r
.get_identifier_as_type (get_type ()));
4688 /* The implementation of class gcc::jit::recording::call. */
4690 /* The constructor for gcc::jit::recording::call. */
4692 recording::call::call (recording::context
*ctxt
,
4693 recording::location
*loc
,
4694 recording::function
*func
,
4697 : rvalue (ctxt
, loc
, func
->get_return_type ()),
4701 for (int i
= 0; i
< numargs
; i
++)
4702 m_args
.safe_push (args
[i
]);
4705 /* Implementation of pure virtual hook recording::memento::replay_into
4706 for recording::call. */
4709 recording::call::replay_into (replayer
*r
)
4711 auto_vec
<playback::rvalue
*> playback_args
;
4712 playback_args
.create (m_args
.length ());
4713 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4714 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
4716 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
4717 m_func
->playback_function (),
4721 /* Implementation of pure virtual hook recording::rvalue::visit_children
4722 for recording::call. */
4725 recording::call::visit_children (rvalue_visitor
*v
)
4727 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4728 v
->visit (m_args
[i
]);
4731 /* Implementation of recording::memento::make_debug_string for
4735 recording::call::make_debug_string ()
4737 enum precedence prec
= get_precedence ();
4738 /* First, build a buffer for the arguments. */
4739 /* Calculate length of said buffer. */
4740 size_t sz
= 1; /* nil terminator */
4741 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4743 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4744 sz
+= 2; /* ", " separator */
4747 /* Now allocate and populate the buffer. */
4748 char *argbuf
= new char[sz
];
4751 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4753 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
4754 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4755 if (i
+ 1 < m_args
.length ())
4757 strcpy (argbuf
+ len
, ", ");
4763 /* ...and use it to get the string for the call as a whole. */
4764 string
*result
= string::from_printf (m_ctxt
,
4766 m_func
->get_debug_string (),
4775 recording::call::write_reproducer (reproducer
&r
)
4777 const char *id
= r
.make_identifier (this, "call");
4778 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
4779 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4782 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4783 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
4785 r
.write (" gcc_jit_rvalue *%s =\n"
4786 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4787 " %s, /* gcc_jit_location *loc */\n"
4788 " %s, /* gcc_jit_function *func */\n"
4789 " %i, /* int numargs */ \n"
4790 " %s); /* gcc_jit_rvalue **args*/\n",
4792 r
.get_identifier (get_context ()),
4793 r
.get_identifier (m_loc
),
4794 r
.get_identifier (m_func
),
4799 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4801 /* The constructor for recording::call_through_ptr. */
4803 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
4804 recording::location
*loc
,
4805 recording::rvalue
*fn_ptr
,
4808 : rvalue (ctxt
, loc
,
4809 fn_ptr
->get_type ()->dereference ()
4810 ->as_a_function_type ()->get_return_type ()),
4814 for (int i
= 0; i
< numargs
; i
++)
4815 m_args
.safe_push (args
[i
]);
4818 /* Implementation of pure virtual hook recording::memento::replay_into
4819 for recording::call_through_ptr. */
4822 recording::call_through_ptr::replay_into (replayer
*r
)
4824 auto_vec
<playback::rvalue
*> playback_args
;
4825 playback_args
.create (m_args
.length ());
4826 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4827 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
4829 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
4830 m_fn_ptr
->playback_rvalue (),
4834 /* Implementation of pure virtual hook recording::rvalue::visit_children
4835 for recording::call_through_ptr. */
4838 recording::call_through_ptr::visit_children (rvalue_visitor
*v
)
4840 v
->visit (m_fn_ptr
);
4841 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4842 v
->visit (m_args
[i
]);
4845 /* Implementation of recording::memento::make_debug_string for
4846 calls through function ptrs. */
4849 recording::call_through_ptr::make_debug_string ()
4851 enum precedence prec
= get_precedence ();
4852 /* First, build a buffer for the arguments. */
4853 /* Calculate length of said buffer. */
4854 size_t sz
= 1; /* nil terminator */
4855 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4857 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4858 sz
+= 2; /* ", " separator */
4861 /* Now allocate and populate the buffer. */
4862 char *argbuf
= new char[sz
];
4865 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4867 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
4868 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4869 if (i
+ 1 < m_args
.length ())
4871 strcpy (argbuf
+ len
, ", ");
4877 /* ...and use it to get the string for the call as a whole. */
4878 string
*result
= string::from_printf (m_ctxt
,
4880 m_fn_ptr
->get_debug_string_parens (prec
),
4888 /* Implementation of recording::memento::write_reproducer for
4889 call_through_ptr. */
4892 recording::call_through_ptr::write_reproducer (reproducer
&r
)
4894 const char *id
= r
.make_identifier (this, "call");
4895 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
4896 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4899 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4900 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
4902 r
.write (" gcc_jit_rvalue *%s =\n"
4903 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
4904 " %s, /* gcc_jit_location *loc */\n"
4905 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
4906 " %i, /* int numargs */ \n"
4907 " %s); /* gcc_jit_rvalue **args*/\n",
4909 r
.get_identifier (get_context ()),
4910 r
.get_identifier (m_loc
),
4911 r
.get_identifier_as_rvalue (m_fn_ptr
),
4916 /* The implementation of class gcc::jit::recording::array_access. */
4918 /* Implementation of pure virtual hook recording::memento::replay_into
4919 for recording::array_access. */
4922 recording::array_access::replay_into (replayer
*r
)
4925 r
->new_array_access (playback_location (r
, m_loc
),
4926 m_ptr
->playback_rvalue (),
4927 m_index
->playback_rvalue ()));
4930 /* Implementation of pure virtual hook recording::rvalue::visit_children
4931 for recording::array_access. */
4934 recording::array_access::visit_children (rvalue_visitor
*v
)
4940 /* Implementation of recording::memento::make_debug_string for
4944 recording::array_access::make_debug_string ()
4946 enum precedence prec
= get_precedence ();
4947 return string::from_printf (m_ctxt
,
4949 m_ptr
->get_debug_string_parens (prec
),
4950 m_index
->get_debug_string_parens (prec
));
4953 /* Implementation of recording::memento::write_reproducer for
4957 recording::array_access::write_reproducer (reproducer
&r
)
4959 const char *id
= r
.make_identifier (this, "lvalue");
4960 r
.write (" gcc_jit_lvalue *%s = \n"
4961 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
4962 " %s, /*gcc_jit_location *loc */\n"
4963 " %s, /* gcc_jit_rvalue *ptr */\n"
4964 " %s); /* gcc_jit_rvalue *index */\n",
4966 r
.get_identifier (get_context ()),
4967 r
.get_identifier (m_loc
),
4968 r
.get_identifier_as_rvalue (m_ptr
),
4969 r
.get_identifier_as_rvalue (m_index
));
4972 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
4974 /* Implementation of pure virtual hook recording::memento::replay_into
4975 for recording::access_field_of_lvalue. */
4978 recording::access_field_of_lvalue::replay_into (replayer
*r
)
4981 m_lvalue
->playback_lvalue ()
4982 ->access_field (playback_location (r
, m_loc
),
4983 m_field
->playback_field ()));
4987 /* Implementation of pure virtual hook recording::rvalue::visit_children
4988 for recording::access_field_of_lvalue. */
4991 recording::access_field_of_lvalue::visit_children (rvalue_visitor
*v
)
4993 v
->visit (m_lvalue
);
4996 /* Implementation of recording::memento::make_debug_string for
4997 accessing a field of an lvalue. */
5000 recording::access_field_of_lvalue::make_debug_string ()
5002 enum precedence prec
= get_precedence ();
5003 return string::from_printf (m_ctxt
,
5005 m_lvalue
->get_debug_string_parens (prec
),
5006 m_field
->get_debug_string ());
5009 /* Implementation of recording::memento::write_reproducer for
5010 access_field_of_lvalue. */
5013 recording::access_field_of_lvalue::write_reproducer (reproducer
&r
)
5015 const char *id
= r
.make_identifier (this, "lvalue");
5016 r
.write (" gcc_jit_lvalue *%s = \n"
5017 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5018 " %s, /*gcc_jit_location *loc */\n"
5021 r
.get_identifier_as_lvalue (m_lvalue
),
5022 r
.get_identifier (m_loc
),
5023 r
.get_identifier (m_field
));
5026 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
5028 /* Implementation of pure virtual hook recording::memento::replay_into
5029 for recording::access_field_rvalue. */
5032 recording::access_field_rvalue::replay_into (replayer
*r
)
5035 m_rvalue
->playback_rvalue ()
5036 ->access_field (playback_location (r
, m_loc
),
5037 m_field
->playback_field ()));
5040 /* Implementation of pure virtual hook recording::rvalue::visit_children
5041 for recording::access_field_rvalue. */
5044 recording::access_field_rvalue::visit_children (rvalue_visitor
*v
)
5046 v
->visit (m_rvalue
);
5049 /* Implementation of recording::memento::make_debug_string for
5050 accessing a field of an rvalue. */
5053 recording::access_field_rvalue::make_debug_string ()
5055 enum precedence prec
= get_precedence ();
5056 return string::from_printf (m_ctxt
,
5058 m_rvalue
->get_debug_string_parens (prec
),
5059 m_field
->get_debug_string ());
5062 /* Implementation of recording::memento::write_reproducer for
5063 access_field_rvalue. */
5066 recording::access_field_rvalue::write_reproducer (reproducer
&r
)
5068 const char *id
= r
.make_identifier (this, "rvalue");
5069 r
.write (" gcc_jit_rvalue *%s = \n"
5070 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5071 " %s, /*gcc_jit_location *loc */\n"
5074 r
.get_identifier_as_rvalue (m_rvalue
),
5075 r
.get_identifier (m_loc
),
5076 r
.get_identifier (m_field
));
5079 /* The implementation of class
5080 gcc::jit::recording::dereference_field_rvalue. */
5082 /* Implementation of pure virtual hook recording::memento::replay_into
5083 for recording::dereference_field_rvalue. */
5086 recording::dereference_field_rvalue::replay_into (replayer
*r
)
5089 m_rvalue
->playback_rvalue ()->
5090 dereference_field (playback_location (r
, m_loc
),
5091 m_field
->playback_field ()));
5094 /* Implementation of pure virtual hook recording::rvalue::visit_children
5095 for recording::dereference_field_rvalue. */
5098 recording::dereference_field_rvalue::visit_children (rvalue_visitor
*v
)
5100 v
->visit (m_rvalue
);
5103 /* Implementation of recording::memento::make_debug_string for
5104 dereferencing a field of an rvalue. */
5107 recording::dereference_field_rvalue::make_debug_string ()
5109 enum precedence prec
= get_precedence ();
5110 return string::from_printf (m_ctxt
,
5112 m_rvalue
->get_debug_string_parens (prec
),
5113 m_field
->get_debug_string ());
5116 /* Implementation of recording::memento::write_reproducer for
5117 dereference_field_rvalue. */
5120 recording::dereference_field_rvalue::write_reproducer (reproducer
&r
)
5122 const char *id
= r
.make_identifier (this, "lvalue");
5123 r
.write (" gcc_jit_lvalue *%s=\n"
5124 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5125 " %s, /* gcc_jit_location *loc */\n"
5126 " %s); /* gcc_jit_field *field */\n",
5128 r
.get_identifier_as_rvalue (m_rvalue
),
5129 r
.get_identifier (m_loc
),
5130 r
.get_identifier (m_field
));
5133 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5135 /* Implementation of pure virtual hook recording::memento::replay_into
5136 for recording::dereference_rvalue. */
5139 recording::dereference_rvalue::replay_into (replayer
*r
)
5142 m_rvalue
->playback_rvalue ()->
5143 dereference (playback_location (r
, m_loc
)));
5146 /* Implementation of pure virtual hook recording::rvalue::visit_children
5147 for recording::dereference_rvalue. */
5150 recording::dereference_rvalue::visit_children (rvalue_visitor
*v
)
5152 v
->visit (m_rvalue
);
5155 /* Implementation of recording::memento::make_debug_string for
5156 dereferencing an rvalue. */
5159 recording::dereference_rvalue::make_debug_string ()
5161 enum precedence prec
= get_precedence ();
5162 return string::from_printf (m_ctxt
,
5164 m_rvalue
->get_debug_string_parens (prec
));
5167 /* Implementation of recording::memento::write_reproducer for
5168 dereference_rvalue. */
5171 recording::dereference_rvalue::write_reproducer (reproducer
&r
)
5173 const char *id
= r
.make_identifier (this, "dereference");
5174 r
.write (" gcc_jit_lvalue *%s =\n"
5175 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5176 " %s); /* gcc_jit_location *loc */\n",
5178 r
.get_identifier_as_rvalue (m_rvalue
),
5179 r
.get_identifier (m_loc
));
5182 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5184 /* Implementation of pure virtual hook recording::memento::replay_into
5185 for recording::get_address_of_lvalue. */
5188 recording::get_address_of_lvalue::replay_into (replayer
*r
)
5191 m_lvalue
->playback_lvalue ()->
5192 get_address (playback_location (r
, m_loc
)));
5195 /* Implementation of pure virtual hook recording::rvalue::visit_children
5196 for recording::get_address_of_lvalue. */
5199 recording::get_address_of_lvalue::visit_children (rvalue_visitor
*v
)
5201 v
->visit (m_lvalue
);
5204 /* Implementation of recording::memento::make_debug_string for
5205 getting the address of an lvalue. */
5208 recording::get_address_of_lvalue::make_debug_string ()
5210 enum precedence prec
= get_precedence ();
5211 return string::from_printf (m_ctxt
,
5213 m_lvalue
->get_debug_string_parens (prec
));
5216 /* Implementation of recording::memento::write_reproducer for
5217 get_address_of_lvalue. */
5220 recording::get_address_of_lvalue::write_reproducer (reproducer
&r
)
5222 const char *id
= r
.make_identifier (this, "address_of");
5223 r
.write (" gcc_jit_rvalue *%s =\n"
5224 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5225 " %s); /* gcc_jit_location *loc */\n",
5227 r
.get_identifier_as_lvalue (m_lvalue
),
5228 r
.get_identifier (m_loc
));
5231 /* The implementation of class gcc::jit::recording::local. */
5233 /* Implementation of pure virtual hook recording::memento::replay_into
5234 for recording::local. */
5237 recording::local::replay_into (replayer
*r
)
5240 m_func
->playback_function ()
5241 ->new_local (playback_location (r
, m_loc
),
5242 m_type
->playback_type (),
5243 playback_string (m_name
)));
5246 /* Override the default implementation of
5247 recording::memento::write_to_dump for locals by writing
5249 for use at the top of the function body as if it were a
5253 recording::local::write_to_dump (dump
&d
)
5255 if (d
.update_locations ())
5256 m_loc
= d
.make_location ();
5257 d
.write(" %s %s;\n",
5258 m_type
->get_debug_string (),
5259 get_debug_string ());
5263 recording::local::write_reproducer (reproducer
&r
)
5265 const char *id
= r
.make_identifier (this, "local");
5266 r
.write (" gcc_jit_lvalue *%s =\n"
5267 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5268 " %s, /* gcc_jit_location *loc */\n"
5269 " %s, /* gcc_jit_type *type */\n"
5270 " %s); /* const char *name */\n",
5272 r
.get_identifier (m_func
),
5273 r
.get_identifier (m_loc
),
5274 r
.get_identifier_as_type (m_type
),
5275 m_name
->get_debug_string ());
5278 /* The implementation of class gcc::jit::recording::statement. */
5280 /* We poison the default implementation of
5281 gcc::jit::recording::statement::get_successor_blocks
5282 since this vfunc must only ever be called on terminator
5285 vec
<recording::block
*>
5286 recording::statement::get_successor_blocks () const
5288 /* The base class implementation is for non-terminating statements,
5289 and thus should never be called. */
5291 vec
<block
*> result
;
5296 /* Extend the default implementation of
5297 recording::memento::write_to_dump for statements by (if requested)
5298 updating the location of the statement to the current location in
5302 recording::statement::write_to_dump (dump
&d
)
5304 memento::write_to_dump (d
);
5305 if (d
.update_locations ())
5306 m_loc
= d
.make_location ();
5309 /* The implementation of class gcc::jit::recording::eval. */
5311 /* Implementation of pure virtual hook recording::memento::replay_into
5312 for recording::eval. */
5315 recording::eval::replay_into (replayer
*r
)
5317 playback_block (get_block ())
5318 ->add_eval (playback_location (r
),
5319 m_rvalue
->playback_rvalue ());
5322 /* Implementation of recording::memento::make_debug_string for
5323 an eval statement. */
5326 recording::eval::make_debug_string ()
5328 return string::from_printf (m_ctxt
,
5330 m_rvalue
->get_debug_string ());
5333 /* Implementation of recording::memento::write_reproducer for
5337 recording::eval::write_reproducer (reproducer
&r
)
5339 r
.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5340 " %s, /* gcc_jit_location *loc */\n"
5341 " %s); /* gcc_jit_rvalue *rvalue */\n",
5342 r
.get_identifier (get_block ()),
5343 r
.get_identifier (get_loc ()),
5344 r
.get_identifier_as_rvalue (m_rvalue
));
5347 /* The implementation of class gcc::jit::recording::assignment. */
5349 /* Implementation of pure virtual hook recording::memento::replay_into
5350 for recording::assignment. */
5353 recording::assignment::replay_into (replayer
*r
)
5355 playback_block (get_block ())
5356 ->add_assignment (playback_location (r
),
5357 m_lvalue
->playback_lvalue (),
5358 m_rvalue
->playback_rvalue ());
5361 /* Implementation of recording::memento::make_debug_string for
5362 an assignment statement. */
5365 recording::assignment::make_debug_string ()
5367 return string::from_printf (m_ctxt
,
5369 m_lvalue
->get_debug_string (),
5370 m_rvalue
->get_debug_string ());
5373 /* Implementation of recording::memento::write_reproducer for
5374 assignment statements. */
5377 recording::assignment::write_reproducer (reproducer
&r
)
5379 r
.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5380 " %s, /* gcc_jit_location *loc */\n"
5381 " %s, /* gcc_jit_lvalue *lvalue */\n"
5382 " %s); /* gcc_jit_rvalue *rvalue */\n",
5383 r
.get_identifier (get_block ()),
5384 r
.get_identifier (get_loc ()),
5385 r
.get_identifier_as_lvalue (m_lvalue
),
5386 r
.get_identifier_as_rvalue (m_rvalue
));
5389 /* The implementation of class gcc::jit::recording::assignment_op. */
5391 /* Implementation of pure virtual hook recording::memento::replay_into
5392 for recording::assignment_op. */
5395 recording::assignment_op::replay_into (replayer
*r
)
5397 playback::type
*result_type
=
5398 m_lvalue
->playback_lvalue ()->get_type ();
5400 playback::rvalue
*binary_op
=
5401 r
->new_binary_op (playback_location (r
),
5404 m_lvalue
->playback_rvalue (),
5405 m_rvalue
->playback_rvalue ());
5407 playback_block (get_block ())
5408 ->add_assignment (playback_location (r
),
5409 m_lvalue
->playback_lvalue (),
5413 /* Implementation of recording::memento::make_debug_string for
5414 an assignment_op statement. */
5417 recording::assignment_op::make_debug_string ()
5419 return string::from_printf (m_ctxt
,
5421 m_lvalue
->get_debug_string (),
5422 binary_op_strings
[m_op
],
5423 m_rvalue
->get_debug_string ());
5426 /* Implementation of recording::memento::write_reproducer for
5427 assignment_op statements. */
5430 recording::assignment_op::write_reproducer (reproducer
&r
)
5432 r
.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5433 " %s, /* gcc_jit_location *loc */\n"
5434 " %s, /* gcc_jit_lvalue *lvalue */\n"
5435 " %s, /* enum gcc_jit_binary_op op */\n"
5436 " %s); /* gcc_jit_rvalue *rvalue */\n",
5437 r
.get_identifier (get_block ()),
5438 r
.get_identifier (get_loc ()),
5439 r
.get_identifier_as_lvalue (m_lvalue
),
5440 binary_op_reproducer_strings
[m_op
],
5441 r
.get_identifier_as_rvalue (m_rvalue
));
5444 /* The implementation of class gcc::jit::recording::comment. */
5446 /* Implementation of pure virtual hook recording::memento::replay_into
5447 for recording::comment. */
5450 recording::comment::replay_into (replayer
*r
)
5452 playback_block (get_block ())
5453 ->add_comment (playback_location (r
),
5457 /* Implementation of recording::memento::make_debug_string for
5458 a comment "statement". */
5461 recording::comment::make_debug_string ()
5463 return string::from_printf (m_ctxt
,
5468 /* Implementation of recording::memento::write_reproducer for
5472 recording::comment::write_reproducer (reproducer
&r
)
5474 r
.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5475 " %s, /* gcc_jit_location *loc */\n"
5476 " %s); /* const char *text */\n",
5477 r
.get_identifier (get_block ()),
5478 r
.get_identifier (get_loc ()),
5479 m_text
->get_debug_string ());
5482 /* The implementation of class gcc::jit::recording::conditional. */
5484 /* Implementation of pure virtual hook recording::memento::replay_into
5485 for recording::conditional. */
5488 recording::conditional::replay_into (replayer
*r
)
5490 playback_block (get_block ())
5491 ->add_conditional (playback_location (r
),
5492 m_boolval
->playback_rvalue (),
5493 playback_block (m_on_true
),
5494 playback_block (m_on_false
));
5497 /* Override the poisoned default implementation of
5498 gcc::jit::recording::statement::get_successor_blocks
5500 A conditional jump has 2 successor blocks. */
5502 vec
<recording::block
*>
5503 recording::conditional::get_successor_blocks () const
5505 vec
<block
*> result
;
5507 result
.quick_push (m_on_true
);
5508 result
.quick_push (m_on_false
);
5512 /* Implementation of recording::memento::make_debug_string for
5513 a conditional jump statement. */
5516 recording::conditional::make_debug_string ()
5519 return string::from_printf (m_ctxt
,
5520 "if (%s) goto %s; else goto %s;",
5521 m_boolval
->get_debug_string (),
5522 m_on_true
->get_debug_string (),
5523 m_on_false
->get_debug_string ());
5525 return string::from_printf (m_ctxt
,
5527 m_boolval
->get_debug_string (),
5528 m_on_true
->get_debug_string ());
5531 /* Implementation of recording::memento::write_reproducer for
5532 conditional statements. */
5535 recording::conditional::write_reproducer (reproducer
&r
)
5537 r
.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5538 " %s, /* gcc_jit_location *loc */\n"
5539 " %s, /* gcc_jit_rvalue *boolval */\n"
5540 " %s, /* gcc_jit_block *on_true */\n"
5541 " %s); /* gcc_jit_block *on_false */\n",
5542 r
.get_identifier (get_block ()),
5543 r
.get_identifier (get_loc ()),
5544 r
.get_identifier_as_rvalue (m_boolval
),
5545 r
.get_identifier (m_on_true
),
5546 r
.get_identifier (m_on_false
));
5549 /* The implementation of class gcc::jit::recording::jump. */
5551 /* Implementation of pure virtual hook recording::memento::replay_into
5552 for recording::jump. */
5555 recording::jump::replay_into (replayer
*r
)
5557 playback_block (get_block ())
5558 ->add_jump (playback_location (r
),
5559 m_target
->playback_block ());
5562 /* Override the poisoned default implementation of
5563 gcc::jit::recording::statement::get_successor_blocks
5565 An unconditional jump has 1 successor block. */
5567 vec
<recording::block
*>
5568 recording::jump::get_successor_blocks () const
5570 vec
<block
*> result
;
5572 result
.quick_push (m_target
);
5576 /* Implementation of recording::memento::make_debug_string for
5577 a unconditional jump statement. */
5580 recording::jump::make_debug_string ()
5582 return string::from_printf (m_ctxt
,
5584 m_target
->get_debug_string ());
5587 /* Implementation of recording::memento::write_reproducer for
5591 recording::jump::write_reproducer (reproducer
&r
)
5593 r
.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5594 " %s, /* gcc_jit_location *loc */\n"
5595 " %s); /* gcc_jit_block *target */\n",
5596 r
.get_identifier (get_block ()),
5597 r
.get_identifier (get_loc ()),
5598 r
.get_identifier (m_target
));
5601 /* The implementation of class gcc::jit::recording::return_. */
5603 /* Implementation of pure virtual hook recording::memento::replay_into
5604 for recording::return_. */
5607 recording::return_::replay_into (replayer
*r
)
5609 playback_block (get_block ())
5610 ->add_return (playback_location (r
),
5611 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
5614 /* Override the poisoned default implementation of
5615 gcc::jit::recording::statement::get_successor_blocks
5617 A return statement has no successor block. */
5619 vec
<recording::block
*>
5620 recording::return_::get_successor_blocks () const
5622 vec
<block
*> result
;
5627 /* Implementation of recording::memento::make_debug_string for
5628 a return statement (covers both those with and without rvalues). */
5631 recording::return_::make_debug_string ()
5634 return string::from_printf (m_ctxt
,
5636 m_rvalue
->get_debug_string ());
5638 return string::from_printf (m_ctxt
,
5642 /* Implementation of recording::memento::write_reproducer for
5643 return statements. */
5646 recording::return_::write_reproducer (reproducer
&r
)
5649 r
.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5650 " %s, /* gcc_jit_location *loc */\n"
5651 " %s); /* gcc_jit_rvalue *rvalue */\n",
5652 r
.get_identifier (get_block ()),
5653 r
.get_identifier (get_loc ()),
5654 r
.get_identifier_as_rvalue (m_rvalue
));
5656 r
.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5657 " %s); /* gcc_jit_location *loc */\n",
5658 r
.get_identifier (get_block ()),
5659 r
.get_identifier (get_loc ()));
5662 /* The implementation of class gcc::jit::recording::case_. */
5665 recording::case_::write_reproducer (reproducer
&r
)
5667 const char *id
= r
.make_identifier (this, "case");
5669 " gcc_jit_case *%s = \n"
5670 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
5671 " %s, /* gcc_jit_rvalue *min_value */\n"
5672 " %s, /* gcc_jit_rvalue *max_value */\n"
5673 " %s); /* gcc_jit_block *dest_block */\n";
5676 r
.get_identifier (get_context ()),
5677 r
.get_identifier_as_rvalue (m_min_value
),
5678 r
.get_identifier_as_rvalue (m_max_value
),
5679 r
.get_identifier (m_dest_block
));
5683 recording::case_::make_debug_string ()
5685 return string::from_printf (get_context (),
5686 "case %s ... %s: goto %s;",
5687 m_min_value
->get_debug_string (),
5688 m_max_value
->get_debug_string (),
5689 m_dest_block
->get_debug_string ());
5692 /* The implementation of class gcc::jit::recording::switch_. */
5694 /* gcc::jit::recording::switch_'s constructor. */
5696 recording::switch_::switch_ (block
*b
,
5699 block
*default_block
,
5702 : statement (b
, loc
),
5704 m_default_block (default_block
)
5706 m_cases
.reserve_exact (num_cases
);
5707 for (int i
= 0; i
< num_cases
; i
++)
5708 m_cases
.quick_push (cases
[i
]);
5711 /* Implementation of pure virtual hook recording::memento::replay_into
5712 for recording::switch_. */
5715 recording::switch_::replay_into (replayer
*r
)
5717 auto_vec
<playback::case_
> pcases
;
5719 recording::case_
*rcase
;
5720 pcases
.reserve_exact (m_cases
.length ());
5721 FOR_EACH_VEC_ELT (m_cases
, i
, rcase
)
5723 playback::case_
pcase (rcase
->get_min_value ()->playback_rvalue (),
5724 rcase
->get_max_value ()->playback_rvalue (),
5725 rcase
->get_dest_block ()->playback_block ());
5726 pcases
.safe_push (pcase
);
5728 playback_block (get_block ())
5729 ->add_switch (playback_location (r
),
5730 m_expr
->playback_rvalue (),
5731 m_default_block
->playback_block (),
5735 /* Override the poisoned default implementation of
5736 gcc::jit::recording::statement::get_successor_blocks
5738 A switch statement has (NUM_CASES + 1) successor blocks. */
5740 vec
<recording::block
*>
5741 recording::switch_::get_successor_blocks () const
5743 vec
<block
*> result
;
5744 result
.create (m_cases
.length () + 1);
5745 result
.quick_push (m_default_block
);
5748 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
5749 result
.quick_push (c
->get_dest_block ());
5753 /* Implementation of recording::memento::make_debug_string for
5754 a switch statement. */
5757 recording::switch_::make_debug_string ()
5759 auto_vec
<char> cases_str
;
5762 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
5764 size_t len
= strlen (c
->get_debug_string ());
5765 unsigned idx
= cases_str
.length ();
5766 cases_str
.safe_grow (idx
+ 1 + len
);
5767 cases_str
[idx
] = ' ';
5768 memcpy (&(cases_str
[idx
+ 1]),
5769 c
->get_debug_string (),
5772 cases_str
.safe_push ('\0');
5774 return string::from_printf (m_ctxt
,
5775 "switch (%s) {default: goto %s;%s}",
5776 m_expr
->get_debug_string (),
5777 m_default_block
->get_debug_string (),
5781 /* Implementation of recording::memento::write_reproducer for
5782 switch statements. */
5785 recording::switch_::write_reproducer (reproducer
&r
)
5787 r
.make_identifier (this, "switch");
5790 const char *cases_id
=
5791 r
.make_tmp_identifier ("cases_for", this);
5792 r
.write (" gcc_jit_case *%s[%i] = {\n",
5795 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
5796 r
.write (" %s,\n", r
.get_identifier (c
));
5799 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
5800 " %s, /* gcc_jit_location *loc */\n"
5801 " %s, /* gcc_jit_rvalue *expr */\n"
5802 " %s, /* gcc_jit_block *default_block */\n"
5803 " %i, /* int num_cases */\n"
5804 " %s); /* gcc_jit_case **cases */\n";
5806 r
.get_identifier (get_block ()),
5807 r
.get_identifier (get_loc ()),
5808 r
.get_identifier_as_rvalue (m_expr
),
5809 r
.get_identifier (m_default_block
),
5814 } // namespace gcc::jit