1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2017 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
25 #include "pretty-print.h"
30 #include "jit-builtins.h"
31 #include "jit-recording.h"
32 #include "jit-playback.h"
39 dump::dump (recording::context
&ctxt
,
41 bool update_locations
)
43 m_filename (filename
),
44 m_update_locations (update_locations
),
48 m_file
= fopen (filename
, "w");
51 "error opening dump file %s for writing: %s",
60 int err
= fclose (m_file
);
62 m_ctxt
.add_error (NULL
,
63 "error closing dump file %s: %s",
69 /* Write the given message to the dump, using printf-formatting
70 conventions, updating the line/column within the dump.
72 Emit an error on the context if a failure occurs. */
75 dump::write (const char *fmt
, ...)
81 /* If there was an error opening the file, we've already reported it.
82 Don't attempt further work. */
87 len
= vasprintf (&buf
, fmt
, ap
);
90 if (buf
== NULL
|| len
< 0)
92 m_ctxt
.add_error (NULL
, "malloc failure writing to dumpfile %s",
97 if (fwrite (buf
, strlen (buf
), 1, m_file
) != 1)
98 m_ctxt
.add_error (NULL
, "error writing to dump file %s",
101 /* Flush after each line, to ease debugging crashes. */
104 /* Update line/column: */
105 for (const char *ptr
= buf
; *ptr
; ptr
++)
119 /* Construct a gcc::jit::recording::location instance for the current
120 location within the dump. */
122 recording::location
*
123 dump::make_location () const
125 return m_ctxt
.new_location (m_filename
, m_line
, m_column
,
126 /* We need to flag such locations as *not*
127 created by the user, so that
128 reproducer::get_identifier can cope with
129 them appearing *after* the memento that
134 /* A collection of allocations, all of which can be released together, to
135 avoid needing to track and release them individually. */
143 xstrdup_printf (const char *, ...)
144 ATTRIBUTE_RETURNS_NONNULL
148 xstrdup_printf_va (const char *, va_list ap
)
149 ATTRIBUTE_RETURNS_NONNULL
153 auto_vec
<void *> m_buffers
;
156 /* allocator's destructor. Call "free" on all of the allocations. */
158 allocator::~allocator ()
162 FOR_EACH_VEC_ELT (m_buffers
, i
, buffer
)
166 /* Formatted printing, allocating to a buffer (or exiting the process if
167 the allocation fails).
169 The buffer exists until the allocator is cleaned up, and is freed at
170 that point, so the caller doesn't need to track the result. */
173 allocator::xstrdup_printf (const char *fmt
, ...)
178 result
= xstrdup_printf_va (fmt
, ap
);
183 /* Formatted printing, allocating to a buffer (or exiting the process if
184 the allocation fails).
186 The buffer exists until the allocator is cleaned up, and is freed at
187 that point, so the caller doesn't need to track the result. */
190 allocator::xstrdup_printf_va (const char *fmt
, va_list ap
)
192 char *result
= xvasprintf (fmt
, ap
);
193 m_buffers
.safe_push (result
);
197 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
198 implementing gcc_jit_context_dump_reproducer_to_file. */
200 class reproducer
: public dump
203 reproducer (recording::context
&ctxt
,
204 const char *filename
);
207 write_params (const vec
<recording::context
*> &contexts
);
210 write_args (const vec
<recording::context
*> &contexts
);
213 make_identifier (recording::memento
*m
, const char *prefix
);
216 make_tmp_identifier (const char *prefix
, recording::memento
*m
);
219 get_identifier (recording::context
*ctxt
);
222 get_identifier (recording::memento
*m
);
225 get_identifier_as_rvalue (recording::rvalue
*m
);
228 get_identifier_as_lvalue (recording::lvalue
*m
);
231 get_identifier_as_type (recording::type
*m
);
234 xstrdup_printf (const char *, ...)
235 ATTRIBUTE_RETURNS_NONNULL
239 const char * ensure_identifier_is_unique (const char *candidate
, void *ptr
);
242 hash_map
<recording::memento
*, const char *> m_map_memento_to_identifier
;
244 struct hash_traits
: public string_hash
246 static void remove (const char *) {}
248 hash_set
<const char *, hash_traits
> m_set_identifiers
;
249 allocator m_allocator
;
252 /* gcc::jit::reproducer's constructor. */
254 reproducer::reproducer (recording::context
&ctxt
,
255 const char *filename
) :
256 dump (ctxt
, filename
, 0),
257 m_map_memento_to_identifier (),
258 m_set_identifiers (),
263 /* Write out a list of contexts as a set of parameters within a
264 C function declaration. */
267 reproducer::write_params (const vec
<recording::context
*> &contexts
)
270 recording::context
*ctxt
;
271 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
273 write ("gcc_jit_context *%s",
274 get_identifier (ctxt
));
275 if (i
< contexts
.length () - 1)
281 /* Write out a list of contexts as a set of arguments within a call
285 reproducer::write_args (const vec
<recording::context
*> &contexts
)
288 recording::context
*ctxt
;
289 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
292 get_identifier (ctxt
));
293 if (i
< contexts
.length () - 1)
299 /* Ensure that STR is a valid C identifier by overwriting
300 any invalid chars in-place with underscores.
302 This doesn't special-case the first character. */
305 convert_to_identifier (char *str
)
307 for (char *p
= str
; *p
; p
++)
312 /* Given CANDIDATE, a possible C identifier for use in a reproducer,
313 ensure that it is unique within the generated source file by
314 appending PTR to it if necessary. Return the resulting string.
316 The reproducer will eventually clean up the buffer in its dtor. */
319 reproducer::ensure_identifier_is_unique (const char *candidate
, void *ptr
)
321 if (m_set_identifiers
.contains (candidate
))
322 candidate
= m_allocator
.xstrdup_printf ("%s_%p", candidate
, ptr
);
323 gcc_assert (!m_set_identifiers
.contains (candidate
));
324 m_set_identifiers
.add (candidate
);
328 /* Generate a C identifier for the given memento, associating the generated
329 buffer with the memento (for future calls to get_identifier et al).
331 The reproducer will eventually clean up the buffer in its dtor. */
333 reproducer::make_identifier (recording::memento
*m
, const char *prefix
)
336 if (strlen (m
->get_debug_string ()) < 100)
338 char *buf
= m_allocator
.xstrdup_printf ("%s_%s",
340 m
->get_debug_string ());
341 convert_to_identifier (buf
);
345 result
= m_allocator
.xstrdup_printf ("%s_%p",
347 result
= ensure_identifier_is_unique (result
, m
);
348 m_map_memento_to_identifier
.put (m
, result
);
352 /* Generate a C identifier for a temporary variable.
353 The reproducer will eventually clean up the buffer in its dtor. */
356 reproducer::make_tmp_identifier (const char *prefix
, recording::memento
*m
)
358 return m_allocator
.xstrdup_printf ("%s_%s",
359 prefix
, get_identifier (m
));
362 /* Generate a C identifier for the given context.
363 The reproducer will eventually clean up the buffer in its dtor. */
366 reproducer::get_identifier (recording::context
*ctxt
)
368 return m_allocator
.xstrdup_printf ("ctxt_%p",
372 /* Locate the C identifier for the given memento, which is assumed to
373 have already been created via make_identifier. */
376 reproducer::get_identifier (recording::memento
*m
)
381 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
382 and hence these locations appear in the context's memento list
383 out-of-order: they appear in the context's memento list *after*
384 the memento that refers to them. For this case, it's simplest to
385 pretend that they're NULL when writing out the code to recreate the
386 memento that uses them. */
387 if (recording::location
*loc
= m
->dyn_cast_location ())
388 if (!loc
->created_by_user ())
391 const char **slot
= m_map_memento_to_identifier
.get (m
);
394 get_context ().add_error (NULL
,
395 "unable to find identifier for %p: %s",
397 m
->get_debug_string ());
403 /* Locate the C identifier for the given rvalue, wrapping it within
404 a gcc_*_as_rvalue upcast if necessary. */
407 reproducer::get_identifier_as_rvalue (recording::rvalue
*m
)
409 return m
->access_as_rvalue (*this);
412 /* Locate the C identifier for the given lvalue, wrapping it within
413 a gcc_*_as_lvalue upcast if necessary. */
416 reproducer::get_identifier_as_lvalue (recording::lvalue
*m
)
418 return m
->access_as_lvalue (*this);
421 /* Locate the C identifier for the given type, wrapping it within
422 a gcc_*_as_type upcast if necessary. */
425 reproducer::get_identifier_as_type (recording::type
*m
)
427 return m
->access_as_type (*this);
430 /* Formatted printing, allocating to a buffer (or exiting the process if
431 the allocation fails).
433 The buffer exists until the allocator is cleaned up, and is freed at
434 that point, so the caller doesn't need to track the result.
436 Note that we can't use ggc_printf since we're not within the compiler
437 proper (when within gcc_jit_context_dump_reproducer_to_file). */
440 reproducer::xstrdup_printf (const char *fmt
, ...)
445 result
= m_allocator
.xstrdup_printf_va (fmt
, ap
);
450 /**********************************************************************
452 **********************************************************************/
454 /* Get the playback::location for the given recording::location,
455 handling a NULL input with a NULL output. */
458 recording::playback_location (replayer
*r
, recording::location
*loc
)
461 return loc
->playback_location (r
);
466 /* Get a const char * for the given recording::string
467 handling a NULL input with a NULL output. */
470 recording::playback_string (recording::string
*str
)
473 return str
->c_str ();
478 /* Get the playback::block for the given recording::block,
479 handling a NULL input with a NULL output. */
482 recording::playback_block (recording::block
*b
)
485 return b
->playback_block ();
490 /* Methods of cc::jit::recording::context. */
492 /* The constructor for gcc::jit::recording::context, used by
493 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
495 recording::context::context (context
*parent_ctxt
)
497 m_parent_ctxt (parent_ctxt
),
498 m_toplevel_ctxt (m_parent_ctxt
? m_parent_ctxt
->m_toplevel_ctxt
: this),
501 m_first_error_str (NULL
),
502 m_owns_first_error_str (false),
503 m_last_error_str (NULL
),
504 m_owns_last_error_str (false),
510 m_builtins_manager(NULL
)
514 /* Inherit options from parent. */
516 i
< sizeof (m_str_options
) / sizeof (m_str_options
[0]);
519 const char *parent_opt
= parent_ctxt
->m_str_options
[i
];
520 m_str_options
[i
] = parent_opt
? xstrdup (parent_opt
) : NULL
;
522 memcpy (m_int_options
,
523 parent_ctxt
->m_int_options
,
524 sizeof (m_int_options
));
525 memcpy (m_bool_options
,
526 parent_ctxt
->m_bool_options
,
527 sizeof (m_bool_options
));
528 memcpy (m_inner_bool_options
,
529 parent_ctxt
->m_inner_bool_options
,
530 sizeof (m_inner_bool_options
));
531 set_logger (parent_ctxt
->get_logger ());
535 memset (m_str_options
, 0, sizeof (m_str_options
));
536 memset (m_int_options
, 0, sizeof (m_int_options
));
537 memset (m_bool_options
, 0, sizeof (m_bool_options
));
538 memset (m_inner_bool_options
, 0, sizeof (m_inner_bool_options
));
541 memset (m_basic_types
, 0, sizeof (m_basic_types
));
544 /* The destructor for gcc::jit::recording::context, implicitly used by
545 gcc_jit_context_release. */
547 recording::context::~context ()
549 JIT_LOG_SCOPE (get_logger ());
552 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
557 for (i
= 0; i
< GCC_JIT_NUM_STR_OPTIONS
; ++i
)
558 free (m_str_options
[i
]);
561 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
564 if (m_builtins_manager
)
565 delete m_builtins_manager
;
567 if (m_owns_first_error_str
)
568 free (m_first_error_str
);
570 if (m_owns_last_error_str
)
571 if (m_last_error_str
!= m_first_error_str
)
572 free (m_last_error_str
);
575 /* Add the given mememto to the list of those tracked by this
576 gcc::jit::recording::context, so that e.g. it can be deleted
577 when this context is released. */
580 recording::context::record (memento
*m
)
584 m_mementos
.safe_push (m
);
587 /* Replay this context (and any parents) into the given replayer. */
590 recording::context::replay_into (replayer
*r
)
592 JIT_LOG_SCOPE (get_logger ());
596 /* If we have a parent context, we must replay it. This will
597 recursively walk backwards up the historical tree, then replay things
598 forwards "in historical order", starting with the ultimate parent
599 context, until we reach the "this" context.
601 Note that we fully replay the parent, then fully replay the child,
602 which means that inter-context references can only exist from child
603 to parent, not the other way around.
605 All of this replaying is suboptimal - it would be better to do the
606 work for the parent context *once*, rather than replaying the parent
607 every time we replay each child. However, fixing this requires deep
608 surgery to lifetime-management: we'd need every context family tree
609 to have its own GC heap, and to initialize the GCC code to use that
610 heap (with a mutex on such a heap). */
612 m_parent_ctxt
->replay_into (r
);
614 if (r
->errors_occurred ())
617 /* Replay this context's saved operations into r. */
618 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
620 /* Disabled low-level debugging, here if we need it: print what
622 Note that the calls to get_debug_string might lead to more
623 mementos being created for the strings.
624 This can also be used to exercise the debug_string
627 printf ("context %p replaying (%p): %s\n",
628 (void *)this, (void *)m
, m
->get_debug_string ());
632 if (r
->errors_occurred ())
637 /* During a playback, we associate objects from the recording with
638 their counterparts during this playback.
640 For simplicity, we store this within the recording objects.
642 The following method cleans away these associations, to ensure that
643 we never have out-of-date associations lingering on subsequent
644 playbacks (the objects pointed to are GC-managed, but the
645 recording objects don't own refs to them). */
648 recording::context::disassociate_from_playback ()
650 JIT_LOG_SCOPE (get_logger ());
655 m_parent_ctxt
->disassociate_from_playback ();
657 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
659 m
->set_playback_obj (NULL
);
663 /* Create a recording::string instance and add it to this context's list
666 This creates a fresh copy of the given 0-terminated buffer. */
669 recording::context::new_string (const char *text
)
674 recording::string
*result
= new string (this, text
);
679 /* Create a recording::location instance and add it to this context's
682 Implements the post-error-checking part of
683 gcc_jit_context_new_location. */
685 recording::location
*
686 recording::context::new_location (const char *filename
,
689 bool created_by_user
)
691 recording::location
*result
=
692 new recording::location (this,
693 new_string (filename
),
700 /* If we haven't seen this enum value yet, create a recording::type
701 instance and add it to this context's list of mementos.
703 If we have seen it before, reuse our cached value, so that repeated
704 calls on the context give the same object.
706 If we have a parent context, the cache is within the ultimate
709 Implements the post-error-checking part of
710 gcc_jit_context_get_type. */
713 recording::context::get_type (enum gcc_jit_types kind
)
715 if (!m_basic_types
[kind
])
718 m_basic_types
[kind
] = m_parent_ctxt
->get_type (kind
);
721 recording::type
*result
= new memento_of_get_type (this, kind
);
723 m_basic_types
[kind
] = result
;
727 return m_basic_types
[kind
];
730 /* Get a recording::type instance for the given size and signedness.
731 This is implemented in terms of recording::context::get_type
734 Implements the post-error-checking part of
735 gcc_jit_context_get_int_type. */
738 recording::context::get_int_type (int num_bytes
, int is_signed
)
740 /* We can't use a switch here since some of the values are macros affected
741 by options; e.g. i386.h has
742 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
743 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
744 are in bits, rather than bytes.
746 const int num_bits
= num_bytes
* 8;
747 if (num_bits
== INT_TYPE_SIZE
)
748 return get_type (is_signed
750 : GCC_JIT_TYPE_UNSIGNED_INT
);
751 if (num_bits
== CHAR_TYPE_SIZE
)
752 return get_type (is_signed
753 ? GCC_JIT_TYPE_SIGNED_CHAR
754 : GCC_JIT_TYPE_UNSIGNED_CHAR
);
755 if (num_bits
== SHORT_TYPE_SIZE
)
756 return get_type (is_signed
758 : GCC_JIT_TYPE_UNSIGNED_SHORT
);
759 if (num_bits
== LONG_TYPE_SIZE
)
760 return get_type (is_signed
762 : GCC_JIT_TYPE_UNSIGNED_LONG
);
763 if (num_bits
== LONG_LONG_TYPE_SIZE
)
764 return get_type (is_signed
765 ? GCC_JIT_TYPE_LONG_LONG
766 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
768 /* Some other size, not corresponding to the C int types. */
769 /* To be written: support arbitrary other sizes, sharing by
770 memoizing at the recording::context level? */
774 /* Create a recording::type instance and add it to this context's list
777 Implements the post-error-checking part of
778 gcc_jit_context_new_array_type. */
781 recording::context::new_array_type (recording::location
*loc
,
782 recording::type
*element_type
,
785 if (struct_
*s
= element_type
->dyn_cast_struct ())
786 if (!s
->get_fields ())
789 "cannot create an array of type %s"
790 " until the fields have been set",
791 s
->get_name ()->c_str ());
794 recording::type
*result
=
795 new recording::array_type (this, loc
, element_type
, num_elements
);
800 /* Create a recording::field instance and add it to this context's list
803 Implements the post-error-checking part of
804 gcc_jit_context_new_field. */
807 recording::context::new_field (recording::location
*loc
,
808 recording::type
*type
,
811 recording::field
*result
=
812 new recording::field (this, loc
, type
, new_string (name
));
817 /* Create a recording::struct_ instance and add it to this context's
818 list of mementos and list of compound types.
820 Implements the post-error-checking part of
821 gcc_jit_context_new_struct_type. */
824 recording::context::new_struct_type (recording::location
*loc
,
827 recording::struct_
*result
= new struct_ (this, loc
, new_string (name
));
829 m_compound_types
.safe_push (result
);
833 /* Create a recording::union_ instance and add it to this context's
834 list of mementos and list of compound types.
836 Implements the first post-error-checking part of
837 gcc_jit_context_new_union_type. */
840 recording::context::new_union_type (recording::location
*loc
,
843 recording::union_
*result
= new union_ (this, loc
, new_string (name
));
845 m_compound_types
.safe_push (result
);
849 /* Create a recording::function_type instance and add it to this context's
852 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
854 recording::function_type
*
855 recording::context::new_function_type (recording::type
*return_type
,
857 recording::type
**param_types
,
860 recording::function_type
*fn_type
861 = new function_type (this,
870 /* Create a recording::type instance and add it to this context's list
873 Implements the post-error-checking part of
874 gcc_jit_context_new_function_ptr_type. */
877 recording::context::new_function_ptr_type (recording::location
*, /* unused loc */
878 recording::type
*return_type
,
880 recording::type
**param_types
,
883 recording::function_type
*fn_type
884 = new_function_type (return_type
,
889 /* Return a pointer-type to the function type. */
890 return fn_type
->get_pointer ();
893 /* Create a recording::param instance and add it to this context's list
896 Implements the post-error-checking part of
897 gcc_jit_context_new_param. */
900 recording::context::new_param (recording::location
*loc
,
901 recording::type
*type
,
904 recording::param
*result
= new recording::param (this, loc
, type
, new_string (name
));
909 /* Create a recording::function instance and add it to this context's list
910 of mementos and list of functions.
912 Implements the post-error-checking part of
913 gcc_jit_context_new_function. */
915 recording::function
*
916 recording::context::new_function (recording::location
*loc
,
917 enum gcc_jit_function_kind kind
,
918 recording::type
*return_type
,
921 recording::param
**params
,
923 enum built_in_function builtin_id
)
925 recording::function
*result
=
926 new recording::function (this,
927 loc
, kind
, return_type
,
929 num_params
, params
, is_variadic
,
932 m_functions
.safe_push (result
);
937 /* Locate the builtins_manager (if any) for this family of contexts,
938 creating it if it doesn't exist already.
940 All of the recording contexts in a family share one builtins_manager:
941 if we have a child context, follow the parent links to get the
942 ultimate ancestor context, and look for it/store it there. */
945 recording::context::get_builtins_manager ()
948 return m_parent_ctxt
->get_builtins_manager ();
950 if (!m_builtins_manager
)
951 m_builtins_manager
= new builtins_manager (this);
953 return m_builtins_manager
;
956 /* Get a recording::function instance, which is lazily-created and added
957 to the context's lists of mementos.
959 Implements the post-error-checking part of
960 gcc_jit_context_get_builtin_function. */
962 recording::function
*
963 recording::context::get_builtin_function (const char *name
)
965 builtins_manager
*bm
= get_builtins_manager ();
966 return bm
->get_builtin_function (name
);
969 /* Create a recording::global instance and add it to this context's list
972 Implements the post-error-checking part of
973 gcc_jit_context_new_global. */
976 recording::context::new_global (recording::location
*loc
,
977 enum gcc_jit_global_kind kind
,
978 recording::type
*type
,
981 recording::global
*result
=
982 new recording::global (this, loc
, kind
, type
, new_string (name
));
984 m_globals
.safe_push (result
);
989 /* Create a recording::memento_of_new_string_literal instance and add it
990 to this context's list of mementos.
992 Implements the post-error-checking part of
993 gcc_jit_context_new_string_literal. */
996 recording::context::new_string_literal (const char *value
)
998 recording::rvalue
*result
=
999 new memento_of_new_string_literal (this, NULL
, new_string (value
));
1004 /* Create a recording::unary_op instance and add it to this context's
1007 Implements the post-error-checking part of
1008 gcc_jit_context_new_unary_op. */
1011 recording::context::new_unary_op (recording::location
*loc
,
1012 enum gcc_jit_unary_op op
,
1013 recording::type
*result_type
,
1014 recording::rvalue
*a
)
1016 recording::rvalue
*result
=
1017 new unary_op (this, loc
, op
, result_type
, a
);
1022 /* Create a recording::binary_op instance and add it to this context's
1025 Implements the post-error-checking part of
1026 gcc_jit_context_new_binary_op. */
1029 recording::context::new_binary_op (recording::location
*loc
,
1030 enum gcc_jit_binary_op op
,
1031 recording::type
*result_type
,
1032 recording::rvalue
*a
,
1033 recording::rvalue
*b
)
1035 recording::rvalue
*result
=
1036 new binary_op (this, loc
, op
, result_type
, a
, b
);
1041 /* Create a recording::comparison instance and add it to this context's
1044 Implements the post-error-checking part of
1045 gcc_jit_context_new_comparison. */
1048 recording::context::new_comparison (recording::location
*loc
,
1049 enum gcc_jit_comparison op
,
1050 recording::rvalue
*a
,
1051 recording::rvalue
*b
)
1053 recording::rvalue
*result
= new comparison (this, loc
, op
, a
, b
);
1058 /* Create a recording::cast instance and add it to this context's list
1061 Implements the post-error-checking part of
1062 gcc_jit_context_new_cast. */
1065 recording::context::new_cast (recording::location
*loc
,
1066 recording::rvalue
*expr
,
1067 recording::type
*type_
)
1069 recording::rvalue
*result
= new cast (this, loc
, expr
, type_
);
1074 /* Create a recording::call instance and add it to this context's list
1077 Implements the post-error-checking part of
1078 gcc_jit_context_new_call. */
1081 recording::context::new_call (recording::location
*loc
,
1083 int numargs
, recording::rvalue
**args
)
1085 recording::rvalue
*result
= new call (this, loc
, func
, numargs
, args
);
1090 /* Create a recording::call_through_ptr instance and add it to this
1091 context's list of mementos.
1093 Implements the post-error-checking part of
1094 gcc_jit_context_new_call_through_ptr. */
1097 recording::context::new_call_through_ptr (recording::location
*loc
,
1098 recording::rvalue
*fn_ptr
,
1100 recording::rvalue
**args
)
1102 recording::rvalue
*result
= new call_through_ptr (this, loc
, fn_ptr
, numargs
, args
);
1107 /* Create a recording::array_access instance and add it to this context's list
1110 Implements the post-error-checking part of
1111 gcc_jit_context_new_array_access. */
1114 recording::context::new_array_access (recording::location
*loc
,
1115 recording::rvalue
*ptr
,
1116 recording::rvalue
*index
)
1118 recording::lvalue
*result
= new array_access (this, loc
, ptr
, index
);
1123 /* Create a recording::case_ instance and add it to this context's list
1126 Implements the post-error-checking part of
1127 gcc_jit_context_new_case. */
1130 recording::context::new_case (recording::rvalue
*min_value
,
1131 recording::rvalue
*max_value
,
1132 recording::block
*block
)
1134 recording::case_
*result
= new case_ (this, min_value
, max_value
, block
);
1139 /* Set the given string option for this context, or add an error if
1140 it's not recognized.
1142 Implements the post-error-checking part of
1143 gcc_jit_context_set_str_option. */
1146 recording::context::set_str_option (enum gcc_jit_str_option opt
,
1149 if (opt
< 0 || opt
>= GCC_JIT_NUM_STR_OPTIONS
)
1152 "unrecognized (enum gcc_jit_str_option) value: %i", opt
);
1155 free (m_str_options
[opt
]);
1156 m_str_options
[opt
] = value
? xstrdup (value
) : NULL
;
1157 log_str_option (opt
);
1160 /* Set the given integer option for this context, or add an error if
1161 it's not recognized.
1163 Implements the post-error-checking part of
1164 gcc_jit_context_set_int_option. */
1167 recording::context::set_int_option (enum gcc_jit_int_option opt
,
1170 if (opt
< 0 || opt
>= GCC_JIT_NUM_INT_OPTIONS
)
1173 "unrecognized (enum gcc_jit_int_option) value: %i", opt
);
1176 m_int_options
[opt
] = value
;
1177 log_int_option (opt
);
1180 /* Set the given boolean option for this context, or add an error if
1181 it's not recognized.
1183 Implements the post-error-checking part of
1184 gcc_jit_context_set_bool_option. */
1187 recording::context::set_bool_option (enum gcc_jit_bool_option opt
,
1190 if (opt
< 0 || opt
>= GCC_JIT_NUM_BOOL_OPTIONS
)
1193 "unrecognized (enum gcc_jit_bool_option) value: %i", opt
);
1196 m_bool_options
[opt
] = value
? true : false;
1197 log_bool_option (opt
);
1201 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt
,
1204 gcc_assert (inner_opt
>= 0 && inner_opt
< NUM_INNER_BOOL_OPTIONS
);
1205 m_inner_bool_options
[inner_opt
] = value
? true : false;
1206 log_inner_bool_option (inner_opt
);
1210 /* Add the given optname to this context's list of extra options.
1212 Implements the post-error-checking part of
1213 gcc_jit_context_add_command_line_option. */
1216 recording::context::add_command_line_option (const char *optname
)
1218 m_command_line_options
.safe_push (xstrdup (optname
));
1221 /* Add any user-provided extra options, starting with any from
1223 Called by playback::context::make_fake_args. */
1226 recording::context::append_command_line_options (vec
<char *> *argvec
)
1229 m_parent_ctxt
->append_command_line_options (argvec
);
1233 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1234 argvec
->safe_push (xstrdup (optname
));
1237 /* Add the given dumpname/out_ptr pair to this context's list of requested
1240 Implements the post-error-checking part of
1241 gcc_jit_context_enable_dump. */
1244 recording::context::enable_dump (const char *dumpname
,
1248 gcc_assert (dumpname
);
1249 gcc_assert (out_ptr
);
1251 d
.m_dumpname
= dumpname
;
1252 d
.m_out_ptr
= out_ptr
;
1254 m_requested_dumps
.safe_push (d
);
1257 /* Validate this context, and if it passes, compile it to memory
1260 Implements the post-error-checking part of
1261 gcc_jit_context_compile. */
1264 recording::context::compile ()
1266 JIT_LOG_SCOPE (get_logger ());
1272 if (errors_occurred ())
1275 /* Set up a compile_to_memory playback context. */
1276 ::gcc::jit::playback::compile_to_memory
replayer (this);
1279 replayer
.compile ();
1281 /* Get the jit::result (or NULL) from the
1282 compile_to_memory playback context. */
1283 return replayer
.get_result_obj ();
1286 /* Validate this context, and if it passes, compile it to a file
1289 Implements the post-error-checking part of
1290 gcc_jit_context_compile_to_file. */
1293 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind
,
1294 const char *output_path
)
1296 JIT_LOG_SCOPE (get_logger ());
1302 if (errors_occurred ())
1305 /* Set up a compile_to_file playback context. */
1306 ::gcc::jit::playback::compile_to_file
replayer (this,
1311 replayer
.compile ();
1314 /* Format the given error using printf's conventions, print
1315 it to stderr, and add it to the context. */
1318 recording::context::add_error (location
*loc
, const char *fmt
, ...)
1322 add_error_va (loc
, fmt
, ap
);
1326 /* Format the given error using printf's conventions, print
1327 it to stderr, and add it to the context. */
1330 recording::context::add_error_va (location
*loc
, const char *fmt
, va_list ap
)
1337 JIT_LOG_SCOPE (get_logger ());
1339 len
= vasprintf (&malloced_msg
, fmt
, ap
);
1340 if (malloced_msg
== NULL
|| len
< 0)
1342 errmsg
= "out of memory generating error message";
1343 has_ownership
= false;
1347 errmsg
= malloced_msg
;
1348 has_ownership
= true;
1351 get_logger ()->log ("error %i: %s", m_error_count
, errmsg
);
1353 const char *ctxt_progname
=
1354 get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
1356 ctxt_progname
= "libgccjit.so";
1359 fprintf (stderr
, "%s: %s: error: %s\n",
1361 loc
->get_debug_string (),
1364 fprintf (stderr
, "%s: error: %s\n",
1370 m_first_error_str
= const_cast <char *> (errmsg
);
1371 m_owns_first_error_str
= has_ownership
;
1374 if (m_owns_last_error_str
)
1375 if (m_last_error_str
!= m_first_error_str
)
1376 free (m_last_error_str
);
1377 m_last_error_str
= const_cast <char *> (errmsg
);
1378 m_owns_last_error_str
= has_ownership
;
1383 /* Get the message for the first error that occurred on this context, or
1384 NULL if no errors have occurred on it.
1386 Implements the post-error-checking part of
1387 gcc_jit_context_get_first_error. */
1390 recording::context::get_first_error () const
1392 return m_first_error_str
;
1395 /* Get the message for the last error that occurred on this context, or
1396 NULL if no errors have occurred on it.
1398 Implements the post-error-checking part of
1399 gcc_jit_context_get_last_error. */
1402 recording::context::get_last_error () const
1404 return m_last_error_str
;
1407 /* Lazily generate and record a recording::type representing an opaque
1408 struct named "FILE".
1410 For use if client code tries to dereference the result of
1411 get_type (GCC_JIT_TYPE_FILE_PTR). */
1414 recording::context::get_opaque_FILE_type ()
1417 m_FILE_type
= new_struct_type (NULL
, "FILE");
1421 /* Dump a C-like representation of the given context to the given path.
1422 If UPDATE_LOCATIONS is true, update the locations within the
1423 context's mementos to point to the dumpfile.
1425 Implements the post-error-checking part of
1426 gcc_jit_context_dump_to_file. */
1429 recording::context::dump_to_file (const char *path
, bool update_locations
)
1432 dump
d (*this, path
, update_locations
);
1434 /* Forward declaration of structs and unions. */
1436 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1438 d
.write ("%s;\n\n", st
->get_debug_string ());
1441 /* Content of structs, where set. */
1442 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1443 if (st
->get_fields ())
1445 st
->get_fields ()->write_to_dump (d
);
1451 FOR_EACH_VEC_ELT (m_globals
, i
, g
)
1453 g
->write_to_dump (d
);
1455 if (!m_globals
.is_empty ())
1459 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1461 fn
->write_to_dump (d
);
1465 static const char * const
1466 str_option_reproducer_strings
[GCC_JIT_NUM_STR_OPTIONS
] = {
1467 "GCC_JIT_STR_OPTION_PROGNAME"
1470 static const char * const
1471 int_option_reproducer_strings
[GCC_JIT_NUM_INT_OPTIONS
] = {
1472 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1475 static const char * const
1476 bool_option_reproducer_strings
[GCC_JIT_NUM_BOOL_OPTIONS
] = {
1477 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1478 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1479 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1480 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1481 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1482 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1483 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1484 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1487 static const char * const
1488 inner_bool_option_reproducer_strings
[NUM_INNER_BOOL_OPTIONS
] = {
1489 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1490 "gcc_jit_context_set_bool_use_external_driver"
1493 /* Write the current value of all options to the log file (if any). */
1496 recording::context::log_all_options () const
1503 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1504 log_str_option ((enum gcc_jit_str_option
)opt_idx
);
1506 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1507 log_int_option ((enum gcc_jit_int_option
)opt_idx
);
1509 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1510 log_bool_option ((enum gcc_jit_bool_option
)opt_idx
);
1511 for (opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1512 log_inner_bool_option ((enum inner_bool_option
)opt_idx
);
1515 /* Write the current value of the given string option to the
1516 log file (if any). */
1519 recording::context::log_str_option (enum gcc_jit_str_option opt
) const
1521 gcc_assert (opt
< GCC_JIT_NUM_STR_OPTIONS
);
1524 if (m_str_options
[opt
])
1526 str_option_reproducer_strings
[opt
],
1527 m_str_options
[opt
]);
1530 str_option_reproducer_strings
[opt
]);
1534 /* Write the current value of the given int option to the
1535 log file (if any). */
1538 recording::context::log_int_option (enum gcc_jit_int_option opt
) const
1540 gcc_assert (opt
< GCC_JIT_NUM_INT_OPTIONS
);
1543 int_option_reproducer_strings
[opt
],
1544 m_int_options
[opt
]);
1547 /* Write the current value of the given bool option to the
1548 log file (if any). */
1551 recording::context::log_bool_option (enum gcc_jit_bool_option opt
) const
1553 gcc_assert (opt
< GCC_JIT_NUM_BOOL_OPTIONS
);
1556 bool_option_reproducer_strings
[opt
],
1557 m_bool_options
[opt
] ? "true" : "false");
1560 /* Write the current value of the given "inner" bool option to the
1561 log file (if any). */
1564 recording::context::log_inner_bool_option (enum inner_bool_option opt
) const
1566 gcc_assert (opt
< NUM_INNER_BOOL_OPTIONS
);
1569 inner_bool_option_reproducer_strings
[opt
],
1570 m_inner_bool_options
[opt
] ? "true" : "false");
1573 /* Write C source code to PATH that attempts to replay the API
1574 calls made to this context (and its parents), for use in
1575 minimizing test cases for libgccjit.
1577 Implements the post-error-checking part of
1578 gcc_jit_context_dump_reproducer_to_file. */
1581 recording::context::dump_reproducer_to_file (const char *path
)
1583 JIT_LOG_SCOPE (get_logger ());
1584 reproducer
r (*this, path
);
1586 /* Generate the "ancestry" of this context, as a list. */
1587 auto_vec
<context
*> ascending_contexts
;
1588 for (context
*ctxt
= this; ctxt
; ctxt
= ctxt
->m_parent_ctxt
)
1589 ascending_contexts
.safe_push (ctxt
);
1591 /* Reverse the list, giving a list of contexts from
1592 top-most parent context down through to youngest child context.
1593 We will use this list as the parameters of the functions in
1594 our generated file. */
1595 unsigned num_ctxts
= ascending_contexts
.length ();
1596 auto_vec
<context
*> contexts (num_ctxts
);
1597 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1598 contexts
.safe_push (ascending_contexts
[num_ctxts
- (i
+ 1)]);
1600 /* contexts[0] should be the top-level context. */
1601 gcc_assert (contexts
[0]);
1602 gcc_assert (contexts
[0]->m_toplevel_ctxt
== contexts
[0]);
1604 /* The final element in contexts should be "this". */
1605 gcc_assert (contexts
[contexts
.length () - 1] == this);
1606 gcc_assert (contexts
[contexts
.length () - 1]->m_toplevel_ctxt
1609 r
.write ("/* This code was autogenerated by"
1610 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1611 print_version (r
.get_file (), " ", false);
1613 r
.write ("#include <libgccjit.h>\n\n");
1614 r
.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1615 r
.write ("static void\nset_options (");
1616 r
.write_params (contexts
);
1618 r
.write ("static void\ncreate_code (");
1619 r
.write_params (contexts
);
1621 r
.write ("int\nmain (int argc, const char **argv)\n");
1623 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1624 r
.write (" gcc_jit_context *%s;\n",
1625 r
.get_identifier (contexts
[i
]));
1626 r
.write (" gcc_jit_result *result;\n"
1629 /* Create the contexts.
1630 The top-level context is acquired from a clean slate, the others as
1631 children of the prior context. */
1632 r
.write (" %s = gcc_jit_context_acquire ();\n",
1633 r
.get_identifier (contexts
[0]));
1634 for (unsigned i
= 1; i
< num_ctxts
; i
++)
1635 r
.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1636 r
.get_identifier (contexts
[i
]),
1637 r
.get_identifier (contexts
[i
- 1]));
1638 r
.write (" set_options (");
1639 r
.write_args (contexts
);
1641 r
.write (" create_code (");
1642 r
.write_args (contexts
);
1645 r
.write (" result = gcc_jit_context_compile (%s);\n",
1646 r
.get_identifier (this));
1648 for (unsigned i
= num_ctxts
; i
> 0; i
--)
1649 r
.write (" gcc_jit_context_release (%s);\n",
1650 r
.get_identifier (contexts
[i
- 1]));
1652 r
.write (" gcc_jit_result_release (result);\n"
1656 /* Define (char *) variables for use in calls to
1657 gcc_jit_context_enable_dump. */
1658 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1660 if (m_requested_dumps
.length ())
1662 r
.write ("/* Requested dumps for %s. */\n",
1663 r
.get_identifier (contexts
[ctxt_idx
]));
1664 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1665 r
.write ("static char *dump_%p;\n",
1666 (void *)&m_requested_dumps
[i
]);
1671 /* Write out values of options. */
1672 r
.write ("static void\nset_options (");
1673 r
.write_params (contexts
);
1675 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1680 r
.write (" /* Set options for %s. */\n",
1681 r
.get_identifier (contexts
[ctxt_idx
]));
1683 r
.write (" /* String options. */\n");
1684 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1686 r
.write (" gcc_jit_context_set_str_option (%s,\n"
1688 r
.get_identifier (contexts
[ctxt_idx
]),
1689 str_option_reproducer_strings
[opt_idx
]);
1690 if (m_str_options
[opt_idx
])
1691 r
.write (" \"%s\");\n",
1692 m_str_options
[opt_idx
]);
1694 r
.write (" NULL);\n");
1696 r
.write (" /* Int options. */\n");
1697 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1698 r
.write (" gcc_jit_context_set_int_option (%s,\n"
1701 r
.get_identifier (contexts
[ctxt_idx
]),
1702 int_option_reproducer_strings
[opt_idx
],
1703 m_int_options
[opt_idx
]);
1704 r
.write (" /* Boolean options. */\n");
1705 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1706 r
.write (" gcc_jit_context_set_bool_option (%s,\n"
1709 r
.get_identifier (contexts
[ctxt_idx
]),
1710 bool_option_reproducer_strings
[opt_idx
],
1711 m_bool_options
[opt_idx
]);
1712 for (int opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1713 r
.write (" %s (%s, %i);\n",
1714 inner_bool_option_reproducer_strings
[opt_idx
],
1715 r
.get_identifier (contexts
[ctxt_idx
]),
1716 m_inner_bool_options
[opt_idx
]);
1718 if (!m_command_line_options
.is_empty ())
1722 r
.write (" /* User-provided command-line options. */\n");
1723 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1724 r
.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1725 r
.get_identifier (contexts
[ctxt_idx
]),
1729 if (m_requested_dumps
.length ())
1731 r
.write (" /* Requested dumps. */\n");
1732 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1733 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1735 r
.write (" gcc_jit_context_enable_dump (%s,\n"
1738 r
.get_identifier (contexts
[ctxt_idx
]),
1739 m_requested_dumps
[i
].m_dumpname
,
1740 (void *)&m_requested_dumps
[i
]);
1746 r
.write ("static void\ncreate_code (");
1747 r
.write_params (contexts
);
1750 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1757 r
.write (" /* Replay of API calls for %s. */\n",
1758 r
.get_identifier (contexts
[ctxt_idx
]));
1759 FOR_EACH_VEC_ELT (contexts
[ctxt_idx
]->m_mementos
, i
, m
)
1760 m
->write_reproducer (r
);
1765 /* Copy the requested dumps within this context and all ancestors into
1769 recording::context::get_all_requested_dumps (vec
<recording::requested_dump
> *out
)
1772 m_parent_ctxt
->get_all_requested_dumps (out
);
1774 out
->reserve (m_requested_dumps
.length ());
1775 out
->splice (m_requested_dumps
);
1778 /* This is a pre-compilation check for the context (and any parents).
1780 Detect errors within the context, adding errors if any are found. */
1783 recording::context::validate ()
1785 JIT_LOG_SCOPE (get_logger ());
1788 m_parent_ctxt
->validate ();
1792 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1796 /* The implementation of class gcc::jit::recording::memento. */
1798 /* Get a (const char *) debug description of the given memento, by
1799 calling the pure-virtual make_debug_string hook, caching the
1802 It is intended that this should only be called in debugging and
1803 error-handling paths, so this doesn't need to be particularly
1807 recording::memento::get_debug_string ()
1809 if (!m_debug_string
)
1810 m_debug_string
= make_debug_string ();
1811 return m_debug_string
->c_str ();
1814 /* Default implementation of recording::memento::write_to_dump, writing
1815 an indented form of the memento's debug string to the dump. */
1818 recording::memento::write_to_dump (dump
&d
)
1820 d
.write(" %s\n", get_debug_string ());
1823 /* The implementation of class gcc::jit::recording::string. */
1825 /* Constructor for gcc::jit::recording::string::string, allocating a
1826 copy of the given text using new char[]. */
1828 recording::string::string (context
*ctxt
, const char *text
)
1831 m_len
= strlen (text
);
1832 m_buffer
= new char[m_len
+ 1];
1833 strcpy (m_buffer
, text
);
1836 /* Destructor for gcc::jit::recording::string::string. */
1838 recording::string::~string ()
1843 /* Function for making gcc::jit::recording::string instances on a
1844 context via printf-style formatting.
1846 It is intended that this should only be called in debugging and
1847 error-handling paths, so this doesn't need to be particularly
1848 optimized, hence the double-copy of the string is acceptable. */
1851 recording::string::from_printf (context
*ctxt
, const char *fmt
, ...)
1856 recording::string
*result
;
1859 len
= vasprintf (&buf
, fmt
, ap
);
1862 if (buf
== NULL
|| len
< 0)
1864 ctxt
->add_error (NULL
, "malloc failure");
1868 result
= ctxt
->new_string (buf
);
1873 /* Implementation of recording::memento::make_debug_string for strings,
1874 wrapping the given string in quotes and escaping as necessary. */
1877 recording::string::make_debug_string ()
1879 /* Hack to avoid infinite recursion into strings when logging all
1880 mementos: don't re-escape strings: */
1881 if (m_buffer
[0] == '"')
1884 /* Wrap in quotes and do escaping etc */
1886 size_t sz
= (1 /* opening quote */
1887 + (m_len
* 2) /* each char might get escaped */
1888 + 1 /* closing quote */
1889 + 1); /* nil termintator */
1890 char *tmp
= new char[sz
];
1893 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1894 APPEND('"'); /* opening quote */
1895 for (size_t i
= 0; i
< m_len
; i
++)
1897 char ch
= m_buffer
[i
];
1898 if (ch
== '\t' || ch
== '\n' || ch
== '\\' || ch
== '"')
1902 APPEND('"'); /* closing quote */
1904 tmp
[len
] = '\0'; /* nil termintator */
1906 string
*result
= m_ctxt
->new_string (tmp
);
1912 /* Implementation of recording::memento::write_reproducer for strings. */
1915 recording::string::write_reproducer (reproducer
&)
1920 /* The implementation of class gcc::jit::recording::location. */
1922 /* Implementation of recording::memento::replay_into for locations.
1924 Create a new playback::location and store it into the
1925 recording::location's m_playback_obj field. */
1928 recording::location::replay_into (replayer
*r
)
1930 m_playback_obj
= r
->new_location (this,
1931 m_filename
->c_str (),
1936 /* Implementation of recording::memento::make_debug_string for locations,
1937 turning them into the usual form:
1938 FILENAME:LINE:COLUMN
1939 like we do when emitting diagnostics. */
1942 recording::location::make_debug_string ()
1944 return string::from_printf (m_ctxt
,
1946 m_filename
->c_str (), m_line
, m_column
);
1949 /* Implementation of recording::memento::write_reproducer for locations. */
1952 recording::location::write_reproducer (reproducer
&r
)
1954 const char *id
= r
.make_identifier (this, "loc");
1955 r
.write (" gcc_jit_location *%s =\n"
1956 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1957 " %s, /* const char *filename */\n"
1958 " %i, /* int line */\n"
1959 " %i);/* int column */\n",
1961 r
.get_identifier (get_context ()),
1962 m_filename
->get_debug_string (),
1966 /* The implementation of class gcc::jit::recording::type. */
1968 /* Given a type T, get the type T*.
1970 If this doesn't already exist, generate a new memento_of_get_pointer
1971 instance and add it to this type's context's list of mementos.
1973 Otherwise, use the cached type.
1975 Implements the post-error-checking part of
1976 gcc_jit_type_get_pointer. */
1979 recording::type::get_pointer ()
1981 if (!m_pointer_to_this_type
)
1983 m_pointer_to_this_type
= new memento_of_get_pointer (this);
1984 m_ctxt
->record (m_pointer_to_this_type
);
1986 return m_pointer_to_this_type
;
1989 /* Given a type T, get the type const T.
1991 Implements the post-error-checking part of
1992 gcc_jit_type_get_const. */
1995 recording::type::get_const ()
1997 recording::type
*result
= new memento_of_get_const (this);
1998 m_ctxt
->record (result
);
2002 /* Given a type T, get the type volatile T.
2004 Implements the post-error-checking part of
2005 gcc_jit_type_get_volatile. */
2008 recording::type::get_volatile ()
2010 recording::type
*result
= new memento_of_get_volatile (this);
2011 m_ctxt
->record (result
);
2015 /* Given a type, get an aligned version of the type.
2017 Implements the post-error-checking part of
2018 gcc_jit_type_get_aligned. */
2021 recording::type::get_aligned (size_t alignment_in_bytes
)
2023 recording::type
*result
2024 = new memento_of_get_aligned (this, alignment_in_bytes
);
2025 m_ctxt
->record (result
);
2029 /* Given a type, get a vector version of the type.
2031 Implements the post-error-checking part of
2032 gcc_jit_type_get_vector. */
2035 recording::type::get_vector (size_t num_units
)
2037 recording::type
*result
2038 = new memento_of_get_vector (this, num_units
);
2039 m_ctxt
->record (result
);
2044 recording::type::access_as_type (reproducer
&r
)
2046 return r
.get_identifier (this);
2049 /* Implementation of pure virtual hook recording::type::dereference for
2050 recording::memento_of_get_type. */
2053 recording::memento_of_get_type::dereference ()
2057 default: gcc_unreachable ();
2059 case GCC_JIT_TYPE_VOID
:
2062 case GCC_JIT_TYPE_VOID_PTR
:
2063 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
2065 case GCC_JIT_TYPE_BOOL
:
2066 case GCC_JIT_TYPE_CHAR
:
2067 case GCC_JIT_TYPE_SIGNED_CHAR
:
2068 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2069 case GCC_JIT_TYPE_SHORT
:
2070 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2071 case GCC_JIT_TYPE_INT
:
2072 case GCC_JIT_TYPE_UNSIGNED_INT
:
2073 case GCC_JIT_TYPE_LONG
:
2074 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2075 case GCC_JIT_TYPE_LONG_LONG
:
2076 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2077 case GCC_JIT_TYPE_FLOAT
:
2078 case GCC_JIT_TYPE_DOUBLE
:
2079 case GCC_JIT_TYPE_LONG_DOUBLE
:
2080 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2081 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2082 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2083 /* Not a pointer: */
2086 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2087 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
2089 case GCC_JIT_TYPE_SIZE_T
:
2090 /* Not a pointer: */
2093 case GCC_JIT_TYPE_FILE_PTR
:
2094 /* Give the client code back an opaque "struct FILE". */
2095 return m_ctxt
->get_opaque_FILE_type ();
2099 /* Implementation of pure virtual hook recording::type::is_int for
2100 recording::memento_of_get_type. */
2103 recording::memento_of_get_type::is_int () const
2107 default: gcc_unreachable ();
2109 case GCC_JIT_TYPE_VOID
:
2112 case GCC_JIT_TYPE_VOID_PTR
:
2115 case GCC_JIT_TYPE_BOOL
:
2118 case GCC_JIT_TYPE_CHAR
:
2119 case GCC_JIT_TYPE_SIGNED_CHAR
:
2120 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2121 case GCC_JIT_TYPE_SHORT
:
2122 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2123 case GCC_JIT_TYPE_INT
:
2124 case GCC_JIT_TYPE_UNSIGNED_INT
:
2125 case GCC_JIT_TYPE_LONG
:
2126 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2127 case GCC_JIT_TYPE_LONG_LONG
:
2128 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2131 case GCC_JIT_TYPE_FLOAT
:
2132 case GCC_JIT_TYPE_DOUBLE
:
2133 case GCC_JIT_TYPE_LONG_DOUBLE
:
2136 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2139 case GCC_JIT_TYPE_SIZE_T
:
2142 case GCC_JIT_TYPE_FILE_PTR
:
2145 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2146 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2147 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2152 /* Implementation of pure virtual hook recording::type::is_float for
2153 recording::memento_of_get_type. */
2156 recording::memento_of_get_type::is_float () const
2160 default: gcc_unreachable ();
2162 case GCC_JIT_TYPE_VOID
:
2165 case GCC_JIT_TYPE_VOID_PTR
:
2168 case GCC_JIT_TYPE_BOOL
:
2171 case GCC_JIT_TYPE_CHAR
:
2172 case GCC_JIT_TYPE_SIGNED_CHAR
:
2173 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2174 case GCC_JIT_TYPE_SHORT
:
2175 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2176 case GCC_JIT_TYPE_INT
:
2177 case GCC_JIT_TYPE_UNSIGNED_INT
:
2178 case GCC_JIT_TYPE_LONG
:
2179 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2180 case GCC_JIT_TYPE_LONG_LONG
:
2181 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2184 case GCC_JIT_TYPE_FLOAT
:
2185 case GCC_JIT_TYPE_DOUBLE
:
2186 case GCC_JIT_TYPE_LONG_DOUBLE
:
2189 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2192 case GCC_JIT_TYPE_SIZE_T
:
2195 case GCC_JIT_TYPE_FILE_PTR
:
2198 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2199 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2200 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2205 /* Implementation of pure virtual hook recording::type::is_bool for
2206 recording::memento_of_get_type. */
2209 recording::memento_of_get_type::is_bool () const
2213 default: gcc_unreachable ();
2215 case GCC_JIT_TYPE_VOID
:
2218 case GCC_JIT_TYPE_VOID_PTR
:
2221 case GCC_JIT_TYPE_BOOL
:
2224 case GCC_JIT_TYPE_CHAR
:
2225 case GCC_JIT_TYPE_SIGNED_CHAR
:
2226 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2227 case GCC_JIT_TYPE_SHORT
:
2228 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2229 case GCC_JIT_TYPE_INT
:
2230 case GCC_JIT_TYPE_UNSIGNED_INT
:
2231 case GCC_JIT_TYPE_LONG
:
2232 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2233 case GCC_JIT_TYPE_LONG_LONG
:
2234 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2237 case GCC_JIT_TYPE_FLOAT
:
2238 case GCC_JIT_TYPE_DOUBLE
:
2239 case GCC_JIT_TYPE_LONG_DOUBLE
:
2242 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2245 case GCC_JIT_TYPE_SIZE_T
:
2248 case GCC_JIT_TYPE_FILE_PTR
:
2251 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2252 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2253 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2258 /* Implementation of pure virtual hook recording::memento::replay_into
2259 for recording::memento_of_get_type. */
2262 recording::memento_of_get_type::replay_into (replayer
*r
)
2264 set_playback_obj (r
->get_type (m_kind
));
2267 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2269 /* Descriptive strings for each of enum gcc_jit_types. */
2271 static const char * const get_type_strings
[] = {
2272 "void", /* GCC_JIT_TYPE_VOID */
2273 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2275 "bool", /* GCC_JIT_TYPE_BOOL */
2277 "char", /* GCC_JIT_TYPE_CHAR */
2278 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2279 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2281 "short", /* GCC_JIT_TYPE_SHORT */
2282 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2284 "int", /* GCC_JIT_TYPE_INT */
2285 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2287 "long", /* GCC_JIT_TYPE_LONG */
2288 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2290 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2291 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2293 "float", /* GCC_JIT_TYPE_FLOAT */
2294 "double", /* GCC_JIT_TYPE_DOUBLE */
2295 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2297 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2299 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2301 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2303 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2304 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2305 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2309 /* Implementation of recording::memento::make_debug_string for
2310 results of get_type, using a simple table of type names. */
2313 recording::memento_of_get_type::make_debug_string ()
2315 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
2318 static const char * const get_type_enum_strings
[] = {
2319 "GCC_JIT_TYPE_VOID",
2320 "GCC_JIT_TYPE_VOID_PTR",
2321 "GCC_JIT_TYPE_BOOL",
2322 "GCC_JIT_TYPE_CHAR",
2323 "GCC_JIT_TYPE_SIGNED_CHAR",
2324 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2325 "GCC_JIT_TYPE_SHORT",
2326 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2328 "GCC_JIT_TYPE_UNSIGNED_INT",
2329 "GCC_JIT_TYPE_LONG",
2330 "GCC_JIT_TYPE_UNSIGNED_LONG",
2331 "GCC_JIT_TYPE_LONG_LONG",
2332 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2333 "GCC_JIT_TYPE_FLOAT",
2334 "GCC_JIT_TYPE_DOUBLE",
2335 "GCC_JIT_TYPE_LONG_DOUBLE",
2336 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2337 "GCC_JIT_TYPE_SIZE_T",
2338 "GCC_JIT_TYPE_FILE_PTR",
2339 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2340 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2341 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2345 recording::memento_of_get_type::write_reproducer (reproducer
&r
)
2347 const char *id
= r
.make_identifier (this, "type");
2348 r
.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2350 r
.get_identifier (get_context ()),
2351 get_type_enum_strings
[m_kind
]);
2354 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2356 /* Override of default implementation of
2357 recording::type::accepts_writes_from for get_pointer.
2359 Require a pointer type, and allowing writes to
2360 (const T *) from a (T*), but not the other way around. */
2363 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
2365 /* Must be a pointer type: */
2366 type
*rtype_points_to
= rtype
->is_pointer ();
2367 if (!rtype_points_to
)
2370 /* It's OK to assign to a (const T *) from a (T *). */
2371 return m_other_type
->unqualified ()
2372 ->accepts_writes_from (rtype_points_to
);
2375 /* Implementation of pure virtual hook recording::memento::replay_into
2376 for recording::memento_of_get_pointer. */
2379 recording::memento_of_get_pointer::replay_into (replayer
*)
2381 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
2384 /* Implementation of recording::memento::make_debug_string for
2385 results of get_pointer, adding " *" to the underlying type,
2386 with special-casing to handle function pointer types. */
2389 recording::memento_of_get_pointer::make_debug_string ()
2391 /* Special-case function pointer types, to put the "*" in parens between
2392 the return type and the params (for one level of dereferencing, at
2394 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2395 return fn_type
->make_debug_string_with_ptr ();
2397 return string::from_printf (m_ctxt
,
2398 "%s *", m_other_type
->get_debug_string ());
2401 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2404 recording::memento_of_get_pointer::write_reproducer (reproducer
&r
)
2406 /* We need to special-case function pointer types; see the notes in
2407 recording::function_type::write_deferred_reproducer. */
2408 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2410 fn_type
->write_deferred_reproducer (r
, this);
2414 const char *id
= r
.make_identifier (this, "type");
2415 r
.write (" gcc_jit_type *%s =\n"
2416 " gcc_jit_type_get_pointer (%s);\n",
2418 r
.get_identifier_as_type (m_other_type
));
2421 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2423 /* Implementation of pure virtual hook recording::memento::replay_into
2424 for recording::memento_of_get_const. */
2427 recording::memento_of_get_const::replay_into (replayer
*)
2429 set_playback_obj (m_other_type
->playback_type ()->get_const ());
2432 /* Implementation of recording::memento::make_debug_string for
2433 results of get_const, prepending "const ". */
2436 recording::memento_of_get_const::make_debug_string ()
2438 return string::from_printf (m_ctxt
,
2439 "const %s", m_other_type
->get_debug_string ());
2442 /* Implementation of recording::memento::write_reproducer for const types. */
2445 recording::memento_of_get_const::write_reproducer (reproducer
&r
)
2447 const char *id
= r
.make_identifier (this, "type");
2448 r
.write (" gcc_jit_type *%s =\n"
2449 " gcc_jit_type_get_const (%s);\n",
2451 r
.get_identifier_as_type (m_other_type
));
2454 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2456 /* Implementation of pure virtual hook recording::memento::replay_into
2457 for recording::memento_of_get_volatile. */
2460 recording::memento_of_get_volatile::replay_into (replayer
*)
2462 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
2465 /* Implementation of recording::memento::make_debug_string for
2466 results of get_volatile, prepending "volatile ". */
2469 recording::memento_of_get_volatile::make_debug_string ()
2471 return string::from_printf (m_ctxt
,
2472 "volatile %s", m_other_type
->get_debug_string ());
2475 /* Implementation of recording::memento::write_reproducer for volatile
2479 recording::memento_of_get_volatile::write_reproducer (reproducer
&r
)
2481 const char *id
= r
.make_identifier (this, "type");
2482 r
.write (" gcc_jit_type *%s =\n"
2483 " gcc_jit_type_get_volatile (%s);\n",
2485 r
.get_identifier_as_type (m_other_type
));
2488 /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
2490 /* Implementation of pure virtual hook recording::memento::replay_into
2491 for recording::memento_of_get_aligned. */
2494 recording::memento_of_get_aligned::replay_into (replayer
*)
2497 (m_other_type
->playback_type ()->get_aligned (m_alignment_in_bytes
));
2500 /* Implementation of recording::memento::make_debug_string for
2501 results of get_aligned. */
2504 recording::memento_of_get_aligned::make_debug_string ()
2506 return string::from_printf (m_ctxt
,
2507 "%s __attribute__((aligned(%zi)))",
2508 m_other_type
->get_debug_string (),
2509 m_alignment_in_bytes
);
2512 /* Implementation of recording::memento::write_reproducer for aligned
2516 recording::memento_of_get_aligned::write_reproducer (reproducer
&r
)
2518 const char *id
= r
.make_identifier (this, "type");
2519 r
.write (" gcc_jit_type *%s =\n"
2520 " gcc_jit_type_get_aligned (%s, %zi);\n",
2522 r
.get_identifier_as_type (m_other_type
),
2523 m_alignment_in_bytes
);
2526 /* The implementation of class gcc::jit::recording::memento_of_get_vector. */
2528 /* Implementation of pure virtual hook recording::memento::replay_into
2529 for recording::memento_of_get_vector. */
2532 recording::memento_of_get_vector::replay_into (replayer
*)
2535 (m_other_type
->playback_type ()->get_vector (m_num_units
));
2538 /* Implementation of recording::memento::make_debug_string for
2539 results of get_vector. */
2542 recording::memento_of_get_vector::make_debug_string ()
2544 return string::from_printf
2546 "%s __attribute__((vector_size(sizeof (%s) * %zi)))",
2547 m_other_type
->get_debug_string (),
2548 m_other_type
->get_debug_string (),
2552 /* Implementation of recording::memento::write_reproducer for volatile
2556 recording::memento_of_get_vector::write_reproducer (reproducer
&r
)
2558 const char *id
= r
.make_identifier (this, "type");
2559 r
.write (" gcc_jit_type *%s =\n"
2560 " gcc_jit_type_get_vector (%s, %zi);\n",
2562 r
.get_identifier_as_type (m_other_type
),
2566 /* The implementation of class gcc::jit::recording::array_type */
2568 /* Implementation of pure virtual hook recording::type::dereference for
2569 recording::array_type. */
2572 recording::array_type::dereference ()
2574 return m_element_type
;
2577 /* Implementation of pure virtual hook recording::memento::replay_into
2578 for recording::array_type. */
2581 recording::array_type::replay_into (replayer
*r
)
2583 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
2584 m_element_type
->playback_type (),
2588 /* Implementation of recording::memento::make_debug_string for
2589 results of new_array_type. */
2592 recording::array_type::make_debug_string ()
2594 return string::from_printf (m_ctxt
,
2596 m_element_type
->get_debug_string (),
2600 /* Implementation of recording::memento::write_reproducer for array
2604 recording::array_type::write_reproducer (reproducer
&r
)
2606 const char *id
= r
.make_identifier (this, "array_type");
2607 r
.write (" gcc_jit_type *%s =\n"
2608 " gcc_jit_context_new_array_type (%s,\n"
2609 " %s, /* gcc_jit_location *loc */\n"
2610 " %s, /* gcc_jit_type *element_type */\n"
2611 " %i); /* int num_elements */\n",
2613 r
.get_identifier (get_context ()),
2614 r
.get_identifier (m_loc
),
2615 r
.get_identifier_as_type (m_element_type
),
2619 /* The implementation of class gcc::jit::recording::function_type */
2621 /* Constructor for gcc::jit::recording::function_type. */
2623 recording::function_type::function_type (context
*ctxt
,
2629 m_return_type (return_type
),
2631 m_is_variadic (is_variadic
)
2633 for (int i
= 0; i
< num_params
; i
++)
2634 m_param_types
.safe_push (param_types
[i
]);
2637 /* Implementation of pure virtual hook recording::type::dereference for
2638 recording::function_type. */
2641 recording::function_type::dereference ()
2646 /* Implementation of pure virtual hook recording::memento::replay_into
2647 for recording::function_type. */
2650 recording::function_type::replay_into (replayer
*r
)
2652 /* Convert m_param_types to a vec of playback type. */
2653 auto_vec
<playback::type
*> param_types
;
2655 recording::type
*type
;
2656 param_types
.create (m_param_types
.length ());
2657 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
2658 param_types
.safe_push (type
->playback_type ());
2660 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
2665 /* Special-casing for make_debug_string for get_pointer results for
2666 handling (one level) of pointers to functions. */
2669 recording::function_type::make_debug_string_with_ptr ()
2671 return make_debug_string_with ("(*) ");
2674 /* Implementation of recording::memento::make_debug_string for
2675 results of new_function_type. */
2678 recording::function_type::make_debug_string ()
2680 return make_debug_string_with ("");
2683 /* Build a debug string representation of the form:
2685 RESULT_TYPE INSERT (PARAM_TYPES)
2687 for use when handling 0 and 1 level of indirection to this
2691 recording::function_type::make_debug_string_with (const char *insert
)
2693 /* First, build a buffer for the arguments. */
2694 /* Calculate length of said buffer. */
2695 size_t sz
= 1; /* nil terminator */
2696 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2698 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
2699 sz
+= 2; /* ", " separator */
2702 sz
+= 5; /* ", ..." separator and ellipsis */
2704 /* Now allocate and populate the buffer. */
2705 char *argbuf
= new char[sz
];
2708 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2710 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
2711 len
+= strlen (m_param_types
[i
]->get_debug_string ());
2712 if (i
+ 1 < m_param_types
.length ())
2714 strcpy (argbuf
+ len
, ", ");
2720 if (m_param_types
.length ())
2722 strcpy (argbuf
+ len
, ", ");
2725 strcpy (argbuf
+ len
, "...");
2730 /* ...and use it to get the string for the call as a whole. */
2731 string
*result
= string::from_printf (m_ctxt
,
2733 m_return_type
->get_debug_string (),
2742 /* Implementation of recording::memento::write_reproducer for function
2746 recording::function_type::write_reproducer (reproducer
&)
2748 /* see notes below. */
2751 /* There's a get_pointer within context::new_function_ptr_type:
2752 the type received by client code isn't the memento for the
2753 function_type, but instead the result of get_pointer on it.
2755 Hence we can't directly write a reproducer that gives function_type.
2756 Instead we special-case things within get_pointer, detecting this
2757 case, calling the following function. */
2760 recording::function_type::write_deferred_reproducer (reproducer
&r
,
2763 gcc_assert (ptr_type
);
2764 r
.make_identifier (this, "function_type");
2765 const char *ptr_id
= r
.make_identifier (ptr_type
, "ptr_to");
2766 const char *param_types_id
= r
.make_tmp_identifier ("params_for", this);
2767 r
.write (" gcc_jit_type *%s[%i] = {\n",
2769 m_param_types
.length ());
2772 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
2773 r
.write (" %s,\n", r
.get_identifier_as_type (param_type
));
2775 r
.write (" gcc_jit_type *%s =\n"
2776 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2777 " %s, /* gcc_jit_location *loc */\n"
2778 " %s, /* gcc_jit_type *return_type */\n"
2779 " %i, /* int num_params */\n"
2780 " %s, /* gcc_jit_type **param_types */\n"
2781 " %i); /* int is_variadic */\n",
2783 r
.get_identifier (get_context ()),
2784 "NULL", /* location is not stored */
2785 r
.get_identifier_as_type (m_return_type
),
2786 m_param_types
.length (),
2791 /* The implementation of class gcc::jit::recording::field. */
2793 /* Implementation of pure virtual hook recording::memento::replay_into
2794 for recording::field. */
2797 recording::field::replay_into (replayer
*r
)
2799 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
2800 m_type
->playback_type (),
2801 playback_string (m_name
)));
2804 /* Override the default implementation of
2805 recording::memento::write_to_dump. Dump each field
2806 by dumping a line of the form:
2808 so that we can build up a struct/union field-byfield. */
2811 recording::field::write_to_dump (dump
&d
)
2813 d
.write (" %s %s;\n",
2814 m_type
->get_debug_string (),
2818 /* Implementation of recording::memento::make_debug_string for
2819 results of new_field. */
2822 recording::field::make_debug_string ()
2827 /* Implementation of recording::memento::write_reproducer for fields. */
2830 recording::field::write_reproducer (reproducer
&r
)
2832 const char *id
= r
.make_identifier (this, "field");
2833 r
.write(" gcc_jit_field *%s =\n"
2834 " gcc_jit_context_new_field (%s,\n"
2835 " %s, /* gcc_jit_location *loc */\n"
2836 " %s, /* gcc_jit_type *type, */\n"
2837 " %s); /* const char *name */\n",
2839 r
.get_identifier (get_context ()),
2840 r
.get_identifier (m_loc
),
2841 r
.get_identifier_as_type (m_type
),
2842 m_name
->get_debug_string ());
2845 /* The implementation of class gcc::jit::recording::compound_type */
2847 /* The constructor for gcc::jit::recording::compound_type. */
2849 recording::compound_type::compound_type (context
*ctxt
,
2859 /* Set the fields of a compound type.
2861 Implements the post-error-checking part of
2862 gcc_jit_struct_set_fields, and is also used by
2863 gcc_jit_context_new_union_type. */
2866 recording::compound_type::set_fields (location
*loc
,
2868 field
**field_array
)
2871 gcc_assert (NULL
== m_fields
);
2873 m_fields
= new fields (this, num_fields
, field_array
);
2874 m_ctxt
->record (m_fields
);
2877 /* Implementation of pure virtual hook recording::type::dereference for
2878 recording::compound_type. */
2881 recording::compound_type::dereference ()
2883 return NULL
; /* not a pointer */
2886 /* The implementation of class gcc::jit::recording::struct_. */
2888 /* The constructor for gcc::jit::recording::struct_. */
2890 recording::struct_::struct_ (context
*ctxt
,
2893 : compound_type (ctxt
, loc
, name
)
2897 /* Implementation of pure virtual hook recording::memento::replay_into
2898 for recording::struct_. */
2901 recording::struct_::replay_into (replayer
*r
)
2904 r
->new_compound_type (playback_location (r
, get_loc ()),
2905 get_name ()->c_str (),
2906 true /* is_struct */));
2910 recording::struct_::access_as_type (reproducer
&r
)
2912 return r
.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2913 r
.get_identifier (this));
2916 /* Implementation of recording::memento::make_debug_string for
2920 recording::struct_::make_debug_string ()
2922 return string::from_printf (m_ctxt
,
2923 "struct %s", get_name ()->c_str ());
2927 recording::struct_::write_reproducer (reproducer
&r
)
2929 const char *id
= r
.make_identifier (this, "struct");
2930 r
.write (" gcc_jit_struct *%s =\n"
2931 " gcc_jit_context_new_opaque_struct (%s,\n"
2932 " %s, /* gcc_jit_location *loc */\n"
2933 " %s); /* const char *name */\n",
2935 r
.get_identifier (get_context ()),
2936 r
.get_identifier (get_loc ()),
2937 get_name ()->get_debug_string ());
2940 /* The implementation of class gcc::jit::recording::union_. */
2942 /* The constructor for gcc::jit::recording::union_. */
2944 recording::union_::union_ (context
*ctxt
,
2947 : compound_type (ctxt
, loc
, name
)
2951 /* Implementation of pure virtual hook recording::memento::replay_into
2952 for recording::union_. */
2955 recording::union_::replay_into (replayer
*r
)
2958 r
->new_compound_type (playback_location (r
, get_loc ()),
2959 get_name ()->c_str (),
2960 false /* is_struct */));
2963 /* Implementation of recording::memento::make_debug_string for
2967 recording::union_::make_debug_string ()
2969 return string::from_printf (m_ctxt
,
2970 "union %s", get_name ()->c_str ());
2973 /* Implementation of recording::memento::write_reproducer for unions. */
2976 recording::union_::write_reproducer (reproducer
&r
)
2978 const char *id
= r
.make_identifier (this, "union");
2980 const char *fields_id
= r
.make_tmp_identifier ("fields_for", this);
2981 r
.write (" gcc_jit_field *%s[%i] = {\n",
2983 get_fields ()->length ());
2984 for (int i
= 0; i
< get_fields ()->length (); i
++)
2985 r
.write (" %s,\n", r
.get_identifier (get_fields ()->get_field (i
)));
2988 r
.write (" gcc_jit_type *%s =\n"
2989 " gcc_jit_context_new_union_type (%s,\n"
2990 " %s, /* gcc_jit_location *loc */\n"
2991 " %s, /* const char *name */\n"
2992 " %i, /* int num_fields */\n"
2993 " %s); /* gcc_jit_field **fields */\n",
2995 r
.get_identifier (get_context ()),
2996 r
.get_identifier (get_loc ()),
2997 get_name ()->get_debug_string (),
2998 get_fields ()->length (),
3002 /* The implementation of class gcc::jit::recording::fields. */
3004 /* The constructor for gcc::jit::recording::fields. */
3006 recording::fields::fields (compound_type
*struct_or_union
,
3009 : memento (struct_or_union
->m_ctxt
),
3010 m_struct_or_union (struct_or_union
),
3013 for (int i
= 0; i
< num_fields
; i
++)
3015 gcc_assert (fields
[i
]->get_container () == NULL
);
3016 fields
[i
]->set_container (m_struct_or_union
);
3017 m_fields
.safe_push (fields
[i
]);
3021 /* Implementation of pure virtual hook recording::memento::replay_into
3022 for recording::fields. */
3025 recording::fields::replay_into (replayer
*)
3027 auto_vec
<playback::field
*> playback_fields
;
3028 playback_fields
.create (m_fields
.length ());
3029 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
3030 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
3031 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
3034 /* Override the default implementation of
3035 recording::memento::write_to_dump by writing a union/struct
3036 declaration of this form:
3048 recording::fields::write_to_dump (dump
&d
)
3053 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
3054 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
3055 f
->write_to_dump (d
);
3059 /* Implementation of recording::memento::write_reproducer for the fields
3063 recording::fields::write_reproducer (reproducer
&r
)
3065 if (m_struct_or_union
)
3066 if (NULL
== m_struct_or_union
->dyn_cast_struct ())
3067 /* We have a union; the fields have already been written by
3068 union::write_reproducer. */
3071 const char *fields_id
= r
.make_identifier (this, "fields");
3072 r
.write (" gcc_jit_field *%s[%i] = {\n",
3074 m_fields
.length ());
3077 FOR_EACH_VEC_ELT (m_fields
, i
, field
)
3078 r
.write (" %s,\n", r
.get_identifier (field
));
3081 r
.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
3082 " %s, /* gcc_jit_location *loc */\n"
3083 " %i, /* int num_fields */\n"
3084 " %s); /* gcc_jit_field **fields */\n",
3085 r
.get_identifier (m_struct_or_union
),
3086 r
.get_identifier ((memento
*)NULL
),
3091 /* Implementation of recording::memento::make_debug_string for
3095 recording::fields::make_debug_string ()
3097 return string::from_printf (m_ctxt
,
3101 /* The implementation of class gcc::jit::recording::rvalue. */
3103 /* Create a recording::access_field_rvalue instance and add it to
3104 the rvalue's context's list of mementos.
3106 Implements the post-error-checking part of
3107 gcc_jit_rvalue_access_field. */
3110 recording::rvalue::access_field (recording::location
*loc
,
3113 recording::rvalue
*result
=
3114 new access_field_rvalue (m_ctxt
, loc
, this, field
);
3115 m_ctxt
->record (result
);
3119 /* Create a recording::dereference_field_rvalue instance and add it to
3120 the rvalue's context's list of mementos.
3122 Implements the post-error-checking part of
3123 gcc_jit_rvalue_dereference_field. */
3126 recording::rvalue::dereference_field (recording::location
*loc
,
3129 recording::lvalue
*result
=
3130 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
3131 m_ctxt
->record (result
);
3135 /* Create a recording::dereference_rvalue instance and add it to the
3136 rvalue's context's list of mementos.
3138 Implements the post-error-checking part of
3139 gcc_jit_rvalue_dereference. */
3142 recording::rvalue::dereference (recording::location
*loc
)
3144 recording::lvalue
*result
=
3145 new dereference_rvalue (m_ctxt
, loc
, this);
3146 m_ctxt
->record (result
);
3150 /* An rvalue visitor, for validating that every rvalue within an expression
3151 trees within "STMT" has the correct scope (e.g. no access to locals
3152 of a different function). */
3154 class rvalue_usage_validator
: public recording::rvalue_visitor
3157 rvalue_usage_validator (const char *api_funcname
,
3158 recording::context
*ctxt
,
3159 recording::statement
*stmt
);
3162 visit (recording::rvalue
*rvalue
) FINAL OVERRIDE
;
3165 const char *m_api_funcname
;
3166 recording::context
*m_ctxt
;
3167 recording::statement
*m_stmt
;
3170 /* The trivial constructor for rvalue_usage_validator. */
3172 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname
,
3173 recording::context
*ctxt
,
3174 recording::statement
*stmt
)
3175 : m_api_funcname (api_funcname
),
3181 /* Verify that the given rvalue is in the correct scope. */
3184 rvalue_usage_validator::visit (recording::rvalue
*rvalue
)
3186 gcc_assert (m_stmt
->get_block ());
3187 recording::function
*stmt_scope
= m_stmt
->get_block ()->get_function ();
3189 /* Most rvalues don't have a scope (only locals and params). */
3190 if (rvalue
->get_scope ())
3192 if (rvalue
->get_scope () != stmt_scope
)
3194 (rvalue
->get_loc (),
3196 " rvalue %s (type: %s)"
3197 " has scope limited to function %s"
3198 " but was used within function %s"
3199 " (in statement: %s)",
3201 rvalue
->get_debug_string (),
3202 rvalue
->get_type ()->get_debug_string (),
3203 rvalue
->get_scope ()->get_debug_string (),
3204 stmt_scope
->get_debug_string (),
3205 m_stmt
->get_debug_string ());
3209 if (rvalue
->dyn_cast_param ())
3211 (rvalue
->get_loc (),
3213 " param %s (type: %s)"
3214 " was used within function %s"
3215 " (in statement: %s)"
3216 " but is not associated with any function",
3218 rvalue
->get_debug_string (),
3219 rvalue
->get_type ()->get_debug_string (),
3220 stmt_scope
->get_debug_string (),
3221 m_stmt
->get_debug_string ());
3225 /* Verify that it's valid to use this rvalue (and all expressions
3226 in the tree below it) within the given statement.
3228 For example, we must reject attempts to use a local from one
3229 function within a different function here, or we'll get
3230 an ICE deep inside toplev::main. */
3233 recording::rvalue::verify_valid_within_stmt (const char *api_funcname
, statement
*s
)
3235 rvalue_usage_validator
v (api_funcname
,
3239 /* Verify that it's OK to use this rvalue within s. */
3242 /* Traverse the expression tree below "this", verifying all rvalues
3244 visit_children (&v
);
3247 /* Set the scope of this rvalue to be the given function. This can only
3248 be done once on a given rvalue. */
3251 recording::rvalue::set_scope (function
*scope
)
3254 gcc_assert (NULL
== m_scope
);
3259 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3261 Instances of rvalue don't need an upcast call. */
3264 recording::rvalue::access_as_rvalue (reproducer
&r
)
3266 return r
.get_identifier (this);
3269 /* Return a debug string for the given rvalue, wrapping it in parentheses
3270 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3271 stronger precedence that this rvalue's precedence.
3285 since MULT has strong precedence than PLUS and MINUS, whereas for:
3297 since PLUS has weaker precedence than MULT and DIVIDE. */
3300 recording::rvalue::get_debug_string_parens (enum precedence outer_prec
)
3302 enum precedence this_prec
= get_precedence ();
3304 /* If this_prec has stronger precedence than outer_prec, we don't
3305 need to wrap this in parens within the outer debug string.
3306 Stronger precedences occur earlier than weaker within the enum,
3307 so this is a less than test. Equal precedences don't need
3309 if (this_prec
<= outer_prec
)
3310 return get_debug_string();
3312 /* Otherwise, we need parentheses. */
3314 /* Lazily-build and cache m_parenthesized_string. */
3315 if (!m_parenthesized_string
)
3317 const char *debug_string
= get_debug_string ();
3318 m_parenthesized_string
= string::from_printf (get_context (),
3322 gcc_assert (m_parenthesized_string
);
3323 return m_parenthesized_string
->c_str ();
3327 /* The implementation of class gcc::jit::recording::lvalue. */
3329 /* Create a recording::new_access_field_of_lvalue instance and add it to
3330 the lvalue's context's list of mementos.
3332 Implements the post-error-checking part of
3333 gcc_jit_lvalue_access_field. */
3336 recording::lvalue::access_field (recording::location
*loc
,
3339 recording::lvalue
*result
=
3340 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
3341 m_ctxt
->record (result
);
3345 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3346 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3350 recording::lvalue::access_as_rvalue (reproducer
&r
)
3352 return r
.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3353 r
.get_identifier (this));
3356 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3357 Instances of lvalue don't need to be upcast. */
3360 recording::lvalue::access_as_lvalue (reproducer
&r
)
3362 return r
.get_identifier (this);
3365 /* Create a recording::get_address_of_lvalue instance and add it to
3366 the lvalue's context's list of mementos.
3368 Implements the post-error-checking part of
3369 gcc_jit_lvalue_get_address. */
3372 recording::lvalue::get_address (recording::location
*loc
)
3374 recording::rvalue
*result
=
3375 new get_address_of_lvalue (m_ctxt
, loc
, this);
3376 m_ctxt
->record (result
);
3380 /* The implementation of class gcc::jit::recording::param. */
3382 /* Implementation of pure virtual hook recording::memento::replay_into
3383 for recording::param. */
3386 recording::param::replay_into (replayer
*r
)
3388 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
3389 m_type
->playback_type (),
3393 /* Implementation of recording::rvalue::access_as_rvalue for params.
3394 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3398 recording::param::access_as_rvalue (reproducer
&r
)
3400 return r
.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3401 r
.get_identifier (this));
3404 /* Implementation of recording::lvalue::access_as_lvalue for params.
3405 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3409 recording::param::access_as_lvalue (reproducer
&r
)
3411 return r
.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3412 r
.get_identifier (this));
3415 /* Implementation of recording::memento::write_reproducer for params. */
3418 recording::param::write_reproducer (reproducer
&r
)
3420 const char *id
= r
.make_identifier (this, "param");
3421 r
.write (" gcc_jit_param *%s =\n"
3422 " gcc_jit_context_new_param (%s,\n"
3423 " %s, /* gcc_jit_location *loc */\n"
3424 " %s, /*gcc_jit_type *type */\n"
3425 " %s); /* const char *name */\n",
3427 r
.get_identifier (get_context ()),
3428 r
.get_identifier (m_loc
),
3429 r
.get_identifier_as_type (m_type
),
3430 m_name
->get_debug_string ());
3433 /* The implementation of class gcc::jit::recording::function. */
3435 /* gcc::jit::recording::function's constructor. */
3437 recording::function::function (context
*ctxt
,
3438 recording::location
*loc
,
3439 enum gcc_jit_function_kind kind
,
3441 recording::string
*name
,
3443 recording::param
**params
,
3445 enum built_in_function builtin_id
)
3449 m_return_type (return_type
),
3452 m_is_variadic (is_variadic
),
3453 m_builtin_id (builtin_id
),
3457 for (int i
= 0; i
< num_params
; i
++)
3459 param
*param
= params
[i
];
3462 /* Associate each param with this function.
3464 Verify that the param doesn't already have a function. */
3465 if (param
->get_scope ())
3467 /* We've already rejected attempts to reuse a param between
3468 different functions (within gcc_jit_context_new_function), so
3469 if the param *does* already have a function, it must be being
3470 reused within the params array for this function. We must
3471 produce an error for this reuse (blocking the compile), since
3472 otherwise we'd have an ICE later on. */
3473 gcc_assert (this == param
->get_scope ());
3476 "gcc_jit_context_new_function:"
3477 " parameter %s (type: %s)"
3478 " is used more than once when creating function %s",
3479 param
->get_debug_string (),
3480 param
->get_type ()->get_debug_string (),
3485 /* The normal, non-error case: associate this function with the
3487 param
->set_scope (this);
3490 m_params
.safe_push (param
);
3494 /* Implementation of pure virtual hook recording::memento::replay_into
3495 for recording::function. */
3498 recording::function::replay_into (replayer
*r
)
3500 /* Convert m_params to a vec of playback param. */
3501 auto_vec
<playback::param
*> params
;
3503 recording::param
*param
;
3504 params
.create (m_params
.length ());
3505 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3506 params
.safe_push (param
->playback_param ());
3508 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
3510 m_return_type
->playback_type (),
3517 /* Create a recording::local instance and add it to
3518 the functions's context's list of mementos, and to the function's
3521 Implements the post-error-checking part of
3522 gcc_jit_function_new_local. */
3525 recording::function::new_local (recording::location
*loc
,
3529 local
*result
= new local (this, loc
, type
, new_string (name
));
3530 m_ctxt
->record (result
);
3531 m_locals
.safe_push (result
);
3535 /* Create a recording::block instance and add it to
3536 the functions's context's list of mementos, and to the function's
3539 Implements the post-error-checking part of
3540 gcc_jit_function_new_block. */
3543 recording::function::new_block (const char *name
)
3545 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
3547 recording::block
*result
=
3548 new recording::block (this, m_blocks
.length (), new_string (name
));
3549 m_ctxt
->record (result
);
3550 m_blocks
.safe_push (result
);
3554 /* Override the default implementation of
3555 recording::memento::write_to_dump by dumping a C-like
3556 representation of the function; either like a prototype
3557 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3558 all other kinds of function. */
3561 recording::function::write_to_dump (dump
&d
)
3565 default: gcc_unreachable ();
3566 case GCC_JIT_FUNCTION_EXPORTED
:
3567 case GCC_JIT_FUNCTION_IMPORTED
:
3568 d
.write ("extern ");
3570 case GCC_JIT_FUNCTION_INTERNAL
:
3571 d
.write ("static ");
3573 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
3574 d
.write ("static inline ");
3577 d
.write ("%s\n", m_return_type
->get_debug_string ());
3579 if (d
.update_locations ())
3580 m_loc
= d
.make_location ();
3582 d
.write ("%s (", get_debug_string ());
3585 recording::param
*param
;
3586 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3591 param
->get_type ()->get_debug_string (),
3592 param
->get_debug_string ());
3595 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
3597 d
.write ("; /* (imported) */\n\n");
3607 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
3608 var
->write_to_dump (d
);
3609 if (m_locals
.length ())
3612 /* Write each block: */
3613 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3617 b
->write_to_dump (d
);
3624 /* Pre-compilation validation of a function, for those things we can't
3625 check until the context is (supposedly) fully-populated. */
3628 recording::function::validate ()
3630 /* Complain about empty functions with non-void return type. */
3631 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
3632 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
3633 if (0 == m_blocks
.length ())
3634 m_ctxt
->add_error (m_loc
,
3635 "function %s returns non-void (type: %s)"
3636 " but has no blocks",
3637 get_debug_string (),
3638 m_return_type
->get_debug_string ());
3640 /* Check that all blocks are terminated. */
3641 int num_invalid_blocks
= 0;
3646 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3647 if (!b
->validate ())
3648 num_invalid_blocks
++;
3651 /* Check that all blocks are reachable. */
3652 if (!m_ctxt
->get_inner_bool_option
3653 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS
)
3654 && m_blocks
.length () > 0 && 0 == num_invalid_blocks
)
3656 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3657 flag, starting at the initial block. */
3658 auto_vec
<block
*> worklist (m_blocks
.length ());
3659 worklist
.safe_push (m_blocks
[0]);
3660 while (worklist
.length () > 0)
3662 block
*b
= worklist
.pop ();
3663 b
->m_is_reachable
= true;
3665 /* Add successor blocks that aren't yet marked to the worklist. */
3666 /* We checked that each block has a terminating statement above . */
3667 vec
<block
*> successors
= b
->get_successor_blocks ();
3670 FOR_EACH_VEC_ELT (successors
, i
, succ
)
3671 if (!succ
->m_is_reachable
)
3672 worklist
.safe_push (succ
);
3673 successors
.release ();
3676 /* Now complain about any blocks that haven't been marked. */
3680 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3681 if (!b
->m_is_reachable
)
3682 m_ctxt
->add_error (b
->get_loc (),
3683 "unreachable block: %s",
3684 b
->get_debug_string ());
3689 /* Implements the post-error-checking part of
3690 gcc_jit_function_dump_to_dot. */
3693 recording::function::dump_to_dot (const char *path
)
3695 FILE *fp
= fopen (path
, "w");
3699 pretty_printer the_pp
;
3700 the_pp
.buffer
->stream
= fp
;
3702 pretty_printer
*pp
= &the_pp
;
3705 "digraph %s {\n", get_debug_string ());
3711 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3712 b
->dump_to_dot (pp
);
3719 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3720 b
->dump_edges_to_dot (pp
);
3723 pp_printf (pp
, "}\n");
3728 /* Implementation of recording::memento::make_debug_string for
3732 recording::function::make_debug_string ()
3737 /* A table of enum gcc_jit_function_kind values expressed in string
3740 static const char * const names_of_function_kinds
[] = {
3741 "GCC_JIT_FUNCTION_EXPORTED",
3742 "GCC_JIT_FUNCTION_INTERNAL",
3743 "GCC_JIT_FUNCTION_IMPORTED",
3744 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3747 /* Implementation of recording::memento::write_reproducer for functions. */
3750 recording::function::write_reproducer (reproducer
&r
)
3752 const char *id
= r
.make_identifier (this, "func");
3756 r
.write (" gcc_jit_function *%s =\n"
3757 " gcc_jit_context_get_builtin_function (%s,\n"
3760 r
.get_identifier (get_context ()),
3761 m_name
->get_debug_string ());
3764 const char *params_id
= r
.make_tmp_identifier ("params_for", this);
3765 r
.write (" gcc_jit_param *%s[%i] = {\n",
3767 m_params
.length ());
3770 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3771 r
.write (" %s,\n", r
.get_identifier (param
));
3773 r
.write (" gcc_jit_function *%s =\n"
3774 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3775 " %s, /* gcc_jit_location *loc */\n"
3776 " %s, /* enum gcc_jit_function_kind kind */\n"
3777 " %s, /* gcc_jit_type *return_type */\n"
3778 " %s, /* const char *name */\n"
3779 " %i, /* int num_params */\n"
3780 " %s, /* gcc_jit_param **params */\n"
3781 " %i); /* int is_variadic */\n",
3783 r
.get_identifier (get_context ()),
3784 r
.get_identifier (m_loc
),
3785 names_of_function_kinds
[m_kind
],
3786 r
.get_identifier_as_type (m_return_type
),
3787 m_name
->get_debug_string (),
3794 /* The implementation of class gcc::jit::recording::block. */
3796 /* Create a recording::eval instance and add it to
3797 the block's context's list of mementos, and to the block's
3800 Implements the heart of gcc_jit_block_add_eval. */
3802 recording::statement
*
3803 recording::block::add_eval (recording::location
*loc
,
3804 recording::rvalue
*rvalue
)
3806 statement
*result
= new eval (this, loc
, rvalue
);
3807 m_ctxt
->record (result
);
3808 m_statements
.safe_push (result
);
3812 /* Create a recording::assignment instance and add it to
3813 the block's context's list of mementos, and to the block's
3816 Implements the heart of gcc_jit_block_add_assignment. */
3818 recording::statement
*
3819 recording::block::add_assignment (recording::location
*loc
,
3820 recording::lvalue
*lvalue
,
3821 recording::rvalue
*rvalue
)
3823 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
3824 m_ctxt
->record (result
);
3825 m_statements
.safe_push (result
);
3829 /* Create a recording::assignment_op instance and add it to
3830 the block's context's list of mementos, and to the block's
3833 Implements the heart of gcc_jit_block_add_assignment_op. */
3835 recording::statement
*
3836 recording::block::add_assignment_op (recording::location
*loc
,
3837 recording::lvalue
*lvalue
,
3838 enum gcc_jit_binary_op op
,
3839 recording::rvalue
*rvalue
)
3841 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
3842 m_ctxt
->record (result
);
3843 m_statements
.safe_push (result
);
3847 /* Create a recording::comment instance and add it to
3848 the block's context's list of mementos, and to the block's
3851 Implements the heart of gcc_jit_block_add_comment. */
3853 recording::statement
*
3854 recording::block::add_comment (recording::location
*loc
,
3857 statement
*result
= new comment (this, loc
, new_string (text
));
3858 m_ctxt
->record (result
);
3859 m_statements
.safe_push (result
);
3863 /* Create a recording::end_with_conditional instance and add it to
3864 the block's context's list of mementos, and to the block's
3867 Implements the heart of gcc_jit_block_end_with_conditional. */
3869 recording::statement
*
3870 recording::block::end_with_conditional (recording::location
*loc
,
3871 recording::rvalue
*boolval
,
3872 recording::block
*on_true
,
3873 recording::block
*on_false
)
3875 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
3876 m_ctxt
->record (result
);
3877 m_statements
.safe_push (result
);
3878 m_has_been_terminated
= true;
3882 /* Create a recording::end_with_jump instance and add it to
3883 the block's context's list of mementos, and to the block's
3886 Implements the heart of gcc_jit_block_end_with_jump. */
3888 recording::statement
*
3889 recording::block::end_with_jump (recording::location
*loc
,
3890 recording::block
*target
)
3892 statement
*result
= new jump (this, loc
, target
);
3893 m_ctxt
->record (result
);
3894 m_statements
.safe_push (result
);
3895 m_has_been_terminated
= true;
3899 /* Create a recording::end_with_return instance and add it to
3900 the block's context's list of mementos, and to the block's
3903 Implements the post-error-checking parts of
3904 gcc_jit_block_end_with_return and
3905 gcc_jit_block_end_with_void_return. */
3907 recording::statement
*
3908 recording::block::end_with_return (recording::location
*loc
,
3909 recording::rvalue
*rvalue
)
3911 /* This is used by both gcc_jit_function_add_return and
3912 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3913 the former and NULL for the latter. */
3914 statement
*result
= new return_ (this, loc
, rvalue
);
3915 m_ctxt
->record (result
);
3916 m_statements
.safe_push (result
);
3917 m_has_been_terminated
= true;
3921 /* Create a recording::switch_ instance and add it to
3922 the block's context's list of mementos, and to the block's
3925 Implements the heart of gcc_jit_block_end_with_switch. */
3927 recording::statement
*
3928 recording::block::end_with_switch (recording::location
*loc
,
3929 recording::rvalue
*expr
,
3930 recording::block
*default_block
,
3932 recording::case_
**cases
)
3934 statement
*result
= new switch_ (this, loc
,
3939 m_ctxt
->record (result
);
3940 m_statements
.safe_push (result
);
3941 m_has_been_terminated
= true;
3945 /* Override the default implementation of
3946 recording::memento::write_to_dump for blocks by writing
3947 an unindented block name as a label, followed by the indented
3957 recording::block::write_to_dump (dump
&d
)
3959 d
.write ("%s:\n", get_debug_string ());
3963 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
3964 s
->write_to_dump (d
);
3967 /* Validate a block by ensuring that it has been terminated. */
3970 recording::block::validate ()
3972 /* Check for termination. */
3973 if (!has_been_terminated ())
3975 statement
*stmt
= get_last_statement ();
3976 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
3977 m_func
->get_context ()->add_error (loc
,
3978 "unterminated block in %s: %s",
3979 m_func
->get_debug_string (),
3980 get_debug_string ());
3987 /* Get the source-location of a block by using that of the first
3988 statement within it, if any. */
3990 recording::location
*
3991 recording::block::get_loc () const
3993 recording::statement
*stmt
= get_first_statement ();
3995 return stmt
->get_loc ();
4000 /* Get the first statement within a block, if any. */
4002 recording::statement
*
4003 recording::block::get_first_statement () const
4005 if (m_statements
.length ())
4006 return m_statements
[0];
4011 /* Get the last statement within a block, if any. */
4013 recording::statement
*
4014 recording::block::get_last_statement () const
4016 if (m_statements
.length ())
4017 return m_statements
[m_statements
.length () - 1];
4022 /* Assuming that this block has been terminated, get the successor blocks
4023 as a vector. Ownership of the vector transfers to the caller, which
4024 must call its release () method.
4026 Used when validating functions, and when dumping dot representations
4029 vec
<recording::block
*>
4030 recording::block::get_successor_blocks () const
4032 gcc_assert (m_has_been_terminated
);
4033 statement
*last_statement
= get_last_statement ();
4034 gcc_assert (last_statement
);
4035 return last_statement
->get_successor_blocks ();
4038 /* Implementation of pure virtual hook recording::memento::replay_into
4039 for recording::block. */
4042 recording::block::replay_into (replayer
*)
4044 set_playback_obj (m_func
->playback_function ()
4045 ->new_block (playback_string (m_name
)));
4048 /* Implementation of recording::memento::make_debug_string for
4052 recording::block::make_debug_string ()
4057 return string::from_printf (m_ctxt
,
4058 "<UNNAMED BLOCK %p>",
4062 /* Implementation of recording::memento::write_reproducer for blocks. */
4065 recording::block::write_reproducer (reproducer
&r
)
4067 const char *id
= r
.make_identifier (this, "block");
4068 r
.write (" gcc_jit_block *%s =\n"
4069 " gcc_jit_function_new_block (%s, %s);\n",
4071 r
.get_identifier (m_func
),
4072 m_name
? m_name
->get_debug_string () : "NULL");
4075 /* Dump a block in graphviz form into PP, capturing the block name (if
4076 any) and the statements. */
4079 recording::block::dump_to_dot (pretty_printer
*pp
)
4083 "[shape=record,style=filled,fillcolor=white,label=\"{"),
4085 pp_write_text_to_stream (pp
);
4088 pp_string (pp
, m_name
->c_str ());
4089 pp_string (pp
, ":");
4091 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
4096 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
4098 pp_string (pp
, s
->get_debug_string ());
4100 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
4108 /* Dump the out-edges of the block in graphviz form into PP. */
4111 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
4113 vec
<block
*> successors
= get_successor_blocks ();
4116 FOR_EACH_VEC_ELT (successors
, i
, succ
)
4118 "\tblock_%d:s -> block_%d:n;\n",
4119 m_index
, succ
->m_index
);
4120 successors
.release ();
4123 /* The implementation of class gcc::jit::recording::global. */
4125 /* Implementation of pure virtual hook recording::memento::replay_into
4126 for recording::global. */
4129 recording::global::replay_into (replayer
*r
)
4131 set_playback_obj (r
->new_global (playback_location (r
, m_loc
),
4133 m_type
->playback_type (),
4134 playback_string (m_name
)));
4137 /* Override the default implementation of
4138 recording::memento::write_to_dump for globals.
4139 This will be of the form:
4141 GCC_JIT_GLOBAL_EXPORTED:
4145 GCC_JIT_GLOBAL_INTERNAL:
4147 e.g. "static int foo;"
4149 GCC_JIT_GLOBAL_IMPORTED:
4151 e.g. "extern int foo;"
4153 These are written to the top of the dump by
4154 recording::context::dump_to_file. */
4157 recording::global::write_to_dump (dump
&d
)
4159 if (d
.update_locations ())
4160 m_loc
= d
.make_location ();
4167 case GCC_JIT_GLOBAL_EXPORTED
:
4170 case GCC_JIT_GLOBAL_INTERNAL
:
4171 d
.write ("static ");
4174 case GCC_JIT_GLOBAL_IMPORTED
:
4175 d
.write ("extern ");
4178 d
.write ("%s %s;\n",
4179 m_type
->get_debug_string (),
4180 get_debug_string ());
4183 /* A table of enum gcc_jit_global_kind values expressed in string
4186 static const char * const global_kind_reproducer_strings
[] = {
4187 "GCC_JIT_GLOBAL_EXPORTED",
4188 "GCC_JIT_GLOBAL_INTERNAL",
4189 "GCC_JIT_GLOBAL_IMPORTED"
4192 /* Implementation of recording::memento::write_reproducer for globals. */
4195 recording::global::write_reproducer (reproducer
&r
)
4197 const char *id
= r
.make_identifier (this, "block");
4198 r
.write (" gcc_jit_lvalue *%s =\n"
4199 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4200 " %s, /* gcc_jit_location *loc */\n"
4201 " %s, /* enum gcc_jit_global_kind kind */\n"
4202 " %s, /* gcc_jit_type *type */\n"
4203 " %s); /* const char *name */\n",
4205 r
.get_identifier (get_context ()),
4206 r
.get_identifier (m_loc
),
4207 global_kind_reproducer_strings
[m_kind
],
4208 r
.get_identifier_as_type (get_type ()),
4209 m_name
->get_debug_string ());
4212 /* The implementation of the various const-handling classes:
4213 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4215 /* Explicit specialization of the various mementos we're interested in. */
4216 template class recording::memento_of_new_rvalue_from_const
<int>;
4217 template class recording::memento_of_new_rvalue_from_const
<long>;
4218 template class recording::memento_of_new_rvalue_from_const
<double>;
4219 template class recording::memento_of_new_rvalue_from_const
<void *>;
4221 /* Implementation of the pure virtual hook recording::memento::replay_into
4222 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4224 template <typename HOST_TYPE
>
4227 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
4230 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
4234 /* The make_debug_string and write_reproducer methods vary between the
4236 memento_of_new_rvalue_from_const <HOST_TYPE>
4237 classes, so we explicitly write specializations of them.
4239 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4240 namespaces are written out explicitly, which is why most of this file
4241 doesn't abbreviate things by entering the "recording" namespace.
4243 However, these specializations are required to be in the same namespace
4244 as the template, hence we now have to enter the gcc::jit::recording
4250 /* The make_debug_string specialization for <int>, which renders it as
4251 (TARGET_TYPE)LITERAL
4257 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
4259 return string::from_printf (m_ctxt
,
4261 m_type
->get_debug_string (),
4265 /* The get_wide_int specialization for <int>. */
4269 memento_of_new_rvalue_from_const
<int>::get_wide_int (wide_int
*out
) const
4271 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
4275 /* The write_reproducer specialization for <int>. */
4279 memento_of_new_rvalue_from_const
<int>::write_reproducer (reproducer
&r
)
4281 const char *id
= r
.make_identifier (this, "rvalue");
4282 r
.write (" gcc_jit_rvalue *%s =\n"
4283 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4284 " %s, /* gcc_jit_type *numeric_type */\n"
4285 " %i); /* int value */\n",
4287 r
.get_identifier (get_context ()),
4288 r
.get_identifier_as_type (m_type
),
4292 /* The make_debug_string specialization for <long>, rendering it as
4293 (TARGET_TYPE)LITERAL
4299 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
4301 return string::from_printf (m_ctxt
,
4303 m_type
->get_debug_string (),
4307 /* The get_wide_int specialization for <long>. */
4311 memento_of_new_rvalue_from_const
<long>::get_wide_int (wide_int
*out
) const
4313 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
4317 /* The write_reproducer specialization for <long>. */
4321 recording::memento_of_new_rvalue_from_const
<long>::write_reproducer (reproducer
&r
)
4323 const char *id
= r
.make_identifier (this, "rvalue");
4325 /* We have to special-case LONG_MIN, since e.g.
4326 -9223372036854775808L
4328 -(9223372036854775808L)
4330 error: integer constant is so large that it is unsigned [-Werror]
4331 Workaround this by writing (LONG_MIN + 1) - 1. */
4332 if (m_value
== LONG_MIN
)
4334 r
.write (" gcc_jit_rvalue *%s =\n"
4335 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4336 " %s, /* gcc_jit_type *numeric_type */\n"
4337 " %ldL - 1); /* long value */\n",
4339 r
.get_identifier (get_context ()),
4340 r
.get_identifier_as_type (m_type
),
4345 r
.write (" gcc_jit_rvalue *%s =\n"
4346 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4347 " %s, /* gcc_jit_type *numeric_type */\n"
4348 " %ldL); /* long value */\n",
4350 r
.get_identifier (get_context ()),
4351 r
.get_identifier_as_type (m_type
),
4355 /* The make_debug_string specialization for <double>, rendering it as
4356 (TARGET_TYPE)LITERAL
4362 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
4364 return string::from_printf (m_ctxt
,
4366 m_type
->get_debug_string (),
4370 /* The get_wide_int specialization for <double>. */
4374 memento_of_new_rvalue_from_const
<double>::get_wide_int (wide_int
*) const
4379 /* The write_reproducer specialization for <double>. */
4383 recording::memento_of_new_rvalue_from_const
<double>::write_reproducer (reproducer
&r
)
4385 const char *id
= r
.make_identifier (this, "rvalue");
4386 r
.write (" gcc_jit_rvalue *%s =\n"
4387 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4388 " %s, /* gcc_jit_type *numeric_type */\n"
4389 " %f); /* double value */\n",
4391 r
.get_identifier (get_context ()),
4392 r
.get_identifier_as_type (m_type
),
4396 /* The make_debug_string specialization for <void *>, rendering it as
4401 Zero is rendered as NULL e.g.
4406 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
4408 if (m_value
!= NULL
)
4409 return string::from_printf (m_ctxt
,
4411 m_type
->get_debug_string (), m_value
);
4413 return string::from_printf (m_ctxt
,
4415 m_type
->get_debug_string ());
4418 /* The get_wide_int specialization for <void *>. */
4422 memento_of_new_rvalue_from_const
<void *>::get_wide_int (wide_int
*) const
4427 /* Implementation of recording::memento::write_reproducer for <void *>
4432 memento_of_new_rvalue_from_const
<void *>::write_reproducer (reproducer
&r
)
4434 const char *id
= r
.make_identifier (this, "rvalue");
4436 r
.write (" gcc_jit_rvalue *%s =\n"
4437 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4438 " %s, /* gcc_jit_type *pointer_type */\n"
4439 " (void *)%p); /* void *value */\n",
4441 r
.get_identifier (get_context ()),
4442 r
.get_identifier_as_type (m_type
),
4445 r
.write (" gcc_jit_rvalue *%s =\n"
4446 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4447 " %s); /* gcc_jit_type *pointer_type */\n",
4449 r
.get_identifier (get_context ()),
4450 r
.get_identifier_as_type (m_type
));
4453 /* We're done specializing make_debug_string and write_reproducer, so we
4454 can exit the gcc::jit::recording namespace. */
4456 } // namespace recording
4458 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4460 /* Implementation of pure virtual hook recording::memento::replay_into
4461 for recording::memento_of_new_string_literal. */
4464 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
4466 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
4469 /* Implementation of recording::memento::make_debug_string for
4473 recording::memento_of_new_string_literal::make_debug_string ()
4475 return string::from_printf (m_ctxt
,
4477 m_value
->get_debug_string ());
4480 /* Implementation of recording::memento::write_reproducer for string literal
4484 recording::memento_of_new_string_literal::write_reproducer (reproducer
&r
)
4486 const char *id
= r
.make_identifier (this, "rvalue");
4487 r
.write (" gcc_jit_rvalue *%s =\n"
4488 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4489 " %s); /* const char *value */\n",
4491 r
.get_identifier (get_context ()),
4492 m_value
->get_debug_string ());
4495 /* The implementation of class gcc::jit::recording::unary_op. */
4497 /* Implementation of pure virtual hook recording::memento::replay_into
4498 for recording::unary_op. */
4501 recording::unary_op::replay_into (replayer
*r
)
4503 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
4505 get_type ()->playback_type (),
4506 m_a
->playback_rvalue ()));
4509 /* Implementation of pure virtual hook recording::rvalue::visit_children
4510 for recording::unary_op. */
4512 recording::unary_op::visit_children (rvalue_visitor
*v
)
4517 /* Implementation of recording::memento::make_debug_string for
4520 static const char * const unary_op_strings
[] = {
4521 "-", /* GCC_JIT_UNARY_OP_MINUS */
4522 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4523 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4524 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4528 recording::unary_op::make_debug_string ()
4530 return string::from_printf (m_ctxt
,
4532 unary_op_strings
[m_op
],
4533 m_a
->get_debug_string ());
4536 static const char * const unary_op_reproducer_strings
[] = {
4537 "GCC_JIT_UNARY_OP_MINUS",
4538 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4539 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4540 "GCC_JIT_UNARY_OP_ABS"
4543 /* Implementation of recording::memento::write_reproducer for unary ops. */
4546 recording::unary_op::write_reproducer (reproducer
&r
)
4548 const char *id
= r
.make_identifier (this, "rvalue");
4549 r
.write (" gcc_jit_rvalue *%s =\n"
4550 " gcc_jit_context_new_unary_op (%s,\n"
4551 " %s, /* gcc_jit_location *loc */\n"
4552 " %s, /* enum gcc_jit_unary_op op */\n"
4553 " %s, /* gcc_jit_type *result_type */\n"
4554 " %s); /* gcc_jit_rvalue *a */\n",
4556 r
.get_identifier (get_context ()),
4557 r
.get_identifier (m_loc
),
4558 unary_op_reproducer_strings
[m_op
],
4559 r
.get_identifier_as_type (get_type ()),
4560 r
.get_identifier_as_rvalue (m_a
));
4563 /* The implementation of class gcc::jit::recording::binary_op. */
4565 /* Implementation of pure virtual hook recording::memento::replay_into
4566 for recording::binary_op. */
4569 recording::binary_op::replay_into (replayer
*r
)
4571 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
4573 get_type ()->playback_type (),
4574 m_a
->playback_rvalue (),
4575 m_b
->playback_rvalue ()));
4578 /* Implementation of pure virtual hook recording::rvalue::visit_children
4579 for recording::binary_op. */
4581 recording::binary_op::visit_children (rvalue_visitor
*v
)
4587 /* Implementation of recording::memento::make_debug_string for
4590 static const char * const binary_op_strings
[] = {
4591 "+", /* GCC_JIT_BINARY_OP_PLUS */
4592 "-", /* GCC_JIT_BINARY_OP_MINUS */
4593 "*", /* GCC_JIT_BINARY_OP_MULT */
4594 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4595 "%", /* GCC_JIT_BINARY_OP_MODULO */
4596 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4597 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4598 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4599 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4600 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4601 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4602 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4606 recording::binary_op::make_debug_string ()
4608 enum precedence prec
= get_precedence ();
4609 return string::from_printf (m_ctxt
,
4611 m_a
->get_debug_string_parens (prec
),
4612 binary_op_strings
[m_op
],
4613 m_b
->get_debug_string_parens (prec
));
4616 static const char * const binary_op_reproducer_strings
[] = {
4617 "GCC_JIT_BINARY_OP_PLUS",
4618 "GCC_JIT_BINARY_OP_MINUS",
4619 "GCC_JIT_BINARY_OP_MULT",
4620 "GCC_JIT_BINARY_OP_DIVIDE",
4621 "GCC_JIT_BINARY_OP_MODULO",
4622 "GCC_JIT_BINARY_OP_BITWISE_AND",
4623 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4624 "GCC_JIT_BINARY_OP_BITWISE_OR",
4625 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4626 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4627 "GCC_JIT_BINARY_OP_LSHIFT",
4628 "GCC_JIT_BINARY_OP_RSHIFT"
4631 /* Implementation of recording::memento::write_reproducer for binary ops. */
4634 recording::binary_op::write_reproducer (reproducer
&r
)
4636 const char *id
= r
.make_identifier (this, "rvalue");
4637 r
.write (" gcc_jit_rvalue *%s =\n"
4638 " gcc_jit_context_new_binary_op (%s,\n"
4639 " %s, /* gcc_jit_location *loc */\n"
4640 " %s, /* enum gcc_jit_binary_op op */\n"
4641 " %s, /* gcc_jit_type *result_type */\n"
4642 " %s, /* gcc_jit_rvalue *a */\n"
4643 " %s); /* gcc_jit_rvalue *b */\n",
4645 r
.get_identifier (get_context ()),
4646 r
.get_identifier (m_loc
),
4647 binary_op_reproducer_strings
[m_op
],
4648 r
.get_identifier_as_type (get_type ()),
4649 r
.get_identifier_as_rvalue (m_a
),
4650 r
.get_identifier_as_rvalue (m_b
));
4653 namespace recording
{
4654 static const enum precedence binary_op_precedence
[] = {
4655 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_PLUS */
4656 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_MINUS */
4658 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MULT */
4659 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_DIVIDE */
4660 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MODULO */
4662 PRECEDENCE_BITWISE_AND
, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4663 PRECEDENCE_BITWISE_XOR
, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4664 PRECEDENCE_BITWISE_IOR
, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4665 PRECEDENCE_LOGICAL_AND
, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4666 PRECEDENCE_LOGICAL_OR
, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4667 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_LSHIFT */
4668 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_RSHIFT */
4670 } /* namespace recording */
4672 enum recording::precedence
4673 recording::binary_op::get_precedence () const
4675 return binary_op_precedence
[m_op
];
4678 /* The implementation of class gcc::jit::recording::comparison. */
4680 /* Implementation of recording::memento::make_debug_string for
4683 static const char * const comparison_strings
[] =
4685 "==", /* GCC_JIT_COMPARISON_EQ */
4686 "!=", /* GCC_JIT_COMPARISON_NE */
4687 "<", /* GCC_JIT_COMPARISON_LT */
4688 "<=", /* GCC_JIT_COMPARISON_LE */
4689 ">", /* GCC_JIT_COMPARISON_GT */
4690 ">=", /* GCC_JIT_COMPARISON_GE */
4694 recording::comparison::make_debug_string ()
4696 enum precedence prec
= get_precedence ();
4697 return string::from_printf (m_ctxt
,
4699 m_a
->get_debug_string_parens (prec
),
4700 comparison_strings
[m_op
],
4701 m_b
->get_debug_string_parens (prec
));
4704 /* A table of enum gcc_jit_comparison values expressed in string
4707 static const char * const comparison_reproducer_strings
[] =
4709 "GCC_JIT_COMPARISON_EQ",
4710 "GCC_JIT_COMPARISON_NE",
4711 "GCC_JIT_COMPARISON_LT",
4712 "GCC_JIT_COMPARISON_LE",
4713 "GCC_JIT_COMPARISON_GT",
4714 "GCC_JIT_COMPARISON_GE"
4717 /* Implementation of recording::memento::write_reproducer for comparisons. */
4720 recording::comparison::write_reproducer (reproducer
&r
)
4722 const char *id
= r
.make_identifier (this, "rvalue");
4723 r
.write (" gcc_jit_rvalue *%s =\n"
4724 " gcc_jit_context_new_comparison (%s,\n"
4725 " %s, /* gcc_jit_location *loc */\n"
4726 " %s, /* enum gcc_jit_comparison op */\n"
4727 " %s, /* gcc_jit_rvalue *a */\n"
4728 " %s); /* gcc_jit_rvalue *b */\n",
4730 r
.get_identifier (get_context ()),
4731 r
.get_identifier (m_loc
),
4732 comparison_reproducer_strings
[m_op
],
4733 r
.get_identifier_as_rvalue (m_a
),
4734 r
.get_identifier_as_rvalue (m_b
));
4737 /* Implementation of pure virtual hook recording::memento::replay_into
4738 for recording::comparison. */
4741 recording::comparison::replay_into (replayer
*r
)
4743 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
4745 m_a
->playback_rvalue (),
4746 m_b
->playback_rvalue ()));
4749 /* Implementation of pure virtual hook recording::rvalue::visit_children
4750 for recording::comparison. */
4753 recording::comparison::visit_children (rvalue_visitor
*v
)
4759 namespace recording
{
4760 static const enum precedence comparison_precedence
[] =
4762 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_EQ */
4763 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_NE */
4765 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LT */
4766 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LE */
4767 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GT */
4768 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GE */
4770 } /* namespace recording */
4772 enum recording::precedence
4773 recording::comparison::get_precedence () const
4775 return comparison_precedence
[m_op
];
4778 /* Implementation of pure virtual hook recording::memento::replay_into
4779 for recording::cast. */
4782 recording::cast::replay_into (replayer
*r
)
4784 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
4785 m_rvalue
->playback_rvalue (),
4786 get_type ()->playback_type ()));
4789 /* Implementation of pure virtual hook recording::rvalue::visit_children
4790 for recording::cast. */
4792 recording::cast::visit_children (rvalue_visitor
*v
)
4794 v
->visit (m_rvalue
);
4797 /* Implementation of recording::memento::make_debug_string for
4801 recording::cast::make_debug_string ()
4803 enum precedence prec
= get_precedence ();
4804 return string::from_printf (m_ctxt
,
4806 get_type ()->get_debug_string (),
4807 m_rvalue
->get_debug_string_parens (prec
));
4810 /* Implementation of recording::memento::write_reproducer for casts. */
4813 recording::cast::write_reproducer (reproducer
&r
)
4815 const char *id
= r
.make_identifier (this, "rvalue");
4816 r
.write (" gcc_jit_rvalue *%s =\n"
4817 " gcc_jit_context_new_cast (%s,\n"
4818 " %s, /* gcc_jit_location *loc */\n"
4819 " %s, /* gcc_jit_rvalue *rvalue */\n"
4820 " %s); /* gcc_jit_type *type */\n",
4822 r
.get_identifier (get_context ()),
4823 r
.get_identifier (m_loc
),
4824 r
.get_identifier_as_rvalue (m_rvalue
),
4825 r
.get_identifier_as_type (get_type ()));
4828 /* The implementation of class gcc::jit::recording::base_call. */
4830 /* The constructor for gcc::jit::recording::base_call. */
4832 recording::base_call::base_call (context
*ctxt
,
4837 : rvalue (ctxt
, loc
, type_
),
4839 m_require_tail_call (0)
4841 for (int i
= 0; i
< numargs
; i
++)
4842 m_args
.safe_push (args
[i
]);
4845 /* Subroutine for use by call and call_though_ptr's write_reproducer
4849 recording::base_call::write_reproducer_tail_call (reproducer
&r
,
4852 if (m_require_tail_call
)
4854 r
.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
4855 " %i); /* int require_tail_call*/\n",
4861 /* The implementation of class gcc::jit::recording::call. */
4863 /* The constructor for gcc::jit::recording::call. */
4865 recording::call::call (recording::context
*ctxt
,
4866 recording::location
*loc
,
4867 recording::function
*func
,
4870 : base_call (ctxt
, loc
, func
->get_return_type (), numargs
, args
),
4875 /* Implementation of pure virtual hook recording::memento::replay_into
4876 for recording::call. */
4879 recording::call::replay_into (replayer
*r
)
4881 auto_vec
<playback::rvalue
*> playback_args
;
4882 playback_args
.create (m_args
.length ());
4883 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4884 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
4886 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
4887 m_func
->playback_function (),
4889 m_require_tail_call
));
4892 /* Implementation of pure virtual hook recording::rvalue::visit_children
4893 for recording::call. */
4896 recording::call::visit_children (rvalue_visitor
*v
)
4898 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4899 v
->visit (m_args
[i
]);
4902 /* Implementation of recording::memento::make_debug_string for
4906 recording::call::make_debug_string ()
4908 enum precedence prec
= get_precedence ();
4909 /* First, build a buffer for the arguments. */
4910 /* Calculate length of said buffer. */
4911 size_t sz
= 1; /* nil terminator */
4912 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4914 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4915 sz
+= 2; /* ", " separator */
4918 /* Now allocate and populate the buffer. */
4919 char *argbuf
= new char[sz
];
4922 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4924 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
4925 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
4926 if (i
+ 1 < m_args
.length ())
4928 strcpy (argbuf
+ len
, ", ");
4934 /* ...and use it to get the string for the call as a whole. */
4935 string
*result
= string::from_printf (m_ctxt
,
4937 m_func
->get_debug_string (),
4946 recording::call::write_reproducer (reproducer
&r
)
4948 const char *id
= r
.make_identifier (this, "call");
4949 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
4950 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4953 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4954 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
4956 r
.write (" gcc_jit_rvalue *%s =\n"
4957 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4958 " %s, /* gcc_jit_location *loc */\n"
4959 " %s, /* gcc_jit_function *func */\n"
4960 " %i, /* int numargs */ \n"
4961 " %s); /* gcc_jit_rvalue **args*/\n",
4963 r
.get_identifier (get_context ()),
4964 r
.get_identifier (m_loc
),
4965 r
.get_identifier (m_func
),
4968 write_reproducer_tail_call (r
, id
);
4971 /* The implementation of class gcc::jit::recording::call_through_ptr. */
4973 /* The constructor for recording::call_through_ptr. */
4975 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
4976 recording::location
*loc
,
4977 recording::rvalue
*fn_ptr
,
4980 : base_call (ctxt
, loc
,
4981 fn_ptr
->get_type ()->dereference ()
4982 ->as_a_function_type ()->get_return_type (),
4988 /* Implementation of pure virtual hook recording::memento::replay_into
4989 for recording::call_through_ptr. */
4992 recording::call_through_ptr::replay_into (replayer
*r
)
4994 auto_vec
<playback::rvalue
*> playback_args
;
4995 playback_args
.create (m_args
.length ());
4996 for (unsigned i
= 0; i
< m_args
.length (); i
++)
4997 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
4999 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
5000 m_fn_ptr
->playback_rvalue (),
5002 m_require_tail_call
));
5005 /* Implementation of pure virtual hook recording::rvalue::visit_children
5006 for recording::call_through_ptr. */
5009 recording::call_through_ptr::visit_children (rvalue_visitor
*v
)
5011 v
->visit (m_fn_ptr
);
5012 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5013 v
->visit (m_args
[i
]);
5016 /* Implementation of recording::memento::make_debug_string for
5017 calls through function ptrs. */
5020 recording::call_through_ptr::make_debug_string ()
5022 enum precedence prec
= get_precedence ();
5023 /* First, build a buffer for the arguments. */
5024 /* Calculate length of said buffer. */
5025 size_t sz
= 1; /* nil terminator */
5026 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5028 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
5029 sz
+= 2; /* ", " separator */
5032 /* Now allocate and populate the buffer. */
5033 char *argbuf
= new char[sz
];
5036 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5038 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
5039 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
5040 if (i
+ 1 < m_args
.length ())
5042 strcpy (argbuf
+ len
, ", ");
5048 /* ...and use it to get the string for the call as a whole. */
5049 string
*result
= string::from_printf (m_ctxt
,
5051 m_fn_ptr
->get_debug_string_parens (prec
),
5059 /* Implementation of recording::memento::write_reproducer for
5060 call_through_ptr. */
5063 recording::call_through_ptr::write_reproducer (reproducer
&r
)
5065 const char *id
= r
.make_identifier (this, "call");
5066 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
5067 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
5070 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5071 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
5073 r
.write (" gcc_jit_rvalue *%s =\n"
5074 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
5075 " %s, /* gcc_jit_location *loc */\n"
5076 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
5077 " %i, /* int numargs */ \n"
5078 " %s); /* gcc_jit_rvalue **args*/\n",
5080 r
.get_identifier (get_context ()),
5081 r
.get_identifier (m_loc
),
5082 r
.get_identifier_as_rvalue (m_fn_ptr
),
5085 write_reproducer_tail_call (r
, id
);
5088 /* The implementation of class gcc::jit::recording::array_access. */
5090 /* Implementation of pure virtual hook recording::memento::replay_into
5091 for recording::array_access. */
5094 recording::array_access::replay_into (replayer
*r
)
5097 r
->new_array_access (playback_location (r
, m_loc
),
5098 m_ptr
->playback_rvalue (),
5099 m_index
->playback_rvalue ()));
5102 /* Implementation of pure virtual hook recording::rvalue::visit_children
5103 for recording::array_access. */
5106 recording::array_access::visit_children (rvalue_visitor
*v
)
5112 /* Implementation of recording::memento::make_debug_string for
5116 recording::array_access::make_debug_string ()
5118 enum precedence prec
= get_precedence ();
5119 return string::from_printf (m_ctxt
,
5121 m_ptr
->get_debug_string_parens (prec
),
5122 m_index
->get_debug_string_parens (prec
));
5125 /* Implementation of recording::memento::write_reproducer for
5129 recording::array_access::write_reproducer (reproducer
&r
)
5131 const char *id
= r
.make_identifier (this, "lvalue");
5132 r
.write (" gcc_jit_lvalue *%s = \n"
5133 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
5134 " %s, /*gcc_jit_location *loc */\n"
5135 " %s, /* gcc_jit_rvalue *ptr */\n"
5136 " %s); /* gcc_jit_rvalue *index */\n",
5138 r
.get_identifier (get_context ()),
5139 r
.get_identifier (m_loc
),
5140 r
.get_identifier_as_rvalue (m_ptr
),
5141 r
.get_identifier_as_rvalue (m_index
));
5144 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
5146 /* Implementation of pure virtual hook recording::memento::replay_into
5147 for recording::access_field_of_lvalue. */
5150 recording::access_field_of_lvalue::replay_into (replayer
*r
)
5153 m_lvalue
->playback_lvalue ()
5154 ->access_field (playback_location (r
, m_loc
),
5155 m_field
->playback_field ()));
5159 /* Implementation of pure virtual hook recording::rvalue::visit_children
5160 for recording::access_field_of_lvalue. */
5163 recording::access_field_of_lvalue::visit_children (rvalue_visitor
*v
)
5165 v
->visit (m_lvalue
);
5168 /* Implementation of recording::memento::make_debug_string for
5169 accessing a field of an lvalue. */
5172 recording::access_field_of_lvalue::make_debug_string ()
5174 enum precedence prec
= get_precedence ();
5175 return string::from_printf (m_ctxt
,
5177 m_lvalue
->get_debug_string_parens (prec
),
5178 m_field
->get_debug_string ());
5181 /* Implementation of recording::memento::write_reproducer for
5182 access_field_of_lvalue. */
5185 recording::access_field_of_lvalue::write_reproducer (reproducer
&r
)
5187 const char *id
= r
.make_identifier (this, "lvalue");
5188 r
.write (" gcc_jit_lvalue *%s = \n"
5189 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5190 " %s, /*gcc_jit_location *loc */\n"
5193 r
.get_identifier_as_lvalue (m_lvalue
),
5194 r
.get_identifier (m_loc
),
5195 r
.get_identifier (m_field
));
5198 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
5200 /* Implementation of pure virtual hook recording::memento::replay_into
5201 for recording::access_field_rvalue. */
5204 recording::access_field_rvalue::replay_into (replayer
*r
)
5207 m_rvalue
->playback_rvalue ()
5208 ->access_field (playback_location (r
, m_loc
),
5209 m_field
->playback_field ()));
5212 /* Implementation of pure virtual hook recording::rvalue::visit_children
5213 for recording::access_field_rvalue. */
5216 recording::access_field_rvalue::visit_children (rvalue_visitor
*v
)
5218 v
->visit (m_rvalue
);
5221 /* Implementation of recording::memento::make_debug_string for
5222 accessing a field of an rvalue. */
5225 recording::access_field_rvalue::make_debug_string ()
5227 enum precedence prec
= get_precedence ();
5228 return string::from_printf (m_ctxt
,
5230 m_rvalue
->get_debug_string_parens (prec
),
5231 m_field
->get_debug_string ());
5234 /* Implementation of recording::memento::write_reproducer for
5235 access_field_rvalue. */
5238 recording::access_field_rvalue::write_reproducer (reproducer
&r
)
5240 const char *id
= r
.make_identifier (this, "rvalue");
5241 r
.write (" gcc_jit_rvalue *%s = \n"
5242 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5243 " %s, /*gcc_jit_location *loc */\n"
5246 r
.get_identifier_as_rvalue (m_rvalue
),
5247 r
.get_identifier (m_loc
),
5248 r
.get_identifier (m_field
));
5251 /* The implementation of class
5252 gcc::jit::recording::dereference_field_rvalue. */
5254 /* Implementation of pure virtual hook recording::memento::replay_into
5255 for recording::dereference_field_rvalue. */
5258 recording::dereference_field_rvalue::replay_into (replayer
*r
)
5261 m_rvalue
->playback_rvalue ()->
5262 dereference_field (playback_location (r
, m_loc
),
5263 m_field
->playback_field ()));
5266 /* Implementation of pure virtual hook recording::rvalue::visit_children
5267 for recording::dereference_field_rvalue. */
5270 recording::dereference_field_rvalue::visit_children (rvalue_visitor
*v
)
5272 v
->visit (m_rvalue
);
5275 /* Implementation of recording::memento::make_debug_string for
5276 dereferencing a field of an rvalue. */
5279 recording::dereference_field_rvalue::make_debug_string ()
5281 enum precedence prec
= get_precedence ();
5282 return string::from_printf (m_ctxt
,
5284 m_rvalue
->get_debug_string_parens (prec
),
5285 m_field
->get_debug_string ());
5288 /* Implementation of recording::memento::write_reproducer for
5289 dereference_field_rvalue. */
5292 recording::dereference_field_rvalue::write_reproducer (reproducer
&r
)
5294 const char *id
= r
.make_identifier (this, "lvalue");
5295 r
.write (" gcc_jit_lvalue *%s=\n"
5296 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5297 " %s, /* gcc_jit_location *loc */\n"
5298 " %s); /* gcc_jit_field *field */\n",
5300 r
.get_identifier_as_rvalue (m_rvalue
),
5301 r
.get_identifier (m_loc
),
5302 r
.get_identifier (m_field
));
5305 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5307 /* Implementation of pure virtual hook recording::memento::replay_into
5308 for recording::dereference_rvalue. */
5311 recording::dereference_rvalue::replay_into (replayer
*r
)
5314 m_rvalue
->playback_rvalue ()->
5315 dereference (playback_location (r
, m_loc
)));
5318 /* Implementation of pure virtual hook recording::rvalue::visit_children
5319 for recording::dereference_rvalue. */
5322 recording::dereference_rvalue::visit_children (rvalue_visitor
*v
)
5324 v
->visit (m_rvalue
);
5327 /* Implementation of recording::memento::make_debug_string for
5328 dereferencing an rvalue. */
5331 recording::dereference_rvalue::make_debug_string ()
5333 enum precedence prec
= get_precedence ();
5334 return string::from_printf (m_ctxt
,
5336 m_rvalue
->get_debug_string_parens (prec
));
5339 /* Implementation of recording::memento::write_reproducer for
5340 dereference_rvalue. */
5343 recording::dereference_rvalue::write_reproducer (reproducer
&r
)
5345 const char *id
= r
.make_identifier (this, "dereference");
5346 r
.write (" gcc_jit_lvalue *%s =\n"
5347 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5348 " %s); /* gcc_jit_location *loc */\n",
5350 r
.get_identifier_as_rvalue (m_rvalue
),
5351 r
.get_identifier (m_loc
));
5354 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5356 /* Implementation of pure virtual hook recording::memento::replay_into
5357 for recording::get_address_of_lvalue. */
5360 recording::get_address_of_lvalue::replay_into (replayer
*r
)
5363 m_lvalue
->playback_lvalue ()->
5364 get_address (playback_location (r
, m_loc
)));
5367 /* Implementation of pure virtual hook recording::rvalue::visit_children
5368 for recording::get_address_of_lvalue. */
5371 recording::get_address_of_lvalue::visit_children (rvalue_visitor
*v
)
5373 v
->visit (m_lvalue
);
5376 /* Implementation of recording::memento::make_debug_string for
5377 getting the address of an lvalue. */
5380 recording::get_address_of_lvalue::make_debug_string ()
5382 enum precedence prec
= get_precedence ();
5383 return string::from_printf (m_ctxt
,
5385 m_lvalue
->get_debug_string_parens (prec
));
5388 /* Implementation of recording::memento::write_reproducer for
5389 get_address_of_lvalue. */
5392 recording::get_address_of_lvalue::write_reproducer (reproducer
&r
)
5394 const char *id
= r
.make_identifier (this, "address_of");
5395 r
.write (" gcc_jit_rvalue *%s =\n"
5396 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5397 " %s); /* gcc_jit_location *loc */\n",
5399 r
.get_identifier_as_lvalue (m_lvalue
),
5400 r
.get_identifier (m_loc
));
5403 /* The implementation of class gcc::jit::recording::local. */
5405 /* Implementation of pure virtual hook recording::memento::replay_into
5406 for recording::local. */
5409 recording::local::replay_into (replayer
*r
)
5412 m_func
->playback_function ()
5413 ->new_local (playback_location (r
, m_loc
),
5414 m_type
->playback_type (),
5415 playback_string (m_name
)));
5418 /* Override the default implementation of
5419 recording::memento::write_to_dump for locals by writing
5421 for use at the top of the function body as if it were a
5425 recording::local::write_to_dump (dump
&d
)
5427 if (d
.update_locations ())
5428 m_loc
= d
.make_location ();
5429 d
.write(" %s %s;\n",
5430 m_type
->get_debug_string (),
5431 get_debug_string ());
5435 recording::local::write_reproducer (reproducer
&r
)
5437 const char *id
= r
.make_identifier (this, "local");
5438 r
.write (" gcc_jit_lvalue *%s =\n"
5439 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5440 " %s, /* gcc_jit_location *loc */\n"
5441 " %s, /* gcc_jit_type *type */\n"
5442 " %s); /* const char *name */\n",
5444 r
.get_identifier (m_func
),
5445 r
.get_identifier (m_loc
),
5446 r
.get_identifier_as_type (m_type
),
5447 m_name
->get_debug_string ());
5450 /* The implementation of class gcc::jit::recording::statement. */
5452 /* We poison the default implementation of
5453 gcc::jit::recording::statement::get_successor_blocks
5454 since this vfunc must only ever be called on terminator
5457 vec
<recording::block
*>
5458 recording::statement::get_successor_blocks () const
5460 /* The base class implementation is for non-terminating statements,
5461 and thus should never be called. */
5463 vec
<block
*> result
;
5468 /* Extend the default implementation of
5469 recording::memento::write_to_dump for statements by (if requested)
5470 updating the location of the statement to the current location in
5474 recording::statement::write_to_dump (dump
&d
)
5476 memento::write_to_dump (d
);
5477 if (d
.update_locations ())
5478 m_loc
= d
.make_location ();
5481 /* The implementation of class gcc::jit::recording::eval. */
5483 /* Implementation of pure virtual hook recording::memento::replay_into
5484 for recording::eval. */
5487 recording::eval::replay_into (replayer
*r
)
5489 playback_block (get_block ())
5490 ->add_eval (playback_location (r
),
5491 m_rvalue
->playback_rvalue ());
5494 /* Implementation of recording::memento::make_debug_string for
5495 an eval statement. */
5498 recording::eval::make_debug_string ()
5500 return string::from_printf (m_ctxt
,
5502 m_rvalue
->get_debug_string ());
5505 /* Implementation of recording::memento::write_reproducer for
5509 recording::eval::write_reproducer (reproducer
&r
)
5511 r
.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5512 " %s, /* gcc_jit_location *loc */\n"
5513 " %s); /* gcc_jit_rvalue *rvalue */\n",
5514 r
.get_identifier (get_block ()),
5515 r
.get_identifier (get_loc ()),
5516 r
.get_identifier_as_rvalue (m_rvalue
));
5519 /* The implementation of class gcc::jit::recording::assignment. */
5521 /* Implementation of pure virtual hook recording::memento::replay_into
5522 for recording::assignment. */
5525 recording::assignment::replay_into (replayer
*r
)
5527 playback_block (get_block ())
5528 ->add_assignment (playback_location (r
),
5529 m_lvalue
->playback_lvalue (),
5530 m_rvalue
->playback_rvalue ());
5533 /* Implementation of recording::memento::make_debug_string for
5534 an assignment statement. */
5537 recording::assignment::make_debug_string ()
5539 return string::from_printf (m_ctxt
,
5541 m_lvalue
->get_debug_string (),
5542 m_rvalue
->get_debug_string ());
5545 /* Implementation of recording::memento::write_reproducer for
5546 assignment statements. */
5549 recording::assignment::write_reproducer (reproducer
&r
)
5551 r
.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5552 " %s, /* gcc_jit_location *loc */\n"
5553 " %s, /* gcc_jit_lvalue *lvalue */\n"
5554 " %s); /* gcc_jit_rvalue *rvalue */\n",
5555 r
.get_identifier (get_block ()),
5556 r
.get_identifier (get_loc ()),
5557 r
.get_identifier_as_lvalue (m_lvalue
),
5558 r
.get_identifier_as_rvalue (m_rvalue
));
5561 /* The implementation of class gcc::jit::recording::assignment_op. */
5563 /* Implementation of pure virtual hook recording::memento::replay_into
5564 for recording::assignment_op. */
5567 recording::assignment_op::replay_into (replayer
*r
)
5569 playback::type
*result_type
=
5570 m_lvalue
->playback_lvalue ()->get_type ();
5572 playback::rvalue
*binary_op
=
5573 r
->new_binary_op (playback_location (r
),
5576 m_lvalue
->playback_rvalue (),
5577 m_rvalue
->playback_rvalue ());
5579 playback_block (get_block ())
5580 ->add_assignment (playback_location (r
),
5581 m_lvalue
->playback_lvalue (),
5585 /* Implementation of recording::memento::make_debug_string for
5586 an assignment_op statement. */
5589 recording::assignment_op::make_debug_string ()
5591 return string::from_printf (m_ctxt
,
5593 m_lvalue
->get_debug_string (),
5594 binary_op_strings
[m_op
],
5595 m_rvalue
->get_debug_string ());
5598 /* Implementation of recording::memento::write_reproducer for
5599 assignment_op statements. */
5602 recording::assignment_op::write_reproducer (reproducer
&r
)
5604 r
.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5605 " %s, /* gcc_jit_location *loc */\n"
5606 " %s, /* gcc_jit_lvalue *lvalue */\n"
5607 " %s, /* enum gcc_jit_binary_op op */\n"
5608 " %s); /* gcc_jit_rvalue *rvalue */\n",
5609 r
.get_identifier (get_block ()),
5610 r
.get_identifier (get_loc ()),
5611 r
.get_identifier_as_lvalue (m_lvalue
),
5612 binary_op_reproducer_strings
[m_op
],
5613 r
.get_identifier_as_rvalue (m_rvalue
));
5616 /* The implementation of class gcc::jit::recording::comment. */
5618 /* Implementation of pure virtual hook recording::memento::replay_into
5619 for recording::comment. */
5622 recording::comment::replay_into (replayer
*r
)
5624 playback_block (get_block ())
5625 ->add_comment (playback_location (r
),
5629 /* Implementation of recording::memento::make_debug_string for
5630 a comment "statement". */
5633 recording::comment::make_debug_string ()
5635 return string::from_printf (m_ctxt
,
5640 /* Implementation of recording::memento::write_reproducer for
5644 recording::comment::write_reproducer (reproducer
&r
)
5646 r
.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5647 " %s, /* gcc_jit_location *loc */\n"
5648 " %s); /* const char *text */\n",
5649 r
.get_identifier (get_block ()),
5650 r
.get_identifier (get_loc ()),
5651 m_text
->get_debug_string ());
5654 /* The implementation of class gcc::jit::recording::conditional. */
5656 /* Implementation of pure virtual hook recording::memento::replay_into
5657 for recording::conditional. */
5660 recording::conditional::replay_into (replayer
*r
)
5662 playback_block (get_block ())
5663 ->add_conditional (playback_location (r
),
5664 m_boolval
->playback_rvalue (),
5665 playback_block (m_on_true
),
5666 playback_block (m_on_false
));
5669 /* Override the poisoned default implementation of
5670 gcc::jit::recording::statement::get_successor_blocks
5672 A conditional jump has 2 successor blocks. */
5674 vec
<recording::block
*>
5675 recording::conditional::get_successor_blocks () const
5677 vec
<block
*> result
;
5679 result
.quick_push (m_on_true
);
5680 result
.quick_push (m_on_false
);
5684 /* Implementation of recording::memento::make_debug_string for
5685 a conditional jump statement. */
5688 recording::conditional::make_debug_string ()
5691 return string::from_printf (m_ctxt
,
5692 "if (%s) goto %s; else goto %s;",
5693 m_boolval
->get_debug_string (),
5694 m_on_true
->get_debug_string (),
5695 m_on_false
->get_debug_string ());
5697 return string::from_printf (m_ctxt
,
5699 m_boolval
->get_debug_string (),
5700 m_on_true
->get_debug_string ());
5703 /* Implementation of recording::memento::write_reproducer for
5704 conditional statements. */
5707 recording::conditional::write_reproducer (reproducer
&r
)
5709 r
.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5710 " %s, /* gcc_jit_location *loc */\n"
5711 " %s, /* gcc_jit_rvalue *boolval */\n"
5712 " %s, /* gcc_jit_block *on_true */\n"
5713 " %s); /* gcc_jit_block *on_false */\n",
5714 r
.get_identifier (get_block ()),
5715 r
.get_identifier (get_loc ()),
5716 r
.get_identifier_as_rvalue (m_boolval
),
5717 r
.get_identifier (m_on_true
),
5718 r
.get_identifier (m_on_false
));
5721 /* The implementation of class gcc::jit::recording::jump. */
5723 /* Implementation of pure virtual hook recording::memento::replay_into
5724 for recording::jump. */
5727 recording::jump::replay_into (replayer
*r
)
5729 playback_block (get_block ())
5730 ->add_jump (playback_location (r
),
5731 m_target
->playback_block ());
5734 /* Override the poisoned default implementation of
5735 gcc::jit::recording::statement::get_successor_blocks
5737 An unconditional jump has 1 successor block. */
5739 vec
<recording::block
*>
5740 recording::jump::get_successor_blocks () const
5742 vec
<block
*> result
;
5744 result
.quick_push (m_target
);
5748 /* Implementation of recording::memento::make_debug_string for
5749 a unconditional jump statement. */
5752 recording::jump::make_debug_string ()
5754 return string::from_printf (m_ctxt
,
5756 m_target
->get_debug_string ());
5759 /* Implementation of recording::memento::write_reproducer for
5763 recording::jump::write_reproducer (reproducer
&r
)
5765 r
.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5766 " %s, /* gcc_jit_location *loc */\n"
5767 " %s); /* gcc_jit_block *target */\n",
5768 r
.get_identifier (get_block ()),
5769 r
.get_identifier (get_loc ()),
5770 r
.get_identifier (m_target
));
5773 /* The implementation of class gcc::jit::recording::return_. */
5775 /* Implementation of pure virtual hook recording::memento::replay_into
5776 for recording::return_. */
5779 recording::return_::replay_into (replayer
*r
)
5781 playback_block (get_block ())
5782 ->add_return (playback_location (r
),
5783 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
5786 /* Override the poisoned default implementation of
5787 gcc::jit::recording::statement::get_successor_blocks
5789 A return statement has no successor block. */
5791 vec
<recording::block
*>
5792 recording::return_::get_successor_blocks () const
5794 vec
<block
*> result
;
5799 /* Implementation of recording::memento::make_debug_string for
5800 a return statement (covers both those with and without rvalues). */
5803 recording::return_::make_debug_string ()
5806 return string::from_printf (m_ctxt
,
5808 m_rvalue
->get_debug_string ());
5810 return string::from_printf (m_ctxt
,
5814 /* Implementation of recording::memento::write_reproducer for
5815 return statements. */
5818 recording::return_::write_reproducer (reproducer
&r
)
5821 r
.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5822 " %s, /* gcc_jit_location *loc */\n"
5823 " %s); /* gcc_jit_rvalue *rvalue */\n",
5824 r
.get_identifier (get_block ()),
5825 r
.get_identifier (get_loc ()),
5826 r
.get_identifier_as_rvalue (m_rvalue
));
5828 r
.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5829 " %s); /* gcc_jit_location *loc */\n",
5830 r
.get_identifier (get_block ()),
5831 r
.get_identifier (get_loc ()));
5834 /* The implementation of class gcc::jit::recording::case_. */
5837 recording::case_::write_reproducer (reproducer
&r
)
5839 const char *id
= r
.make_identifier (this, "case");
5841 " gcc_jit_case *%s = \n"
5842 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
5843 " %s, /* gcc_jit_rvalue *min_value */\n"
5844 " %s, /* gcc_jit_rvalue *max_value */\n"
5845 " %s); /* gcc_jit_block *dest_block */\n";
5848 r
.get_identifier (get_context ()),
5849 r
.get_identifier_as_rvalue (m_min_value
),
5850 r
.get_identifier_as_rvalue (m_max_value
),
5851 r
.get_identifier (m_dest_block
));
5855 recording::case_::make_debug_string ()
5857 return string::from_printf (get_context (),
5858 "case %s ... %s: goto %s;",
5859 m_min_value
->get_debug_string (),
5860 m_max_value
->get_debug_string (),
5861 m_dest_block
->get_debug_string ());
5864 /* The implementation of class gcc::jit::recording::switch_. */
5866 /* gcc::jit::recording::switch_'s constructor. */
5868 recording::switch_::switch_ (block
*b
,
5871 block
*default_block
,
5874 : statement (b
, loc
),
5876 m_default_block (default_block
)
5878 m_cases
.reserve_exact (num_cases
);
5879 for (int i
= 0; i
< num_cases
; i
++)
5880 m_cases
.quick_push (cases
[i
]);
5883 /* Implementation of pure virtual hook recording::memento::replay_into
5884 for recording::switch_. */
5887 recording::switch_::replay_into (replayer
*r
)
5889 auto_vec
<playback::case_
> pcases
;
5891 recording::case_
*rcase
;
5892 pcases
.reserve_exact (m_cases
.length ());
5893 FOR_EACH_VEC_ELT (m_cases
, i
, rcase
)
5895 playback::case_
pcase (rcase
->get_min_value ()->playback_rvalue (),
5896 rcase
->get_max_value ()->playback_rvalue (),
5897 rcase
->get_dest_block ()->playback_block ());
5898 pcases
.safe_push (pcase
);
5900 playback_block (get_block ())
5901 ->add_switch (playback_location (r
),
5902 m_expr
->playback_rvalue (),
5903 m_default_block
->playback_block (),
5907 /* Override the poisoned default implementation of
5908 gcc::jit::recording::statement::get_successor_blocks
5910 A switch statement has (NUM_CASES + 1) successor blocks. */
5912 vec
<recording::block
*>
5913 recording::switch_::get_successor_blocks () const
5915 vec
<block
*> result
;
5916 result
.create (m_cases
.length () + 1);
5917 result
.quick_push (m_default_block
);
5920 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
5921 result
.quick_push (c
->get_dest_block ());
5925 /* Implementation of recording::memento::make_debug_string for
5926 a switch statement. */
5929 recording::switch_::make_debug_string ()
5931 auto_vec
<char> cases_str
;
5934 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
5936 size_t len
= strlen (c
->get_debug_string ());
5937 unsigned idx
= cases_str
.length ();
5938 cases_str
.safe_grow (idx
+ 1 + len
);
5939 cases_str
[idx
] = ' ';
5940 memcpy (&(cases_str
[idx
+ 1]),
5941 c
->get_debug_string (),
5944 cases_str
.safe_push ('\0');
5946 return string::from_printf (m_ctxt
,
5947 "switch (%s) {default: goto %s;%s}",
5948 m_expr
->get_debug_string (),
5949 m_default_block
->get_debug_string (),
5953 /* Implementation of recording::memento::write_reproducer for
5954 switch statements. */
5957 recording::switch_::write_reproducer (reproducer
&r
)
5959 r
.make_identifier (this, "switch");
5962 const char *cases_id
=
5963 r
.make_tmp_identifier ("cases_for", this);
5964 r
.write (" gcc_jit_case *%s[%i] = {\n",
5967 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
5968 r
.write (" %s,\n", r
.get_identifier (c
));
5971 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
5972 " %s, /* gcc_jit_location *loc */\n"
5973 " %s, /* gcc_jit_rvalue *expr */\n"
5974 " %s, /* gcc_jit_block *default_block */\n"
5975 " %i, /* int num_cases */\n"
5976 " %s); /* gcc_jit_case **cases */\n";
5978 r
.get_identifier (get_block ()),
5979 r
.get_identifier (get_loc ()),
5980 r
.get_identifier_as_rvalue (m_expr
),
5981 r
.get_identifier (m_default_block
),
5986 } // namespace gcc::jit