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"
30 #include "jit-common.h"
31 #include "jit-builtins.h"
32 #include "jit-logging.h"
33 #include "jit-recording.h"
34 #include "jit-playback.h"
41 dump::dump (recording::context
&ctxt
,
43 bool update_locations
)
45 m_filename (filename
),
46 m_update_locations (update_locations
),
50 m_file
= fopen (filename
, "w");
53 "error opening dump file %s for writing: %s",
62 int err
= fclose (m_file
);
64 m_ctxt
.add_error (NULL
,
65 "error closing dump file %s: %s",
71 /* Write the given message to the dump, using printf-formatting
72 conventions, updating the line/column within the dump.
74 Emit an error on the context if a failure occurs. */
77 dump::write (const char *fmt
, ...)
82 /* If there was an error opening the file, we've already reported it.
83 Don't attempt further work. */
88 vasprintf (&buf
, fmt
, ap
);
93 m_ctxt
.add_error (NULL
, "malloc failure writing to dumpfile %s",
98 if (fwrite (buf
, strlen (buf
), 1, m_file
) != 1)
99 m_ctxt
.add_error (NULL
, "error writing to dump file %s",
102 /* Flush after each line, to ease debugging crashes. */
105 /* Update line/column: */
106 for (const char *ptr
= buf
; *ptr
; ptr
++)
120 /* Construct a gcc::jit::recording::location instance for the current
121 location within the dump. */
123 recording::location
*
124 dump::make_location () const
126 return m_ctxt
.new_location (m_filename
, m_line
, m_column
,
127 /* We need to flag such locations as *not*
128 created by the user, so that
129 reproducer::get_identifier can cope with
130 them appearing *after* the memento that
135 /* A collection of allocations, all of which can be released together, to
136 avoid needing to track and release them individually. */
144 xstrdup_printf (const char *, ...)
145 ATTRIBUTE_RETURNS_NONNULL
149 xstrdup_printf_va (const char *, va_list ap
)
150 ATTRIBUTE_RETURNS_NONNULL
154 auto_vec
<void *> m_buffers
;
157 /* allocator's destructor. Call "free" on all of the allocations. */
159 allocator::~allocator ()
163 FOR_EACH_VEC_ELT (m_buffers
, i
, buffer
)
167 /* Formatted printing, allocating to a buffer (or exiting the process if
168 the allocation fails).
170 The buffer exists until the allocator is cleaned up, and is freed at
171 that point, so the caller doesn't need to track the result. */
174 allocator::xstrdup_printf (const char *fmt
, ...)
179 result
= xstrdup_printf_va (fmt
, ap
);
184 /* Formatted printing, allocating to a buffer (or exiting the process if
185 the allocation fails).
187 The buffer exists until the allocator is cleaned up, and is freed at
188 that point, so the caller doesn't need to track the result. */
191 allocator::xstrdup_printf_va (const char *fmt
, va_list ap
)
193 char *result
= xvasprintf (fmt
, ap
);
194 m_buffers
.safe_push (result
);
198 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
199 implementing gcc_jit_context_dump_reproducer_to_file. */
201 class reproducer
: public dump
204 reproducer (recording::context
&ctxt
,
205 const char *filename
);
208 write_params (const vec
<recording::context
*> &contexts
);
211 write_args (const vec
<recording::context
*> &contexts
);
214 make_identifier (recording::memento
*m
, const char *prefix
);
217 make_tmp_identifier (const char *prefix
, recording::memento
*m
);
220 get_identifier (recording::context
*ctxt
);
223 get_identifier (recording::memento
*m
);
226 get_identifier_as_rvalue (recording::rvalue
*m
);
229 get_identifier_as_lvalue (recording::lvalue
*m
);
232 get_identifier_as_type (recording::type
*m
);
235 xstrdup_printf (const char *, ...)
236 ATTRIBUTE_RETURNS_NONNULL
240 hash_map
<recording::memento
*, const char *> m_identifiers
;
241 allocator m_allocator
;
244 /* gcc::jit::reproducer's constructor. */
246 reproducer::reproducer (recording::context
&ctxt
,
247 const char *filename
) :
248 dump (ctxt
, filename
, 0),
254 /* Write out a list of contexts as a set of parameters within a
255 C function declaration. */
258 reproducer::write_params (const vec
<recording::context
*> &contexts
)
261 recording::context
*ctxt
;
262 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
264 write ("gcc_jit_context *%s",
265 get_identifier (ctxt
));
266 if (i
< contexts
.length () - 1)
272 /* Write out a list of contexts as a set of arguments within a call
276 reproducer::write_args (const vec
<recording::context
*> &contexts
)
279 recording::context
*ctxt
;
280 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
283 get_identifier (ctxt
));
284 if (i
< contexts
.length () - 1)
290 /* Generate a C identifier for the given memento, associating the generated
291 buffer with the memento (for future calls to get_identifier et al).
293 The reproducer will eventually clean up the buffer in its dtor. */
295 reproducer::make_identifier (recording::memento
*m
, const char *prefix
)
298 if (strlen (m
->get_debug_string ()) < 100)
300 result
= m_allocator
.xstrdup_printf ("%s_%s_%p",
302 m
->get_debug_string (),
304 for (char *p
= result
; *p
; p
++)
309 result
= m_allocator
.xstrdup_printf ("%s_%p",
311 m_identifiers
.put (m
, result
);
315 /* Generate a C identifier for a temporary variable.
316 The reproducer will eventually clean up the buffer in its dtor. */
319 reproducer::make_tmp_identifier (const char *prefix
, recording::memento
*m
)
321 return m_allocator
.xstrdup_printf ("%s_%s",
322 prefix
, get_identifier (m
));
325 /* Generate a C identifier for the given context.
326 The reproducer will eventually clean up the buffer in its dtor. */
329 reproducer::get_identifier (recording::context
*ctxt
)
331 return m_allocator
.xstrdup_printf ("ctxt_%p",
335 /* Locate the C identifier for the given memento, which is assumed to
336 have already been created via make_identifier. */
339 reproducer::get_identifier (recording::memento
*m
)
344 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
345 and hence these locations appear in the context's memento list
346 out-of-order: they appear in the context's memento list *after*
347 the memento that refers to them. For this case, it's simplest to
348 pretend that they're NULL when writing out the code to recreate the
349 memento that uses them. */
350 if (recording::location
*loc
= m
->dyn_cast_location ())
351 if (!loc
->created_by_user ())
354 const char **slot
= m_identifiers
.get (m
);
357 get_context ().add_error (NULL
,
358 "unable to find identifier for %p: %s",
360 m
->get_debug_string ());
366 /* Locate the C identifier for the given rvalue, wrapping it within
367 a gcc_*_as_rvalue upcast if necessary. */
370 reproducer::get_identifier_as_rvalue (recording::rvalue
*m
)
372 return m
->access_as_rvalue (*this);
375 /* Locate the C identifier for the given lvalue, wrapping it within
376 a gcc_*_as_lvalue upcast if necessary. */
379 reproducer::get_identifier_as_lvalue (recording::lvalue
*m
)
381 return m
->access_as_lvalue (*this);
384 /* Locate the C identifier for the given type, wrapping it within
385 a gcc_*_as_type upcast if necessary. */
388 reproducer::get_identifier_as_type (recording::type
*m
)
390 return m
->access_as_type (*this);
393 /* Formatted printing, allocating to a buffer (or exiting the process if
394 the allocation fails).
396 The buffer exists until the allocator is cleaned up, and is freed at
397 that point, so the caller doesn't need to track the result.
399 Note that we can't use ggc_printf since we're not within the compiler
400 proper (when within gcc_jit_context_dump_reproducer_to_file). */
403 reproducer::xstrdup_printf (const char *fmt
, ...)
408 result
= m_allocator
.xstrdup_printf_va (fmt
, ap
);
413 /**********************************************************************
415 **********************************************************************/
417 /* Get the playback::location for the given recording::location,
418 handling a NULL input with a NULL output. */
421 recording::playback_location (replayer
*r
, recording::location
*loc
)
424 return loc
->playback_location (r
);
429 /* Get a const char * for the given recording::string
430 handling a NULL input with a NULL output. */
433 recording::playback_string (recording::string
*str
)
436 return str
->c_str ();
441 /* Get the playback::block for the given recording::block,
442 handling a NULL input with a NULL output. */
445 recording::playback_block (recording::block
*b
)
448 return b
->playback_block ();
453 /* Methods of cc::jit::recording::context. */
455 /* The constructor for gcc::jit::recording::context, used by
456 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
458 recording::context::context (context
*parent_ctxt
)
460 m_parent_ctxt (parent_ctxt
),
461 m_toplevel_ctxt (m_parent_ctxt
? m_parent_ctxt
->m_toplevel_ctxt
: this),
463 m_first_error_str (NULL
),
464 m_owns_first_error_str (false),
465 m_last_error_str (NULL
),
466 m_owns_last_error_str (false),
472 m_builtins_manager(NULL
)
476 /* Inherit options from parent. */
478 i
< sizeof (m_str_options
) / sizeof (m_str_options
[0]);
481 const char *parent_opt
= parent_ctxt
->m_str_options
[i
];
482 m_str_options
[i
] = parent_opt
? xstrdup (parent_opt
) : NULL
;
484 memcpy (m_int_options
,
485 parent_ctxt
->m_int_options
,
486 sizeof (m_int_options
));
487 memcpy (m_bool_options
,
488 parent_ctxt
->m_bool_options
,
489 sizeof (m_bool_options
));
490 set_logger (parent_ctxt
->get_logger ());
494 memset (m_str_options
, 0, sizeof (m_str_options
));
495 memset (m_int_options
, 0, sizeof (m_int_options
));
496 memset (m_bool_options
, 0, sizeof (m_bool_options
));
499 memset (m_basic_types
, 0, sizeof (m_basic_types
));
502 /* The destructor for gcc::jit::recording::context, implicitly used by
503 gcc_jit_context_release. */
505 recording::context::~context ()
507 JIT_LOG_SCOPE (get_logger ());
510 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
515 for (i
= 0; i
< GCC_JIT_NUM_STR_OPTIONS
; ++i
)
516 free (m_str_options
[i
]);
518 if (m_builtins_manager
)
519 delete m_builtins_manager
;
521 if (m_owns_first_error_str
)
522 free (m_first_error_str
);
524 if (m_owns_last_error_str
)
525 if (m_last_error_str
!= m_first_error_str
)
526 free (m_last_error_str
);
529 /* Add the given mememto to the list of those tracked by this
530 gcc::jit::recording::context, so that e.g. it can be deleted
531 when this context is released. */
534 recording::context::record (memento
*m
)
538 m_mementos
.safe_push (m
);
541 /* Replay this context (and any parents) into the given replayer. */
544 recording::context::replay_into (replayer
*r
)
546 JIT_LOG_SCOPE (get_logger ());
550 /* If we have a parent context, we must replay it. This will
551 recursively walk backwards up the historical tree, then replay things
552 forwards "in historical order", starting with the ultimate parent
553 context, until we reach the "this" context.
555 Note that we fully replay the parent, then fully replay the child,
556 which means that inter-context references can only exist from child
557 to parent, not the other way around.
559 All of this replaying is suboptimal - it would be better to do the
560 work for the parent context *once*, rather than replaying the parent
561 every time we replay each child. However, fixing this requires deep
562 surgery to lifetime-management: we'd need every context family tree
563 to have its own GC heap, and to initialize the GCC code to use that
564 heap (with a mutex on such a heap). */
566 m_parent_ctxt
->replay_into (r
);
568 if (r
->errors_occurred ())
571 /* Replay this context's saved operations into r. */
572 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
574 /* Disabled low-level debugging, here if we need it: print what
576 Note that the calls to get_debug_string might lead to more
577 mementos being created for the strings.
578 This can also be used to exercise the debug_string
581 printf ("context %p replaying (%p): %s\n",
582 (void *)this, (void *)m
, m
->get_debug_string ());
586 if (r
->errors_occurred ())
591 /* During a playback, we associate objects from the recording with
592 their counterparts during this playback.
594 For simplicity, we store this within the recording objects.
596 The following method cleans away these associations, to ensure that
597 we never have out-of-date associations lingering on subsequent
598 playbacks (the objects pointed to are GC-managed, but the
599 recording objects don't own refs to them). */
602 recording::context::disassociate_from_playback ()
604 JIT_LOG_SCOPE (get_logger ());
609 m_parent_ctxt
->disassociate_from_playback ();
611 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
613 m
->set_playback_obj (NULL
);
617 /* Create a recording::string instance and add it to this context's list
620 This creates a fresh copy of the given 0-terminated buffer. */
623 recording::context::new_string (const char *text
)
628 recording::string
*result
= new string (this, text
);
633 /* Create a recording::location instance and add it to this context's
636 Implements the post-error-checking part of
637 gcc_jit_context_new_location. */
639 recording::location
*
640 recording::context::new_location (const char *filename
,
643 bool created_by_user
)
645 recording::location
*result
=
646 new recording::location (this,
647 new_string (filename
),
654 /* If we haven't seen this enum value yet, create a recording::type
655 instance and add it to this context's list of mementos.
657 If we have seen it before, reuse our cached value, so that repeated
658 calls on the context give the same object.
660 If we have a parent context, the cache is within the ultimate
663 Implements the post-error-checking part of
664 gcc_jit_context_get_type. */
667 recording::context::get_type (enum gcc_jit_types kind
)
669 if (!m_basic_types
[kind
])
672 m_basic_types
[kind
] = m_parent_ctxt
->get_type (kind
);
675 recording::type
*result
= new memento_of_get_type (this, kind
);
677 m_basic_types
[kind
] = result
;
681 return m_basic_types
[kind
];
684 /* Get a recording::type instance for the given size and signedness.
685 This is implemented in terms of recording::context::get_type
688 Implements the post-error-checking part of
689 gcc_jit_context_get_int_type. */
692 recording::context::get_int_type (int num_bytes
, int is_signed
)
694 /* We can't use a switch here since some of the values are macros affected
695 by options; e.g. i386.h has
696 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
697 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
698 are in bits, rather than bytes.
700 const int num_bits
= num_bytes
* 8;
701 if (num_bits
== INT_TYPE_SIZE
)
702 return get_type (is_signed
704 : GCC_JIT_TYPE_UNSIGNED_INT
);
705 if (num_bits
== CHAR_TYPE_SIZE
)
706 return get_type (is_signed
707 ? GCC_JIT_TYPE_SIGNED_CHAR
708 : GCC_JIT_TYPE_UNSIGNED_CHAR
);
709 if (num_bits
== SHORT_TYPE_SIZE
)
710 return get_type (is_signed
712 : GCC_JIT_TYPE_UNSIGNED_SHORT
);
713 if (num_bits
== LONG_TYPE_SIZE
)
714 return get_type (is_signed
716 : GCC_JIT_TYPE_UNSIGNED_LONG
);
717 if (num_bits
== LONG_LONG_TYPE_SIZE
)
718 return get_type (is_signed
719 ? GCC_JIT_TYPE_LONG_LONG
720 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
722 /* Some other size, not corresponding to the C int types. */
723 /* To be written: support arbitrary other sizes, sharing by
724 memoizing at the recording::context level? */
728 /* Create a recording::type instance and add it to this context's list
731 Implements the post-error-checking part of
732 gcc_jit_context_new_array_type. */
735 recording::context::new_array_type (recording::location
*loc
,
736 recording::type
*element_type
,
739 if (struct_
*s
= element_type
->dyn_cast_struct ())
740 if (!s
->get_fields ())
743 "cannot create an array of type %s"
744 " until the fields have been set",
745 s
->get_name ()->c_str ());
748 recording::type
*result
=
749 new recording::array_type (this, loc
, element_type
, num_elements
);
754 /* Create a recording::field instance and add it to this context's list
757 Implements the post-error-checking part of
758 gcc_jit_context_new_field. */
761 recording::context::new_field (recording::location
*loc
,
762 recording::type
*type
,
765 recording::field
*result
=
766 new recording::field (this, loc
, type
, new_string (name
));
771 /* Create a recording::struct_ instance and add it to this context's
772 list of mementos and list of compound types.
774 Implements the post-error-checking part of
775 gcc_jit_context_new_struct_type. */
778 recording::context::new_struct_type (recording::location
*loc
,
781 recording::struct_
*result
= new struct_ (this, loc
, new_string (name
));
783 m_compound_types
.safe_push (result
);
787 /* Create a recording::union_ instance and add it to this context's
788 list of mementos and list of compound types.
790 Implements the first post-error-checking part of
791 gcc_jit_context_new_union_type. */
794 recording::context::new_union_type (recording::location
*loc
,
797 recording::union_
*result
= new union_ (this, loc
, new_string (name
));
799 m_compound_types
.safe_push (result
);
803 /* Create a recording::function_type instance and add it to this context's
806 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
808 recording::function_type
*
809 recording::context::new_function_type (recording::type
*return_type
,
811 recording::type
**param_types
,
814 recording::function_type
*fn_type
815 = new function_type (this,
824 /* Create a recording::type instance and add it to this context's list
827 Implements the post-error-checking part of
828 gcc_jit_context_new_function_ptr_type. */
831 recording::context::new_function_ptr_type (recording::location
*, /* unused loc */
832 recording::type
*return_type
,
834 recording::type
**param_types
,
837 recording::function_type
*fn_type
838 = new_function_type (return_type
,
843 /* Return a pointer-type to the the function type. */
844 return fn_type
->get_pointer ();
847 /* Create a recording::param instance and add it to this context's list
850 Implements the post-error-checking part of
851 gcc_jit_context_new_param. */
854 recording::context::new_param (recording::location
*loc
,
855 recording::type
*type
,
858 recording::param
*result
= new recording::param (this, loc
, type
, new_string (name
));
863 /* Create a recording::function instance and add it to this context's list
864 of mementos and list of functions.
866 Implements the post-error-checking part of
867 gcc_jit_context_new_function. */
869 recording::function
*
870 recording::context::new_function (recording::location
*loc
,
871 enum gcc_jit_function_kind kind
,
872 recording::type
*return_type
,
875 recording::param
**params
,
877 enum built_in_function builtin_id
)
879 recording::function
*result
=
880 new recording::function (this,
881 loc
, kind
, return_type
,
883 num_params
, params
, is_variadic
,
886 m_functions
.safe_push (result
);
891 /* Locate the builtins_manager (if any) for this family of contexts,
892 creating it if it doesn't exist already.
894 All of the recording contexts in a family share one builtins_manager:
895 if we have a child context, follow the parent links to get the
896 ultimate ancestor context, and look for it/store it there. */
899 recording::context::get_builtins_manager ()
902 return m_parent_ctxt
->get_builtins_manager ();
904 if (!m_builtins_manager
)
905 m_builtins_manager
= new builtins_manager (this);
907 return m_builtins_manager
;
910 /* Get a recording::function instance, which is lazily-created and added
911 to the context's lists of mementos.
913 Implements the post-error-checking part of
914 gcc_jit_context_get_builtin_function. */
916 recording::function
*
917 recording::context::get_builtin_function (const char *name
)
919 builtins_manager
*bm
= get_builtins_manager ();
920 return bm
->get_builtin_function (name
);
923 /* Create a recording::global instance and add it to this context's list
926 Implements the post-error-checking part of
927 gcc_jit_context_new_global. */
930 recording::context::new_global (recording::location
*loc
,
931 enum gcc_jit_global_kind kind
,
932 recording::type
*type
,
935 recording::global
*result
=
936 new recording::global (this, loc
, kind
, type
, new_string (name
));
938 m_globals
.safe_push (result
);
943 /* Create a recording::memento_of_new_string_literal instance and add it
944 to this context's list of mementos.
946 Implements the post-error-checking part of
947 gcc_jit_context_new_string_literal. */
950 recording::context::new_string_literal (const char *value
)
952 recording::rvalue
*result
=
953 new memento_of_new_string_literal (this, NULL
, new_string (value
));
958 /* Create a recording::unary_op instance and add it to this context's
961 Implements the post-error-checking part of
962 gcc_jit_context_new_unary_op. */
965 recording::context::new_unary_op (recording::location
*loc
,
966 enum gcc_jit_unary_op op
,
967 recording::type
*result_type
,
968 recording::rvalue
*a
)
970 recording::rvalue
*result
=
971 new unary_op (this, loc
, op
, result_type
, a
);
976 /* Create a recording::binary_op instance and add it to this context's
979 Implements the post-error-checking part of
980 gcc_jit_context_new_binary_op. */
983 recording::context::new_binary_op (recording::location
*loc
,
984 enum gcc_jit_binary_op op
,
985 recording::type
*result_type
,
986 recording::rvalue
*a
,
987 recording::rvalue
*b
)
989 recording::rvalue
*result
=
990 new binary_op (this, loc
, op
, result_type
, a
, b
);
995 /* Create a recording::comparison instance and add it to this context's
998 Implements the post-error-checking part of
999 gcc_jit_context_new_comparison. */
1002 recording::context::new_comparison (recording::location
*loc
,
1003 enum gcc_jit_comparison op
,
1004 recording::rvalue
*a
,
1005 recording::rvalue
*b
)
1007 recording::rvalue
*result
= new comparison (this, loc
, op
, a
, b
);
1012 /* Create a recording::cast instance and add it to this context's list
1015 Implements the post-error-checking part of
1016 gcc_jit_context_new_cast. */
1019 recording::context::new_cast (recording::location
*loc
,
1020 recording::rvalue
*expr
,
1021 recording::type
*type_
)
1023 recording::rvalue
*result
= new cast (this, loc
, expr
, type_
);
1028 /* Create a recording::call instance and add it to this context's list
1031 Implements the post-error-checking part of
1032 gcc_jit_context_new_call. */
1035 recording::context::new_call (recording::location
*loc
,
1037 int numargs
, recording::rvalue
**args
)
1039 recording::rvalue
*result
= new call (this, loc
, func
, numargs
, args
);
1044 /* Create a recording::call_through_ptr instance and add it to this
1045 context's list of mementos.
1047 Implements the post-error-checking part of
1048 gcc_jit_context_new_call_through_ptr. */
1051 recording::context::new_call_through_ptr (recording::location
*loc
,
1052 recording::rvalue
*fn_ptr
,
1054 recording::rvalue
**args
)
1056 recording::rvalue
*result
= new call_through_ptr (this, loc
, fn_ptr
, numargs
, args
);
1061 /* Create a recording::array_access instance and add it to this context's list
1064 Implements the post-error-checking part of
1065 gcc_jit_context_new_array_access. */
1068 recording::context::new_array_access (recording::location
*loc
,
1069 recording::rvalue
*ptr
,
1070 recording::rvalue
*index
)
1072 recording::lvalue
*result
= new array_access (this, loc
, ptr
, index
);
1077 /* Set the given string option for this context, or add an error if
1078 it's not recognized.
1080 Implements the post-error-checking part of
1081 gcc_jit_context_set_str_option. */
1084 recording::context::set_str_option (enum gcc_jit_str_option opt
,
1087 if (opt
< 0 || opt
>= GCC_JIT_NUM_STR_OPTIONS
)
1090 "unrecognized (enum gcc_jit_str_option) value: %i", opt
);
1093 free (m_str_options
[opt
]);
1094 m_str_options
[opt
] = value
? xstrdup (value
) : NULL
;
1097 /* Set the given integer option for this context, or add an error if
1098 it's not recognized.
1100 Implements the post-error-checking part of
1101 gcc_jit_context_set_int_option. */
1104 recording::context::set_int_option (enum gcc_jit_int_option opt
,
1107 if (opt
< 0 || opt
>= GCC_JIT_NUM_INT_OPTIONS
)
1110 "unrecognized (enum gcc_jit_int_option) value: %i", opt
);
1113 m_int_options
[opt
] = value
;
1116 /* Set the given boolean option for this context, or add an error if
1117 it's not recognized.
1119 Implements the post-error-checking part of
1120 gcc_jit_context_set_bool_option. */
1123 recording::context::set_bool_option (enum gcc_jit_bool_option opt
,
1126 if (opt
< 0 || opt
>= GCC_JIT_NUM_BOOL_OPTIONS
)
1129 "unrecognized (enum gcc_jit_bool_option) value: %i", opt
);
1132 m_bool_options
[opt
] = value
? true : false;
1135 /* Add the given dumpname/out_ptr pair to this context's list of requested
1138 Implements the post-error-checking part of
1139 gcc_jit_context_enable_dump. */
1142 recording::context::enable_dump (const char *dumpname
,
1146 gcc_assert (dumpname
);
1147 gcc_assert (out_ptr
);
1149 d
.m_dumpname
= dumpname
;
1150 d
.m_out_ptr
= out_ptr
;
1152 m_requested_dumps
.safe_push (d
);
1155 /* Validate this context, and if it passes, compile it within a
1158 Implements the post-error-checking part of
1159 gcc_jit_context_compile. */
1162 recording::context::compile ()
1164 JIT_LOG_SCOPE (get_logger ());
1168 if (errors_occurred ())
1171 /* Set up a playback context. */
1172 ::gcc::jit::playback::context
replayer (this);
1175 result
*result_obj
= replayer
.compile ();
1180 /* Format the given error using printf's conventions, print
1181 it to stderr, and add it to the context. */
1184 recording::context::add_error (location
*loc
, const char *fmt
, ...)
1188 add_error_va (loc
, fmt
, ap
);
1192 /* Format the given error using printf's conventions, print
1193 it to stderr, and add it to the context. */
1196 recording::context::add_error_va (location
*loc
, const char *fmt
, va_list ap
)
1202 JIT_LOG_SCOPE (get_logger ());
1204 vasprintf (&malloced_msg
, fmt
, ap
);
1207 errmsg
= malloced_msg
;
1208 has_ownership
= true;
1212 errmsg
= "out of memory generating error message";
1213 has_ownership
= false;
1216 get_logger ()->log ("error %i: %s", m_error_count
, errmsg
);
1218 const char *ctxt_progname
=
1219 get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
1221 ctxt_progname
= "libgccjit.so";
1224 fprintf (stderr
, "%s: %s: error: %s\n",
1226 loc
->get_debug_string (),
1229 fprintf (stderr
, "%s: error: %s\n",
1235 m_first_error_str
= const_cast <char *> (errmsg
);
1236 m_owns_first_error_str
= has_ownership
;
1239 if (m_owns_last_error_str
)
1240 if (m_last_error_str
!= m_first_error_str
)
1241 free (m_last_error_str
);
1242 m_last_error_str
= const_cast <char *> (errmsg
);
1243 m_owns_last_error_str
= has_ownership
;
1248 /* Get the message for the first error that occurred on this context, or
1249 NULL if no errors have occurred on it.
1251 Implements the post-error-checking part of
1252 gcc_jit_context_get_first_error. */
1255 recording::context::get_first_error () const
1257 return m_first_error_str
;
1260 /* Get the message for the last error that occurred on this context, or
1261 NULL if no errors have occurred on it.
1263 Implements the post-error-checking part of
1264 gcc_jit_context_get_last_error. */
1267 recording::context::get_last_error () const
1269 return m_last_error_str
;
1272 /* Lazily generate and record a recording::type representing an opaque
1273 struct named "FILE".
1275 For use if client code tries to dereference the result of
1276 get_type (GCC_JIT_TYPE_FILE_PTR). */
1279 recording::context::get_opaque_FILE_type ()
1282 m_FILE_type
= new_struct_type (NULL
, "FILE");
1286 /* Dump a C-like representation of the given context to the given path.
1287 If UPDATE_LOCATIONS is true, update the locations within the
1288 context's mementos to point to the dumpfile.
1290 Implements the post-error-checking part of
1291 gcc_jit_context_dump_to_file. */
1294 recording::context::dump_to_file (const char *path
, bool update_locations
)
1297 dump
d (*this, path
, update_locations
);
1299 /* Forward declaration of structs and unions. */
1301 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1303 d
.write ("%s;\n\n", st
->get_debug_string ());
1306 /* Content of structs, where set. */
1307 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1308 if (st
->get_fields ())
1310 st
->get_fields ()->write_to_dump (d
);
1316 FOR_EACH_VEC_ELT (m_globals
, i
, g
)
1318 g
->write_to_dump (d
);
1320 if (!m_globals
.is_empty ())
1324 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1326 fn
->write_to_dump (d
);
1330 static const char * const
1331 str_option_reproducer_strings
[GCC_JIT_NUM_STR_OPTIONS
] = {
1332 "GCC_JIT_STR_OPTION_PROGNAME"
1335 static const char * const
1336 int_option_reproducer_strings
[GCC_JIT_NUM_INT_OPTIONS
] = {
1337 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1340 static const char * const
1341 bool_option_reproducer_strings
[GCC_JIT_NUM_BOOL_OPTIONS
] = {
1342 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1343 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1344 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1345 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1346 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1347 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1348 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1349 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1352 /* Write C source code to PATH that attempts to replay the API
1353 calls made to this context (and its parents), for use in
1354 minimizing test cases for libgccjit.
1356 Implements the post-error-checking part of
1357 gcc_jit_context_dump_reproducer_to_file. */
1360 recording::context::dump_reproducer_to_file (const char *path
)
1362 JIT_LOG_SCOPE (get_logger ());
1363 reproducer
r (*this, path
);
1365 /* Generate the "ancestry" of this context, as a list. */
1366 auto_vec
<context
*> ascending_contexts
;
1367 for (context
*ctxt
= this; ctxt
; ctxt
= ctxt
->m_parent_ctxt
)
1368 ascending_contexts
.safe_push (ctxt
);
1370 /* Reverse the list, giving a list of contexts from
1371 top-most parent context down through to youngest child context.
1372 We will use this list as the parameters of the functions in
1373 our generated file. */
1374 unsigned num_ctxts
= ascending_contexts
.length ();
1375 auto_vec
<context
*> contexts (num_ctxts
);
1376 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1377 contexts
.safe_push (ascending_contexts
[num_ctxts
- (i
+ 1)]);
1379 /* contexts[0] should be the top-level context. */
1380 gcc_assert (contexts
[0]);
1381 gcc_assert (contexts
[0]->m_toplevel_ctxt
== contexts
[0]);
1383 /* The final element in contexts should be "this". */
1384 gcc_assert (contexts
[contexts
.length () - 1] == this);
1385 gcc_assert (contexts
[contexts
.length () - 1]->m_toplevel_ctxt
1388 r
.write ("/* This code was autogenerated by"
1389 " gcc_jit_context_dump_reproducer_to_file. */\n\n");
1390 r
.write ("#include <libgccjit.h>\n\n");
1391 r
.write ("static void\nset_options (");
1392 r
.write_params (contexts
);
1394 r
.write ("static void\ncreate_code (");
1395 r
.write_params (contexts
);
1397 r
.write ("int\nmain (int argc, const char **argv)\n");
1399 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1400 r
.write (" gcc_jit_context *%s;\n",
1401 r
.get_identifier (contexts
[i
]));
1402 r
.write (" gcc_jit_result *result;\n"
1405 /* Create the contexts.
1406 The top-level context is acquired from a clean slate, the others as
1407 children of the prior context. */
1408 r
.write (" %s = gcc_jit_context_acquire ();\n",
1409 r
.get_identifier (contexts
[0]));
1410 for (unsigned i
= 1; i
< num_ctxts
; i
++)
1411 r
.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1412 r
.get_identifier (contexts
[i
]),
1413 r
.get_identifier (contexts
[i
- 1]));
1414 r
.write (" set_options (");
1415 r
.write_args (contexts
);
1417 r
.write (" create_code (");
1418 r
.write_args (contexts
);
1421 r
.write (" result = gcc_jit_context_compile (%s);\n",
1422 r
.get_identifier (this));
1424 for (unsigned i
= num_ctxts
; i
> 0; i
--)
1425 r
.write (" gcc_jit_context_release (%s);\n",
1426 r
.get_identifier (contexts
[i
- 1]));
1428 r
.write (" gcc_jit_result_release (result);\n"
1432 /* Define (char *) variables for use in calls to
1433 gcc_jit_context_enable_dump. */
1434 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1436 if (m_requested_dumps
.length ())
1438 r
.write ("/* Requested dumps for %s. */\n",
1439 r
.get_identifier (contexts
[ctxt_idx
]));
1440 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1441 r
.write ("static char *dump_%p;\n",
1442 (void *)&m_requested_dumps
[i
]);
1447 /* Write out values of options. */
1448 r
.write ("static void\nset_options (");
1449 r
.write_params (contexts
);
1451 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1456 r
.write (" /* Set options for %s. */\n",
1457 r
.get_identifier (contexts
[ctxt_idx
]));
1459 r
.write (" /* String options. */\n");
1460 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1461 r
.write (" gcc_jit_context_set_str_option (%s,\n"
1464 r
.get_identifier (contexts
[ctxt_idx
]),
1465 str_option_reproducer_strings
[opt_idx
],
1466 m_str_options
[opt_idx
] ? m_str_options
[opt_idx
] : "NULL");
1467 r
.write (" /* Int options. */\n");
1468 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1469 r
.write (" gcc_jit_context_set_int_option (%s,\n"
1472 r
.get_identifier (contexts
[ctxt_idx
]),
1473 int_option_reproducer_strings
[opt_idx
],
1474 m_int_options
[opt_idx
]);
1475 r
.write (" /* Boolean options. */\n");
1476 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1477 r
.write (" gcc_jit_context_set_bool_option (%s,\n"
1480 r
.get_identifier (contexts
[ctxt_idx
]),
1481 bool_option_reproducer_strings
[opt_idx
],
1482 m_bool_options
[opt_idx
]);
1484 if (m_requested_dumps
.length ())
1486 r
.write (" /* Requested dumps. */\n");
1487 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1488 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1490 r
.write (" gcc_jit_context_enable_dump (%s,\n"
1493 r
.get_identifier (contexts
[ctxt_idx
]),
1494 m_requested_dumps
[i
].m_dumpname
,
1495 (void *)&m_requested_dumps
[i
]);
1501 r
.write ("static void\ncreate_code (");
1502 r
.write_params (contexts
);
1505 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1512 r
.write (" /* Replay of API calls for %s. */\n",
1513 r
.get_identifier (contexts
[ctxt_idx
]));
1514 FOR_EACH_VEC_ELT (contexts
[ctxt_idx
]->m_mementos
, i
, m
)
1515 m
->write_reproducer (r
);
1520 /* Copy the requested dumps within this context and all ancestors into
1524 recording::context::get_all_requested_dumps (vec
<recording::requested_dump
> *out
)
1527 m_parent_ctxt
->get_all_requested_dumps (out
);
1529 out
->reserve (m_requested_dumps
.length ());
1530 out
->splice (m_requested_dumps
);
1533 /* This is a pre-compilation check for the context (and any parents).
1535 Detect errors within the context, adding errors if any are found. */
1538 recording::context::validate ()
1540 JIT_LOG_SCOPE (get_logger ());
1543 m_parent_ctxt
->validate ();
1547 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1551 /* The implementation of class gcc::jit::recording::memento. */
1553 /* Get a (const char *) debug description of the given memento, by
1554 calling the pure-virtual make_debug_string hook, caching the
1557 It is intended that this should only be called in debugging and
1558 error-handling paths, so this doesn't need to be particularly
1562 recording::memento::get_debug_string ()
1564 if (!m_debug_string
)
1565 m_debug_string
= make_debug_string ();
1566 return m_debug_string
->c_str ();
1569 /* Default implementation of recording::memento::write_to_dump, writing
1570 an indented form of the memento's debug string to the dump. */
1573 recording::memento::write_to_dump (dump
&d
)
1575 d
.write(" %s\n", get_debug_string ());
1578 /* The implementation of class gcc::jit::recording::string. */
1580 /* Constructor for gcc::jit::recording::string::string, allocating a
1581 copy of the given text using new char[]. */
1583 recording::string::string (context
*ctxt
, const char *text
)
1586 m_len
= strlen (text
);
1587 m_buffer
= new char[m_len
+ 1];
1588 strcpy (m_buffer
, text
);
1591 /* Destructor for gcc::jit::recording::string::string. */
1593 recording::string::~string ()
1598 /* Function for making gcc::jit::recording::string instances on a
1599 context via printf-style formatting.
1601 It is intended that this should only be called in debugging and
1602 error-handling paths, so this doesn't need to be particularly
1603 optimized, hence the double-copy of the string is acceptable. */
1606 recording::string::from_printf (context
*ctxt
, const char *fmt
, ...)
1610 recording::string
*result
;
1613 vasprintf (&buf
, fmt
, ap
);
1618 ctxt
->add_error (NULL
, "malloc failure");
1622 result
= ctxt
->new_string (buf
);
1627 /* Implementation of recording::memento::make_debug_string for strings,
1628 wrapping the given string in quotes and escaping as necessary. */
1631 recording::string::make_debug_string ()
1633 /* Hack to avoid infinite recursion into strings when logging all
1634 mementos: don't re-escape strings: */
1635 if (m_buffer
[0] == '"')
1638 /* Wrap in quotes and do escaping etc */
1640 size_t sz
= (1 /* opening quote */
1641 + (m_len
* 2) /* each char might get escaped */
1642 + 1 /* closing quote */
1643 + 1); /* nil termintator */
1644 char *tmp
= new char[sz
];
1647 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1648 APPEND('"'); /* opening quote */
1649 for (size_t i
= 0; i
< m_len
; i
++)
1651 char ch
= m_buffer
[i
];
1652 if (ch
== '\t' || ch
== '\n' || ch
== '\\' || ch
== '"')
1656 APPEND('"'); /* closing quote */
1658 tmp
[len
] = '\0'; /* nil termintator */
1660 string
*result
= m_ctxt
->new_string (tmp
);
1666 /* Implementation of recording::memento::write_reproducer for strings. */
1669 recording::string::write_reproducer (reproducer
&)
1674 /* The implementation of class gcc::jit::recording::location. */
1676 /* Implementation of recording::memento::replay_into for locations.
1678 Create a new playback::location and store it into the
1679 recording::location's m_playback_obj field. */
1682 recording::location::replay_into (replayer
*r
)
1684 m_playback_obj
= r
->new_location (this,
1685 m_filename
->c_str (),
1690 /* Implementation of recording::memento::make_debug_string for locations,
1691 turning them into the usual form:
1692 FILENAME:LINE:COLUMN
1693 like we do when emitting diagnostics. */
1696 recording::location::make_debug_string ()
1698 return string::from_printf (m_ctxt
,
1700 m_filename
->c_str (), m_line
, m_column
);
1703 /* Implementation of recording::memento::write_reproducer for locations. */
1706 recording::location::write_reproducer (reproducer
&r
)
1708 const char *id
= r
.make_identifier (this, "loc");
1709 r
.write (" gcc_jit_location *%s =\n"
1710 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1711 " %s, /* const char *filename */\n"
1712 " %i, /* int line */\n"
1713 " %i);/* int column */\n",
1715 r
.get_identifier (get_context ()),
1716 m_filename
->get_debug_string (),
1720 /* The implementation of class gcc::jit::recording::type. */
1722 /* Given a type T, get the type T*.
1724 If this doesn't already exist, generate a new memento_of_get_pointer
1725 instance and add it to this type's context's list of mementos.
1727 Otherwise, use the cached type.
1729 Implements the post-error-checking part of
1730 gcc_jit_type_get_pointer. */
1733 recording::type::get_pointer ()
1735 if (!m_pointer_to_this_type
)
1737 m_pointer_to_this_type
= new memento_of_get_pointer (this);
1738 m_ctxt
->record (m_pointer_to_this_type
);
1740 return m_pointer_to_this_type
;
1743 /* Given a type T, get the type const T.
1745 Implements the post-error-checking part of
1746 gcc_jit_type_get_const. */
1749 recording::type::get_const ()
1751 recording::type
*result
= new memento_of_get_const (this);
1752 m_ctxt
->record (result
);
1756 /* Given a type T, get the type volatile T.
1758 Implements the post-error-checking part of
1759 gcc_jit_type_get_volatile. */
1762 recording::type::get_volatile ()
1764 recording::type
*result
= new memento_of_get_volatile (this);
1765 m_ctxt
->record (result
);
1770 recording::type::access_as_type (reproducer
&r
)
1772 return r
.get_identifier (this);
1775 /* Implementation of pure virtual hook recording::type::dereference for
1776 recording::memento_of_get_type. */
1779 recording::memento_of_get_type::dereference ()
1783 default: gcc_unreachable ();
1785 case GCC_JIT_TYPE_VOID
:
1788 case GCC_JIT_TYPE_VOID_PTR
:
1789 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
1791 case GCC_JIT_TYPE_BOOL
:
1792 case GCC_JIT_TYPE_CHAR
:
1793 case GCC_JIT_TYPE_SIGNED_CHAR
:
1794 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1795 case GCC_JIT_TYPE_SHORT
:
1796 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1797 case GCC_JIT_TYPE_INT
:
1798 case GCC_JIT_TYPE_UNSIGNED_INT
:
1799 case GCC_JIT_TYPE_LONG
:
1800 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1801 case GCC_JIT_TYPE_LONG_LONG
:
1802 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1803 case GCC_JIT_TYPE_FLOAT
:
1804 case GCC_JIT_TYPE_DOUBLE
:
1805 case GCC_JIT_TYPE_LONG_DOUBLE
:
1806 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1807 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1808 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1809 /* Not a pointer: */
1812 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1813 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
1815 case GCC_JIT_TYPE_SIZE_T
:
1816 /* Not a pointer: */
1819 case GCC_JIT_TYPE_FILE_PTR
:
1820 /* Give the client code back an opaque "struct FILE". */
1821 return m_ctxt
->get_opaque_FILE_type ();
1825 /* Implementation of pure virtual hook recording::type::is_int for
1826 recording::memento_of_get_type. */
1829 recording::memento_of_get_type::is_int () const
1833 default: gcc_unreachable ();
1835 case GCC_JIT_TYPE_VOID
:
1838 case GCC_JIT_TYPE_VOID_PTR
:
1841 case GCC_JIT_TYPE_BOOL
:
1844 case GCC_JIT_TYPE_CHAR
:
1845 case GCC_JIT_TYPE_SIGNED_CHAR
:
1846 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1847 case GCC_JIT_TYPE_SHORT
:
1848 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1849 case GCC_JIT_TYPE_INT
:
1850 case GCC_JIT_TYPE_UNSIGNED_INT
:
1851 case GCC_JIT_TYPE_LONG
:
1852 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1853 case GCC_JIT_TYPE_LONG_LONG
:
1854 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1857 case GCC_JIT_TYPE_FLOAT
:
1858 case GCC_JIT_TYPE_DOUBLE
:
1859 case GCC_JIT_TYPE_LONG_DOUBLE
:
1862 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1865 case GCC_JIT_TYPE_SIZE_T
:
1868 case GCC_JIT_TYPE_FILE_PTR
:
1871 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1872 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1873 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1878 /* Implementation of pure virtual hook recording::type::is_float for
1879 recording::memento_of_get_type. */
1882 recording::memento_of_get_type::is_float () const
1886 default: gcc_unreachable ();
1888 case GCC_JIT_TYPE_VOID
:
1891 case GCC_JIT_TYPE_VOID_PTR
:
1894 case GCC_JIT_TYPE_BOOL
:
1897 case GCC_JIT_TYPE_CHAR
:
1898 case GCC_JIT_TYPE_SIGNED_CHAR
:
1899 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1900 case GCC_JIT_TYPE_SHORT
:
1901 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1902 case GCC_JIT_TYPE_INT
:
1903 case GCC_JIT_TYPE_UNSIGNED_INT
:
1904 case GCC_JIT_TYPE_LONG
:
1905 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1906 case GCC_JIT_TYPE_LONG_LONG
:
1907 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1910 case GCC_JIT_TYPE_FLOAT
:
1911 case GCC_JIT_TYPE_DOUBLE
:
1912 case GCC_JIT_TYPE_LONG_DOUBLE
:
1915 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1918 case GCC_JIT_TYPE_SIZE_T
:
1921 case GCC_JIT_TYPE_FILE_PTR
:
1924 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1925 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1926 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1931 /* Implementation of pure virtual hook recording::type::is_bool for
1932 recording::memento_of_get_type. */
1935 recording::memento_of_get_type::is_bool () const
1939 default: gcc_unreachable ();
1941 case GCC_JIT_TYPE_VOID
:
1944 case GCC_JIT_TYPE_VOID_PTR
:
1947 case GCC_JIT_TYPE_BOOL
:
1950 case GCC_JIT_TYPE_CHAR
:
1951 case GCC_JIT_TYPE_SIGNED_CHAR
:
1952 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1953 case GCC_JIT_TYPE_SHORT
:
1954 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1955 case GCC_JIT_TYPE_INT
:
1956 case GCC_JIT_TYPE_UNSIGNED_INT
:
1957 case GCC_JIT_TYPE_LONG
:
1958 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1959 case GCC_JIT_TYPE_LONG_LONG
:
1960 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1963 case GCC_JIT_TYPE_FLOAT
:
1964 case GCC_JIT_TYPE_DOUBLE
:
1965 case GCC_JIT_TYPE_LONG_DOUBLE
:
1968 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1971 case GCC_JIT_TYPE_SIZE_T
:
1974 case GCC_JIT_TYPE_FILE_PTR
:
1977 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1978 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1979 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1984 /* Implementation of pure virtual hook recording::memento::replay_into
1985 for recording::memento_of_get_type. */
1988 recording::memento_of_get_type::replay_into (replayer
*r
)
1990 set_playback_obj (r
->get_type (m_kind
));
1993 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
1995 /* Descriptive strings for each of enum gcc_jit_types. */
1997 static const char * const get_type_strings
[] = {
1998 "void", /* GCC_JIT_TYPE_VOID */
1999 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2001 "bool", /* GCC_JIT_TYPE_BOOL */
2003 "char", /* GCC_JIT_TYPE_CHAR */
2004 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2005 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2007 "short", /* GCC_JIT_TYPE_SHORT */
2008 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2010 "int", /* GCC_JIT_TYPE_INT */
2011 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2013 "long", /* GCC_JIT_TYPE_LONG */
2014 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2016 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2017 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2019 "float", /* GCC_JIT_TYPE_FLOAT */
2020 "double", /* GCC_JIT_TYPE_DOUBLE */
2021 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2023 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2025 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2027 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2029 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2030 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2031 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2035 /* Implementation of recording::memento::make_debug_string for
2036 results of get_type, using a simple table of type names. */
2039 recording::memento_of_get_type::make_debug_string ()
2041 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
2044 static const char * const get_type_enum_strings
[] = {
2045 "GCC_JIT_TYPE_VOID",
2046 "GCC_JIT_TYPE_VOID_PTR",
2047 "GCC_JIT_TYPE_BOOL",
2048 "GCC_JIT_TYPE_CHAR",
2049 "GCC_JIT_TYPE_SIGNED_CHAR",
2050 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2051 "GCC_JIT_TYPE_SHORT",
2052 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2054 "GCC_JIT_TYPE_UNSIGNED_INT",
2055 "GCC_JIT_TYPE_LONG",
2056 "GCC_JIT_TYPE_UNSIGNED_LONG",
2057 "GCC_JIT_TYPE_LONG_LONG",
2058 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2059 "GCC_JIT_TYPE_FLOAT",
2060 "GCC_JIT_TYPE_DOUBLE",
2061 "GCC_JIT_TYPE_LONG_DOUBLE",
2062 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2063 "GCC_JIT_TYPE_SIZE_T",
2064 "GCC_JIT_TYPE_FILE_PTR",
2065 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2066 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2067 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2071 recording::memento_of_get_type::write_reproducer (reproducer
&r
)
2073 const char *id
= r
.make_identifier (this, "type");
2074 r
.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2076 r
.get_identifier (get_context ()),
2077 get_type_enum_strings
[m_kind
]);
2080 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2082 /* Override of default implementation of
2083 recording::type::accepts_writes_from for get_pointer.
2085 Require a pointer type, and allowing writes to
2086 (const T *) from a (T*), but not the other way around. */
2089 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
2091 /* Must be a pointer type: */
2092 type
*rtype_points_to
= rtype
->is_pointer ();
2093 if (!rtype_points_to
)
2096 /* It's OK to assign to a (const T *) from a (T *). */
2097 return m_other_type
->unqualified ()
2098 ->accepts_writes_from (rtype_points_to
);
2101 /* Implementation of pure virtual hook recording::memento::replay_into
2102 for recording::memento_of_get_pointer. */
2105 recording::memento_of_get_pointer::replay_into (replayer
*)
2107 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
2110 /* Implementation of recording::memento::make_debug_string for
2111 results of get_pointer, adding " *" to the underlying type,
2112 with special-casing to handle function pointer types. */
2115 recording::memento_of_get_pointer::make_debug_string ()
2117 /* Special-case function pointer types, to put the "*" in parens between
2118 the return type and the params (for one level of dereferencing, at
2120 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2121 return fn_type
->make_debug_string_with_ptr ();
2123 return string::from_printf (m_ctxt
,
2124 "%s *", m_other_type
->get_debug_string ());
2127 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2130 recording::memento_of_get_pointer::write_reproducer (reproducer
&r
)
2132 /* We need to special-case function pointer types; see the notes in
2133 recording::function_type::write_deferred_reproducer. */
2134 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2136 fn_type
->write_deferred_reproducer (r
, this);
2140 const char *id
= r
.make_identifier (this, "type");
2141 r
.write (" gcc_jit_type *%s =\n"
2142 " gcc_jit_type_get_pointer (%s);\n",
2144 r
.get_identifier_as_type (m_other_type
));
2147 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2149 /* Implementation of pure virtual hook recording::memento::replay_into
2150 for recording::memento_of_get_const. */
2153 recording::memento_of_get_const::replay_into (replayer
*)
2155 set_playback_obj (m_other_type
->playback_type ()->get_const ());
2158 /* Implementation of recording::memento::make_debug_string for
2159 results of get_const, prepending "const ". */
2162 recording::memento_of_get_const::make_debug_string ()
2164 return string::from_printf (m_ctxt
,
2165 "const %s", m_other_type
->get_debug_string ());
2168 /* Implementation of recording::memento::write_reproducer for const types. */
2171 recording::memento_of_get_const::write_reproducer (reproducer
&r
)
2173 const char *id
= r
.make_identifier (this, "type");
2174 r
.write (" gcc_jit_type *%s =\n"
2175 " gcc_jit_type_get_const (%s);\n",
2177 r
.get_identifier_as_type (m_other_type
));
2180 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2182 /* Implementation of pure virtual hook recording::memento::replay_into
2183 for recording::memento_of_get_volatile. */
2186 recording::memento_of_get_volatile::replay_into (replayer
*)
2188 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
2191 /* Implementation of recording::memento::make_debug_string for
2192 results of get_volatile, prepending "volatile ". */
2195 recording::memento_of_get_volatile::make_debug_string ()
2197 return string::from_printf (m_ctxt
,
2198 "volatile %s", m_other_type
->get_debug_string ());
2201 /* Implementation of recording::memento::write_reproducer for volatile
2205 recording::memento_of_get_volatile::write_reproducer (reproducer
&r
)
2207 const char *id
= r
.make_identifier (this, "type");
2208 r
.write (" gcc_jit_type *%s =\n"
2209 " gcc_jit_type_get_volatile (%s);\n",
2211 r
.get_identifier_as_type (m_other_type
));
2214 /* The implementation of class gcc::jit::recording::array_type */
2216 /* Implementation of pure virtual hook recording::type::dereference for
2217 recording::array_type. */
2220 recording::array_type::dereference ()
2222 return m_element_type
;
2225 /* Implementation of pure virtual hook recording::memento::replay_into
2226 for recording::array_type. */
2229 recording::array_type::replay_into (replayer
*r
)
2231 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
2232 m_element_type
->playback_type (),
2236 /* Implementation of recording::memento::make_debug_string for
2237 results of new_array_type. */
2240 recording::array_type::make_debug_string ()
2242 return string::from_printf (m_ctxt
,
2244 m_element_type
->get_debug_string (),
2248 /* Implementation of recording::memento::write_reproducer for array
2252 recording::array_type::write_reproducer (reproducer
&r
)
2254 const char *id
= r
.make_identifier (this, "array_type");
2255 r
.write (" gcc_jit_type *%s =\n"
2256 " gcc_jit_context_new_array_type (%s,\n"
2257 " %s, /* gcc_jit_location *loc */\n"
2258 " %s, /* gcc_jit_type *element_type */\n"
2259 " %i); /* int num_elements */\n",
2261 r
.get_identifier (get_context ()),
2262 r
.get_identifier (m_loc
),
2263 r
.get_identifier_as_type (m_element_type
),
2267 /* The implementation of class gcc::jit::recording::function_type */
2269 /* Constructor for gcc::jit::recording::function_type. */
2271 recording::function_type::function_type (context
*ctxt
,
2277 m_return_type (return_type
),
2279 m_is_variadic (is_variadic
)
2281 for (int i
= 0; i
< num_params
; i
++)
2282 m_param_types
.safe_push (param_types
[i
]);
2285 /* Implementation of pure virtual hook recording::type::dereference for
2286 recording::function_type. */
2289 recording::function_type::dereference ()
2294 /* Implementation of pure virtual hook recording::memento::replay_into
2295 for recording::function_type. */
2298 recording::function_type::replay_into (replayer
*r
)
2300 /* Convert m_param_types to a vec of playback type. */
2301 auto_vec
<playback::type
*> param_types
;
2303 recording::type
*type
;
2304 param_types
.create (m_param_types
.length ());
2305 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
2306 param_types
.safe_push (type
->playback_type ());
2308 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
2313 /* Special-casing for make_debug_string for get_pointer results for
2314 handling (one level) of pointers to functions. */
2317 recording::function_type::make_debug_string_with_ptr ()
2319 return make_debug_string_with ("(*) ");
2322 /* Implementation of recording::memento::make_debug_string for
2323 results of new_function_type. */
2326 recording::function_type::make_debug_string ()
2328 return make_debug_string_with ("");
2331 /* Build a debug string representation of the form:
2333 RESULT_TYPE INSERT (PARAM_TYPES)
2335 for use when handling 0 and 1 level of indirection to this
2339 recording::function_type::make_debug_string_with (const char *insert
)
2341 /* First, build a buffer for the arguments. */
2342 /* Calculate length of said buffer. */
2343 size_t sz
= 1; /* nil terminator */
2344 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2346 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
2347 sz
+= 2; /* ", " separator */
2350 sz
+= 5; /* ", ..." separator and ellipsis */
2352 /* Now allocate and populate the buffer. */
2353 char *argbuf
= new char[sz
];
2356 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2358 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
2359 len
+= strlen (m_param_types
[i
]->get_debug_string ());
2360 if (i
+ 1 < m_param_types
.length ())
2362 strcpy (argbuf
+ len
, ", ");
2368 if (m_param_types
.length ())
2370 strcpy (argbuf
+ len
, ", ");
2373 strcpy (argbuf
+ len
, "...");
2378 /* ...and use it to get the string for the call as a whole. */
2379 string
*result
= string::from_printf (m_ctxt
,
2381 m_return_type
->get_debug_string (),
2390 /* Implementation of recording::memento::write_reproducer for function
2394 recording::function_type::write_reproducer (reproducer
&)
2396 /* see notes below. */
2399 /* There's a get_pointer within context::new_function_ptr_type:
2400 the type received by client code isn't the memento for the
2401 function_type, but instead the result of get_pointer on it.
2403 Hence we can't directly write a reproducer that gives function_type.
2404 Instead we special-case things within get_pointer, detecting this
2405 case, calling the following function. */
2408 recording::function_type::write_deferred_reproducer (reproducer
&r
,
2411 gcc_assert (ptr_type
);
2412 r
.make_identifier (this, "function_type");
2413 const char *ptr_id
= r
.make_identifier (ptr_type
, "ptr_to");
2414 const char *param_types_id
= r
.make_tmp_identifier ("params_for", this);
2415 r
.write (" gcc_jit_type *%s[%i] = {\n",
2417 m_param_types
.length ());
2420 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
2421 r
.write (" %s,\n", r
.get_identifier_as_type (param_type
));
2423 r
.write (" gcc_jit_type *%s =\n"
2424 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2425 " %s, /* gcc_jit_location *loc */\n"
2426 " %s, /* gcc_jit_type *return_type */\n"
2427 " %i, /* int num_params */\n"
2428 " %s, /* gcc_jit_type **param_types */\n"
2429 " %i); /* int is_variadic */\n",
2431 r
.get_identifier (get_context ()),
2432 "NULL", /* location is not stored */
2433 r
.get_identifier_as_type (m_return_type
),
2434 m_param_types
.length (),
2439 /* The implementation of class gcc::jit::recording::field. */
2441 /* Implementation of pure virtual hook recording::memento::replay_into
2442 for recording::field. */
2445 recording::field::replay_into (replayer
*r
)
2447 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
2448 m_type
->playback_type (),
2449 playback_string (m_name
)));
2452 /* Override the default implementation of
2453 recording::memento::write_to_dump. Dump each field
2454 by dumping a line of the form:
2456 so that we can build up a struct/union field-byfield. */
2459 recording::field::write_to_dump (dump
&d
)
2461 d
.write (" %s %s;\n",
2462 m_type
->get_debug_string (),
2466 /* Implementation of recording::memento::make_debug_string for
2467 results of new_field. */
2470 recording::field::make_debug_string ()
2475 /* Implementation of recording::memento::write_reproducer for fields. */
2478 recording::field::write_reproducer (reproducer
&r
)
2480 const char *id
= r
.make_identifier (this, "field");
2481 r
.write(" gcc_jit_field *%s =\n"
2482 " gcc_jit_context_new_field (%s,\n"
2483 " %s, /* gcc_jit_location *loc */\n"
2484 " %s, /* gcc_jit_type *type, */\n"
2485 " %s); /* const char *name */\n",
2487 r
.get_identifier (get_context ()),
2488 r
.get_identifier (m_loc
),
2489 r
.get_identifier_as_type (m_type
),
2490 m_name
->get_debug_string ());
2493 /* The implementation of class gcc::jit::recording::compound_type */
2495 /* The constructor for gcc::jit::recording::compound_type. */
2497 recording::compound_type::compound_type (context
*ctxt
,
2507 /* Set the fields of a compound type.
2509 Implements the post-error-checking part of
2510 gcc_jit_struct_set_fields, and is also used by
2511 gcc_jit_context_new_union_type. */
2514 recording::compound_type::set_fields (location
*loc
,
2516 field
**field_array
)
2519 gcc_assert (NULL
== m_fields
);
2521 m_fields
= new fields (this, num_fields
, field_array
);
2522 m_ctxt
->record (m_fields
);
2525 /* Implementation of pure virtual hook recording::type::dereference for
2526 recording::compound_type. */
2529 recording::compound_type::dereference ()
2531 return NULL
; /* not a pointer */
2534 /* The implementation of class gcc::jit::recording::struct_. */
2536 /* The constructor for gcc::jit::recording::struct_. */
2538 recording::struct_::struct_ (context
*ctxt
,
2541 : compound_type (ctxt
, loc
, name
)
2545 /* Implementation of pure virtual hook recording::memento::replay_into
2546 for recording::struct_. */
2549 recording::struct_::replay_into (replayer
*r
)
2552 r
->new_compound_type (playback_location (r
, get_loc ()),
2553 get_name ()->c_str (),
2554 true /* is_struct */));
2558 recording::struct_::access_as_type (reproducer
&r
)
2560 return r
.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2561 r
.get_identifier (this));
2564 /* Implementation of recording::memento::make_debug_string for
2568 recording::struct_::make_debug_string ()
2570 return string::from_printf (m_ctxt
,
2571 "struct %s", get_name ()->c_str ());
2575 recording::struct_::write_reproducer (reproducer
&r
)
2577 const char *id
= r
.make_identifier (this, "struct");
2578 r
.write (" gcc_jit_struct *%s =\n"
2579 " gcc_jit_context_new_opaque_struct (%s,\n"
2580 " %s, /* gcc_jit_location *loc */\n"
2581 " %s); /* const char *name */\n",
2583 r
.get_identifier (get_context ()),
2584 r
.get_identifier (get_loc ()),
2585 get_name ()->get_debug_string ());
2588 /* The implementation of class gcc::jit::recording::union_. */
2590 /* The constructor for gcc::jit::recording::union_. */
2592 recording::union_::union_ (context
*ctxt
,
2595 : compound_type (ctxt
, loc
, name
)
2599 /* Implementation of pure virtual hook recording::memento::replay_into
2600 for recording::union_. */
2603 recording::union_::replay_into (replayer
*r
)
2606 r
->new_compound_type (playback_location (r
, get_loc ()),
2607 get_name ()->c_str (),
2608 false /* is_struct */));
2611 /* Implementation of recording::memento::make_debug_string for
2615 recording::union_::make_debug_string ()
2617 return string::from_printf (m_ctxt
,
2618 "union %s", get_name ()->c_str ());
2621 /* Implementation of recording::memento::write_reproducer for unions. */
2624 recording::union_::write_reproducer (reproducer
&r
)
2626 const char *id
= r
.make_identifier (this, "union");
2628 const char *fields_id
= r
.make_tmp_identifier ("fields_for", this);
2629 r
.write (" gcc_jit_field *%s[%i] = {\n",
2631 get_fields ()->length ());
2632 for (int i
= 0; i
< get_fields ()->length (); i
++)
2633 r
.write (" %s,\n", r
.get_identifier (get_fields ()->get_field (i
)));
2636 r
.write (" gcc_jit_type *%s =\n"
2637 " gcc_jit_context_new_union_type (%s,\n"
2638 " %s, /* gcc_jit_location *loc */\n"
2639 " %s, /* const char *name */\n"
2640 " %i, /* int num_fields */\n"
2641 " %s); /* gcc_jit_field **fields */\n",
2643 r
.get_identifier (get_context ()),
2644 r
.get_identifier (get_loc ()),
2645 get_name ()->get_debug_string (),
2646 get_fields ()->length (),
2650 /* The implementation of class gcc::jit::recording::fields. */
2652 /* The constructor for gcc::jit::recording::fields. */
2654 recording::fields::fields (compound_type
*struct_or_union
,
2657 : memento (struct_or_union
->m_ctxt
),
2658 m_struct_or_union (struct_or_union
),
2661 for (int i
= 0; i
< num_fields
; i
++)
2663 gcc_assert (fields
[i
]->get_container () == NULL
);
2664 fields
[i
]->set_container (m_struct_or_union
);
2665 m_fields
.safe_push (fields
[i
]);
2669 /* Implementation of pure virtual hook recording::memento::replay_into
2670 for recording::fields. */
2673 recording::fields::replay_into (replayer
*)
2675 auto_vec
<playback::field
*> playback_fields
;
2676 playback_fields
.create (m_fields
.length ());
2677 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
2678 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
2679 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
2682 /* Override the default implementation of
2683 recording::memento::write_to_dump by writing a union/struct
2684 declaration of this form:
2696 recording::fields::write_to_dump (dump
&d
)
2701 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
2702 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
2703 f
->write_to_dump (d
);
2707 /* Implementation of recording::memento::write_reproducer for the fields
2711 recording::fields::write_reproducer (reproducer
&r
)
2713 if (m_struct_or_union
)
2714 if (NULL
== m_struct_or_union
->dyn_cast_struct ())
2715 /* We have a union; the fields have already been written by
2716 union::write_reproducer. */
2719 const char *fields_id
= r
.make_identifier (this, "fields");
2720 r
.write (" gcc_jit_field *%s[%i] = {\n",
2722 m_fields
.length ());
2725 FOR_EACH_VEC_ELT (m_fields
, i
, field
)
2726 r
.write (" %s,\n", r
.get_identifier (field
));
2729 r
.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
2730 " %s, /* gcc_jit_location *loc */\n"
2731 " %i, /* int num_fields */\n"
2732 " %s); /* gcc_jit_field **fields */\n",
2733 r
.get_identifier (m_struct_or_union
),
2734 r
.get_identifier ((memento
*)NULL
),
2739 /* Implementation of recording::memento::make_debug_string for
2743 recording::fields::make_debug_string ()
2745 return string::from_printf (m_ctxt
,
2749 /* The implementation of class gcc::jit::recording::rvalue. */
2751 /* Create a recording::access_field_rvalue instance and add it to
2752 the rvalue's context's list of mementos.
2754 Implements the post-error-checking part of
2755 gcc_jit_rvalue_access_field. */
2758 recording::rvalue::access_field (recording::location
*loc
,
2761 recording::rvalue
*result
=
2762 new access_field_rvalue (m_ctxt
, loc
, this, field
);
2763 m_ctxt
->record (result
);
2767 /* Create a recording::dereference_field_rvalue instance and add it to
2768 the rvalue's context's list of mementos.
2770 Implements the post-error-checking part of
2771 gcc_jit_rvalue_dereference_field. */
2774 recording::rvalue::dereference_field (recording::location
*loc
,
2777 recording::lvalue
*result
=
2778 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
2779 m_ctxt
->record (result
);
2783 /* Create a recording::dereference_rvalue instance and add it to the
2784 rvalue's context's list of mementos.
2786 Implements the post-error-checking part of
2787 gcc_jit_rvalue_dereference. */
2790 recording::rvalue::dereference (recording::location
*loc
)
2792 recording::lvalue
*result
=
2793 new dereference_rvalue (m_ctxt
, loc
, this);
2794 m_ctxt
->record (result
);
2798 /* An rvalue visitor, for validating that every rvalue within an expression
2799 trees within "STMT" has the correct scope (e.g. no access to locals
2800 of a different function). */
2802 class rvalue_usage_validator
: public recording::rvalue_visitor
2805 rvalue_usage_validator (const char *api_funcname
,
2806 recording::context
*ctxt
,
2807 recording::statement
*stmt
);
2810 visit (recording::rvalue
*rvalue
);
2813 const char *m_api_funcname
;
2814 recording::context
*m_ctxt
;
2815 recording::statement
*m_stmt
;
2818 /* The trivial constructor for rvalue_usage_validator. */
2820 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname
,
2821 recording::context
*ctxt
,
2822 recording::statement
*stmt
)
2823 : m_api_funcname (api_funcname
),
2829 /* Verify that the given rvalue is in the correct scope. */
2832 rvalue_usage_validator::visit (recording::rvalue
*rvalue
)
2834 gcc_assert (m_stmt
->get_block ());
2835 recording::function
*stmt_scope
= m_stmt
->get_block ()->get_function ();
2837 /* Most rvalues don't have a scope (only locals and params). */
2838 if (rvalue
->get_scope ())
2840 if (rvalue
->get_scope () != stmt_scope
)
2842 (rvalue
->get_loc (),
2844 " rvalue %s (type: %s)"
2845 " has scope limited to function %s"
2846 " but was used within function %s"
2847 " (in statement: %s)",
2849 rvalue
->get_debug_string (),
2850 rvalue
->get_type ()->get_debug_string (),
2851 rvalue
->get_scope ()->get_debug_string (),
2852 stmt_scope
->get_debug_string (),
2853 m_stmt
->get_debug_string ());
2857 if (rvalue
->dyn_cast_param ())
2859 (rvalue
->get_loc (),
2861 " param %s (type: %s)"
2862 " was used within function %s"
2863 " (in statement: %s)"
2864 " but is not associated with any function",
2866 rvalue
->get_debug_string (),
2867 rvalue
->get_type ()->get_debug_string (),
2868 stmt_scope
->get_debug_string (),
2869 m_stmt
->get_debug_string ());
2873 /* Verify that it's valid to use this rvalue (and all expressions
2874 in the tree below it) within the given statement.
2876 For example, we must reject attempts to use a local from one
2877 function within a different function here, or we'll get
2878 an ICE deep inside toplev::main. */
2881 recording::rvalue::verify_valid_within_stmt (const char *api_funcname
, statement
*s
)
2883 rvalue_usage_validator
v (api_funcname
,
2887 /* Verify that it's OK to use this rvalue within s. */
2890 /* Traverse the expression tree below "this", verifying all rvalues
2892 visit_children (&v
);
2895 /* Set the scope of this rvalue to be the given function. This can only
2896 be done once on a given rvalue. */
2899 recording::rvalue::set_scope (function
*scope
)
2902 gcc_assert (NULL
== m_scope
);
2907 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
2909 Instances of rvalue don't need an upcast call. */
2912 recording::rvalue::access_as_rvalue (reproducer
&r
)
2914 return r
.get_identifier (this);
2918 /* The implementation of class gcc::jit::recording::lvalue. */
2920 /* Create a recording::new_access_field_of_lvalue instance and add it to
2921 the lvalue's context's list of mementos.
2923 Implements the post-error-checking part of
2924 gcc_jit_lvalue_access_field. */
2927 recording::lvalue::access_field (recording::location
*loc
,
2930 recording::lvalue
*result
=
2931 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
2932 m_ctxt
->record (result
);
2936 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
2937 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
2941 recording::lvalue::access_as_rvalue (reproducer
&r
)
2943 return r
.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
2944 r
.get_identifier (this));
2947 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
2948 Instances of lvalue don't need to be upcast. */
2951 recording::lvalue::access_as_lvalue (reproducer
&r
)
2953 return r
.get_identifier (this);
2956 /* Create a recording::get_address_of_lvalue instance and add it to
2957 the lvalue's context's list of mementos.
2959 Implements the post-error-checking part of
2960 gcc_jit_lvalue_get_address. */
2963 recording::lvalue::get_address (recording::location
*loc
)
2965 recording::rvalue
*result
=
2966 new get_address_of_lvalue (m_ctxt
, loc
, this);
2967 m_ctxt
->record (result
);
2971 /* The implementation of class gcc::jit::recording::param. */
2973 /* Implementation of pure virtual hook recording::memento::replay_into
2974 for recording::param. */
2977 recording::param::replay_into (replayer
*r
)
2979 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
2980 m_type
->playback_type (),
2984 /* Implementation of recording::rvalue::access_as_rvalue for params.
2985 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
2989 recording::param::access_as_rvalue (reproducer
&r
)
2991 return r
.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
2992 r
.get_identifier (this));
2995 /* Implementation of recording::lvalue::access_as_lvalue for params.
2996 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3000 recording::param::access_as_lvalue (reproducer
&r
)
3002 return r
.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3003 r
.get_identifier (this));
3006 /* Implementation of recording::memento::write_reproducer for params. */
3009 recording::param::write_reproducer (reproducer
&r
)
3011 const char *id
= r
.make_identifier (this, "param");
3012 r
.write (" gcc_jit_param *%s =\n"
3013 " gcc_jit_context_new_param (%s,\n"
3014 " %s, /* gcc_jit_location *loc */\n"
3015 " %s, /*gcc_jit_type *type */\n"
3016 " %s); /* const char *name */\n",
3018 r
.get_identifier (get_context ()),
3019 r
.get_identifier (m_loc
),
3020 r
.get_identifier_as_type (m_type
),
3021 m_name
->get_debug_string ());
3024 /* The implementation of class gcc::jit::recording::function. */
3026 /* gcc::jit::recording::function's constructor. */
3028 recording::function::function (context
*ctxt
,
3029 recording::location
*loc
,
3030 enum gcc_jit_function_kind kind
,
3032 recording::string
*name
,
3034 recording::param
**params
,
3036 enum built_in_function builtin_id
)
3040 m_return_type (return_type
),
3043 m_is_variadic (is_variadic
),
3044 m_builtin_id (builtin_id
),
3048 for (int i
= 0; i
< num_params
; i
++)
3050 param
*param
= params
[i
];
3053 /* Associate each param with this function.
3055 Verify that the param doesn't already have a function. */
3056 if (param
->get_scope ())
3058 /* We've already rejected attempts to reuse a param between
3059 different functions (within gcc_jit_context_new_function), so
3060 if the param *does* already have a function, it must be being
3061 reused within the params array for this function. We must
3062 produce an error for this reuse (blocking the compile), since
3063 otherwise we'd have an ICE later on. */
3064 gcc_assert (this == param
->get_scope ());
3067 "gcc_jit_context_new_function:"
3068 " parameter %s (type: %s)"
3069 " is used more than once when creating function %s",
3070 param
->get_debug_string (),
3071 param
->get_type ()->get_debug_string (),
3076 /* The normal, non-error case: associate this function with the
3078 param
->set_scope (this);
3081 m_params
.safe_push (param
);
3085 /* Implementation of pure virtual hook recording::memento::replay_into
3086 for recording::function. */
3089 recording::function::replay_into (replayer
*r
)
3091 /* Convert m_params to a vec of playback param. */
3092 auto_vec
<playback::param
*> params
;
3094 recording::param
*param
;
3095 params
.create (m_params
.length ());
3096 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3097 params
.safe_push (param
->playback_param ());
3099 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
3101 m_return_type
->playback_type (),
3108 /* Create a recording::local instance and add it to
3109 the functions's context's list of mementos, and to the function's
3112 Implements the post-error-checking part of
3113 gcc_jit_function_new_local. */
3116 recording::function::new_local (recording::location
*loc
,
3120 local
*result
= new local (this, loc
, type
, new_string (name
));
3121 m_ctxt
->record (result
);
3122 m_locals
.safe_push (result
);
3126 /* Create a recording::block instance and add it to
3127 the functions's context's list of mementos, and to the function's
3130 Implements the post-error-checking part of
3131 gcc_jit_function_new_block. */
3134 recording::function::new_block (const char *name
)
3136 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
3138 recording::block
*result
=
3139 new recording::block (this, m_blocks
.length (), new_string (name
));
3140 m_ctxt
->record (result
);
3141 m_blocks
.safe_push (result
);
3145 /* Override the default implementation of
3146 recording::memento::write_to_dump by dumping a C-like
3147 representation of the function; either like a prototype
3148 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3149 all other kinds of function. */
3152 recording::function::write_to_dump (dump
&d
)
3156 default: gcc_unreachable ();
3157 case GCC_JIT_FUNCTION_EXPORTED
:
3158 case GCC_JIT_FUNCTION_IMPORTED
:
3159 d
.write ("extern ");
3161 case GCC_JIT_FUNCTION_INTERNAL
:
3162 d
.write ("static ");
3164 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
3165 d
.write ("static inline ");
3168 d
.write ("%s\n", m_return_type
->get_debug_string ());
3170 if (d
.update_locations ())
3171 m_loc
= d
.make_location ();
3173 d
.write ("%s (", get_debug_string ());
3176 recording::param
*param
;
3177 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3182 param
->get_type ()->get_debug_string (),
3183 param
->get_debug_string ());
3186 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
3188 d
.write ("; /* (imported) */\n\n");
3198 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
3199 var
->write_to_dump (d
);
3200 if (m_locals
.length ())
3203 /* Write each block: */
3204 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3208 b
->write_to_dump (d
);
3215 /* Pre-compilation validation of a function, for those things we can't
3216 check until the context is (supposedly) fully-populated. */
3219 recording::function::validate ()
3221 /* Complain about empty functions with non-void return type. */
3222 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
3223 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
3224 if (0 == m_blocks
.length ())
3225 m_ctxt
->add_error (m_loc
,
3226 "function %s returns non-void (type: %s)"
3227 " but has no blocks",
3228 get_debug_string (),
3229 m_return_type
->get_debug_string ());
3231 /* Check that all blocks are terminated. */
3232 int num_invalid_blocks
= 0;
3237 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3238 if (!b
->validate ())
3239 num_invalid_blocks
++;
3242 /* Check that all blocks are reachable. */
3243 if (m_blocks
.length () > 0 && 0 == num_invalid_blocks
)
3245 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3246 flag, starting at the initial block. */
3247 auto_vec
<block
*> worklist (m_blocks
.length ());
3248 worklist
.safe_push (m_blocks
[0]);
3249 while (worklist
.length () > 0)
3251 block
*b
= worklist
.pop ();
3252 b
->m_is_reachable
= true;
3254 /* Add successor blocks that aren't yet marked to the worklist. */
3255 /* We checked that each block has a terminating statement above . */
3256 block
*next1
, *next2
;
3257 int n
= b
->get_successor_blocks (&next1
, &next2
);
3263 if (!next2
->m_is_reachable
)
3264 worklist
.safe_push (next2
);
3267 if (!next1
->m_is_reachable
)
3268 worklist
.safe_push (next1
);
3275 /* Now complain about any blocks that haven't been marked. */
3279 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3280 if (!b
->m_is_reachable
)
3281 m_ctxt
->add_error (b
->get_loc (),
3282 "unreachable block: %s",
3283 b
->get_debug_string ());
3288 /* Implements the post-error-checking part of
3289 gcc_jit_function_dump_to_dot. */
3292 recording::function::dump_to_dot (const char *path
)
3294 FILE *fp
= fopen (path
, "w");
3298 pretty_printer the_pp
;
3299 the_pp
.buffer
->stream
= fp
;
3301 pretty_printer
*pp
= &the_pp
;
3304 "digraph %s {\n", get_debug_string ());
3310 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3311 b
->dump_to_dot (pp
);
3318 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3319 b
->dump_edges_to_dot (pp
);
3322 pp_printf (pp
, "}\n");
3327 /* Implementation of recording::memento::make_debug_string for
3331 recording::function::make_debug_string ()
3336 /* A table of enum gcc_jit_function_kind values expressed in string
3339 static const char * const names_of_function_kinds
[] = {
3340 "GCC_JIT_FUNCTION_EXPORTED",
3341 "GCC_JIT_FUNCTION_INTERNAL",
3342 "GCC_JIT_FUNCTION_IMPORTED",
3343 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3346 /* Implementation of recording::memento::write_reproducer for functions. */
3349 recording::function::write_reproducer (reproducer
&r
)
3351 const char *id
= r
.make_identifier (this, "func");
3355 r
.write (" gcc_jit_function *%s =\n"
3356 " gcc_jit_context_get_builtin_function (%s,\n"
3359 r
.get_identifier (get_context ()),
3360 m_name
->get_debug_string ());
3363 const char *params_id
= r
.make_tmp_identifier ("params_for", this);
3364 r
.write (" gcc_jit_param *%s[%i] = {\n",
3366 m_params
.length ());
3369 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3370 r
.write (" %s,\n", r
.get_identifier (param
));
3372 r
.write (" gcc_jit_function *%s =\n"
3373 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3374 " %s, /* gcc_jit_location *loc */\n"
3375 " %s, /* enum gcc_jit_function_kind kind */\n"
3376 " %s, /* gcc_jit_type *return_type */\n"
3377 " %s, /* const char *name */\n"
3378 " %i, /* int num_params */\n"
3379 " %s, /* gcc_jit_param **params */\n"
3380 " %i); /* int is_variadic */\n",
3382 r
.get_identifier (get_context ()),
3383 r
.get_identifier (m_loc
),
3384 names_of_function_kinds
[m_kind
],
3385 r
.get_identifier_as_type (m_return_type
),
3386 m_name
->get_debug_string (),
3393 /* The implementation of class gcc::jit::recording::block. */
3395 /* Create a recording::eval instance and add it to
3396 the block's context's list of mementos, and to the block's
3399 Implements the heart of gcc_jit_block_add_eval. */
3401 recording::statement
*
3402 recording::block::add_eval (recording::location
*loc
,
3403 recording::rvalue
*rvalue
)
3405 statement
*result
= new eval (this, loc
, rvalue
);
3406 m_ctxt
->record (result
);
3407 m_statements
.safe_push (result
);
3411 /* Create a recording::assignment instance and add it to
3412 the block's context's list of mementos, and to the block's
3415 Implements the heart of gcc_jit_block_add_assignment. */
3417 recording::statement
*
3418 recording::block::add_assignment (recording::location
*loc
,
3419 recording::lvalue
*lvalue
,
3420 recording::rvalue
*rvalue
)
3422 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
3423 m_ctxt
->record (result
);
3424 m_statements
.safe_push (result
);
3428 /* Create a recording::assignment_op instance and add it to
3429 the block's context's list of mementos, and to the block's
3432 Implements the heart of gcc_jit_block_add_assignment_op. */
3434 recording::statement
*
3435 recording::block::add_assignment_op (recording::location
*loc
,
3436 recording::lvalue
*lvalue
,
3437 enum gcc_jit_binary_op op
,
3438 recording::rvalue
*rvalue
)
3440 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
3441 m_ctxt
->record (result
);
3442 m_statements
.safe_push (result
);
3446 /* Create a recording::comment instance and add it to
3447 the block's context's list of mementos, and to the block's
3450 Implements the heart of gcc_jit_block_add_comment. */
3452 recording::statement
*
3453 recording::block::add_comment (recording::location
*loc
,
3456 statement
*result
= new comment (this, loc
, new_string (text
));
3457 m_ctxt
->record (result
);
3458 m_statements
.safe_push (result
);
3462 /* Create a recording::end_with_conditional instance and add it to
3463 the block's context's list of mementos, and to the block's
3466 Implements the heart of gcc_jit_block_end_with_conditional. */
3468 recording::statement
*
3469 recording::block::end_with_conditional (recording::location
*loc
,
3470 recording::rvalue
*boolval
,
3471 recording::block
*on_true
,
3472 recording::block
*on_false
)
3474 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
3475 m_ctxt
->record (result
);
3476 m_statements
.safe_push (result
);
3477 m_has_been_terminated
= true;
3481 /* Create a recording::end_with_jump instance and add it to
3482 the block's context's list of mementos, and to the block's
3485 Implements the heart of gcc_jit_block_end_with_jump. */
3487 recording::statement
*
3488 recording::block::end_with_jump (recording::location
*loc
,
3489 recording::block
*target
)
3491 statement
*result
= new jump (this, loc
, target
);
3492 m_ctxt
->record (result
);
3493 m_statements
.safe_push (result
);
3494 m_has_been_terminated
= true;
3498 /* Create a recording::end_with_return instance and add it to
3499 the block's context's list of mementos, and to the block's
3502 Implements the post-error-checking parts of
3503 gcc_jit_block_end_with_return and
3504 gcc_jit_block_end_with_void_return. */
3506 recording::statement
*
3507 recording::block::end_with_return (recording::location
*loc
,
3508 recording::rvalue
*rvalue
)
3510 /* This is used by both gcc_jit_function_add_return and
3511 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3512 the former and NULL for the latter. */
3513 statement
*result
= new return_ (this, loc
, rvalue
);
3514 m_ctxt
->record (result
);
3515 m_statements
.safe_push (result
);
3516 m_has_been_terminated
= true;
3520 /* Override the default implementation of
3521 recording::memento::write_to_dump for blocks by writing
3522 an unindented block name as a label, followed by the indented
3532 recording::block::write_to_dump (dump
&d
)
3534 d
.write ("%s:\n", get_debug_string ());
3538 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
3539 s
->write_to_dump (d
);
3542 /* Validate a block by ensuring that it has been terminated. */
3545 recording::block::validate ()
3547 /* Check for termination. */
3548 if (!has_been_terminated ())
3550 statement
*stmt
= get_last_statement ();
3551 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
3552 m_func
->get_context ()->add_error (loc
,
3553 "unterminated block in %s: %s",
3554 m_func
->get_debug_string (),
3555 get_debug_string ());
3562 /* Get the source-location of a block by using that of the first
3563 statement within it, if any. */
3565 recording::location
*
3566 recording::block::get_loc () const
3568 recording::statement
*stmt
= get_first_statement ();
3570 return stmt
->get_loc ();
3575 /* Get the first statement within a block, if any. */
3577 recording::statement
*
3578 recording::block::get_first_statement () const
3580 if (m_statements
.length ())
3581 return m_statements
[0];
3586 /* Get the last statement within a block, if any. */
3588 recording::statement
*
3589 recording::block::get_last_statement () const
3591 if (m_statements
.length ())
3592 return m_statements
[m_statements
.length () - 1];
3597 /* Assuming that this block has been terminated, get the number of
3598 successor blocks, which will be 0, 1 or 2, for return, unconditional
3599 jump, and conditional jump respectively.
3600 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
3601 is written to NEXT1, and the second (if any) to NEXT2.
3603 Used when validating functions, and when dumping dot representations
3607 recording::block::get_successor_blocks (block
**next1
, block
**next2
) const
3609 gcc_assert (m_has_been_terminated
);
3612 statement
*last_statement
= get_last_statement ();
3613 gcc_assert (last_statement
);
3614 return last_statement
->get_successor_blocks (next1
, next2
);
3617 /* Implementation of pure virtual hook recording::memento::replay_into
3618 for recording::block. */
3621 recording::block::replay_into (replayer
*)
3623 set_playback_obj (m_func
->playback_function ()
3624 ->new_block (playback_string (m_name
)));
3627 /* Implementation of recording::memento::make_debug_string for
3631 recording::block::make_debug_string ()
3636 return string::from_printf (m_ctxt
,
3637 "<UNNAMED BLOCK %p>",
3641 /* Implementation of recording::memento::write_reproducer for blocks. */
3644 recording::block::write_reproducer (reproducer
&r
)
3646 const char *id
= r
.make_identifier (this, "block");
3647 r
.write (" gcc_jit_block *%s =\n"
3648 " gcc_jit_function_new_block (%s, %s);\n",
3650 r
.get_identifier (m_func
),
3651 m_name
? m_name
->get_debug_string () : "NULL");
3654 /* Dump a block in graphviz form into PP, capturing the block name (if
3655 any) and the statements. */
3658 recording::block::dump_to_dot (pretty_printer
*pp
)
3662 "[shape=record,style=filled,fillcolor=white,label=\"{"),
3664 pp_write_text_to_stream (pp
);
3667 pp_string (pp
, m_name
->c_str ());
3668 pp_string (pp
, ":");
3670 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
3675 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
3677 pp_string (pp
, s
->get_debug_string ());
3679 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
3687 /* Dump the out-edges of the block in graphviz form into PP. */
3690 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
3693 int num_succs
= get_successor_blocks (&next
[0], &next
[1]);
3694 for (int i
= 0; i
< num_succs
; i
++)
3696 "\tblock_%d:s -> block_%d:n;\n",
3697 m_index
, next
[i
]->m_index
);
3700 /* The implementation of class gcc::jit::recording::global. */
3702 /* Implementation of pure virtual hook recording::memento::replay_into
3703 for recording::global. */
3706 recording::global::replay_into (replayer
*r
)
3708 set_playback_obj (r
->new_global (playback_location (r
, m_loc
),
3710 m_type
->playback_type (),
3711 playback_string (m_name
)));
3714 /* Override the default implementation of
3715 recording::memento::write_to_dump for globals.
3716 This will be of the form:
3718 GCC_JIT_GLOBAL_EXPORTED:
3722 GCC_JIT_GLOBAL_INTERNAL:
3724 e.g. "static int foo;"
3726 GCC_JIT_GLOBAL_IMPORTED:
3728 e.g. "extern int foo;"
3730 These are written to the top of the dump by
3731 recording::context::dump_to_file. */
3734 recording::global::write_to_dump (dump
&d
)
3736 if (d
.update_locations ())
3737 m_loc
= d
.make_location ();
3744 case GCC_JIT_GLOBAL_EXPORTED
:
3747 case GCC_JIT_GLOBAL_INTERNAL
:
3748 d
.write ("static ");
3751 case GCC_JIT_GLOBAL_IMPORTED
:
3752 d
.write ("extern ");
3755 d
.write ("%s %s;\n",
3756 m_type
->get_debug_string (),
3757 get_debug_string ());
3760 /* A table of enum gcc_jit_global_kind values expressed in string
3763 static const char * const global_kind_reproducer_strings
[] = {
3764 "GCC_JIT_GLOBAL_EXPORTED",
3765 "GCC_JIT_GLOBAL_INTERNAL",
3766 "GCC_JIT_GLOBAL_IMPORTED"
3769 /* Implementation of recording::memento::write_reproducer for globals. */
3772 recording::global::write_reproducer (reproducer
&r
)
3774 const char *id
= r
.make_identifier (this, "block");
3775 r
.write (" gcc_jit_lvalue *%s =\n"
3776 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
3777 " %s, /* gcc_jit_location *loc */\n"
3778 " %s, /* enum gcc_jit_global_kind kind */\n"
3779 " %s, /* gcc_jit_type *type */\n"
3780 " %s); /* const char *name */\n",
3782 r
.get_identifier (get_context ()),
3783 r
.get_identifier (m_loc
),
3784 global_kind_reproducer_strings
[m_kind
],
3785 r
.get_identifier_as_type (get_type ()),
3786 m_name
->get_debug_string ());
3789 /* The implementation of the various const-handling classes:
3790 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
3792 /* Explicit specialization of the various mementos we're interested in. */
3793 template class recording::memento_of_new_rvalue_from_const
<int>;
3794 template class recording::memento_of_new_rvalue_from_const
<long>;
3795 template class recording::memento_of_new_rvalue_from_const
<double>;
3796 template class recording::memento_of_new_rvalue_from_const
<void *>;
3798 /* Implementation of the pure virtual hook recording::memento::replay_into
3799 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
3801 template <typename HOST_TYPE
>
3804 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
3807 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
3811 /* The make_debug_string and write_reproducer methods vary between the
3813 memento_of_new_rvalue_from_const <HOST_TYPE>
3814 classes, so we explicitly write specializations of them.
3816 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
3817 namespaces are written out explicitly, which is why most of this file
3818 doesn't abbreviate things by entering the "recording" namespace.
3820 However, these specializations are required to be in the same namespace
3821 as the template, hence we now have to enter the gcc::jit::recording
3827 /* The make_debug_string specialization for <int>, which renders it as
3828 (TARGET_TYPE)LITERAL
3834 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
3836 return string::from_printf (m_ctxt
,
3838 m_type
->get_debug_string (),
3842 /* The write_reproducer specialization for <int>. */
3846 memento_of_new_rvalue_from_const
<int>::write_reproducer (reproducer
&r
)
3848 const char *id
= r
.make_identifier (this, "rvalue");
3849 r
.write (" gcc_jit_rvalue *%s =\n"
3850 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
3851 " %s, /* gcc_jit_type *numeric_type */\n"
3852 " %i); /* int value */\n",
3854 r
.get_identifier (get_context ()),
3855 r
.get_identifier_as_type (m_type
),
3859 /* The make_debug_string specialization for <long>, rendering it as
3860 (TARGET_TYPE)LITERAL
3866 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
3868 return string::from_printf (m_ctxt
,
3870 m_type
->get_debug_string (),
3874 /* The write_reproducer specialization for <long>. */
3878 recording::memento_of_new_rvalue_from_const
<long>::write_reproducer (reproducer
&r
)
3880 const char *id
= r
.make_identifier (this, "rvalue");
3882 /* We have to special-case LONG_MIN, since e.g.
3883 -9223372036854775808L
3885 -(9223372036854775808L)
3887 error: integer constant is so large that it is unsigned [-Werror]
3888 Workaround this by writing (LONG_MIN + 1) - 1. */
3889 if (m_value
== LONG_MIN
)
3891 r
.write (" gcc_jit_rvalue *%s =\n"
3892 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
3893 " %s, /* gcc_jit_type *numeric_type */\n"
3894 " %ldL - 1); /* long value */\n",
3896 r
.get_identifier (get_context ()),
3897 r
.get_identifier_as_type (m_type
),
3902 r
.write (" gcc_jit_rvalue *%s =\n"
3903 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
3904 " %s, /* gcc_jit_type *numeric_type */\n"
3905 " %ldL); /* long value */\n",
3907 r
.get_identifier (get_context ()),
3908 r
.get_identifier_as_type (m_type
),
3912 /* The make_debug_string specialization for <double>, rendering it as
3913 (TARGET_TYPE)LITERAL
3919 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
3921 return string::from_printf (m_ctxt
,
3923 m_type
->get_debug_string (),
3927 /* The write_reproducer specialization for <double>. */
3931 recording::memento_of_new_rvalue_from_const
<double>::write_reproducer (reproducer
&r
)
3933 const char *id
= r
.make_identifier (this, "rvalue");
3934 r
.write (" gcc_jit_rvalue *%s =\n"
3935 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
3936 " %s, /* gcc_jit_type *numeric_type */\n"
3937 " %f); /* double value */\n",
3939 r
.get_identifier (get_context ()),
3940 r
.get_identifier_as_type (m_type
),
3944 /* The make_debug_string specialization for <void *>, rendering it as
3949 Zero is rendered as NULL e.g.
3954 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
3956 if (m_value
!= NULL
)
3957 return string::from_printf (m_ctxt
,
3959 m_type
->get_debug_string (), m_value
);
3961 return string::from_printf (m_ctxt
,
3963 m_type
->get_debug_string ());
3966 /* Implementation of recording::memento::write_reproducer for <void *>
3971 memento_of_new_rvalue_from_const
<void *>::write_reproducer (reproducer
&r
)
3973 const char *id
= r
.make_identifier (this, "rvalue");
3975 r
.write (" gcc_jit_rvalue *%s =\n"
3976 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
3977 " %s, /* gcc_jit_type *pointer_type */\n"
3978 " (void *)%p); /* void *value */\n",
3980 r
.get_identifier (get_context ()),
3981 r
.get_identifier_as_type (m_type
),
3984 r
.write (" gcc_jit_rvalue *%s =\n"
3985 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
3986 " %s); /* gcc_jit_type *pointer_type */\n",
3988 r
.get_identifier (get_context ()),
3989 r
.get_identifier_as_type (m_type
));
3992 /* We're done specializing make_debug_string and write_reproducer, so we
3993 can exit the gcc::jit::recording namespace. */
3995 } // namespace recording
3997 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
3999 /* Implementation of pure virtual hook recording::memento::replay_into
4000 for recording::memento_of_new_string_literal. */
4003 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
4005 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
4008 /* Implementation of recording::memento::make_debug_string for
4012 recording::memento_of_new_string_literal::make_debug_string ()
4014 return string::from_printf (m_ctxt
,
4016 m_value
->get_debug_string ());
4019 /* Implementation of recording::memento::write_reproducer for string literal
4023 recording::memento_of_new_string_literal::write_reproducer (reproducer
&r
)
4025 const char *id
= r
.make_identifier (this, "rvalue");
4026 r
.write (" gcc_jit_rvalue *%s =\n"
4027 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4028 " %s); /* const char *value */\n",
4030 r
.get_identifier (get_context ()),
4031 m_value
->get_debug_string ());
4034 /* The implementation of class gcc::jit::recording::unary_op. */
4036 /* Implementation of pure virtual hook recording::memento::replay_into
4037 for recording::unary_op. */
4040 recording::unary_op::replay_into (replayer
*r
)
4042 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
4044 get_type ()->playback_type (),
4045 m_a
->playback_rvalue ()));
4048 /* Implementation of pure virtual hook recording::rvalue::visit_children
4049 for recording::unary_op. */
4051 recording::unary_op::visit_children (rvalue_visitor
*v
)
4056 /* Implementation of recording::memento::make_debug_string for
4059 static const char * const unary_op_strings
[] = {
4060 "-", /* GCC_JIT_UNARY_OP_MINUS */
4061 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4062 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4063 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4067 recording::unary_op::make_debug_string ()
4069 return string::from_printf (m_ctxt
,
4071 unary_op_strings
[m_op
],
4072 m_a
->get_debug_string ());
4075 static const char * const unary_op_reproducer_strings
[] = {
4076 "GCC_JIT_UNARY_OP_MINUS",
4077 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4078 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4079 "GCC_JIT_UNARY_OP_ABS"
4082 /* Implementation of recording::memento::write_reproducer for unary ops. */
4085 recording::unary_op::write_reproducer (reproducer
&r
)
4087 const char *id
= r
.make_identifier (this, "rvalue");
4088 r
.write (" gcc_jit_rvalue *%s =\n"
4089 " gcc_jit_context_new_unary_op (%s,\n"
4090 " %s, /* gcc_jit_location *loc */\n"
4091 " %s, /* enum gcc_jit_unary_op op */\n"
4092 " %s, /* gcc_jit_type *result_type */\n"
4093 " %s); /* gcc_jit_rvalue *a */\n",
4095 r
.get_identifier (get_context ()),
4096 r
.get_identifier (m_loc
),
4097 unary_op_reproducer_strings
[m_op
],
4098 r
.get_identifier_as_type (get_type ()),
4099 r
.get_identifier_as_rvalue (m_a
));
4102 /* The implementation of class gcc::jit::recording::binary_op. */
4104 /* Implementation of pure virtual hook recording::memento::replay_into
4105 for recording::binary_op. */
4108 recording::binary_op::replay_into (replayer
*r
)
4110 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
4112 get_type ()->playback_type (),
4113 m_a
->playback_rvalue (),
4114 m_b
->playback_rvalue ()));
4117 /* Implementation of pure virtual hook recording::rvalue::visit_children
4118 for recording::binary_op. */
4120 recording::binary_op::visit_children (rvalue_visitor
*v
)
4126 /* Implementation of recording::memento::make_debug_string for
4129 static const char * const binary_op_strings
[] = {
4130 "+", /* GCC_JIT_BINARY_OP_PLUS */
4131 "-", /* GCC_JIT_BINARY_OP_MINUS */
4132 "*", /* GCC_JIT_BINARY_OP_MULT */
4133 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4134 "%", /* GCC_JIT_BINARY_OP_MODULO */
4135 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4136 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4137 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4138 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4139 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4140 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4141 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4145 recording::binary_op::make_debug_string ()
4147 return string::from_printf (m_ctxt
,
4149 m_a
->get_debug_string (),
4150 binary_op_strings
[m_op
],
4151 m_b
->get_debug_string ());
4154 static const char * const binary_op_reproducer_strings
[] = {
4155 "GCC_JIT_BINARY_OP_PLUS",
4156 "GCC_JIT_BINARY_OP_MINUS",
4157 "GCC_JIT_BINARY_OP_MULT",
4158 "GCC_JIT_BINARY_OP_DIVIDE",
4159 "GCC_JIT_BINARY_OP_MODULO",
4160 "GCC_JIT_BINARY_OP_BITWISE_AND",
4161 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4162 "GCC_JIT_BINARY_OP_BITWISE_OR",
4163 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4164 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4165 "GCC_JIT_BINARY_OP_LSHIFT",
4166 "GCC_JIT_BINARY_OP_RSHIFT"
4169 /* Implementation of recording::memento::write_reproducer for binary ops. */
4172 recording::binary_op::write_reproducer (reproducer
&r
)
4174 const char *id
= r
.make_identifier (this, "rvalue");
4175 r
.write (" gcc_jit_rvalue *%s =\n"
4176 " gcc_jit_context_new_binary_op (%s,\n"
4177 " %s, /* gcc_jit_location *loc */\n"
4178 " %s, /* enum gcc_jit_binary_op op */\n"
4179 " %s, /* gcc_jit_type *result_type */\n"
4180 " %s, /* gcc_jit_rvalue *a */\n"
4181 " %s); /* gcc_jit_rvalue *b */\n",
4183 r
.get_identifier (get_context ()),
4184 r
.get_identifier (m_loc
),
4185 binary_op_reproducer_strings
[m_op
],
4186 r
.get_identifier_as_type (get_type ()),
4187 r
.get_identifier_as_rvalue (m_a
),
4188 r
.get_identifier_as_rvalue (m_b
));
4191 /* The implementation of class gcc::jit::recording::comparison. */
4193 /* Implementation of recording::memento::make_debug_string for
4196 static const char * const comparison_strings
[] =
4198 "==", /* GCC_JIT_COMPARISON_EQ */
4199 "!=", /* GCC_JIT_COMPARISON_NE */
4200 "<", /* GCC_JIT_COMPARISON_LT */
4201 "<=", /* GCC_JIT_COMPARISON_LE */
4202 ">", /* GCC_JIT_COMPARISON_GT */
4203 ">=", /* GCC_JIT_COMPARISON_GE */
4207 recording::comparison::make_debug_string ()
4209 return string::from_printf (m_ctxt
,
4211 m_a
->get_debug_string (),
4212 comparison_strings
[m_op
],
4213 m_b
->get_debug_string ());
4216 /* A table of enum gcc_jit_comparison values expressed in string
4219 static const char * const comparison_reproducer_strings
[] =
4221 "GCC_JIT_COMPARISON_EQ",
4222 "GCC_JIT_COMPARISON_NE",
4223 "GCC_JIT_COMPARISON_LT",
4224 "GCC_JIT_COMPARISON_LE",
4225 "GCC_JIT_COMPARISON_GT",
4226 "GCC_JIT_COMPARISON_GE"
4229 /* Implementation of recording::memento::write_reproducer for comparisons. */
4232 recording::comparison::write_reproducer (reproducer
&r
)
4234 const char *id
= r
.make_identifier (this, "rvalue");
4235 r
.write (" gcc_jit_rvalue *%s =\n"
4236 " gcc_jit_context_new_comparison (%s,\n"
4237 " %s, /* gcc_jit_location *loc */\n"
4238 " %s, /* enum gcc_jit_comparison op */\n"
4239 " %s, /* gcc_jit_rvalue *a */\n"
4240 " %s); /* gcc_jit_rvalue *b */\n",
4242 r
.get_identifier (get_context ()),
4243 r
.get_identifier (m_loc
),
4244 comparison_reproducer_strings
[m_op
],
4245 r
.get_identifier_as_rvalue (m_a
),
4246 r
.get_identifier_as_rvalue (m_b
));
4249 /* Implementation of pure virtual hook recording::memento::replay_into
4250 for recording::comparison. */
4253 recording::comparison::replay_into (replayer
*r
)
4255 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
4257 m_a
->playback_rvalue (),
4258 m_b
->playback_rvalue ()));
4261 /* Implementation of pure virtual hook recording::rvalue::visit_children
4262 for recording::comparison. */
4265 recording::comparison::visit_children (rvalue_visitor
*v
)
4271 /* Implementation of pure virtual hook recording::memento::replay_into
4272 for recording::cast. */
4275 recording::cast::replay_into (replayer
*r
)
4277 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
4278 m_rvalue
->playback_rvalue (),
4279 get_type ()->playback_type ()));
4282 /* Implementation of pure virtual hook recording::rvalue::visit_children
4283 for recording::cast. */
4285 recording::cast::visit_children (rvalue_visitor
*v
)
4287 v
->visit (m_rvalue
);
4290 /* Implementation of recording::memento::make_debug_string for
4294 recording::cast::make_debug_string ()
4296 return string::from_printf (m_ctxt
,
4298 get_type ()->get_debug_string (),
4299 m_rvalue
->get_debug_string ());
4302 /* Implementation of recording::memento::write_reproducer for casts. */
4305 recording::cast::write_reproducer (reproducer
&r
)
4307 const char *id
= r
.make_identifier (this, "rvalue");
4308 r
.write (" gcc_jit_rvalue *%s =\n"
4309 " gcc_jit_context_new_cast (%s,\n"
4310 " %s, /* gcc_jit_location *loc */\n"
4311 " %s, /* gcc_jit_rvalue *rvalue */\n"
4312 " %s); /* gcc_jit_type *type */\n",
4314 r
.get_identifier (get_context ()),
4315 r
.get_identifier (m_loc
),
4316 r
.get_identifier_as_rvalue (m_rvalue
),
4317 r
.get_identifier_as_type (get_type ()));
4320 /* The implementation of class gcc::jit::recording::call. */
4322 /* The constructor for gcc::jit::recording::call. */
4324 recording::call::call (recording::context
*ctxt
,
4325 recording::location
*loc
,
4326 recording::function
*func
,
4329 : rvalue (ctxt
, loc
, func
->get_return_type ()),
4333 for (int i
= 0; i
< numargs
; i
++)
4334 m_args
.safe_push (args
[i
]);
4337 /* Implementation of pure virtual hook recording::memento::replay_into
4338 for recording::call. */
4341 recording::call::replay_into (replayer
*r
)
4343 auto_vec
<playback::rvalue
*> playback_args
;
4344 playback_args
.create (m_args
.length ());
4345 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4346 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
4348 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
4349 m_func
->playback_function (),
4353 /* Implementation of pure virtual hook recording::rvalue::visit_children
4354 for recording::call. */
4357 recording::call::visit_children (rvalue_visitor
*v
)
4359 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4360 v
->visit (m_args
[i
]);
4363 /* Implementation of recording::memento::make_debug_string for
4367 recording::call::make_debug_string ()
4369 /* First, build a buffer for the arguments. */
4370 /* Calculate length of said buffer. */
4371 size_t sz
= 1; /* nil terminator */
4372 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4374 sz
+= strlen (m_args
[i
]->get_debug_string ());
4375 sz
+= 2; /* ", " separator */
4378 /* Now allocate and populate the buffer. */
4379 char *argbuf
= new char[sz
];
4382 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4384 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string ());
4385 len
+= strlen (m_args
[i
]->get_debug_string ());
4386 if (i
+ 1 < m_args
.length ())
4388 strcpy (argbuf
+ len
, ", ");
4394 /* ...and use it to get the string for the call as a whole. */
4395 string
*result
= string::from_printf (m_ctxt
,
4397 m_func
->get_debug_string (),
4406 recording::call::write_reproducer (reproducer
&r
)
4408 const char *id
= r
.make_identifier (this, "call");
4409 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
4410 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4413 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4414 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
4416 r
.write (" gcc_jit_rvalue *%s =\n"
4417 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4418 " %s, /* gcc_jit_location *loc */\n"
4419 " %s, /* gcc_jit_function *func */\n"
4420 " %i, /* int numargs */ \n"
4421 " %s); /* gcc_jit_rvalue **args*/\n",
4423 r
.get_identifier (get_context ()),
4424 r
.get_identifier (m_loc
),
4425 r
.get_identifier (m_func
),
4430 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4432 /* The constructor for recording::call_through_ptr. */
4434 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
4435 recording::location
*loc
,
4436 recording::rvalue
*fn_ptr
,
4439 : rvalue (ctxt
, loc
,
4440 fn_ptr
->get_type ()->dereference ()
4441 ->as_a_function_type ()->get_return_type ()),
4445 for (int i
= 0; i
< numargs
; i
++)
4446 m_args
.safe_push (args
[i
]);
4449 /* Implementation of pure virtual hook recording::memento::replay_into
4450 for recording::call_through_ptr. */
4453 recording::call_through_ptr::replay_into (replayer
*r
)
4455 auto_vec
<playback::rvalue
*> playback_args
;
4456 playback_args
.create (m_args
.length ());
4457 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4458 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
4460 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
4461 m_fn_ptr
->playback_rvalue (),
4465 /* Implementation of pure virtual hook recording::rvalue::visit_children
4466 for recording::call_through_ptr. */
4469 recording::call_through_ptr::visit_children (rvalue_visitor
*v
)
4471 v
->visit (m_fn_ptr
);
4472 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4473 v
->visit (m_args
[i
]);
4476 /* Implementation of recording::memento::make_debug_string for
4477 calls through function ptrs. */
4480 recording::call_through_ptr::make_debug_string ()
4482 /* First, build a buffer for the arguments. */
4483 /* Calculate length of said buffer. */
4484 size_t sz
= 1; /* nil terminator */
4485 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4487 sz
+= strlen (m_args
[i
]->get_debug_string ());
4488 sz
+= 2; /* ", " separator */
4491 /* Now allocate and populate the buffer. */
4492 char *argbuf
= new char[sz
];
4495 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4497 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string ());
4498 len
+= strlen (m_args
[i
]->get_debug_string ());
4499 if (i
+ 1 < m_args
.length ())
4501 strcpy (argbuf
+ len
, ", ");
4507 /* ...and use it to get the string for the call as a whole. */
4508 string
*result
= string::from_printf (m_ctxt
,
4510 m_fn_ptr
->get_debug_string (),
4518 /* Implementation of recording::memento::write_reproducer for
4519 call_through_ptr. */
4522 recording::call_through_ptr::write_reproducer (reproducer
&r
)
4524 const char *id
= r
.make_identifier (this, "call");
4525 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
4526 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4529 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4530 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
4532 r
.write (" gcc_jit_rvalue *%s =\n"
4533 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
4534 " %s, /* gcc_jit_location *loc */\n"
4535 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
4536 " %i, /* int numargs */ \n"
4537 " %s); /* gcc_jit_rvalue **args*/\n",
4539 r
.get_identifier (get_context ()),
4540 r
.get_identifier (m_loc
),
4541 r
.get_identifier_as_rvalue (m_fn_ptr
),
4546 /* The implementation of class gcc::jit::recording::array_access. */
4548 /* Implementation of pure virtual hook recording::memento::replay_into
4549 for recording::array_access. */
4552 recording::array_access::replay_into (replayer
*r
)
4555 r
->new_array_access (playback_location (r
, m_loc
),
4556 m_ptr
->playback_rvalue (),
4557 m_index
->playback_rvalue ()));
4560 /* Implementation of pure virtual hook recording::rvalue::visit_children
4561 for recording::array_access. */
4564 recording::array_access::visit_children (rvalue_visitor
*v
)
4570 /* Implementation of recording::memento::make_debug_string for
4574 recording::array_access::make_debug_string ()
4576 return string::from_printf (m_ctxt
,
4578 m_ptr
->get_debug_string (),
4579 m_index
->get_debug_string ());
4582 /* Implementation of recording::memento::write_reproducer for
4586 recording::array_access::write_reproducer (reproducer
&r
)
4588 const char *id
= r
.make_identifier (this, "lvalue");
4589 r
.write (" gcc_jit_lvalue *%s = \n"
4590 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
4591 " %s, /*gcc_jit_location *loc */\n"
4592 " %s, /* gcc_jit_rvalue *ptr */\n"
4593 " %s); /* gcc_jit_rvalue *index */\n",
4595 r
.get_identifier (get_context ()),
4596 r
.get_identifier (m_loc
),
4597 r
.get_identifier_as_rvalue (m_ptr
),
4598 r
.get_identifier_as_rvalue (m_index
));
4601 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
4603 /* Implementation of pure virtual hook recording::memento::replay_into
4604 for recording::access_field_of_lvalue. */
4607 recording::access_field_of_lvalue::replay_into (replayer
*r
)
4610 m_lvalue
->playback_lvalue ()
4611 ->access_field (playback_location (r
, m_loc
),
4612 m_field
->playback_field ()));
4616 /* Implementation of pure virtual hook recording::rvalue::visit_children
4617 for recording::access_field_of_lvalue. */
4620 recording::access_field_of_lvalue::visit_children (rvalue_visitor
*v
)
4622 v
->visit (m_lvalue
);
4625 /* Implementation of recording::memento::make_debug_string for
4626 accessing a field of an lvalue. */
4629 recording::access_field_of_lvalue::make_debug_string ()
4631 return string::from_printf (m_ctxt
,
4633 m_lvalue
->get_debug_string (),
4634 m_field
->get_debug_string ());
4637 /* Implementation of recording::memento::write_reproducer for
4638 access_field_of_lvalue. */
4641 recording::access_field_of_lvalue::write_reproducer (reproducer
&r
)
4643 const char *id
= r
.make_identifier (this, "lvalue");
4644 r
.write (" gcc_jit_lvalue *%s = \n"
4645 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
4646 " %s, /*gcc_jit_location *loc */\n"
4649 r
.get_identifier_as_lvalue (m_lvalue
),
4650 r
.get_identifier (m_loc
),
4651 r
.get_identifier (m_field
));
4654 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
4656 /* Implementation of pure virtual hook recording::memento::replay_into
4657 for recording::access_field_rvalue. */
4660 recording::access_field_rvalue::replay_into (replayer
*r
)
4663 m_rvalue
->playback_rvalue ()
4664 ->access_field (playback_location (r
, m_loc
),
4665 m_field
->playback_field ()));
4668 /* Implementation of pure virtual hook recording::rvalue::visit_children
4669 for recording::access_field_rvalue. */
4672 recording::access_field_rvalue::visit_children (rvalue_visitor
*v
)
4674 v
->visit (m_rvalue
);
4677 /* Implementation of recording::memento::make_debug_string for
4678 accessing a field of an rvalue. */
4681 recording::access_field_rvalue::make_debug_string ()
4683 return string::from_printf (m_ctxt
,
4685 m_rvalue
->get_debug_string (),
4686 m_field
->get_debug_string ());
4689 /* Implementation of recording::memento::write_reproducer for
4690 access_field_rvalue. */
4693 recording::access_field_rvalue::write_reproducer (reproducer
&r
)
4695 const char *id
= r
.make_identifier (this, "rvalue");
4696 r
.write (" gcc_jit_rvalue *%s = \n"
4697 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
4698 " %s, /*gcc_jit_location *loc */\n"
4701 r
.get_identifier_as_rvalue (m_rvalue
),
4702 r
.get_identifier (m_loc
),
4703 r
.get_identifier (m_field
));
4706 /* The implementation of class
4707 gcc::jit::recording::dereference_field_rvalue. */
4709 /* Implementation of pure virtual hook recording::memento::replay_into
4710 for recording::dereference_field_rvalue. */
4713 recording::dereference_field_rvalue::replay_into (replayer
*r
)
4716 m_rvalue
->playback_rvalue ()->
4717 dereference_field (playback_location (r
, m_loc
),
4718 m_field
->playback_field ()));
4721 /* Implementation of pure virtual hook recording::rvalue::visit_children
4722 for recording::dereference_field_rvalue. */
4725 recording::dereference_field_rvalue::visit_children (rvalue_visitor
*v
)
4727 v
->visit (m_rvalue
);
4730 /* Implementation of recording::memento::make_debug_string for
4731 dereferencing a field of an rvalue. */
4734 recording::dereference_field_rvalue::make_debug_string ()
4736 return string::from_printf (m_ctxt
,
4738 m_rvalue
->get_debug_string (),
4739 m_field
->get_debug_string ());
4742 /* Implementation of recording::memento::write_reproducer for
4743 dereference_field_rvalue. */
4746 recording::dereference_field_rvalue::write_reproducer (reproducer
&r
)
4748 const char *id
= r
.make_identifier (this, "lvalue");
4749 r
.write (" gcc_jit_lvalue *%s=\n"
4750 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
4751 " %s, /* gcc_jit_location *loc */\n"
4752 " %s); /* gcc_jit_field *field */\n",
4754 r
.get_identifier_as_rvalue (m_rvalue
),
4755 r
.get_identifier (m_loc
),
4756 r
.get_identifier (m_field
));
4759 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
4761 /* Implementation of pure virtual hook recording::memento::replay_into
4762 for recording::dereference_rvalue. */
4765 recording::dereference_rvalue::replay_into (replayer
*r
)
4768 m_rvalue
->playback_rvalue ()->
4769 dereference (playback_location (r
, m_loc
)));
4772 /* Implementation of pure virtual hook recording::rvalue::visit_children
4773 for recording::dereference_rvalue. */
4776 recording::dereference_rvalue::visit_children (rvalue_visitor
*v
)
4778 v
->visit (m_rvalue
);
4781 /* Implementation of recording::memento::make_debug_string for
4782 dereferencing an rvalue. */
4785 recording::dereference_rvalue::make_debug_string ()
4787 return string::from_printf (m_ctxt
,
4789 m_rvalue
->get_debug_string ());
4792 /* Implementation of recording::memento::write_reproducer for
4793 dereference_rvalue. */
4796 recording::dereference_rvalue::write_reproducer (reproducer
&r
)
4798 const char *id
= r
.make_identifier (this, "dereference");
4799 r
.write (" gcc_jit_lvalue *%s =\n"
4800 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
4801 " %s); /* gcc_jit_location *loc */\n",
4803 r
.get_identifier_as_rvalue (m_rvalue
),
4804 r
.get_identifier (m_loc
));
4807 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
4809 /* Implementation of pure virtual hook recording::memento::replay_into
4810 for recording::get_address_of_lvalue. */
4813 recording::get_address_of_lvalue::replay_into (replayer
*r
)
4816 m_lvalue
->playback_lvalue ()->
4817 get_address (playback_location (r
, m_loc
)));
4820 /* Implementation of pure virtual hook recording::rvalue::visit_children
4821 for recording::get_address_of_lvalue. */
4824 recording::get_address_of_lvalue::visit_children (rvalue_visitor
*v
)
4826 v
->visit (m_lvalue
);
4829 /* Implementation of recording::memento::make_debug_string for
4830 getting the address of an lvalue. */
4833 recording::get_address_of_lvalue::make_debug_string ()
4835 return string::from_printf (m_ctxt
,
4837 m_lvalue
->get_debug_string ());
4840 /* Implementation of recording::memento::write_reproducer for
4841 get_address_of_lvalue. */
4844 recording::get_address_of_lvalue::write_reproducer (reproducer
&r
)
4846 const char *id
= r
.make_identifier (this, "address_of");
4847 r
.write (" gcc_jit_rvalue *%s =\n"
4848 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
4849 " %s); /* gcc_jit_location *loc */\n",
4851 r
.get_identifier_as_lvalue (m_lvalue
),
4852 r
.get_identifier (m_loc
));
4855 /* The implementation of class gcc::jit::recording::local. */
4857 /* Implementation of pure virtual hook recording::memento::replay_into
4858 for recording::local. */
4861 recording::local::replay_into (replayer
*r
)
4864 m_func
->playback_function ()
4865 ->new_local (playback_location (r
, m_loc
),
4866 m_type
->playback_type (),
4867 playback_string (m_name
)));
4870 /* Override the default implementation of
4871 recording::memento::write_to_dump for locals by writing
4873 for use at the top of the function body as if it were a
4877 recording::local::write_to_dump (dump
&d
)
4879 if (d
.update_locations ())
4880 m_loc
= d
.make_location ();
4881 d
.write(" %s %s;\n",
4882 m_type
->get_debug_string (),
4883 get_debug_string ());
4887 recording::local::write_reproducer (reproducer
&r
)
4889 const char *id
= r
.make_identifier (this, "local");
4890 r
.write (" gcc_jit_lvalue *%s =\n"
4891 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
4892 " %s, /* gcc_jit_location *loc */\n"
4893 " %s, /* gcc_jit_type *type */\n"
4894 " %s); /* const char *name */\n",
4896 r
.get_identifier (m_func
),
4897 r
.get_identifier (m_loc
),
4898 r
.get_identifier_as_type (m_type
),
4899 m_name
->get_debug_string ());
4902 /* The implementation of class gcc::jit::recording::statement. */
4904 /* We poison the default implementation of
4905 gcc::jit::recording::statement::get_successor_blocks
4906 since this vfunc must only ever be called on terminator
4910 recording::statement::get_successor_blocks (block
**/
*out_next1*/
,
4911 block
**/
*out_next2*/
) const
4913 /* The base class implementation is for non-terminating statements,
4914 and thus should never be called. */
4919 /* Extend the default implementation of
4920 recording::memento::write_to_dump for statements by (if requested)
4921 updating the location of the statement to the current location in
4925 recording::statement::write_to_dump (dump
&d
)
4927 memento::write_to_dump (d
);
4928 if (d
.update_locations ())
4929 m_loc
= d
.make_location ();
4932 /* The implementation of class gcc::jit::recording::eval. */
4934 /* Implementation of pure virtual hook recording::memento::replay_into
4935 for recording::eval. */
4938 recording::eval::replay_into (replayer
*r
)
4940 playback_block (get_block ())
4941 ->add_eval (playback_location (r
),
4942 m_rvalue
->playback_rvalue ());
4945 /* Implementation of recording::memento::make_debug_string for
4946 an eval statement. */
4949 recording::eval::make_debug_string ()
4951 return string::from_printf (m_ctxt
,
4953 m_rvalue
->get_debug_string ());
4956 /* Implementation of recording::memento::write_reproducer for
4960 recording::eval::write_reproducer (reproducer
&r
)
4962 r
.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
4963 " %s, /* gcc_jit_location *loc */\n"
4964 " %s); /* gcc_jit_rvalue *rvalue */\n",
4965 r
.get_identifier (get_block ()),
4966 r
.get_identifier (get_loc ()),
4967 r
.get_identifier_as_rvalue (m_rvalue
));
4970 /* The implementation of class gcc::jit::recording::assignment. */
4972 /* Implementation of pure virtual hook recording::memento::replay_into
4973 for recording::assignment. */
4976 recording::assignment::replay_into (replayer
*r
)
4978 playback_block (get_block ())
4979 ->add_assignment (playback_location (r
),
4980 m_lvalue
->playback_lvalue (),
4981 m_rvalue
->playback_rvalue ());
4984 /* Implementation of recording::memento::make_debug_string for
4985 an assignment statement. */
4988 recording::assignment::make_debug_string ()
4990 return string::from_printf (m_ctxt
,
4992 m_lvalue
->get_debug_string (),
4993 m_rvalue
->get_debug_string ());
4996 /* Implementation of recording::memento::write_reproducer for
4997 assignment statements. */
5000 recording::assignment::write_reproducer (reproducer
&r
)
5002 r
.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5003 " %s, /* gcc_jit_location *loc */\n"
5004 " %s, /* gcc_jit_lvalue *lvalue */\n"
5005 " %s); /* gcc_jit_rvalue *rvalue */\n",
5006 r
.get_identifier (get_block ()),
5007 r
.get_identifier (get_loc ()),
5008 r
.get_identifier_as_lvalue (m_lvalue
),
5009 r
.get_identifier_as_rvalue (m_rvalue
));
5012 /* The implementation of class gcc::jit::recording::assignment_op. */
5014 /* Implementation of pure virtual hook recording::memento::replay_into
5015 for recording::assignment_op. */
5018 recording::assignment_op::replay_into (replayer
*r
)
5020 playback::type
*result_type
=
5021 m_lvalue
->playback_lvalue ()->get_type ();
5023 playback::rvalue
*binary_op
=
5024 r
->new_binary_op (playback_location (r
),
5027 m_lvalue
->playback_rvalue (),
5028 m_rvalue
->playback_rvalue ());
5030 playback_block (get_block ())
5031 ->add_assignment (playback_location (r
),
5032 m_lvalue
->playback_lvalue (),
5036 /* Implementation of recording::memento::make_debug_string for
5037 an assignment_op statement. */
5040 recording::assignment_op::make_debug_string ()
5042 return string::from_printf (m_ctxt
,
5044 m_lvalue
->get_debug_string (),
5045 binary_op_strings
[m_op
],
5046 m_rvalue
->get_debug_string ());
5049 /* Implementation of recording::memento::write_reproducer for
5050 assignment_op statements. */
5053 recording::assignment_op::write_reproducer (reproducer
&r
)
5055 r
.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5056 " %s, /* gcc_jit_location *loc */\n"
5057 " %s, /* gcc_jit_lvalue *lvalue */\n"
5058 " %s, /* enum gcc_jit_binary_op op */\n"
5059 " %s); /* gcc_jit_rvalue *rvalue */\n",
5060 r
.get_identifier (get_block ()),
5061 r
.get_identifier (get_loc ()),
5062 r
.get_identifier_as_lvalue (m_lvalue
),
5063 binary_op_reproducer_strings
[m_op
],
5064 r
.get_identifier_as_rvalue (m_rvalue
));
5067 /* The implementation of class gcc::jit::recording::comment. */
5069 /* Implementation of pure virtual hook recording::memento::replay_into
5070 for recording::comment. */
5073 recording::comment::replay_into (replayer
*r
)
5075 playback_block (get_block ())
5076 ->add_comment (playback_location (r
),
5080 /* Implementation of recording::memento::make_debug_string for
5081 a comment "statement". */
5084 recording::comment::make_debug_string ()
5086 return string::from_printf (m_ctxt
,
5091 /* Implementation of recording::memento::write_reproducer for
5095 recording::comment::write_reproducer (reproducer
&r
)
5097 r
.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5098 " %s, /* gcc_jit_location *loc */\n"
5099 " %s); /* const char *text */\n",
5100 r
.get_identifier (get_block ()),
5101 r
.get_identifier (get_loc ()),
5102 m_text
->get_debug_string ());
5105 /* The implementation of class gcc::jit::recording::conditional. */
5107 /* Implementation of pure virtual hook recording::memento::replay_into
5108 for recording::conditional. */
5111 recording::conditional::replay_into (replayer
*r
)
5113 playback_block (get_block ())
5114 ->add_conditional (playback_location (r
),
5115 m_boolval
->playback_rvalue (),
5116 playback_block (m_on_true
),
5117 playback_block (m_on_false
));
5120 /* Override the poisoned default implementation of
5121 gcc::jit::recording::statement::get_successor_blocks
5123 A conditional jump has 2 successor blocks. */
5126 recording::conditional::get_successor_blocks (block
**out_next1
,
5127 block
**out_next2
) const
5129 *out_next1
= m_on_true
;
5130 *out_next2
= m_on_false
;
5134 /* Implementation of recording::memento::make_debug_string for
5135 a conditional jump statement. */
5138 recording::conditional::make_debug_string ()
5141 return string::from_printf (m_ctxt
,
5142 "if (%s) goto %s; else goto %s;",
5143 m_boolval
->get_debug_string (),
5144 m_on_true
->get_debug_string (),
5145 m_on_false
->get_debug_string ());
5147 return string::from_printf (m_ctxt
,
5149 m_boolval
->get_debug_string (),
5150 m_on_true
->get_debug_string ());
5153 /* Implementation of recording::memento::write_reproducer for
5154 conditional statements. */
5157 recording::conditional::write_reproducer (reproducer
&r
)
5159 r
.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5160 " %s, /* gcc_jit_location *loc */\n"
5161 " %s, /* gcc_jit_rvalue *boolval */\n"
5162 " %s, /* gcc_jit_block *on_true */\n"
5163 " %s); /* gcc_jit_block *on_false */\n",
5164 r
.get_identifier (get_block ()),
5165 r
.get_identifier (get_loc ()),
5166 r
.get_identifier_as_rvalue (m_boolval
),
5167 r
.get_identifier (m_on_true
),
5168 r
.get_identifier (m_on_false
));
5171 /* The implementation of class gcc::jit::recording::jump. */
5173 /* Implementation of pure virtual hook recording::memento::replay_into
5174 for recording::jump. */
5177 recording::jump::replay_into (replayer
*r
)
5179 playback_block (get_block ())
5180 ->add_jump (playback_location (r
),
5181 m_target
->playback_block ());
5184 /* Override the poisoned default implementation of
5185 gcc::jit::recording::statement::get_successor_blocks
5187 An unconditional jump has 1 successor block. */
5190 recording::jump::get_successor_blocks (block
**out_next1
,
5191 block
**/
*out_next2*/
) const
5193 *out_next1
= m_target
;
5197 /* Implementation of recording::memento::make_debug_string for
5198 a unconditional jump statement. */
5201 recording::jump::make_debug_string ()
5203 return string::from_printf (m_ctxt
,
5205 m_target
->get_debug_string ());
5208 /* Implementation of recording::memento::write_reproducer for
5212 recording::jump::write_reproducer (reproducer
&r
)
5214 r
.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5215 " %s, /* gcc_jit_location *loc */\n"
5216 " %s); /* gcc_jit_block *target */\n",
5217 r
.get_identifier (get_block ()),
5218 r
.get_identifier (get_loc ()),
5219 r
.get_identifier (m_target
));
5222 /* The implementation of class gcc::jit::recording::return_. */
5224 /* Implementation of pure virtual hook recording::memento::replay_into
5225 for recording::return_. */
5228 recording::return_::replay_into (replayer
*r
)
5230 playback_block (get_block ())
5231 ->add_return (playback_location (r
),
5232 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
5235 /* Override the poisoned default implementation of
5236 gcc::jit::recording::statement::get_successor_blocks
5238 A return statement has no successor block. */
5241 recording::return_::get_successor_blocks (block
**/
*out_next1*/
,
5242 block
**/
*out_next2*/
) const
5247 /* Implementation of recording::memento::make_debug_string for
5248 a return statement (covers both those with and without rvalues). */
5251 recording::return_::make_debug_string ()
5254 return string::from_printf (m_ctxt
,
5256 m_rvalue
->get_debug_string ());
5258 return string::from_printf (m_ctxt
,
5262 /* Implementation of recording::memento::write_reproducer for
5263 return statements. */
5266 recording::return_::write_reproducer (reproducer
&r
)
5269 r
.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5270 " %s, /* gcc_jit_location *loc */\n"
5271 " %s); /* gcc_jit_rvalue *rvalue */\n",
5272 r
.get_identifier (get_block ()),
5273 r
.get_identifier (get_loc ()),
5274 r
.get_identifier_as_rvalue (m_rvalue
));
5276 r
.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5277 " %s); /* gcc_jit_location *loc */\n",
5278 r
.get_identifier (get_block ()),
5279 r
.get_identifier (get_loc ()));
5282 } // namespace gcc::jit