1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2024 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"
29 #include "jit-builtins.h"
30 #include "jit-recording.h"
31 #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 *, false, 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 /* A helper class for implementing make_debug_string, for building
451 a temporary string from a vec of rvalues. */
453 class comma_separated_string
456 comma_separated_string (const auto_vec
<recording::rvalue
*> &rvalues
,
457 enum recording::precedence prec
);
458 ~comma_separated_string ();
460 const char *as_char_ptr () const { return m_buf
; }
466 /* comma_separated_string's ctor
469 comma_separated_string::comma_separated_string
470 (const auto_vec
<recording::rvalue
*> &rvalues
,
471 enum recording::precedence prec
)
474 /* Calculate length of said buffer. */
475 size_t sz
= 1; /* nil terminator */
476 for (unsigned i
= 0; i
< rvalues
.length (); i
++)
478 sz
+= strlen (rvalues
[i
]->get_debug_string_parens (prec
));
479 sz
+= 2; /* ", " separator */
482 /* Now allocate and populate the buffer. */
483 m_buf
= new char[sz
];
486 for (unsigned i
= 0; i
< rvalues
.length (); i
++)
488 strcpy (m_buf
+ len
, rvalues
[i
]->get_debug_string_parens (prec
));
489 len
+= strlen (rvalues
[i
]->get_debug_string_parens (prec
));
490 if (i
+ 1 < rvalues
.length ())
492 strcpy (m_buf
+ len
, ", ");
499 /* comma_separated_string's dtor. */
501 comma_separated_string::~comma_separated_string ()
506 /**********************************************************************
508 **********************************************************************/
510 /* Get the playback::location for the given recording::location,
511 handling a NULL input with a NULL output. */
514 recording::playback_location (replayer
*r
, recording::location
*loc
)
517 return loc
->playback_location (r
);
522 /* Get a const char * for the given recording::string
523 handling a NULL input with a NULL output. */
526 recording::playback_string (recording::string
*str
)
529 return str
->c_str ();
534 /* Get the playback::block for the given recording::block,
535 handling a NULL input with a NULL output. */
538 recording::playback_block (recording::block
*b
)
541 return b
->playback_block ();
546 /* Methods of cc::jit::recording::context. */
548 /* The constructor for gcc::jit::recording::context, used by
549 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
551 recording::context::context (context
*parent_ctxt
)
553 m_parent_ctxt (parent_ctxt
),
554 m_toplevel_ctxt (m_parent_ctxt
? m_parent_ctxt
->m_toplevel_ctxt
: this),
557 m_first_error_str (NULL
),
558 m_owns_first_error_str (false),
559 m_last_error_str (NULL
),
560 m_owns_last_error_str (false),
566 m_builtins_manager(NULL
)
570 /* Inherit options from parent. */
571 for (unsigned i
= 0; i
< ARRAY_SIZE (m_str_options
); i
++)
573 const char *parent_opt
= parent_ctxt
->m_str_options
[i
];
574 m_str_options
[i
] = parent_opt
? xstrdup (parent_opt
) : NULL
;
576 memcpy (m_int_options
,
577 parent_ctxt
->m_int_options
,
578 sizeof (m_int_options
));
579 memcpy (m_bool_options
,
580 parent_ctxt
->m_bool_options
,
581 sizeof (m_bool_options
));
582 memcpy (m_inner_bool_options
,
583 parent_ctxt
->m_inner_bool_options
,
584 sizeof (m_inner_bool_options
));
585 set_logger (parent_ctxt
->get_logger ());
589 memset (m_str_options
, 0, sizeof (m_str_options
));
590 memset (m_int_options
, 0, sizeof (m_int_options
));
591 memset (m_bool_options
, 0, sizeof (m_bool_options
));
592 memset (m_inner_bool_options
, 0, sizeof (m_inner_bool_options
));
593 m_inner_bool_options
[INNER_BOOL_OPTION_PRINT_ERRORS_TO_STDERR
] = true;
596 memset (m_basic_types
, 0, sizeof (m_basic_types
));
599 /* The destructor for gcc::jit::recording::context, implicitly used by
600 gcc_jit_context_release. */
602 recording::context::~context ()
604 JIT_LOG_SCOPE (get_logger ());
607 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
612 for (i
= 0; i
< GCC_JIT_NUM_STR_OPTIONS
; ++i
)
613 free (m_str_options
[i
]);
616 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
618 FOR_EACH_VEC_ELT (m_driver_options
, i
, optname
)
621 if (m_builtins_manager
)
622 delete m_builtins_manager
;
624 if (m_owns_first_error_str
)
625 free (m_first_error_str
);
627 if (m_owns_last_error_str
)
628 if (m_last_error_str
!= m_first_error_str
)
629 free (m_last_error_str
);
632 /* Add the given mememto to the list of those tracked by this
633 gcc::jit::recording::context, so that e.g. it can be deleted
634 when this context is released. */
637 recording::context::record (memento
*m
)
641 m_mementos
.safe_push (m
);
644 /* Replay this context (and any parents) into the given replayer. */
647 recording::context::replay_into (replayer
*r
)
649 JIT_LOG_SCOPE (get_logger ());
653 /* If we have a parent context, we must replay it. This will
654 recursively walk backwards up the historical tree, then replay things
655 forwards "in historical order", starting with the ultimate parent
656 context, until we reach the "this" context.
658 Note that we fully replay the parent, then fully replay the child,
659 which means that inter-context references can only exist from child
660 to parent, not the other way around.
662 All of this replaying is suboptimal - it would be better to do the
663 work for the parent context *once*, rather than replaying the parent
664 every time we replay each child. However, fixing this requires deep
665 surgery to lifetime-management: we'd need every context family tree
666 to have its own GC heap, and to initialize the GCC code to use that
667 heap (with a mutex on such a heap). */
669 m_parent_ctxt
->replay_into (r
);
671 if (r
->errors_occurred ())
674 /* Replay this context's saved operations into r. */
675 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
677 /* Disabled low-level debugging, here if we need it: print what
679 Note that the calls to get_debug_string might lead to more
680 mementos being created for the strings.
681 This can also be used to exercise the debug_string
684 printf ("context %p replaying (%p): %s\n",
685 (void *)this, (void *)m
, m
->get_debug_string ());
689 if (r
->errors_occurred ())
694 /* During a playback, we associate objects from the recording with
695 their counterparts during this playback.
697 For simplicity, we store this within the recording objects.
699 The following method cleans away these associations, to ensure that
700 we never have out-of-date associations lingering on subsequent
701 playbacks (the objects pointed to are GC-managed, but the
702 recording objects don't own refs to them). */
705 recording::context::disassociate_from_playback ()
707 JIT_LOG_SCOPE (get_logger ());
712 m_parent_ctxt
->disassociate_from_playback ();
714 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
716 m
->set_playback_obj (NULL
);
720 /* Create a recording::string instance and add it to this context's list
723 This creates a fresh copy of the given 0-terminated buffer. */
726 recording::context::new_string (const char *text
, bool escaped
)
731 recording::string
*result
= new string (this, text
, escaped
);
736 /* Create a recording::location instance and add it to this context's
739 Implements the post-error-checking part of
740 gcc_jit_context_new_location. */
742 recording::location
*
743 recording::context::new_location (const char *filename
,
746 bool created_by_user
)
748 recording::location
*result
=
749 new recording::location (this,
750 new_string (filename
),
757 /* If we haven't seen this enum value yet, create a recording::type
758 instance and add it to this context's list of mementos.
760 If we have seen it before, reuse our cached value, so that repeated
761 calls on the context give the same object.
763 If we have a parent context, the cache is within the ultimate
766 Implements the post-error-checking part of
767 gcc_jit_context_get_type. */
770 recording::context::get_type (enum gcc_jit_types kind
)
772 if (!m_basic_types
[kind
])
775 m_basic_types
[kind
] = m_parent_ctxt
->get_type (kind
);
778 recording::type
*result
= new memento_of_get_type (this, kind
);
780 m_basic_types
[kind
] = result
;
784 return m_basic_types
[kind
];
787 /* Get a recording::type instance for the given size and signedness.
788 This is implemented in terms of recording::context::get_type
791 Implements the post-error-checking part of
792 gcc_jit_context_get_int_type. */
795 recording::context::get_int_type (int num_bytes
, int is_signed
)
797 /* We can't use a switch here since some of the values are macros affected
798 by options; e.g. i386.h has
799 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
800 Compare with tree.cc's make_or_reuse_type. Note that the _SIZE macros
801 are in bits, rather than bytes.
803 const int num_bits
= num_bytes
* 8;
804 if (num_bits
== INT_TYPE_SIZE
)
805 return get_type (is_signed
807 : GCC_JIT_TYPE_UNSIGNED_INT
);
808 if (num_bits
== CHAR_TYPE_SIZE
)
809 return get_type (is_signed
810 ? GCC_JIT_TYPE_SIGNED_CHAR
811 : GCC_JIT_TYPE_UNSIGNED_CHAR
);
812 if (num_bits
== SHORT_TYPE_SIZE
)
813 return get_type (is_signed
815 : GCC_JIT_TYPE_UNSIGNED_SHORT
);
816 if (num_bits
== LONG_TYPE_SIZE
)
817 return get_type (is_signed
819 : GCC_JIT_TYPE_UNSIGNED_LONG
);
820 if (num_bits
== LONG_LONG_TYPE_SIZE
)
821 return get_type (is_signed
822 ? GCC_JIT_TYPE_LONG_LONG
823 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
825 return get_type (is_signed
826 ? GCC_JIT_TYPE_INT128_T
827 : GCC_JIT_TYPE_UINT128_T
);
829 /* Some other size, not corresponding to the C int types. */
830 /* To be written: support arbitrary other sizes, sharing by
831 memoizing at the recording::context level? */
835 /* Create a recording::type instance and add it to this context's list
838 Implements the post-error-checking part of
839 gcc_jit_context_new_array_type. */
842 recording::context::new_array_type (recording::location
*loc
,
843 recording::type
*element_type
,
846 if (struct_
*s
= element_type
->dyn_cast_struct ())
847 if (!s
->get_fields ())
850 "cannot create an array of type %s"
851 " until the fields have been set",
852 s
->get_name ()->c_str ());
855 recording::type
*result
=
856 new recording::array_type (this, loc
, element_type
, num_elements
);
861 /* Create a recording::field instance and add it to this context's list
864 Implements the post-error-checking part of
865 gcc_jit_context_new_field. */
868 recording::context::new_field (recording::location
*loc
,
869 recording::type
*type
,
872 recording::field
*result
=
873 new recording::field (this, loc
, type
, new_string (name
));
878 /* Create a recording::bitfield instance and add it to this context's list
881 Implements the post-error-checking part of
882 gcc_jit_context_new_bitfield. */
885 recording::context::new_bitfield (recording::location
*loc
,
886 recording::type
*type
,
890 recording::field
*result
=
891 new recording::bitfield (this, loc
, type
, width
, new_string (name
));
896 /* Create a recording::struct_ instance and add it to this context's
897 list of mementos and list of compound types.
899 Implements the post-error-checking part of
900 gcc_jit_context_new_struct_type. */
903 recording::context::new_struct_type (recording::location
*loc
,
906 recording::struct_
*result
= new struct_ (this, loc
, new_string (name
));
908 m_compound_types
.safe_push (result
);
912 /* Create a recording::union_ instance and add it to this context's
913 list of mementos and list of compound types.
915 Implements the first post-error-checking part of
916 gcc_jit_context_new_union_type. */
919 recording::context::new_union_type (recording::location
*loc
,
922 recording::union_
*result
= new union_ (this, loc
, new_string (name
));
924 m_compound_types
.safe_push (result
);
928 /* Create a recording::function_type instance and add it to this context's
931 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
933 recording::function_type
*
934 recording::context::new_function_type (recording::type
*return_type
,
936 recording::type
**param_types
,
939 recording::function_type
*fn_type
940 = new function_type (this,
949 /* Create a recording::type instance and add it to this context's list
952 Implements the post-error-checking part of
953 gcc_jit_context_new_function_ptr_type. */
956 recording::context::new_function_ptr_type (recording::location
*, /* unused loc */
957 recording::type
*return_type
,
959 recording::type
**param_types
,
962 recording::function_type
*fn_type
963 = new_function_type (return_type
,
968 /* Return a pointer-type to the function type. */
969 return fn_type
->get_pointer ();
972 /* Create a recording::param instance and add it to this context's list
975 Implements the post-error-checking part of
976 gcc_jit_context_new_param. */
979 recording::context::new_param (recording::location
*loc
,
980 recording::type
*type
,
983 recording::param
*result
= new recording::param (this, loc
, type
, new_string (name
));
988 /* Create a recording::function instance and add it to this context's list
989 of mementos and list of functions.
991 Implements the post-error-checking part of
992 gcc_jit_context_new_function. */
994 recording::function
*
995 recording::context::new_function (recording::location
*loc
,
996 enum gcc_jit_function_kind kind
,
997 recording::type
*return_type
,
1000 recording::param
**params
,
1002 enum built_in_function builtin_id
)
1004 recording::function
*result
=
1005 new recording::function (this,
1006 loc
, kind
, return_type
,
1008 num_params
, params
, is_variadic
,
1011 m_functions
.safe_push (result
);
1016 /* Locate the builtins_manager (if any) for this family of contexts,
1017 creating it if it doesn't exist already.
1019 All of the recording contexts in a family share one builtins_manager:
1020 if we have a child context, follow the parent links to get the
1021 ultimate ancestor context, and look for it/store it there. */
1024 recording::context::get_builtins_manager ()
1027 return m_parent_ctxt
->get_builtins_manager ();
1029 if (!m_builtins_manager
)
1030 m_builtins_manager
= new builtins_manager (this);
1032 return m_builtins_manager
;
1035 /* Get a recording::function instance, which is lazily-created and added
1036 to the context's lists of mementos.
1038 Implements the post-error-checking part of
1039 gcc_jit_context_get_builtin_function. */
1041 recording::function
*
1042 recording::context::get_builtin_function (const char *name
)
1044 builtins_manager
*bm
= get_builtins_manager ();
1045 return bm
->get_builtin_function (name
);
1048 /* Create a recording::global instance and add it to this context's list
1051 Implements the post-error-checking part of
1052 gcc_jit_context_new_global. */
1055 recording::context::new_global (recording::location
*loc
,
1056 enum gcc_jit_global_kind kind
,
1057 recording::type
*type
,
1060 recording::global
*result
=
1061 new recording::global (this, loc
, kind
, type
, new_string (name
));
1063 m_globals
.safe_push (result
);
1069 recording::context::new_global_init_rvalue (lvalue
*variable
,
1072 recording::global_init_rvalue
*obj
=
1073 new recording::global_init_rvalue (this, variable
, init
);
1076 global
*gbl
= (global
*) variable
;
1077 gbl
->set_rvalue_init (init
); /* Needed by the global for write dump. */
1080 /* Create a recording::memento_of_new_string_literal instance and add it
1081 to this context's list of mementos.
1083 Implements the post-error-checking part of
1084 gcc_jit_context_new_string_literal. */
1087 recording::context::new_string_literal (const char *value
)
1089 recording::rvalue
*result
=
1090 new memento_of_new_string_literal (this, NULL
, new_string (value
));
1095 /* Create a recording::memento_of_new_rvalue_from_vector instance and add it
1096 to this context's list of mementos.
1098 Implements the post-error-checking part of
1099 gcc_jit_context_new_rvalue_from_vector. */
1102 recording::context::new_rvalue_from_vector (location
*loc
,
1106 recording::rvalue
*result
1107 = new memento_of_new_rvalue_from_vector (this, loc
, type
, elements
);
1113 recording::context::new_ctor (recording::location
*loc
,
1114 recording::type
*type
,
1119 recording::ctor
*result
= new ctor (this, loc
, type
);
1121 /* Short cut for zero init. */
1128 bool is_struct_or_union
= type
->is_struct () || type
->is_union ();
1130 /* We need to copy fields and values into result's auto_vec:s.
1131 Both for structs and unions and only values for arrays. */
1132 if (type
->is_array () != NULL
)
1134 result
->m_values
.reserve (num_values
, false);
1136 for (size_t i
= 0; i
< num_values
; i
++)
1137 result
->m_values
.quick_push (values
[i
]);
1139 else if (is_struct_or_union
&& fields
)
1141 /* ctor values are paired with user specified fields. */
1143 result
->m_values
.reserve (num_values
, false);
1144 result
->m_fields
.reserve (num_values
, false);
1146 for (size_t i
= 0; i
< num_values
; i
++)
1148 result
->m_values
.quick_push (values
[i
]);
1149 result
->m_fields
.quick_push (fields
[i
]);
1152 else if (is_struct_or_union
&& !fields
)
1154 /* ctor values are in definition order one by one,
1155 so take the fields from the type object. */
1157 result
->m_values
.reserve (num_values
, false);
1158 result
->m_fields
.reserve (num_values
, false);
1160 compound_type
*ct
= reinterpret_cast<compound_type
*>(type
);
1161 recording::fields
*fields
= ct
->get_fields ();
1163 /* The entry point checks that num_values is not greater than
1164 the amount of fields in 'fields'. */
1165 for (size_t i
= 0; i
< num_values
; i
++)
1167 result
->m_values
.quick_push (values
[i
]);
1168 result
->m_fields
.quick_push (fields
->get_field (i
));
1178 /* Create a recording::unary_op instance and add it to this context's
1181 Implements the post-error-checking part of
1182 gcc_jit_context_new_unary_op. */
1185 recording::context::new_unary_op (recording::location
*loc
,
1186 enum gcc_jit_unary_op op
,
1187 recording::type
*result_type
,
1188 recording::rvalue
*a
)
1190 recording::rvalue
*result
=
1191 new unary_op (this, loc
, op
, result_type
, a
);
1196 /* Create a recording::binary_op instance and add it to this context's
1199 Implements the post-error-checking part of
1200 gcc_jit_context_new_binary_op. */
1203 recording::context::new_binary_op (recording::location
*loc
,
1204 enum gcc_jit_binary_op op
,
1205 recording::type
*result_type
,
1206 recording::rvalue
*a
,
1207 recording::rvalue
*b
)
1209 recording::rvalue
*result
=
1210 new binary_op (this, loc
, op
, result_type
, a
, b
);
1215 /* Create a recording::comparison instance and add it to this context's
1218 Implements the post-error-checking part of
1219 gcc_jit_context_new_comparison. */
1222 recording::context::new_comparison (recording::location
*loc
,
1223 enum gcc_jit_comparison op
,
1224 recording::rvalue
*a
,
1225 recording::rvalue
*b
)
1227 recording::rvalue
*result
= new comparison (this, loc
, op
, a
, b
);
1232 /* Create a recording::cast instance and add it to this context's list
1235 Implements the post-error-checking part of
1236 gcc_jit_context_new_cast. */
1239 recording::context::new_cast (recording::location
*loc
,
1240 recording::rvalue
*expr
,
1241 recording::type
*type_
)
1243 recording::rvalue
*result
= new cast (this, loc
, expr
, type_
);
1248 /* Create a recording::bitcast instance and add it to this context's list
1251 Implements the post-error-checking part of
1252 gcc_jit_context_new_bitcast. */
1255 recording::context::new_bitcast (location
*loc
,
1259 recording::rvalue
*result
= new bitcast (this, loc
, expr
, type_
);
1264 /* Create a recording::call instance and add it to this context's list
1267 Implements the post-error-checking part of
1268 gcc_jit_context_new_call. */
1271 recording::context::new_call (recording::location
*loc
,
1273 int numargs
, recording::rvalue
**args
)
1275 recording::rvalue
*result
= new call (this, loc
, func
, numargs
, args
);
1280 /* Create a recording::call_through_ptr instance and add it to this
1281 context's list of mementos.
1283 Implements the post-error-checking part of
1284 gcc_jit_context_new_call_through_ptr. */
1287 recording::context::new_call_through_ptr (recording::location
*loc
,
1288 recording::rvalue
*fn_ptr
,
1290 recording::rvalue
**args
)
1292 recording::rvalue
*result
= new call_through_ptr (this, loc
, fn_ptr
, numargs
, args
);
1297 /* Create a recording::array_access instance and add it to this context's list
1300 Implements the post-error-checking part of
1301 gcc_jit_context_new_array_access. */
1304 recording::context::new_array_access (recording::location
*loc
,
1305 recording::rvalue
*ptr
,
1306 recording::rvalue
*index
)
1308 recording::lvalue
*result
= new array_access (this, loc
, ptr
, index
);
1313 /* Create a recording::case_ instance and add it to this context's list
1316 Implements the post-error-checking part of
1317 gcc_jit_context_new_case. */
1320 recording::context::new_case (recording::rvalue
*min_value
,
1321 recording::rvalue
*max_value
,
1322 recording::block
*block
)
1324 recording::case_
*result
= new case_ (this, min_value
, max_value
, block
);
1329 /* Set the given string option for this context, or add an error if
1330 it's not recognized.
1332 Implements the post-error-checking part of
1333 gcc_jit_context_set_str_option. */
1336 recording::context::set_str_option (enum gcc_jit_str_option opt
,
1339 if (opt
< 0 || opt
>= GCC_JIT_NUM_STR_OPTIONS
)
1342 "unrecognized (enum gcc_jit_str_option) value: %i", opt
);
1345 free (m_str_options
[opt
]);
1346 m_str_options
[opt
] = value
? xstrdup (value
) : NULL
;
1347 log_str_option (opt
);
1350 /* Set the given integer option for this context, or add an error if
1351 it's not recognized.
1353 Implements the post-error-checking part of
1354 gcc_jit_context_set_int_option. */
1357 recording::context::set_int_option (enum gcc_jit_int_option opt
,
1360 if (opt
< 0 || opt
>= GCC_JIT_NUM_INT_OPTIONS
)
1363 "unrecognized (enum gcc_jit_int_option) value: %i", opt
);
1366 m_int_options
[opt
] = value
;
1367 log_int_option (opt
);
1370 /* Set the given boolean option for this context, or add an error if
1371 it's not recognized.
1373 Implements the post-error-checking part of
1374 gcc_jit_context_set_bool_option. */
1377 recording::context::set_bool_option (enum gcc_jit_bool_option opt
,
1380 if (opt
< 0 || opt
>= GCC_JIT_NUM_BOOL_OPTIONS
)
1383 "unrecognized (enum gcc_jit_bool_option) value: %i", opt
);
1386 m_bool_options
[opt
] = value
? true : false;
1387 log_bool_option (opt
);
1391 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt
,
1394 gcc_assert (inner_opt
>= 0 && inner_opt
< NUM_INNER_BOOL_OPTIONS
);
1395 m_inner_bool_options
[inner_opt
] = value
? true : false;
1396 log_inner_bool_option (inner_opt
);
1400 /* Add the given optname to this context's list of extra options.
1402 Implements the post-error-checking part of
1403 gcc_jit_context_add_command_line_option. */
1406 recording::context::add_command_line_option (const char *optname
)
1408 m_command_line_options
.safe_push (xstrdup (optname
));
1411 /* Add any user-provided extra options, starting with any from
1413 Called by playback::context::make_fake_args. */
1416 recording::context::append_command_line_options (vec
<char *> *argvec
)
1419 m_parent_ctxt
->append_command_line_options (argvec
);
1423 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1424 argvec
->safe_push (xstrdup (optname
));
1427 /* Add the given optname to this context's list of extra driver options. */
1430 recording::context::add_driver_option (const char *optname
)
1432 m_driver_options
.safe_push (xstrdup (optname
));
1435 /* Add any user-provided driver options, starting with any from
1437 Called by playback::context::invoke_driver. */
1440 recording::context::append_driver_options (auto_string_vec
*argvec
)
1443 m_parent_ctxt
->append_driver_options (argvec
);
1448 FOR_EACH_VEC_ELT (m_driver_options
, i
, optname
)
1449 argvec
->safe_push (xstrdup (optname
));
1452 /* Add the given dumpname/out_ptr pair to this context's list of requested
1455 Implements the post-error-checking part of
1456 gcc_jit_context_enable_dump. */
1459 recording::context::enable_dump (const char *dumpname
,
1463 gcc_assert (dumpname
);
1464 gcc_assert (out_ptr
);
1466 d
.m_dumpname
= dumpname
;
1467 d
.m_out_ptr
= out_ptr
;
1469 m_requested_dumps
.safe_push (d
);
1472 /* Validate this context, and if it passes, compile it to memory
1475 Implements the post-error-checking part of
1476 gcc_jit_context_compile. */
1479 recording::context::compile ()
1481 JIT_LOG_SCOPE (get_logger ());
1487 if (errors_occurred ())
1490 /* Set up a compile_to_memory playback context. */
1491 ::gcc::jit::playback::compile_to_memory
replayer (this);
1494 replayer
.compile ();
1496 /* Get the jit::result (or NULL) from the
1497 compile_to_memory playback context. */
1498 return replayer
.get_result_obj ();
1501 /* Validate this context, and if it passes, compile it to a file
1504 Implements the post-error-checking part of
1505 gcc_jit_context_compile_to_file. */
1508 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind
,
1509 const char *output_path
)
1511 JIT_LOG_SCOPE (get_logger ());
1517 if (errors_occurred ())
1520 /* Set up a compile_to_file playback context. */
1521 ::gcc::jit::playback::compile_to_file
replayer (this,
1526 replayer
.compile ();
1529 /* Format the given error using printf's conventions, print
1530 it to stderr, and add it to the context. */
1533 recording::context::add_error (location
*loc
, const char *fmt
, ...)
1537 add_error_va (loc
, fmt
, ap
);
1541 /* Format the given error using printf's conventions, print
1542 it to stderr, and add it to the context. */
1545 recording::context::add_error_va (location
*loc
, const char *fmt
, va_list ap
)
1552 JIT_LOG_SCOPE (get_logger ());
1554 len
= vasprintf (&malloced_msg
, fmt
, ap
);
1555 if (malloced_msg
== NULL
|| len
< 0)
1557 errmsg
= "out of memory generating error message";
1558 has_ownership
= false;
1562 errmsg
= malloced_msg
;
1563 has_ownership
= true;
1566 get_logger ()->log ("error %i: %s", m_error_count
, errmsg
);
1568 const char *ctxt_progname
=
1569 get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
1571 ctxt_progname
= "libgccjit.so";
1573 bool print_errors_to_stderr
=
1574 get_inner_bool_option (INNER_BOOL_OPTION_PRINT_ERRORS_TO_STDERR
);
1575 if (print_errors_to_stderr
)
1578 fprintf (stderr
, "%s: %s: error: %s\n",
1580 loc
->get_debug_string (),
1583 fprintf (stderr
, "%s: error: %s\n",
1590 m_first_error_str
= const_cast <char *> (errmsg
);
1591 m_owns_first_error_str
= has_ownership
;
1594 if (m_owns_last_error_str
)
1595 if (m_last_error_str
!= m_first_error_str
)
1596 free (m_last_error_str
);
1597 m_last_error_str
= const_cast <char *> (errmsg
);
1598 m_owns_last_error_str
= has_ownership
;
1603 /* Get the message for the first error that occurred on this context, or
1604 NULL if no errors have occurred on it.
1606 Implements the post-error-checking part of
1607 gcc_jit_context_get_first_error. */
1610 recording::context::get_first_error () const
1612 return m_first_error_str
;
1615 /* Get the message for the last error that occurred on this context, or
1616 NULL if no errors have occurred on it.
1618 Implements the post-error-checking part of
1619 gcc_jit_context_get_last_error. */
1622 recording::context::get_last_error () const
1624 return m_last_error_str
;
1627 /* Lazily generate and record a recording::type representing an opaque
1628 struct named "FILE".
1630 For use if client code tries to dereference the result of
1631 get_type (GCC_JIT_TYPE_FILE_PTR). */
1634 recording::context::get_opaque_FILE_type ()
1637 m_FILE_type
= new_struct_type (NULL
, "FILE");
1641 /* Dump a C-like representation of the given context to the given path.
1642 If UPDATE_LOCATIONS is true, update the locations within the
1643 context's mementos to point to the dumpfile.
1645 Implements the post-error-checking part of
1646 gcc_jit_context_dump_to_file. */
1649 recording::context::dump_to_file (const char *path
, bool update_locations
)
1652 dump
d (*this, path
, update_locations
);
1654 /* Forward declaration of structs and unions. */
1656 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1658 d
.write ("%s;\n\n", st
->get_debug_string ());
1661 /* Content of structs, where set. */
1662 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1663 if (st
->get_fields ())
1665 st
->get_fields ()->write_to_dump (d
);
1671 FOR_EACH_VEC_ELT (m_globals
, i
, g
)
1673 g
->write_to_dump (d
);
1675 if (!m_globals
.is_empty ())
1679 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1681 fn
->write_to_dump (d
);
1685 FOR_EACH_VEC_ELT (m_top_level_asms
, i
, tla
)
1686 tla
->write_to_dump (d
);
1689 static const char * const
1690 str_option_reproducer_strings
[GCC_JIT_NUM_STR_OPTIONS
] = {
1691 "GCC_JIT_STR_OPTION_PROGNAME"
1694 static const char * const
1695 int_option_reproducer_strings
[GCC_JIT_NUM_INT_OPTIONS
] = {
1696 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1699 static const char * const
1700 bool_option_reproducer_strings
[GCC_JIT_NUM_BOOL_OPTIONS
] = {
1701 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1702 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1703 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1704 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1705 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1706 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1707 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1708 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1711 static const char * const
1712 inner_bool_option_reproducer_strings
[NUM_INNER_BOOL_OPTIONS
] = {
1713 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1714 "gcc_jit_context_set_bool_use_external_driver",
1715 "gcc_jit_context_set_bool_print_errors_to_stderr",
1718 /* Write the current value of all options to the log file (if any). */
1721 recording::context::log_all_options () const
1728 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1729 log_str_option ((enum gcc_jit_str_option
)opt_idx
);
1731 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1732 log_int_option ((enum gcc_jit_int_option
)opt_idx
);
1734 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1735 log_bool_option ((enum gcc_jit_bool_option
)opt_idx
);
1736 for (opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1737 log_inner_bool_option ((enum inner_bool_option
)opt_idx
);
1740 /* Write the current value of the given string option to the
1741 log file (if any). */
1744 recording::context::log_str_option (enum gcc_jit_str_option opt
) const
1746 gcc_assert (opt
< GCC_JIT_NUM_STR_OPTIONS
);
1749 if (m_str_options
[opt
])
1751 str_option_reproducer_strings
[opt
],
1752 m_str_options
[opt
]);
1755 str_option_reproducer_strings
[opt
]);
1759 /* Write the current value of the given int option to the
1760 log file (if any). */
1763 recording::context::log_int_option (enum gcc_jit_int_option opt
) const
1765 gcc_assert (opt
< GCC_JIT_NUM_INT_OPTIONS
);
1768 int_option_reproducer_strings
[opt
],
1769 m_int_options
[opt
]);
1772 /* Write the current value of the given bool option to the
1773 log file (if any). */
1776 recording::context::log_bool_option (enum gcc_jit_bool_option opt
) const
1778 gcc_assert (opt
< GCC_JIT_NUM_BOOL_OPTIONS
);
1781 bool_option_reproducer_strings
[opt
],
1782 m_bool_options
[opt
] ? "true" : "false");
1785 /* Write the current value of the given "inner" bool option to the
1786 log file (if any). */
1789 recording::context::log_inner_bool_option (enum inner_bool_option opt
) const
1791 gcc_assert (opt
< NUM_INNER_BOOL_OPTIONS
);
1794 inner_bool_option_reproducer_strings
[opt
],
1795 m_inner_bool_options
[opt
] ? "true" : "false");
1798 /* Write C source code to PATH that attempts to replay the API
1799 calls made to this context (and its parents), for use in
1800 minimizing test cases for libgccjit.
1802 Implements the post-error-checking part of
1803 gcc_jit_context_dump_reproducer_to_file. */
1806 recording::context::dump_reproducer_to_file (const char *path
)
1808 JIT_LOG_SCOPE (get_logger ());
1809 reproducer
r (*this, path
);
1811 /* Generate the "ancestry" of this context, as a list. */
1812 auto_vec
<context
*> ascending_contexts
;
1813 for (context
*ctxt
= this; ctxt
; ctxt
= ctxt
->m_parent_ctxt
)
1814 ascending_contexts
.safe_push (ctxt
);
1816 /* Reverse the list, giving a list of contexts from
1817 top-most parent context down through to youngest child context.
1818 We will use this list as the parameters of the functions in
1819 our generated file. */
1820 unsigned num_ctxts
= ascending_contexts
.length ();
1821 auto_vec
<context
*> contexts (num_ctxts
);
1822 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1823 contexts
.safe_push (ascending_contexts
[num_ctxts
- (i
+ 1)]);
1825 /* contexts[0] should be the top-level context. */
1826 gcc_assert (contexts
[0]);
1827 gcc_assert (contexts
[0]->m_toplevel_ctxt
== contexts
[0]);
1829 /* The final element in contexts should be "this". */
1830 gcc_assert (contexts
[contexts
.length () - 1] == this);
1831 gcc_assert (contexts
[contexts
.length () - 1]->m_toplevel_ctxt
1834 r
.write ("/* This code was autogenerated by"
1835 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1836 print_version (r
.get_file (), " ", false);
1838 r
.write ("#include <libgccjit.h>\n\n");
1839 r
.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1840 r
.write ("static void\nset_options (");
1841 r
.write_params (contexts
);
1843 r
.write ("static void\ncreate_code (");
1844 r
.write_params (contexts
);
1846 r
.write ("int\nmain (int argc, const char **argv)\n");
1848 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1849 r
.write (" gcc_jit_context *%s;\n",
1850 r
.get_identifier (contexts
[i
]));
1851 r
.write (" gcc_jit_result *result;\n"
1854 /* Create the contexts.
1855 The top-level context is acquired from a clean slate, the others as
1856 children of the prior context. */
1857 r
.write (" %s = gcc_jit_context_acquire ();\n",
1858 r
.get_identifier (contexts
[0]));
1859 for (unsigned i
= 1; i
< num_ctxts
; i
++)
1860 r
.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1861 r
.get_identifier (contexts
[i
]),
1862 r
.get_identifier (contexts
[i
- 1]));
1863 r
.write (" set_options (");
1864 r
.write_args (contexts
);
1866 r
.write (" create_code (");
1867 r
.write_args (contexts
);
1870 r
.write (" result = gcc_jit_context_compile (%s);\n",
1871 r
.get_identifier (this));
1873 for (unsigned i
= num_ctxts
; i
> 0; i
--)
1874 r
.write (" gcc_jit_context_release (%s);\n",
1875 r
.get_identifier (contexts
[i
- 1]));
1877 r
.write (" gcc_jit_result_release (result);\n"
1881 /* Define (char *) variables for use in calls to
1882 gcc_jit_context_enable_dump. */
1883 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1885 if (m_requested_dumps
.length ())
1887 r
.write ("/* Requested dumps for %s. */\n",
1888 r
.get_identifier (contexts
[ctxt_idx
]));
1889 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1890 r
.write ("static char *dump_%p;\n",
1891 (void *)&m_requested_dumps
[i
]);
1896 /* Write out values of options. */
1897 r
.write ("static void\nset_options (");
1898 r
.write_params (contexts
);
1900 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1905 r
.write (" /* Set options for %s. */\n",
1906 r
.get_identifier (contexts
[ctxt_idx
]));
1908 r
.write (" /* String options. */\n");
1909 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1911 r
.write (" gcc_jit_context_set_str_option (%s,\n"
1913 r
.get_identifier (contexts
[ctxt_idx
]),
1914 str_option_reproducer_strings
[opt_idx
]);
1915 if (m_str_options
[opt_idx
])
1916 r
.write (" \"%s\");\n",
1917 m_str_options
[opt_idx
]);
1919 r
.write (" NULL);\n");
1921 r
.write (" /* Int options. */\n");
1922 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1923 r
.write (" gcc_jit_context_set_int_option (%s,\n"
1926 r
.get_identifier (contexts
[ctxt_idx
]),
1927 int_option_reproducer_strings
[opt_idx
],
1928 m_int_options
[opt_idx
]);
1929 r
.write (" /* Boolean options. */\n");
1930 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1931 r
.write (" gcc_jit_context_set_bool_option (%s,\n"
1934 r
.get_identifier (contexts
[ctxt_idx
]),
1935 bool_option_reproducer_strings
[opt_idx
],
1936 m_bool_options
[opt_idx
]);
1937 for (int opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1938 r
.write (" %s (%s, %i);\n",
1939 inner_bool_option_reproducer_strings
[opt_idx
],
1940 r
.get_identifier (contexts
[ctxt_idx
]),
1941 m_inner_bool_options
[opt_idx
]);
1943 if (!m_command_line_options
.is_empty ())
1947 r
.write (" /* User-provided command-line options. */\n");
1948 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1949 r
.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1950 r
.get_identifier (contexts
[ctxt_idx
]),
1954 if (!m_driver_options
.is_empty ())
1958 r
.write (" /* User-provided driver options. */\n");
1959 FOR_EACH_VEC_ELT (m_driver_options
, i
, optname
)
1960 r
.write (" gcc_jit_context_add_driver_option (%s, \"%s\");\n",
1961 r
.get_identifier (contexts
[ctxt_idx
]),
1965 if (m_requested_dumps
.length ())
1967 r
.write (" /* Requested dumps. */\n");
1968 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1969 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1971 r
.write (" gcc_jit_context_enable_dump (%s,\n"
1974 r
.get_identifier (contexts
[ctxt_idx
]),
1975 m_requested_dumps
[i
].m_dumpname
,
1976 (void *)&m_requested_dumps
[i
]);
1982 r
.write ("static void\ncreate_code (");
1983 r
.write_params (contexts
);
1986 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1993 r
.write (" /* Replay of API calls for %s. */\n",
1994 r
.get_identifier (contexts
[ctxt_idx
]));
1995 FOR_EACH_VEC_ELT (contexts
[ctxt_idx
]->m_mementos
, i
, m
)
1996 m
->write_reproducer (r
);
2001 /* Copy the requested dumps within this context and all ancestors into
2005 recording::context::get_all_requested_dumps (vec
<recording::requested_dump
> *out
)
2008 m_parent_ctxt
->get_all_requested_dumps (out
);
2010 out
->reserve (m_requested_dumps
.length ());
2011 out
->splice (m_requested_dumps
);
2014 /* Create a recording::top_level_asm instance and add it to this
2015 context's list of mementos and to m_top_level_asms.
2017 Implements the post-error-checking part of
2018 gcc_jit_context_add_top_level_asm. */
2021 recording::context::add_top_level_asm (recording::location
*loc
,
2022 const char *asm_stmts
)
2024 recording::top_level_asm
*asm_obj
2025 = new recording::top_level_asm (this, loc
, new_string (asm_stmts
));
2027 m_top_level_asms
.safe_push (asm_obj
);
2030 /* This is a pre-compilation check for the context (and any parents).
2032 Detect errors within the context, adding errors if any are found. */
2035 recording::context::validate ()
2037 JIT_LOG_SCOPE (get_logger ());
2040 m_parent_ctxt
->validate ();
2044 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
2048 /* The implementation of class gcc::jit::recording::memento. */
2050 /* Get a (const char *) debug description of the given memento, by
2051 calling the pure-virtual make_debug_string hook, caching the
2054 It is intended that this should only be called in debugging and
2055 error-handling paths, so this doesn't need to be particularly
2059 recording::memento::get_debug_string ()
2061 if (!m_debug_string
)
2062 m_debug_string
= make_debug_string ();
2063 return m_debug_string
->c_str ();
2066 /* Default implementation of recording::memento::write_to_dump, writing
2067 an indented form of the memento's debug string to the dump. */
2070 recording::memento::write_to_dump (dump
&d
)
2072 d
.write (" %s\n", get_debug_string ());
2075 /* The implementation of class gcc::jit::recording::string. */
2077 /* Constructor for gcc::jit::recording::string::string, allocating a
2078 copy of the given text using new char[]. */
2080 recording::string::string (context
*ctxt
, const char *text
, bool escaped
)
2084 m_len
= strlen (text
);
2085 m_buffer
= new char[m_len
+ 1];
2086 strcpy (m_buffer
, text
);
2089 /* Destructor for gcc::jit::recording::string::string. */
2091 recording::string::~string ()
2096 /* Function for making gcc::jit::recording::string instances on a
2097 context via printf-style formatting.
2099 It is intended that this should only be called in debugging and
2100 error-handling paths, so this doesn't need to be particularly
2101 optimized, hence the double-copy of the string is acceptable. */
2104 recording::string::from_printf (context
*ctxt
, const char *fmt
, ...)
2109 recording::string
*result
;
2112 len
= vasprintf (&buf
, fmt
, ap
);
2115 if (buf
== NULL
|| len
< 0)
2117 ctxt
->add_error (NULL
, "malloc failure");
2121 result
= ctxt
->new_string (buf
);
2126 /* Implementation of recording::memento::make_debug_string for strings,
2127 wrapping the given string in quotes and escaping as necessary. */
2130 recording::string::make_debug_string ()
2132 /* Avoid infinite recursion into strings when logging all mementos:
2133 don't re-escape strings: */
2137 /* Wrap in quotes and do escaping etc */
2139 size_t sz
= (1 /* opening quote */
2140 + (m_len
* 2) /* each char might get escaped */
2141 + 1 /* closing quote */
2142 + 1); /* nil termintator */
2143 char *tmp
= new char[sz
];
2146 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
2147 APPEND('"'); /* opening quote */
2148 for (size_t i
= 0; i
< m_len
; i
++)
2150 char ch
= m_buffer
[i
];
2171 APPEND('"'); /* closing quote */
2173 tmp
[len
] = '\0'; /* nil termintator */
2175 string
*result
= m_ctxt
->new_string (tmp
, true);
2181 /* Implementation of recording::memento::write_reproducer for strings. */
2184 recording::string::write_reproducer (reproducer
&)
2189 /* The implementation of class gcc::jit::recording::location. */
2191 /* Implementation of recording::memento::replay_into for locations.
2193 Create a new playback::location and store it into the
2194 recording::location's m_playback_obj field. */
2197 recording::location::replay_into (replayer
*r
)
2199 m_playback_obj
= r
->new_location (this,
2200 m_filename
->c_str (),
2205 /* Implementation of recording::memento::make_debug_string for locations,
2206 turning them into the usual form:
2207 FILENAME:LINE:COLUMN
2208 like we do when emitting diagnostics. */
2211 recording::location::make_debug_string ()
2213 return string::from_printf (m_ctxt
,
2215 m_filename
->c_str (), m_line
, m_column
);
2218 /* Implementation of recording::memento::write_reproducer for locations. */
2221 recording::location::write_reproducer (reproducer
&r
)
2223 const char *id
= r
.make_identifier (this, "loc");
2224 r
.write (" gcc_jit_location *%s =\n"
2225 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
2226 " %s, /* const char *filename */\n"
2227 " %i, /* int line */\n"
2228 " %i);/* int column */\n",
2230 r
.get_identifier (get_context ()),
2231 m_filename
->get_debug_string (),
2235 /* The implementation of class gcc::jit::recording::type. */
2237 /* Given a type T, get the type T*.
2239 If this doesn't already exist, generate a new memento_of_get_pointer
2240 instance and add it to this type's context's list of mementos.
2242 Otherwise, use the cached type.
2244 Implements the post-error-checking part of
2245 gcc_jit_type_get_pointer. */
2248 recording::type::get_pointer ()
2250 if (!m_pointer_to_this_type
)
2252 m_pointer_to_this_type
= new memento_of_get_pointer (this);
2253 m_ctxt
->record (m_pointer_to_this_type
);
2255 return m_pointer_to_this_type
;
2258 /* Given a type T, get the type const T.
2260 Implements the post-error-checking part of
2261 gcc_jit_type_get_const. */
2264 recording::type::get_const ()
2266 recording::type
*result
= new memento_of_get_const (this);
2267 m_ctxt
->record (result
);
2271 /* Given a type T, get the type restrict T.
2273 Implements the post-error-checking part of
2274 gcc_jit_type_get_restrict. */
2277 recording::type::get_restrict ()
2279 recording::type
*result
= new memento_of_get_restrict (this);
2280 m_ctxt
->record (result
);
2284 /* Given a type T, get the type volatile T.
2286 Implements the post-error-checking part of
2287 gcc_jit_type_get_volatile. */
2290 recording::type::get_volatile ()
2292 recording::type
*result
= new memento_of_get_volatile (this);
2293 m_ctxt
->record (result
);
2297 /* Given a type, get an aligned version of the type.
2299 Implements the post-error-checking part of
2300 gcc_jit_type_get_aligned. */
2303 recording::type::get_aligned (size_t alignment_in_bytes
)
2305 recording::type
*result
2306 = new memento_of_get_aligned (this, alignment_in_bytes
);
2307 m_ctxt
->record (result
);
2311 /* Given a type, get a vector version of the type.
2313 Implements the post-error-checking part of
2314 gcc_jit_type_get_vector. */
2317 recording::type::get_vector (size_t num_units
)
2319 recording::type
*result
2320 = new vector_type (this, num_units
);
2321 m_ctxt
->record (result
);
2326 recording::type::access_as_type (reproducer
&r
)
2328 return r
.get_identifier (this);
2331 /* Override of default implementation of
2332 recording::type::get_size.
2334 Return the size in bytes. This is in use for global
2338 recording::memento_of_get_type::get_size ()
2343 case GCC_JIT_TYPE_VOID
:
2345 case GCC_JIT_TYPE_BOOL
:
2346 case GCC_JIT_TYPE_CHAR
:
2347 case GCC_JIT_TYPE_SIGNED_CHAR
:
2348 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2350 case GCC_JIT_TYPE_SHORT
:
2351 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2352 size
= SHORT_TYPE_SIZE
;
2354 case GCC_JIT_TYPE_INT
:
2355 case GCC_JIT_TYPE_UNSIGNED_INT
:
2356 size
= INT_TYPE_SIZE
;
2358 case GCC_JIT_TYPE_LONG
:
2359 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2360 size
= LONG_TYPE_SIZE
;
2362 case GCC_JIT_TYPE_LONG_LONG
:
2363 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2364 size
= LONG_LONG_TYPE_SIZE
;
2366 case GCC_JIT_TYPE_UINT8_T
:
2367 case GCC_JIT_TYPE_INT8_T
:
2370 case GCC_JIT_TYPE_UINT16_T
:
2371 case GCC_JIT_TYPE_INT16_T
:
2374 case GCC_JIT_TYPE_UINT32_T
:
2375 case GCC_JIT_TYPE_INT32_T
:
2378 case GCC_JIT_TYPE_UINT64_T
:
2379 case GCC_JIT_TYPE_INT64_T
:
2382 case GCC_JIT_TYPE_UINT128_T
:
2383 case GCC_JIT_TYPE_INT128_T
:
2386 case GCC_JIT_TYPE_FLOAT
:
2387 size
= FLOAT_TYPE_SIZE
;
2389 case GCC_JIT_TYPE_DOUBLE
:
2390 size
= DOUBLE_TYPE_SIZE
;
2392 case GCC_JIT_TYPE_LONG_DOUBLE
:
2393 size
= LONG_DOUBLE_TYPE_SIZE
;
2395 case GCC_JIT_TYPE_SIZE_T
:
2396 size
= MAX_BITS_PER_WORD
;
2399 /* As this function is called by
2400 'gcc_jit_global_set_initializer' and
2401 'recording::global::write_reproducer' possible types are only
2402 integrals and are covered by the previous cases. */
2406 return size
/ BITS_PER_UNIT
;
2409 /* Implementation of pure virtual hook recording::type::dereference for
2410 recording::memento_of_get_type. */
2413 recording::memento_of_get_type::dereference ()
2417 default: gcc_unreachable ();
2419 case GCC_JIT_TYPE_VOID
:
2422 case GCC_JIT_TYPE_VOID_PTR
:
2423 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
2425 case GCC_JIT_TYPE_BOOL
:
2426 case GCC_JIT_TYPE_CHAR
:
2427 case GCC_JIT_TYPE_SIGNED_CHAR
:
2428 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2429 case GCC_JIT_TYPE_SHORT
:
2430 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2431 case GCC_JIT_TYPE_INT
:
2432 case GCC_JIT_TYPE_UNSIGNED_INT
:
2433 case GCC_JIT_TYPE_LONG
:
2434 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2435 case GCC_JIT_TYPE_LONG_LONG
:
2436 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2437 case GCC_JIT_TYPE_UINT8_T
:
2438 case GCC_JIT_TYPE_UINT16_T
:
2439 case GCC_JIT_TYPE_UINT32_T
:
2440 case GCC_JIT_TYPE_UINT64_T
:
2441 case GCC_JIT_TYPE_UINT128_T
:
2442 case GCC_JIT_TYPE_INT8_T
:
2443 case GCC_JIT_TYPE_INT16_T
:
2444 case GCC_JIT_TYPE_INT32_T
:
2445 case GCC_JIT_TYPE_INT64_T
:
2446 case GCC_JIT_TYPE_INT128_T
:
2447 case GCC_JIT_TYPE_FLOAT
:
2448 case GCC_JIT_TYPE_DOUBLE
:
2449 case GCC_JIT_TYPE_LONG_DOUBLE
:
2450 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2451 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2452 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2453 /* Not a pointer: */
2456 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2457 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
2459 case GCC_JIT_TYPE_SIZE_T
:
2460 /* Not a pointer: */
2463 case GCC_JIT_TYPE_FILE_PTR
:
2464 /* Give the client code back an opaque "struct FILE". */
2465 return m_ctxt
->get_opaque_FILE_type ();
2469 /* Implementation of pure virtual hook recording::type::is_int for
2470 recording::memento_of_get_type. */
2473 recording::memento_of_get_type::is_int () const
2477 default: gcc_unreachable ();
2479 case GCC_JIT_TYPE_VOID
:
2482 case GCC_JIT_TYPE_VOID_PTR
:
2485 case GCC_JIT_TYPE_BOOL
:
2488 case GCC_JIT_TYPE_CHAR
:
2489 case GCC_JIT_TYPE_SIGNED_CHAR
:
2490 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2491 case GCC_JIT_TYPE_SHORT
:
2492 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2493 case GCC_JIT_TYPE_INT
:
2494 case GCC_JIT_TYPE_UNSIGNED_INT
:
2495 case GCC_JIT_TYPE_LONG
:
2496 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2497 case GCC_JIT_TYPE_LONG_LONG
:
2498 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2499 case GCC_JIT_TYPE_UINT8_T
:
2500 case GCC_JIT_TYPE_UINT16_T
:
2501 case GCC_JIT_TYPE_UINT32_T
:
2502 case GCC_JIT_TYPE_UINT64_T
:
2503 case GCC_JIT_TYPE_UINT128_T
:
2504 case GCC_JIT_TYPE_INT8_T
:
2505 case GCC_JIT_TYPE_INT16_T
:
2506 case GCC_JIT_TYPE_INT32_T
:
2507 case GCC_JIT_TYPE_INT64_T
:
2508 case GCC_JIT_TYPE_INT128_T
:
2511 case GCC_JIT_TYPE_FLOAT
:
2512 case GCC_JIT_TYPE_DOUBLE
:
2513 case GCC_JIT_TYPE_LONG_DOUBLE
:
2516 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2519 case GCC_JIT_TYPE_SIZE_T
:
2522 case GCC_JIT_TYPE_FILE_PTR
:
2525 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2526 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2527 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2532 /* Implementation of pure virtual hook recording::type::is_signed for
2533 recording::memento_of_get_type. */
2536 recording::memento_of_get_type::is_signed () const
2540 default: gcc_unreachable ();
2542 case GCC_JIT_TYPE_SIGNED_CHAR
:
2543 case GCC_JIT_TYPE_CHAR
:
2544 case GCC_JIT_TYPE_SHORT
:
2545 case GCC_JIT_TYPE_INT
:
2546 case GCC_JIT_TYPE_LONG
:
2547 case GCC_JIT_TYPE_LONG_LONG
:
2548 case GCC_JIT_TYPE_INT8_T
:
2549 case GCC_JIT_TYPE_INT16_T
:
2550 case GCC_JIT_TYPE_INT32_T
:
2551 case GCC_JIT_TYPE_INT64_T
:
2552 case GCC_JIT_TYPE_INT128_T
:
2555 case GCC_JIT_TYPE_VOID
:
2556 case GCC_JIT_TYPE_VOID_PTR
:
2557 case GCC_JIT_TYPE_BOOL
:
2558 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2559 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2560 case GCC_JIT_TYPE_UNSIGNED_INT
:
2561 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2562 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2563 case GCC_JIT_TYPE_UINT8_T
:
2564 case GCC_JIT_TYPE_UINT16_T
:
2565 case GCC_JIT_TYPE_UINT32_T
:
2566 case GCC_JIT_TYPE_UINT64_T
:
2567 case GCC_JIT_TYPE_UINT128_T
:
2569 case GCC_JIT_TYPE_FLOAT
:
2570 case GCC_JIT_TYPE_DOUBLE
:
2571 case GCC_JIT_TYPE_LONG_DOUBLE
:
2573 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2575 case GCC_JIT_TYPE_SIZE_T
:
2577 case GCC_JIT_TYPE_FILE_PTR
:
2579 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2580 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2581 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2586 /* Implementation of pure virtual hook recording::type::is_float for
2587 recording::memento_of_get_type. */
2590 recording::memento_of_get_type::is_float () const
2594 default: gcc_unreachable ();
2596 case GCC_JIT_TYPE_VOID
:
2599 case GCC_JIT_TYPE_VOID_PTR
:
2602 case GCC_JIT_TYPE_BOOL
:
2605 case GCC_JIT_TYPE_CHAR
:
2606 case GCC_JIT_TYPE_SIGNED_CHAR
:
2607 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2608 case GCC_JIT_TYPE_SHORT
:
2609 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2610 case GCC_JIT_TYPE_INT
:
2611 case GCC_JIT_TYPE_UNSIGNED_INT
:
2612 case GCC_JIT_TYPE_LONG
:
2613 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2614 case GCC_JIT_TYPE_LONG_LONG
:
2615 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2616 case GCC_JIT_TYPE_UINT8_T
:
2617 case GCC_JIT_TYPE_UINT16_T
:
2618 case GCC_JIT_TYPE_UINT32_T
:
2619 case GCC_JIT_TYPE_UINT64_T
:
2620 case GCC_JIT_TYPE_UINT128_T
:
2621 case GCC_JIT_TYPE_INT8_T
:
2622 case GCC_JIT_TYPE_INT16_T
:
2623 case GCC_JIT_TYPE_INT32_T
:
2624 case GCC_JIT_TYPE_INT64_T
:
2625 case GCC_JIT_TYPE_INT128_T
:
2628 case GCC_JIT_TYPE_FLOAT
:
2629 case GCC_JIT_TYPE_DOUBLE
:
2630 case GCC_JIT_TYPE_LONG_DOUBLE
:
2633 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2636 case GCC_JIT_TYPE_SIZE_T
:
2639 case GCC_JIT_TYPE_FILE_PTR
:
2642 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2643 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2644 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2649 /* Implementation of pure virtual hook recording::type::is_bool for
2650 recording::memento_of_get_type. */
2653 recording::memento_of_get_type::is_bool () const
2657 default: gcc_unreachable ();
2659 case GCC_JIT_TYPE_VOID
:
2662 case GCC_JIT_TYPE_VOID_PTR
:
2665 case GCC_JIT_TYPE_BOOL
:
2668 case GCC_JIT_TYPE_CHAR
:
2669 case GCC_JIT_TYPE_SIGNED_CHAR
:
2670 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2671 case GCC_JIT_TYPE_SHORT
:
2672 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2673 case GCC_JIT_TYPE_INT
:
2674 case GCC_JIT_TYPE_UNSIGNED_INT
:
2675 case GCC_JIT_TYPE_LONG
:
2676 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2677 case GCC_JIT_TYPE_LONG_LONG
:
2678 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2679 case GCC_JIT_TYPE_UINT8_T
:
2680 case GCC_JIT_TYPE_UINT16_T
:
2681 case GCC_JIT_TYPE_UINT32_T
:
2682 case GCC_JIT_TYPE_UINT64_T
:
2683 case GCC_JIT_TYPE_UINT128_T
:
2684 case GCC_JIT_TYPE_INT8_T
:
2685 case GCC_JIT_TYPE_INT16_T
:
2686 case GCC_JIT_TYPE_INT32_T
:
2687 case GCC_JIT_TYPE_INT64_T
:
2688 case GCC_JIT_TYPE_INT128_T
:
2691 case GCC_JIT_TYPE_FLOAT
:
2692 case GCC_JIT_TYPE_DOUBLE
:
2693 case GCC_JIT_TYPE_LONG_DOUBLE
:
2696 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2699 case GCC_JIT_TYPE_SIZE_T
:
2702 case GCC_JIT_TYPE_FILE_PTR
:
2705 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2706 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2707 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2712 /* Implementation of pure virtual hook recording::memento::replay_into
2713 for recording::memento_of_get_type. */
2716 recording::memento_of_get_type::replay_into (replayer
*r
)
2718 set_playback_obj (r
->get_type (m_kind
));
2721 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2723 /* Descriptive strings for each of enum gcc_jit_types. */
2725 static const char * const get_type_strings
[] = {
2726 "void", /* GCC_JIT_TYPE_VOID */
2727 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2729 "bool", /* GCC_JIT_TYPE_BOOL */
2731 "char", /* GCC_JIT_TYPE_CHAR */
2732 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2733 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2735 "short", /* GCC_JIT_TYPE_SHORT */
2736 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2738 "int", /* GCC_JIT_TYPE_INT */
2739 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2741 "long", /* GCC_JIT_TYPE_LONG */
2742 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2744 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2745 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2747 "float", /* GCC_JIT_TYPE_FLOAT */
2748 "double", /* GCC_JIT_TYPE_DOUBLE */
2749 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2751 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2753 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2755 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2757 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2758 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2759 "complex long double", /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2761 "__uint8_t", /* GCC_JIT_TYPE_UINT8_T */
2762 "__uint16_t", /* GCC_JIT_TYPE_UINT16_T */
2763 "__uint32_t", /* GCC_JIT_TYPE_UINT32_T */
2764 "__uint64_t", /* GCC_JIT_TYPE_UINT64_T */
2765 "__uint128_t", /* GCC_JIT_TYPE_UINT128_T */
2766 "__int8_t", /* GCC_JIT_TYPE_INT8_T */
2767 "__int16_t", /* GCC_JIT_TYPE_INT16_T */
2768 "__int32_t", /* GCC_JIT_TYPE_INT32_T */
2769 "__int64_t", /* GCC_JIT_TYPE_INT64_T */
2770 "__int128_t", /* GCC_JIT_TYPE_INT128_T */
2774 /* Implementation of recording::memento::make_debug_string for
2775 results of get_type, using a simple table of type names. */
2778 recording::memento_of_get_type::make_debug_string ()
2780 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
2783 static const char * const get_type_enum_strings
[] = {
2784 "GCC_JIT_TYPE_VOID",
2785 "GCC_JIT_TYPE_VOID_PTR",
2786 "GCC_JIT_TYPE_BOOL",
2787 "GCC_JIT_TYPE_CHAR",
2788 "GCC_JIT_TYPE_SIGNED_CHAR",
2789 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2790 "GCC_JIT_TYPE_SHORT",
2791 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2793 "GCC_JIT_TYPE_UNSIGNED_INT",
2794 "GCC_JIT_TYPE_LONG",
2795 "GCC_JIT_TYPE_UNSIGNED_LONG",
2796 "GCC_JIT_TYPE_LONG_LONG",
2797 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2798 "GCC_JIT_TYPE_FLOAT",
2799 "GCC_JIT_TYPE_DOUBLE",
2800 "GCC_JIT_TYPE_LONG_DOUBLE",
2801 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2802 "GCC_JIT_TYPE_SIZE_T",
2803 "GCC_JIT_TYPE_FILE_PTR",
2804 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2805 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2806 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE",
2807 "GCC_JIT_TYPE_UINT8_T",
2808 "GCC_JIT_TYPE_UINT16_T",
2809 "GCC_JIT_TYPE_UINT32_T",
2810 "GCC_JIT_TYPE_UINT64_T",
2811 "GCC_JIT_TYPE_UINT128_T",
2812 "GCC_JIT_TYPE_INT8_T",
2813 "GCC_JIT_TYPE_INT16_T",
2814 "GCC_JIT_TYPE_INT32_T",
2815 "GCC_JIT_TYPE_INT64_T",
2816 "GCC_JIT_TYPE_INT128_T",
2820 recording::memento_of_get_type::write_reproducer (reproducer
&r
)
2822 const char *id
= r
.make_identifier (this, "type");
2823 r
.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2825 r
.get_identifier (get_context ()),
2826 get_type_enum_strings
[m_kind
]);
2829 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2831 /* Override of default implementation of
2832 recording::type::get_size for get_pointer. */
2835 recording::memento_of_get_pointer::get_size ()
2837 return POINTER_SIZE
/ BITS_PER_UNIT
;
2840 /* Override of default implementation of
2841 recording::type::accepts_writes_from for get_pointer.
2843 Require a pointer type, and allowing writes to
2844 (const T *) from a (T*), but not the other way around. */
2847 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
2849 /* Must be a pointer type: */
2850 type
*rtype_points_to
= rtype
->is_pointer ();
2851 if (!rtype_points_to
)
2854 /* It's OK to assign to a (const T *) from a (T *). */
2855 if (m_other_type
->unqualified ()->accepts_writes_from (rtype_points_to
))
2860 /* It's OK to assign to a (volatile const T *) from a (volatile const T *). */
2861 return m_other_type
->is_same_type_as (rtype_points_to
);
2864 /* Implementation of pure virtual hook recording::memento::replay_into
2865 for recording::memento_of_get_pointer. */
2868 recording::memento_of_get_pointer::replay_into (replayer
*)
2870 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
2873 /* Implementation of recording::memento::make_debug_string for
2874 results of get_pointer, adding " *" to the underlying type,
2875 with special-casing to handle function pointer types. */
2878 recording::memento_of_get_pointer::make_debug_string ()
2880 /* Special-case function pointer types, to put the "*" in parens between
2881 the return type and the params (for one level of dereferencing, at
2883 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2884 return fn_type
->make_debug_string_with_ptr ();
2886 return string::from_printf (m_ctxt
,
2887 "%s *", m_other_type
->get_debug_string ());
2890 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2893 recording::memento_of_get_pointer::write_reproducer (reproducer
&r
)
2895 /* We need to special-case function pointer types; see the notes in
2896 recording::function_type::write_deferred_reproducer. */
2897 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2899 fn_type
->write_deferred_reproducer (r
, this);
2903 const char *id
= r
.make_identifier (this, "type");
2904 r
.write (" gcc_jit_type *%s =\n"
2905 " gcc_jit_type_get_pointer (%s);\n",
2907 r
.get_identifier_as_type (m_other_type
));
2910 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2912 /* Implementation of pure virtual hook recording::memento::replay_into
2913 for recording::memento_of_get_const. */
2916 recording::memento_of_get_const::replay_into (replayer
*)
2918 set_playback_obj (m_other_type
->playback_type ()->get_const ());
2921 /* Implementation of recording::memento::make_debug_string for
2922 results of get_const, prepending "const ". */
2925 recording::memento_of_get_const::make_debug_string ()
2927 return string::from_printf (m_ctxt
,
2928 "const %s", m_other_type
->get_debug_string ());
2931 /* Implementation of recording::memento::write_reproducer for const types. */
2934 recording::memento_of_get_const::write_reproducer (reproducer
&r
)
2936 const char *id
= r
.make_identifier (this, "type");
2937 r
.write (" gcc_jit_type *%s =\n"
2938 " gcc_jit_type_get_const (%s);\n",
2940 r
.get_identifier_as_type (m_other_type
));
2943 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2945 /* Implementation of pure virtual hook recording::memento::replay_into
2946 for recording::memento_of_get_volatile. */
2949 recording::memento_of_get_volatile::replay_into (replayer
*)
2951 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
2954 /* Implementation of recording::memento::make_debug_string for
2955 results of get_volatile, prepending "volatile ". */
2958 recording::memento_of_get_volatile::make_debug_string ()
2960 return string::from_printf (m_ctxt
,
2961 "volatile %s", m_other_type
->get_debug_string ());
2964 /* Implementation of recording::memento::write_reproducer for volatile
2968 recording::memento_of_get_volatile::write_reproducer (reproducer
&r
)
2970 const char *id
= r
.make_identifier (this, "type");
2971 r
.write (" gcc_jit_type *%s =\n"
2972 " gcc_jit_type_get_volatile (%s);\n",
2974 r
.get_identifier_as_type (m_other_type
));
2977 /* The implementation of class gcc::jit::recording::memento_of_get_restrict. */
2979 /* Implementation of pure virtual hook recording::memento::replay_into
2980 for recording::memento_of_get_restrict. */
2983 recording::memento_of_get_restrict::replay_into (replayer
*)
2985 set_playback_obj (m_other_type
->playback_type ()->get_restrict ());
2988 /* Implementation of recording::memento::make_debug_string for
2989 results of get_restrict, prepending "restrict ". */
2992 recording::memento_of_get_restrict::make_debug_string ()
2994 return string::from_printf (m_ctxt
,
2995 "restrict %s", m_other_type
->get_debug_string ());
2998 /* Implementation of recording::memento::write_reproducer for restrict
3002 recording::memento_of_get_restrict::write_reproducer (reproducer
&r
)
3004 const char *id
= r
.make_identifier (this, "type");
3005 r
.write (" gcc_jit_type *%s =\n"
3006 " gcc_jit_type_get_restrict (%s);\n",
3008 r
.get_identifier_as_type (m_other_type
));
3011 /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
3013 /* Implementation of pure virtual hook recording::memento::replay_into
3014 for recording::memento_of_get_aligned. */
3017 recording::memento_of_get_aligned::replay_into (replayer
*)
3020 (m_other_type
->playback_type ()->get_aligned (m_alignment_in_bytes
));
3023 /* Implementation of recording::memento::make_debug_string for
3024 results of get_aligned. */
3027 recording::memento_of_get_aligned::make_debug_string ()
3029 return string::from_printf (m_ctxt
,
3030 "%s __attribute__((aligned(%zi)))",
3031 m_other_type
->get_debug_string (),
3032 m_alignment_in_bytes
);
3035 /* Implementation of recording::memento::write_reproducer for aligned
3039 recording::memento_of_get_aligned::write_reproducer (reproducer
&r
)
3041 const char *id
= r
.make_identifier (this, "type");
3042 r
.write (" gcc_jit_type *%s =\n"
3043 " gcc_jit_type_get_aligned (%s, %zi);\n",
3045 r
.get_identifier_as_type (m_other_type
),
3046 m_alignment_in_bytes
);
3049 /* The implementation of class gcc::jit::recording::vector_type. */
3051 /* Implementation of pure virtual hook recording::memento::replay_into
3052 for recording::vector_type. */
3055 recording::vector_type::replay_into (replayer
*)
3058 (m_other_type
->playback_type ()->get_vector (m_num_units
));
3061 /* Implementation of recording::memento::make_debug_string for
3062 results of get_vector. */
3065 recording::vector_type::make_debug_string ()
3067 return string::from_printf
3069 "%s __attribute__((vector_size(sizeof (%s) * %zi)))",
3070 m_other_type
->get_debug_string (),
3071 m_other_type
->get_debug_string (),
3075 /* Implementation of recording::memento::write_reproducer for vector types. */
3078 recording::vector_type::write_reproducer (reproducer
&r
)
3080 const char *id
= r
.make_identifier (this, "type");
3081 r
.write (" gcc_jit_type *%s =\n"
3082 " gcc_jit_type_get_vector (%s, %zi);\n",
3084 r
.get_identifier_as_type (m_other_type
),
3088 /* The implementation of class gcc::jit::recording::array_type */
3090 /* Implementation of pure virtual hook recording::type::dereference for
3091 recording::array_type. */
3094 recording::array_type::dereference ()
3096 return m_element_type
;
3099 /* Implementation of pure virtual hook recording::memento::replay_into
3100 for recording::array_type. */
3103 recording::array_type::replay_into (replayer
*r
)
3105 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
3106 m_element_type
->playback_type (),
3110 /* Implementation of recording::memento::make_debug_string for
3111 results of new_array_type. */
3114 recording::array_type::make_debug_string ()
3116 return string::from_printf (m_ctxt
,
3118 m_element_type
->get_debug_string (),
3122 /* Implementation of recording::memento::write_reproducer for array
3126 recording::array_type::write_reproducer (reproducer
&r
)
3128 const char *id
= r
.make_identifier (this, "array_type");
3129 r
.write (" gcc_jit_type *%s =\n"
3130 " gcc_jit_context_new_array_type (%s,\n"
3131 " %s, /* gcc_jit_location *loc */\n"
3132 " %s, /* gcc_jit_type *element_type */\n"
3133 " %i); /* int num_elements */\n",
3135 r
.get_identifier (get_context ()),
3136 r
.get_identifier (m_loc
),
3137 r
.get_identifier_as_type (m_element_type
),
3141 /* The implementation of class gcc::jit::recording::function_type */
3143 /* Constructor for gcc::jit::recording::function_type. */
3145 recording::function_type::function_type (context
*ctxt
,
3151 m_return_type (return_type
),
3153 m_is_variadic (is_variadic
)
3155 for (int i
= 0; i
< num_params
; i
++)
3156 m_param_types
.safe_push (param_types
[i
]);
3159 /* Implementation of pure virtual hook recording::type::dereference for
3160 recording::function_type. */
3163 recording::function_type::dereference ()
3168 /* Implementation of virtual hook recording::type::is_same_type_as for
3169 recording::function_type.
3171 We override this to avoid requiring identity of function pointer types,
3172 so that if client code has obtained the same signature in
3173 different ways (e.g. via gcc_jit_context_new_function_ptr_type
3174 vs gcc_jit_function_get_address), the different function_type
3175 instances are treated as compatible.
3177 We can't use type::accepts_writes_from for this as we need a stronger
3178 notion of "sameness": if we have a fn_ptr type that has args that are
3179 themselves fn_ptr types, then those args still need to match exactly.
3181 Alternatively, we could consolidate attempts to create identical
3182 function_type instances so that pointer equality works, but that runs
3183 into issues about the lifetimes of the cache (w.r.t. nested contexts). */
3186 recording::function_type::is_same_type_as (type
*other
)
3190 function_type
*other_fn_type
= other
->dyn_cast_function_type ();
3194 /* Everything must match. */
3196 if (!m_return_type
->is_same_type_as (other_fn_type
->m_return_type
))
3199 if (m_param_types
.length () != other_fn_type
->m_param_types
.length ())
3204 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
3205 if (!param_type
->is_same_type_as (other_fn_type
->m_param_types
[i
]))
3208 if (m_is_variadic
!= other_fn_type
->m_is_variadic
)
3211 /* Passed all tests. */
3215 /* Implementation of pure virtual hook recording::memento::replay_into
3216 for recording::function_type. */
3219 recording::function_type::replay_into (replayer
*r
)
3221 /* Convert m_param_types to a vec of playback type. */
3222 auto_vec
<playback::type
*> param_types
;
3224 recording::type
*type
;
3225 param_types
.create (m_param_types
.length ());
3226 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
3227 param_types
.safe_push (type
->playback_type ());
3229 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
3234 /* Special-casing for make_debug_string for get_pointer results for
3235 handling (one level) of pointers to functions. */
3238 recording::function_type::make_debug_string_with_ptr ()
3240 return make_debug_string_with ("(*) ");
3243 /* Implementation of recording::memento::make_debug_string for
3244 results of new_function_type. */
3247 recording::function_type::make_debug_string ()
3249 return make_debug_string_with ("");
3252 /* Build a debug string representation of the form:
3254 RESULT_TYPE INSERT (PARAM_TYPES)
3256 for use when handling 0 and 1 level of indirection to this
3260 recording::function_type::make_debug_string_with (const char *insert
)
3262 /* First, build a buffer for the arguments. */
3263 /* Calculate length of said buffer. */
3264 size_t sz
= 1; /* nil terminator */
3265 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
3267 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
3268 sz
+= 2; /* ", " separator */
3271 sz
+= 5; /* ", ..." separator and ellipsis */
3273 /* Now allocate and populate the buffer. */
3274 char *argbuf
= new char[sz
];
3277 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
3279 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
3280 len
+= strlen (m_param_types
[i
]->get_debug_string ());
3281 if (i
+ 1 < m_param_types
.length ())
3283 strcpy (argbuf
+ len
, ", ");
3289 if (m_param_types
.length ())
3291 strcpy (argbuf
+ len
, ", ");
3294 strcpy (argbuf
+ len
, "...");
3299 /* ...and use it to get the string for the call as a whole. */
3300 string
*result
= string::from_printf (m_ctxt
,
3302 m_return_type
->get_debug_string (),
3311 /* Implementation of recording::memento::write_reproducer for function
3315 recording::function_type::write_reproducer (reproducer
&)
3317 /* see notes below. */
3320 /* There's a get_pointer within context::new_function_ptr_type:
3321 the type received by client code isn't the memento for the
3322 function_type, but instead the result of get_pointer on it.
3324 Hence we can't directly write a reproducer that gives function_type.
3325 Instead we special-case things within get_pointer, detecting this
3326 case, calling the following function. */
3329 recording::function_type::write_deferred_reproducer (reproducer
&r
,
3332 gcc_assert (ptr_type
);
3333 r
.make_identifier (this, "function_type");
3334 const char *ptr_id
= r
.make_identifier (ptr_type
, "ptr_to");
3335 const char *param_types_id
= r
.make_tmp_identifier ("params_for", this);
3336 r
.write (" gcc_jit_type *%s[%i] = {\n",
3338 m_param_types
.length ());
3341 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
3342 r
.write (" %s,\n", r
.get_identifier_as_type (param_type
));
3344 r
.write (" gcc_jit_type *%s =\n"
3345 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
3346 " %s, /* gcc_jit_location *loc */\n"
3347 " %s, /* gcc_jit_type *return_type */\n"
3348 " %i, /* int num_params */\n"
3349 " %s, /* gcc_jit_type **param_types */\n"
3350 " %i); /* int is_variadic */\n",
3352 r
.get_identifier (get_context ()),
3353 "NULL", /* location is not stored */
3354 r
.get_identifier_as_type (m_return_type
),
3355 m_param_types
.length (),
3360 /* The implementation of class gcc::jit::recording::field. */
3362 /* Implementation of pure virtual hook recording::memento::replay_into
3363 for recording::field. */
3366 recording::field::replay_into (replayer
*r
)
3368 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
3369 m_type
->playback_type (),
3370 playback_string (m_name
)));
3373 /* Override the default implementation of
3374 recording::memento::write_to_dump. Dump each field
3375 by dumping a line of the form:
3377 so that we can build up a struct/union field by field. */
3380 recording::field::write_to_dump (dump
&d
)
3382 d
.write (" %s %s;\n",
3383 m_type
->get_debug_string (),
3387 /* Implementation of recording::memento::make_debug_string for
3388 results of new_field. */
3391 recording::field::make_debug_string ()
3396 /* Implementation of recording::memento::write_reproducer for fields. */
3399 recording::field::write_reproducer (reproducer
&r
)
3401 const char *id
= r
.make_identifier (this, "field");
3402 r
.write(" gcc_jit_field *%s =\n"
3403 " gcc_jit_context_new_field (%s,\n"
3404 " %s, /* gcc_jit_location *loc */\n"
3405 " %s, /* gcc_jit_type *type, */\n"
3406 " %s); /* const char *name */\n",
3408 r
.get_identifier (get_context ()),
3409 r
.get_identifier (m_loc
),
3410 r
.get_identifier_as_type (m_type
),
3411 m_name
->get_debug_string ());
3414 /* The implementation of class gcc::jit::recording::bitfield. */
3416 /* Implementation of pure virtual hook recording::memento::replay_into
3417 for recording::bitfield. */
3420 recording::bitfield::replay_into (replayer
*r
)
3422 set_playback_obj (r
->new_bitfield (playback_location (r
, m_loc
),
3423 m_type
->playback_type (),
3425 playback_string (m_name
)));
3428 /* Override the default implementation of
3429 recording::memento::write_to_dump. Dump each bit field
3430 by dumping a line of the form:
3432 so that we can build up a struct/union field by field. */
3435 recording::bitfield::write_to_dump (dump
&d
)
3437 d
.write (" %s %s:%d;\n",
3438 m_type
->get_debug_string (),
3443 /* Implementation of recording::memento::make_debug_string for
3444 results of new_bitfield. */
3447 recording::bitfield::make_debug_string ()
3449 return string::from_printf (m_ctxt
,
3451 m_name
->c_str (), m_width
);
3454 /* Implementation of recording::memento::write_reproducer for bitfields. */
3457 recording::bitfield::write_reproducer (reproducer
&r
)
3459 const char *id
= r
.make_identifier (this, "bitfield");
3460 r
.write (" gcc_jit_field *%s =\n"
3461 " gcc_jit_context_new_bitfield (%s,\n"
3462 " %s, /* gcc_jit_location *loc */\n"
3463 " %s, /* gcc_jit_type *type, */\n"
3464 " %d, /* int width, */\n"
3465 " %s); /* const char *name */\n",
3467 r
.get_identifier (get_context ()),
3468 r
.get_identifier (m_loc
),
3469 r
.get_identifier_as_type (m_type
),
3471 m_name
->get_debug_string ());
3474 /* The implementation of class gcc::jit::recording::compound_type */
3476 /* The constructor for gcc::jit::recording::compound_type. */
3478 recording::compound_type::compound_type (context
*ctxt
,
3488 /* Set the fields of a compound type.
3490 Implements the post-error-checking part of
3491 gcc_jit_struct_set_fields, and is also used by
3492 gcc_jit_context_new_union_type. */
3495 recording::compound_type::set_fields (location
*loc
,
3497 field
**field_array
)
3500 gcc_assert (m_fields
== NULL
);
3502 m_fields
= new fields (this, num_fields
, field_array
);
3503 m_ctxt
->record (m_fields
);
3506 /* Implementation of pure virtual hook recording::type::dereference for
3507 recording::compound_type. */
3510 recording::compound_type::dereference ()
3512 return NULL
; /* not a pointer */
3515 /* The implementation of class gcc::jit::recording::struct_. */
3517 /* The constructor for gcc::jit::recording::struct_. */
3519 recording::struct_::struct_ (context
*ctxt
,
3522 : compound_type (ctxt
, loc
, name
)
3526 /* Implementation of pure virtual hook recording::memento::replay_into
3527 for recording::struct_. */
3530 recording::struct_::replay_into (replayer
*r
)
3533 r
->new_compound_type (playback_location (r
, get_loc ()),
3534 get_name ()->c_str (),
3535 true /* is_struct */));
3539 recording::struct_::access_as_type (reproducer
&r
)
3541 return r
.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
3542 r
.get_identifier (this));
3545 /* Implementation of recording::memento::make_debug_string for
3549 recording::struct_::make_debug_string ()
3551 return string::from_printf (m_ctxt
,
3552 "struct %s", get_name ()->c_str ());
3556 recording::struct_::write_reproducer (reproducer
&r
)
3558 const char *id
= r
.make_identifier (this, "struct");
3559 r
.write (" gcc_jit_struct *%s =\n"
3560 " gcc_jit_context_new_opaque_struct (%s,\n"
3561 " %s, /* gcc_jit_location *loc */\n"
3562 " %s); /* const char *name */\n",
3564 r
.get_identifier (get_context ()),
3565 r
.get_identifier (get_loc ()),
3566 get_name ()->get_debug_string ());
3569 /* The implementation of class gcc::jit::recording::union_. */
3571 /* The constructor for gcc::jit::recording::union_. */
3573 recording::union_::union_ (context
*ctxt
,
3576 : compound_type (ctxt
, loc
, name
)
3580 /* Implementation of pure virtual hook recording::memento::replay_into
3581 for recording::union_. */
3584 recording::union_::replay_into (replayer
*r
)
3587 r
->new_compound_type (playback_location (r
, get_loc ()),
3588 get_name ()->c_str (),
3589 false /* is_struct */));
3592 /* Implementation of recording::memento::make_debug_string for
3596 recording::union_::make_debug_string ()
3598 return string::from_printf (m_ctxt
,
3599 "union %s", get_name ()->c_str ());
3602 /* Implementation of recording::memento::write_reproducer for unions. */
3605 recording::union_::write_reproducer (reproducer
&r
)
3607 const char *id
= r
.make_identifier (this, "union");
3609 const char *fields_id
= r
.make_tmp_identifier ("fields_for", this);
3610 r
.write (" gcc_jit_field *%s[%i] = {\n",
3612 get_fields ()->length ());
3613 for (int i
= 0; i
< get_fields ()->length (); i
++)
3614 r
.write (" %s,\n", r
.get_identifier (get_fields ()->get_field (i
)));
3617 r
.write (" gcc_jit_type *%s =\n"
3618 " gcc_jit_context_new_union_type (%s,\n"
3619 " %s, /* gcc_jit_location *loc */\n"
3620 " %s, /* const char *name */\n"
3621 " %i, /* int num_fields */\n"
3622 " %s); /* gcc_jit_field **fields */\n",
3624 r
.get_identifier (get_context ()),
3625 r
.get_identifier (get_loc ()),
3626 get_name ()->get_debug_string (),
3627 get_fields ()->length (),
3631 /* The implementation of class gcc::jit::recording::fields. */
3633 /* The constructor for gcc::jit::recording::fields. */
3635 recording::fields::fields (compound_type
*struct_or_union
,
3638 : memento (struct_or_union
->m_ctxt
),
3639 m_struct_or_union (struct_or_union
),
3642 for (int i
= 0; i
< num_fields
; i
++)
3644 gcc_assert (fields
[i
]->get_container () == NULL
);
3645 fields
[i
]->set_container (m_struct_or_union
);
3646 m_fields
.safe_push (fields
[i
]);
3650 /* Implementation of pure virtual hook recording::memento::replay_into
3651 for recording::fields. */
3654 recording::fields::replay_into (replayer
*)
3656 auto_vec
<playback::field
*> playback_fields
;
3657 playback_fields
.create (m_fields
.length ());
3658 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
3659 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
3660 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
3663 /* Override the default implementation of
3664 recording::memento::write_to_dump by writing a union/struct
3665 declaration of this form:
3677 recording::fields::write_to_dump (dump
&d
)
3682 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
3683 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
3684 f
->write_to_dump (d
);
3688 /* Implementation of recording::memento::write_reproducer for the fields
3692 recording::fields::write_reproducer (reproducer
&r
)
3694 if (m_struct_or_union
)
3695 if (m_struct_or_union
->dyn_cast_struct () == NULL
)
3696 /* We have a union; the fields have already been written by
3697 union::write_reproducer. */
3700 const char *fields_id
= r
.make_identifier (this, "fields");
3701 r
.write (" gcc_jit_field *%s[%i] = {\n",
3703 m_fields
.length ());
3706 FOR_EACH_VEC_ELT (m_fields
, i
, field
)
3707 r
.write (" %s,\n", r
.get_identifier (field
));
3710 r
.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
3711 " %s, /* gcc_jit_location *loc */\n"
3712 " %i, /* int num_fields */\n"
3713 " %s); /* gcc_jit_field **fields */\n",
3714 r
.get_identifier (m_struct_or_union
),
3715 r
.get_identifier ((memento
*)NULL
),
3720 /* Implementation of recording::memento::make_debug_string for
3724 recording::fields::make_debug_string ()
3726 return string::from_printf (m_ctxt
,
3730 /* The implementation of class gcc::jit::recording::rvalue. */
3732 /* Create a recording::access_field_rvalue instance and add it to
3733 the rvalue's context's list of mementos.
3735 Implements the post-error-checking part of
3736 gcc_jit_rvalue_access_field. */
3739 recording::rvalue::access_field (recording::location
*loc
,
3742 recording::rvalue
*result
=
3743 new access_field_rvalue (m_ctxt
, loc
, this, field
);
3744 m_ctxt
->record (result
);
3748 /* Create a recording::dereference_field_rvalue instance and add it to
3749 the rvalue's context's list of mementos.
3751 Implements the post-error-checking part of
3752 gcc_jit_rvalue_dereference_field. */
3755 recording::rvalue::dereference_field (recording::location
*loc
,
3758 recording::lvalue
*result
=
3759 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
3760 m_ctxt
->record (result
);
3764 /* Create a recording::dereference_rvalue instance and add it to the
3765 rvalue's context's list of mementos.
3767 Implements the post-error-checking part of
3768 gcc_jit_rvalue_dereference. */
3771 recording::rvalue::dereference (recording::location
*loc
)
3773 recording::lvalue
*result
=
3774 new dereference_rvalue (m_ctxt
, loc
, this);
3775 m_ctxt
->record (result
);
3779 /* An rvalue visitor, for validating that every rvalue within an expression
3780 trees within "STMT" has the correct scope (e.g. no access to locals
3781 of a different function). */
3783 class rvalue_usage_validator
: public recording::rvalue_visitor
3786 rvalue_usage_validator (const char *api_funcname
,
3787 recording::context
*ctxt
,
3788 recording::statement
*stmt
);
3791 visit (recording::rvalue
*rvalue
) final override
;
3794 const char *m_api_funcname
;
3795 recording::context
*m_ctxt
;
3796 recording::statement
*m_stmt
;
3799 /* The trivial constructor for rvalue_usage_validator. */
3801 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname
,
3802 recording::context
*ctxt
,
3803 recording::statement
*stmt
)
3804 : m_api_funcname (api_funcname
),
3810 /* Verify that the given rvalue is in the correct scope. */
3813 rvalue_usage_validator::visit (recording::rvalue
*rvalue
)
3815 gcc_assert (m_stmt
->get_block ());
3816 recording::function
*stmt_scope
= m_stmt
->get_block ()->get_function ();
3818 /* Most rvalues don't have a scope (only locals and params). */
3819 if (rvalue
->get_scope ())
3821 if (rvalue
->get_scope () != stmt_scope
)
3823 (rvalue
->get_loc (),
3825 " rvalue %s (type: %s)"
3826 " has scope limited to function %s"
3827 " but was used within function %s"
3828 " (in statement: %s)",
3830 rvalue
->get_debug_string (),
3831 rvalue
->get_type ()->get_debug_string (),
3832 rvalue
->get_scope ()->get_debug_string (),
3833 stmt_scope
->get_debug_string (),
3834 m_stmt
->get_debug_string ());
3838 if (rvalue
->dyn_cast_param ())
3840 (rvalue
->get_loc (),
3842 " param %s (type: %s)"
3843 " was used within function %s"
3844 " (in statement: %s)"
3845 " but is not associated with any function",
3847 rvalue
->get_debug_string (),
3848 rvalue
->get_type ()->get_debug_string (),
3849 stmt_scope
->get_debug_string (),
3850 m_stmt
->get_debug_string ());
3854 /* Verify that it's valid to use this rvalue (and all expressions
3855 in the tree below it) within the given statement.
3857 For example, we must reject attempts to use a local from one
3858 function within a different function here, or we'll get
3859 an ICE deep inside toplev::main. */
3862 recording::rvalue::verify_valid_within_stmt (const char *api_funcname
, statement
*s
)
3864 rvalue_usage_validator
v (api_funcname
,
3868 /* Verify that it's OK to use this rvalue within s. */
3871 /* Traverse the expression tree below "this", verifying all rvalues
3873 visit_children (&v
);
3876 /* Set the scope of this rvalue to be the given function. This can only
3877 be done once on a given rvalue. */
3880 recording::rvalue::set_scope (function
*scope
)
3883 gcc_assert (m_scope
== NULL
);
3888 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3890 Instances of rvalue don't need an upcast call. */
3893 recording::rvalue::access_as_rvalue (reproducer
&r
)
3895 return r
.get_identifier (this);
3898 /* Return a debug string for the given rvalue, wrapping it in parentheses
3899 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3900 stronger precedence that this rvalue's precedence.
3914 since MULT has strong precedence than PLUS and MINUS, whereas for:
3926 since PLUS has weaker precedence than MULT and DIVIDE. */
3929 recording::rvalue::get_debug_string_parens (enum precedence outer_prec
)
3931 enum precedence this_prec
= get_precedence ();
3933 /* If this_prec has stronger precedence than outer_prec, we don't
3934 need to wrap this in parens within the outer debug string.
3935 Stronger precedences occur earlier than weaker within the enum,
3936 so this is a less than test. Equal precedences don't need
3938 if (this_prec
<= outer_prec
)
3939 return get_debug_string();
3941 /* Otherwise, we need parentheses. */
3943 /* Lazily-build and cache m_parenthesized_string. */
3944 if (!m_parenthesized_string
)
3946 const char *debug_string
= get_debug_string ();
3947 m_parenthesized_string
= string::from_printf (get_context (),
3951 gcc_assert (m_parenthesized_string
);
3952 return m_parenthesized_string
->c_str ();
3956 /* The implementation of class gcc::jit::recording::lvalue. */
3958 /* Create a recording::new_access_field_of_lvalue instance and add it to
3959 the lvalue's context's list of mementos.
3961 Implements the post-error-checking part of
3962 gcc_jit_lvalue_access_field. */
3965 recording::lvalue::access_field (recording::location
*loc
,
3968 recording::lvalue
*result
=
3969 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
3970 m_ctxt
->record (result
);
3974 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3975 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3979 recording::lvalue::access_as_rvalue (reproducer
&r
)
3981 return r
.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3982 r
.get_identifier (this));
3985 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3986 Instances of lvalue don't need to be upcast. */
3989 recording::lvalue::access_as_lvalue (reproducer
&r
)
3991 return r
.get_identifier (this);
3994 /* Create a recording::get_address_of_lvalue instance and add it to
3995 the lvalue's context's list of mementos.
3997 Implements the post-error-checking part of
3998 gcc_jit_lvalue_get_address. */
4001 recording::lvalue::get_address (recording::location
*loc
)
4003 recording::rvalue
*result
=
4004 new get_address_of_lvalue (m_ctxt
, loc
, this);
4005 m_ctxt
->record (result
);
4010 recording::lvalue::set_tls_model (enum gcc_jit_tls_model model
)
4012 m_tls_model
= model
;
4015 void recording::lvalue::set_link_section (const char *name
)
4017 m_link_section
= new_string (name
);
4020 void recording::lvalue::set_register_name (const char *reg_name
)
4022 m_reg_name
= new_string (reg_name
);
4025 void recording::lvalue::set_alignment (unsigned bytes
)
4027 m_alignment
= bytes
;
4030 void recording::lvalue::add_string_attribute (
4031 gcc_jit_variable_attribute attribute
,
4034 m_string_attributes
.push_back (std::make_pair (attribute
, std::string (value
)));
4037 /* The implementation of class gcc::jit::recording::param. */
4039 /* Implementation of pure virtual hook recording::memento::replay_into
4040 for recording::param. */
4043 recording::param::replay_into (replayer
*r
)
4045 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
4046 m_type
->playback_type (),
4050 /* Implementation of recording::rvalue::access_as_rvalue for params.
4051 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
4055 recording::param::access_as_rvalue (reproducer
&r
)
4057 return r
.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
4058 r
.get_identifier (this));
4061 /* Implementation of recording::lvalue::access_as_lvalue for params.
4062 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
4066 recording::param::access_as_lvalue (reproducer
&r
)
4068 return r
.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
4069 r
.get_identifier (this));
4072 /* Implementation of recording::memento::write_reproducer for params. */
4075 recording::param::write_reproducer (reproducer
&r
)
4077 const char *id
= r
.make_identifier (this, "param");
4078 r
.write (" gcc_jit_param *%s =\n"
4079 " gcc_jit_context_new_param (%s,\n"
4080 " %s, /* gcc_jit_location *loc */\n"
4081 " %s, /*gcc_jit_type *type */\n"
4082 " %s); /* const char *name */\n",
4084 r
.get_identifier (get_context ()),
4085 r
.get_identifier (m_loc
),
4086 r
.get_identifier_as_type (m_type
),
4087 m_name
->get_debug_string ());
4090 /* The implementation of class gcc::jit::recording::function. */
4092 /* gcc::jit::recording::function's constructor. */
4094 recording::function::function (context
*ctxt
,
4095 recording::location
*loc
,
4096 enum gcc_jit_function_kind kind
,
4098 recording::string
*name
,
4100 recording::param
**params
,
4102 enum built_in_function builtin_id
)
4106 m_return_type (return_type
),
4109 m_is_variadic (is_variadic
),
4110 m_builtin_id (builtin_id
),
4113 m_fn_ptr_type (NULL
),
4115 m_string_attributes (),
4116 m_int_array_attributes ()
4118 for (int i
= 0; i
< num_params
; i
++)
4120 param
*param
= params
[i
];
4123 /* Associate each param with this function.
4125 Verify that the param doesn't already have a function. */
4126 if (param
->get_scope ())
4128 /* We've already rejected attempts to reuse a param between
4129 different functions (within gcc_jit_context_new_function), so
4130 if the param *does* already have a function, it must be being
4131 reused within the params array for this function. We must
4132 produce an error for this reuse (blocking the compile), since
4133 otherwise we'd have an ICE later on. */
4134 gcc_assert (this == param
->get_scope ());
4137 "gcc_jit_context_new_function:"
4138 " parameter %s (type: %s)"
4139 " is used more than once when creating function %s",
4140 param
->get_debug_string (),
4141 param
->get_type ()->get_debug_string (),
4146 /* The normal, non-error case: associate this function with the
4148 param
->set_scope (this);
4151 m_params
.safe_push (param
);
4155 /* Implementation of pure virtual hook recording::memento::replay_into
4156 for recording::function. */
4159 recording::function::replay_into (replayer
*r
)
4161 /* Convert m_params to a vec of playback param. */
4162 auto_vec
<playback::param
*> params
;
4164 recording::param
*param
;
4165 params
.create (m_params
.length ());
4166 FOR_EACH_VEC_ELT (m_params
, i
, param
)
4167 params
.safe_push (param
->playback_param ());
4169 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
4171 m_return_type
->playback_type (),
4177 m_string_attributes
,
4178 m_int_array_attributes
));
4181 /* Create a recording::local instance and add it to
4182 the functions's context's list of mementos, and to the function's
4185 Implements the post-error-checking part of
4186 gcc_jit_function_new_local. */
4189 recording::function::new_local (recording::location
*loc
,
4193 local
*result
= new local (this, loc
, type
, new_string (name
));
4194 m_ctxt
->record (result
);
4195 m_locals
.safe_push (result
);
4199 /* Create a recording::block instance and add it to
4200 the functions's context's list of mementos, and to the function's
4203 Implements the post-error-checking part of
4204 gcc_jit_function_new_block. */
4207 recording::function::new_block (const char *name
)
4209 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
4211 recording::block
*result
=
4212 new recording::block (this, m_blocks
.length (), new_string (name
));
4213 m_ctxt
->record (result
);
4214 m_blocks
.safe_push (result
);
4218 /* Override the default implementation of
4219 recording::memento::write_to_dump by dumping a C-like
4220 representation of the function; either like a prototype
4221 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
4222 all other kinds of function. */
4225 recording::function::write_to_dump (dump
&d
)
4227 for (auto attr
: m_attributes
)
4229 const char* attribute
= fn_attribute_to_string (attr
);
4231 d
.write ("__attribute(%s)__\n", attribute
);
4233 for (auto attr
: m_string_attributes
)
4235 gcc_jit_fn_attribute
& name
= std::get
<0>(attr
);
4236 std::string
& value
= std::get
<1>(attr
);
4237 const char* attribute
= fn_attribute_to_string (name
);
4240 d
.write ("__attribute(%s(\"%s\"))__\n", attribute
, value
.c_str());
4242 for (auto attr
: m_int_array_attributes
)
4244 gcc_jit_fn_attribute
& name
= std::get
<0>(attr
);
4245 std::vector
<int>& values
= std::get
<1>(attr
);
4246 const char* attribute
= fn_attribute_to_string (name
);
4249 d
.write ("__attribute(%s(", attribute
);
4250 for (size_t i
= 0; i
< values
.size(); ++i
)
4253 d
.write (", %d", values
[i
]);
4255 d
.write ("%d", values
[i
]);
4263 default: gcc_unreachable ();
4264 case GCC_JIT_FUNCTION_EXPORTED
:
4265 case GCC_JIT_FUNCTION_IMPORTED
:
4266 d
.write ("extern ");
4268 case GCC_JIT_FUNCTION_INTERNAL
:
4269 d
.write ("static ");
4271 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
4272 d
.write ("static inline ");
4275 d
.write ("%s\n", m_return_type
->get_debug_string ());
4277 if (d
.update_locations ())
4278 m_loc
= d
.make_location ();
4280 d
.write ("%s (", get_debug_string ());
4283 recording::param
*param
;
4284 FOR_EACH_VEC_ELT (m_params
, i
, param
)
4289 param
->get_type ()->get_debug_string (),
4290 param
->get_debug_string ());
4293 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
4295 d
.write ("; /* (imported) */\n\n");
4305 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
4306 var
->write_to_dump (d
);
4307 if (m_locals
.length ())
4310 /* Write each block: */
4311 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
4315 b
->write_to_dump (d
);
4322 /* Pre-compilation validation of a function, for those things we can't
4323 check until the context is (supposedly) fully-populated. */
4326 recording::function::validate ()
4328 /* Complain about empty functions with non-void return type. */
4329 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
4330 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
4331 if (m_blocks
.length () == 0)
4332 m_ctxt
->add_error (m_loc
,
4333 "function %s returns non-void (type: %s)"
4334 " but has no blocks",
4335 get_debug_string (),
4336 m_return_type
->get_debug_string ());
4338 /* Check that all blocks are terminated. */
4339 int num_invalid_blocks
= 0;
4344 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
4345 if (!b
->validate ())
4346 num_invalid_blocks
++;
4349 /* Check that all blocks are reachable. */
4350 if (!m_ctxt
->get_inner_bool_option
4351 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS
)
4352 && m_blocks
.length () > 0 && num_invalid_blocks
== 0)
4354 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
4355 flag, starting at the initial block. */
4356 auto_vec
<block
*> worklist (m_blocks
.length ());
4357 worklist
.safe_push (m_blocks
[0]);
4358 while (worklist
.length () > 0)
4360 block
*b
= worklist
.pop ();
4361 b
->m_is_reachable
= true;
4363 /* Add successor blocks that aren't yet marked to the worklist. */
4364 /* We checked that each block has a terminating statement above . */
4365 vec
<block
*> successors
= b
->get_successor_blocks ();
4368 FOR_EACH_VEC_ELT (successors
, i
, succ
)
4369 if (!succ
->m_is_reachable
)
4370 worklist
.safe_push (succ
);
4371 successors
.release ();
4374 /* Now complain about any blocks that haven't been marked. */
4378 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
4379 if (!b
->m_is_reachable
)
4380 m_ctxt
->add_error (b
->get_loc (),
4381 "unreachable block: %s",
4382 b
->get_debug_string ());
4387 /* Implements the post-error-checking part of
4388 gcc_jit_function_dump_to_dot. */
4391 recording::function::dump_to_dot (const char *path
)
4393 FILE *fp
= fopen (path
, "w");
4397 pretty_printer the_pp
;
4398 the_pp
.buffer
->stream
= fp
;
4400 pretty_printer
*pp
= &the_pp
;
4402 pp_printf (pp
, "digraph %s", get_debug_string ());
4403 pp_string (pp
, " {\n");
4409 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
4410 b
->dump_to_dot (pp
);
4417 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
4418 b
->dump_edges_to_dot (pp
);
4421 pp_string (pp
, "}\n");
4426 /* Implements the post-error-checking part of
4427 gcc_jit_function_get_address. */
4430 recording::function::get_address (recording::location
*loc
)
4432 /* Lazily create and cache the function pointer type. */
4435 /* Make a recording::function_type for this function. */
4436 auto_vec
<recording::type
*> param_types (m_params
.length ());
4438 recording::param
*param
;
4439 FOR_EACH_VEC_ELT (m_params
, i
, param
)
4440 param_types
.safe_push (param
->get_type ());
4441 recording::function_type
*fn_type
4442 = m_ctxt
->new_function_type (m_return_type
,
4444 param_types
.address (),
4446 m_fn_ptr_type
= fn_type
->get_pointer ();
4448 gcc_assert (m_fn_ptr_type
);
4450 rvalue
*result
= new function_pointer (get_context (), loc
, this, m_fn_ptr_type
);
4451 m_ctxt
->record (result
);
4456 recording::function::add_attribute (gcc_jit_fn_attribute attribute
)
4458 m_attributes
.push_back (attribute
);
4462 recording::function::add_string_attribute (gcc_jit_fn_attribute attribute
,
4465 m_string_attributes
.push_back (
4466 std::make_pair (attribute
, std::string (value
)));
4470 recording::function::add_integer_array_attribute (
4471 gcc_jit_fn_attribute attribute
,
4475 m_int_array_attributes
.push_back (std::make_pair (
4477 std::vector
<int> (value
, value
+ length
)));
4480 /* Implementation of recording::memento::make_debug_string for
4484 recording::function::make_debug_string ()
4489 /* A table of enum gcc_jit_function_kind values expressed in string
4492 static const char * const names_of_function_kinds
[] = {
4493 "GCC_JIT_FUNCTION_EXPORTED",
4494 "GCC_JIT_FUNCTION_INTERNAL",
4495 "GCC_JIT_FUNCTION_IMPORTED",
4496 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
4499 /* Implementation of recording::memento::write_reproducer for functions. */
4501 static const char * const fn_attribute_reproducer_strings
[] =
4503 "GCC_JIT_FN_ATTRIBUTE_ALIAS",
4504 "GCC_JIT_FN_ATTRIBUTE_ALWAYS_INLINE",
4505 "GCC_JIT_FN_ATTRIBUTE_INLINE",
4506 "GCC_JIT_FN_ATTRIBUTE_NOINLINE",
4507 "GCC_JIT_FN_ATTRIBUTE_TARGET",
4508 "GCC_JIT_FN_ATTRIBUTE_USED",
4509 "GCC_JIT_FN_ATTRIBUTE_VISIBILITY",
4510 "GCC_JIT_FN_ATTRIBUTE_COLD",
4511 "GCC_JIT_FN_ATTRIBUTE_RETURNS_TWICE",
4512 "GCC_JIT_FN_ATTRIBUTE_PURE",
4513 "GCC_JIT_FN_ATTRIBUTE_CONST",
4514 "GCC_JIT_FN_ATTRIBUTE_WEAK",
4515 "GCC_JIT_FN_ATTRIBUTE_NONNULL",
4519 get_vector_int_debug (std::vector
<int> &values
)
4521 std::stringstream s
;
4524 for(auto it
= values
.begin(); it
!= values
.end(); ++it
)
4526 if (it
!= values
.begin() )
4535 recording::function::write_reproducer (reproducer
&r
)
4537 const char *id
= r
.make_identifier (this, "func");
4541 r
.write (" gcc_jit_function *%s =\n"
4542 " gcc_jit_context_get_builtin_function (%s,\n"
4545 r
.get_identifier (get_context ()),
4546 m_name
->get_debug_string ());
4549 const char *params_id
= r
.make_tmp_identifier ("params_for", this);
4550 r
.write (" gcc_jit_param *%s[%i] = {\n",
4552 m_params
.length ());
4555 FOR_EACH_VEC_ELT (m_params
, i
, param
)
4556 r
.write (" %s,\n", r
.get_identifier (param
));
4558 r
.write (" gcc_jit_function *%s =\n"
4559 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
4560 " %s, /* gcc_jit_location *loc */\n"
4561 " %s, /* enum gcc_jit_function_kind kind */\n"
4562 " %s, /* gcc_jit_type *return_type */\n"
4563 " %s, /* const char *name */\n"
4564 " %i, /* int num_params */\n"
4565 " %s, /* gcc_jit_param **params */\n"
4566 " %i); /* int is_variadic */\n",
4568 r
.get_identifier (get_context ()),
4569 r
.get_identifier (m_loc
),
4570 names_of_function_kinds
[m_kind
],
4571 r
.get_identifier_as_type (m_return_type
),
4572 m_name
->get_debug_string (),
4576 for (auto attribute
: m_attributes
)
4577 r
.write(" gcc_jit_function_add_attribute (%s, %s);\n",
4579 fn_attribute_reproducer_strings
[attribute
]);
4580 for (auto attribute
: m_string_attributes
)
4581 r
.write(" gcc_jit_function_add_string_attribute (%s, %s, \"%s\");\n",
4583 fn_attribute_reproducer_strings
[std::get
<0>(attribute
)],
4584 std::get
<1>(attribute
).c_str());
4585 for (auto attribute
: m_int_array_attributes
) {
4586 r
.write(" gcc_jit_function_add_integer_array_attribute (%s,\n"
4591 fn_attribute_reproducer_strings
[std::get
<0>(attribute
)],
4592 get_vector_int_debug (std::get
<1>(attribute
)).c_str(),
4593 std::get
<1>(attribute
).size ());
4598 /* The implementation of class gcc::jit::recording::block. */
4600 /* Create a recording::eval instance and add it to
4601 the block's context's list of mementos, and to the block's
4604 Implements the heart of gcc_jit_block_add_eval. */
4606 recording::statement
*
4607 recording::block::add_eval (recording::location
*loc
,
4608 recording::rvalue
*rvalue
)
4610 statement
*result
= new eval (this, loc
, rvalue
);
4611 m_ctxt
->record (result
);
4612 m_statements
.safe_push (result
);
4616 /* Create a recording::assignment instance and add it to
4617 the block's context's list of mementos, and to the block's
4620 Implements the heart of gcc_jit_block_add_assignment. */
4622 recording::statement
*
4623 recording::block::add_assignment (recording::location
*loc
,
4624 recording::lvalue
*lvalue
,
4625 recording::rvalue
*rvalue
)
4627 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
4628 m_ctxt
->record (result
);
4629 m_statements
.safe_push (result
);
4633 /* Create a recording::assignment_op instance and add it to
4634 the block's context's list of mementos, and to the block's
4637 Implements the heart of gcc_jit_block_add_assignment_op. */
4639 recording::statement
*
4640 recording::block::add_assignment_op (recording::location
*loc
,
4641 recording::lvalue
*lvalue
,
4642 enum gcc_jit_binary_op op
,
4643 recording::rvalue
*rvalue
)
4645 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
4646 m_ctxt
->record (result
);
4647 m_statements
.safe_push (result
);
4651 /* Create a recording::comment instance and add it to
4652 the block's context's list of mementos, and to the block's
4655 Implements the heart of gcc_jit_block_add_comment. */
4657 recording::statement
*
4658 recording::block::add_comment (recording::location
*loc
,
4661 statement
*result
= new comment (this, loc
, new_string (text
));
4662 m_ctxt
->record (result
);
4663 m_statements
.safe_push (result
);
4667 /* Create a recording::extended_asm_simple instance and add it to
4668 the block's context's list of mementos, and to the block's
4671 Implements the heart of gcc_jit_block_add_extended_asm. */
4673 recording::extended_asm
*
4674 recording::block::add_extended_asm (location
*loc
,
4675 const char *asm_template
)
4677 extended_asm
*result
4678 = new extended_asm_simple (this, loc
, new_string (asm_template
));
4679 m_ctxt
->record (result
);
4680 m_statements
.safe_push (result
);
4684 /* Create a recording::end_with_conditional instance and add it to
4685 the block's context's list of mementos, and to the block's
4688 Implements the heart of gcc_jit_block_end_with_conditional. */
4690 recording::statement
*
4691 recording::block::end_with_conditional (recording::location
*loc
,
4692 recording::rvalue
*boolval
,
4693 recording::block
*on_true
,
4694 recording::block
*on_false
)
4696 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
4697 m_ctxt
->record (result
);
4698 m_statements
.safe_push (result
);
4699 m_has_been_terminated
= true;
4703 /* Create a recording::end_with_jump instance and add it to
4704 the block's context's list of mementos, and to the block's
4707 Implements the heart of gcc_jit_block_end_with_jump. */
4709 recording::statement
*
4710 recording::block::end_with_jump (recording::location
*loc
,
4711 recording::block
*target
)
4713 statement
*result
= new jump (this, loc
, target
);
4714 m_ctxt
->record (result
);
4715 m_statements
.safe_push (result
);
4716 m_has_been_terminated
= true;
4720 /* Create a recording::end_with_return instance and add it to
4721 the block's context's list of mementos, and to the block's
4724 Implements the post-error-checking parts of
4725 gcc_jit_block_end_with_return and
4726 gcc_jit_block_end_with_void_return. */
4728 recording::statement
*
4729 recording::block::end_with_return (recording::location
*loc
,
4730 recording::rvalue
*rvalue
)
4732 /* This is used by both gcc_jit_function_add_return and
4733 gcc_jit_function_add_void_return; rvalue will be non-NULL for
4734 the former and NULL for the latter. */
4735 statement
*result
= new return_ (this, loc
, rvalue
);
4736 m_ctxt
->record (result
);
4737 m_statements
.safe_push (result
);
4738 m_has_been_terminated
= true;
4742 /* Create a recording::switch_ instance and add it to
4743 the block's context's list of mementos, and to the block's
4746 Implements the heart of gcc_jit_block_end_with_switch. */
4748 recording::statement
*
4749 recording::block::end_with_switch (recording::location
*loc
,
4750 recording::rvalue
*expr
,
4751 recording::block
*default_block
,
4753 recording::case_
**cases
)
4755 statement
*result
= new switch_ (this, loc
,
4760 m_ctxt
->record (result
);
4761 m_statements
.safe_push (result
);
4762 m_has_been_terminated
= true;
4766 /* Create a recording::extended_asm_goto instance and add it to
4767 the block's context's list of mementos, and to the block's
4770 Implements the heart of gcc_jit_block_end_with_extended_asm_goto. */
4773 recording::extended_asm
*
4774 recording::block::end_with_extended_asm_goto (location
*loc
,
4775 const char *asm_template
,
4776 int num_goto_blocks
,
4777 block
**goto_blocks
,
4778 block
*fallthrough_block
)
4780 extended_asm
*result
4781 = new extended_asm_goto (this, loc
, new_string (asm_template
),
4782 num_goto_blocks
, goto_blocks
,
4784 m_ctxt
->record (result
);
4785 m_statements
.safe_push (result
);
4786 m_has_been_terminated
= true;
4790 /* Override the default implementation of
4791 recording::memento::write_to_dump for blocks by writing
4792 an unindented block name as a label, followed by the indented
4802 recording::block::write_to_dump (dump
&d
)
4804 d
.write ("%s:\n", get_debug_string ());
4808 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
4809 s
->write_to_dump (d
);
4812 /* Validate a block by ensuring that it has been terminated. */
4815 recording::block::validate ()
4817 /* Check for termination. */
4818 if (!has_been_terminated ())
4820 statement
*stmt
= get_last_statement ();
4821 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
4822 m_func
->get_context ()->add_error (loc
,
4823 "unterminated block in %s: %s",
4824 m_func
->get_debug_string (),
4825 get_debug_string ());
4832 /* Get the source-location of a block by using that of the first
4833 statement within it, if any. */
4835 recording::location
*
4836 recording::block::get_loc () const
4838 recording::statement
*stmt
= get_first_statement ();
4840 return stmt
->get_loc ();
4845 /* Get the first statement within a block, if any. */
4847 recording::statement
*
4848 recording::block::get_first_statement () const
4850 if (m_statements
.length ())
4851 return m_statements
[0];
4856 /* Get the last statement within a block, if any. */
4858 recording::statement
*
4859 recording::block::get_last_statement () const
4861 if (m_statements
.length ())
4862 return m_statements
[m_statements
.length () - 1];
4867 /* Assuming that this block has been terminated, get the successor blocks
4868 as a vector. Ownership of the vector transfers to the caller, which
4869 must call its release () method.
4871 Used when validating functions, and when dumping dot representations
4874 vec
<recording::block
*>
4875 recording::block::get_successor_blocks () const
4877 gcc_assert (m_has_been_terminated
);
4878 statement
*last_statement
= get_last_statement ();
4879 gcc_assert (last_statement
);
4880 return last_statement
->get_successor_blocks ();
4883 /* Implementation of pure virtual hook recording::memento::replay_into
4884 for recording::block. */
4887 recording::block::replay_into (replayer
*)
4889 set_playback_obj (m_func
->playback_function ()
4890 ->new_block (playback_string (m_name
)));
4893 /* Implementation of recording::memento::make_debug_string for
4897 recording::block::make_debug_string ()
4902 return string::from_printf (m_ctxt
,
4903 "<UNNAMED BLOCK %p>",
4907 /* Implementation of recording::memento::write_reproducer for blocks. */
4910 recording::block::write_reproducer (reproducer
&r
)
4912 const char *id
= r
.make_identifier (this, "block");
4913 r
.write (" gcc_jit_block *%s =\n"
4914 " gcc_jit_function_new_block (%s, %s);\n",
4916 r
.get_identifier (m_func
),
4917 m_name
? m_name
->get_debug_string () : "NULL");
4920 /* Disable warnings about missing quoting in GCC diagnostics for
4921 the pp_printf calls. Their format strings deliberately don't
4922 follow GCC diagnostic conventions. */
4924 # pragma GCC diagnostic push
4925 # pragma GCC diagnostic ignored "-Wformat-diag"
4928 /* Dump a block in graphviz form into PP, capturing the block name (if
4929 any) and the statements. */
4932 recording::block::dump_to_dot (pretty_printer
*pp
)
4936 "[shape=record,style=filled,fillcolor=white,label=\"{"),
4938 pp_write_text_to_stream (pp
);
4941 pp_string (pp
, m_name
->c_str ());
4942 pp_string (pp
, ":");
4944 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
4949 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
4951 pp_string (pp
, s
->get_debug_string ());
4953 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
4961 /* Dump the out-edges of the block in graphviz form into PP. */
4964 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
4966 vec
<block
*> successors
= get_successor_blocks ();
4969 FOR_EACH_VEC_ELT (successors
, i
, succ
)
4971 "\tblock_%d:s -> block_%d:n;\n",
4972 m_index
, succ
->m_index
);
4973 successors
.release ();
4977 # pragma GCC diagnostic pop
4980 namespace recording
{
4981 static const enum tls_model tls_models
[] = {
4982 TLS_MODEL_NONE
, /* GCC_JIT_TLS_MODEL_NONE */
4983 TLS_MODEL_GLOBAL_DYNAMIC
, /* GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC */
4984 TLS_MODEL_LOCAL_DYNAMIC
, /* GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC */
4985 TLS_MODEL_INITIAL_EXEC
, /* GCC_JIT_TLS_MODEL_INITIAL_EXEC */
4986 TLS_MODEL_LOCAL_EXEC
, /* GCC_JIT_TLS_MODEL_LOCAL_EXEC */
4988 } /* namespace recording */
4990 /* The implementation of class gcc::jit::recording::global. */
4992 /* Implementation of pure virtual hook recording::memento::replay_into
4993 for recording::global. */
4996 recording::global::replay_into (replayer
*r
)
4998 playback::lvalue
*global
= m_initializer
4999 ? r
->new_global_initialized (playback_location (r
, m_loc
),
5001 m_type
->playback_type (),
5002 m_type
->dereference ()->get_size (),
5003 m_initializer_num_bytes
5004 / m_type
->dereference ()->get_size (),
5006 playback_string (m_name
),
5008 m_string_attributes
)
5009 : r
->new_global (playback_location (r
, m_loc
),
5011 m_type
->playback_type (),
5012 playback_string (m_name
),
5014 m_string_attributes
);
5016 if (m_tls_model
!= GCC_JIT_TLS_MODEL_NONE
)
5017 global
->set_tls_model (recording::tls_models
[m_tls_model
]);
5019 if (m_link_section
!= NULL
)
5020 global
->set_link_section (m_link_section
->c_str ());
5022 if (m_reg_name
!= NULL
)
5023 global
->set_register_name (m_reg_name
->c_str ());
5025 if (m_alignment
!= 0)
5026 global
->set_alignment (m_alignment
);
5028 set_playback_obj (global
);
5031 /* Override the default implementation of
5032 recording::memento::write_to_dump for globals.
5033 This will be of the form:
5035 GCC_JIT_GLOBAL_EXPORTED:
5039 GCC_JIT_GLOBAL_INTERNAL:
5041 e.g. "static int foo;"
5043 GCC_JIT_GLOBAL_IMPORTED:
5045 e.g. "extern int foo;"
5047 These are written to the top of the dump by
5048 recording::context::dump_to_file. */
5051 recording::global::write_to_dump (dump
&d
)
5053 if (d
.update_locations ())
5054 m_loc
= d
.make_location ();
5061 case GCC_JIT_GLOBAL_EXPORTED
:
5064 case GCC_JIT_GLOBAL_INTERNAL
:
5065 d
.write ("static ");
5068 case GCC_JIT_GLOBAL_IMPORTED
:
5069 d
.write ("extern ");
5073 for (auto attr
: m_string_attributes
)
5075 gcc_jit_variable_attribute
& name
= std::get
<0>(attr
);
5076 std::string
& value
= std::get
<1>(attr
);
5077 const char* attribute
= variable_attribute_to_string (name
);
5080 d
.write ("__attribute(%s(\"%s\"))__\n", attribute
, value
.c_str());
5083 m_type
->get_debug_string (),
5084 get_debug_string ());
5086 if (!m_initializer
&& !m_rvalue_init
)
5090 else if (m_initializer
)
5093 const unsigned char *p
= (const unsigned char *)m_initializer
;
5094 for (size_t i
= 0; i
< m_initializer_num_bytes
; i
++)
5096 d
.write ("0x%x, ", p
[i
]);
5102 else if (m_rvalue_init
)
5105 d
.write ("%s", m_rvalue_init
->get_debug_string ());
5112 /* A table of enum gcc_jit_global_kind values expressed in string
5115 static const char * const global_kind_reproducer_strings
[] = {
5116 "GCC_JIT_GLOBAL_EXPORTED",
5117 "GCC_JIT_GLOBAL_INTERNAL",
5118 "GCC_JIT_GLOBAL_IMPORTED"
5121 template <typename T
>
5123 recording::global::write_initializer_reproducer (const char *id
, reproducer
&r
)
5125 const char *init_id
= r
.make_tmp_identifier ("init_for", this);
5126 r
.write (" %s %s[] =\n {",
5127 m_type
->dereference ()->get_debug_string (),
5130 const T
*p
= (const T
*)m_initializer
;
5131 for (size_t i
= 0; i
< m_initializer_num_bytes
/ sizeof (T
); i
++)
5133 r
.write ("%" PRIu64
", ", (uint64_t)p
[i
]);
5138 r
.write (" gcc_jit_global_set_initializer (%s, %s, sizeof (%s));\n",
5139 id
, init_id
, init_id
);
5142 /* Implementation of recording::memento::write_reproducer for globals. */
5144 static const char * const tls_model_enum_strings
[] = {
5145 "GCC_JIT_TLS_MODEL_NONE",
5146 "GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC",
5147 "GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC",
5148 "GCC_JIT_TLS_MODEL_INITIAL_EXEC",
5149 "GCC_JIT_TLS_MODEL_LOCAL_EXEC",
5152 static const char * const gcc_jit_variable_attribute_enum_strings
[] = {
5153 "GCC_JIT_VARIABLE_ATTRIBUTE_VISIBILITY",
5157 recording::global::write_reproducer (reproducer
&r
)
5159 const char *id
= r
.make_identifier (this, "block");
5160 r
.write (" gcc_jit_lvalue *%s =\n"
5161 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
5162 " %s, /* gcc_jit_location *loc */\n"
5163 " %s, /* enum gcc_jit_global_kind kind */\n"
5164 " %s, /* gcc_jit_type *type */\n"
5165 " %s); /* const char *name */\n",
5167 r
.get_identifier (get_context ()),
5168 r
.get_identifier (m_loc
),
5169 global_kind_reproducer_strings
[m_kind
],
5170 r
.get_identifier_as_type (get_type ()),
5171 m_name
->get_debug_string ());
5173 if (m_tls_model
!= GCC_JIT_TLS_MODEL_NONE
)
5174 r
.write (" gcc_jit_lvalue_set_tls_model (%s, /* gcc_jit_lvalue *lvalue */\n"
5175 " %s); /* enum gcc_jit_tls_model model */\n",
5177 tls_model_enum_strings
[m_tls_model
]);
5179 if (m_link_section
!= NULL
)
5180 r
.write (" gcc_jit_lvalue_set_link_section (%s, /* gcc_jit_lvalue *lvalue */\n"
5181 " \"%s\"); /* */\n",
5183 m_link_section
->c_str ());
5185 for (auto attribute
: m_string_attributes
)
5186 r
.write(" gcc_jit_lvalue_add_string_attribute (%s, %s, \"%s\");\n",
5188 gcc_jit_variable_attribute_enum_strings
[std::get
<0>(attribute
)],
5189 std::get
<1>(attribute
).c_str());
5193 switch (m_type
->dereference ()->get_size ())
5196 write_initializer_reproducer
<uint8_t> (id
, r
);
5199 write_initializer_reproducer
<uint16_t> (id
, r
);
5202 write_initializer_reproducer
<uint32_t> (id
, r
);
5205 write_initializer_reproducer
<uint64_t> (id
, r
);
5208 /* This function is serving on sizes returned by 'get_size',
5209 these are all covered by the previous cases. */
5214 /* The implementation of the various const-handling classes:
5215 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
5217 /* Explicit specialization of the various mementos we're interested in. */
5218 template class recording::memento_of_new_rvalue_from_const
<int>;
5219 template class recording::memento_of_new_rvalue_from_const
<long>;
5220 template class recording::memento_of_new_rvalue_from_const
<double>;
5221 template class recording::memento_of_new_rvalue_from_const
<void *>;
5223 /* Implementation of the pure virtual hook recording::memento::replay_into
5224 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
5226 template <typename HOST_TYPE
>
5229 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
5232 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
5236 /* The make_debug_string and write_reproducer methods vary between the
5238 memento_of_new_rvalue_from_const <HOST_TYPE>
5239 classes, so we explicitly write specializations of them.
5241 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
5242 namespaces are written out explicitly, which is why most of this file
5243 doesn't abbreviate things by entering the "recording" namespace.
5245 However, these specializations are required to be in the same namespace
5246 as the template, hence we now have to enter the gcc::jit::recording
5252 /* The make_debug_string specialization for <int>, which renders it as
5253 (TARGET_TYPE)LITERAL
5259 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
5261 return string::from_printf (m_ctxt
,
5263 m_type
->get_debug_string (),
5267 /* The get_wide_int specialization for <int>. */
5271 memento_of_new_rvalue_from_const
<int>::get_wide_int (wide_int
*out
) const
5273 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
5277 /* The write_reproducer specialization for <int>. */
5281 memento_of_new_rvalue_from_const
<int>::write_reproducer (reproducer
&r
)
5283 const char *id
= r
.make_identifier (this, "rvalue");
5284 r
.write (" gcc_jit_rvalue *%s =\n"
5285 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
5286 " %s, /* gcc_jit_type *numeric_type */\n"
5287 " %i); /* int value */\n",
5289 r
.get_identifier (get_context ()),
5290 r
.get_identifier_as_type (m_type
),
5294 /* The make_debug_string specialization for <long>, rendering it as
5295 (TARGET_TYPE)LITERAL
5301 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
5303 return string::from_printf (m_ctxt
,
5305 m_type
->get_debug_string (),
5309 /* The get_wide_int specialization for <long>. */
5313 memento_of_new_rvalue_from_const
<long>::get_wide_int (wide_int
*out
) const
5315 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
5319 /* The write_reproducer specialization for <long>. */
5323 recording::memento_of_new_rvalue_from_const
<long>::write_reproducer (reproducer
&r
)
5325 const char *id
= r
.make_identifier (this, "rvalue");
5327 /* We have to special-case LONG_MIN, since e.g.
5328 -9223372036854775808L
5330 -(9223372036854775808L)
5332 error: integer constant is so large that it is unsigned [-Werror]
5333 Workaround this by writing (LONG_MIN + 1) - 1. */
5334 if (m_value
== LONG_MIN
)
5336 r
.write (" gcc_jit_rvalue *%s =\n"
5337 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
5338 " %s, /* gcc_jit_type *numeric_type */\n"
5339 " %ldL - 1); /* long value */\n",
5341 r
.get_identifier (get_context ()),
5342 r
.get_identifier_as_type (m_type
),
5347 r
.write (" gcc_jit_rvalue *%s =\n"
5348 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
5349 " %s, /* gcc_jit_type *numeric_type */\n"
5350 " %ldL); /* long value */\n",
5352 r
.get_identifier (get_context ()),
5353 r
.get_identifier_as_type (m_type
),
5357 /* The make_debug_string specialization for <double>, rendering it as
5358 (TARGET_TYPE)LITERAL
5364 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
5366 return string::from_printf (m_ctxt
,
5368 m_type
->get_debug_string (),
5372 /* The get_wide_int specialization for <double>. */
5376 memento_of_new_rvalue_from_const
<double>::get_wide_int (wide_int
*) const
5381 /* The write_reproducer specialization for <double>. */
5385 recording::memento_of_new_rvalue_from_const
<double>::write_reproducer (reproducer
&r
)
5387 const char *id
= r
.make_identifier (this, "rvalue");
5388 r
.write (" gcc_jit_rvalue *%s =\n"
5389 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
5390 " %s, /* gcc_jit_type *numeric_type */\n"
5391 " %f); /* double value */\n",
5393 r
.get_identifier (get_context ()),
5394 r
.get_identifier_as_type (m_type
),
5398 /* The make_debug_string specialization for <void *>, rendering it as
5403 Zero is rendered as NULL e.g.
5408 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
5410 if (m_value
!= NULL
)
5411 return string::from_printf (m_ctxt
,
5413 m_type
->get_debug_string (), m_value
);
5415 return string::from_printf (m_ctxt
,
5417 m_type
->get_debug_string ());
5420 /* The get_wide_int specialization for <void *>. */
5424 memento_of_new_rvalue_from_const
<void *>::get_wide_int (wide_int
*) const
5429 /* Implementation of recording::memento::write_reproducer for <void *>
5434 memento_of_new_rvalue_from_const
<void *>::write_reproducer (reproducer
&r
)
5436 const char *id
= r
.make_identifier (this, "rvalue");
5438 r
.write (" gcc_jit_rvalue *%s =\n"
5439 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
5440 " %s, /* gcc_jit_type *pointer_type */\n"
5441 " (void *)%p); /* void *value */\n",
5443 r
.get_identifier (get_context ()),
5444 r
.get_identifier_as_type (m_type
),
5447 r
.write (" gcc_jit_rvalue *%s =\n"
5448 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
5449 " %s); /* gcc_jit_type *pointer_type */\n",
5451 r
.get_identifier (get_context ()),
5452 r
.get_identifier_as_type (m_type
));
5455 /* We're done specializing make_debug_string and write_reproducer, so we
5456 can exit the gcc::jit::recording namespace. */
5458 } // namespace recording
5460 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
5462 /* Implementation of pure virtual hook recording::memento::replay_into
5463 for recording::memento_of_new_string_literal. */
5466 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
5468 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
5471 /* Implementation of recording::memento::make_debug_string for
5475 recording::memento_of_new_string_literal::make_debug_string ()
5477 return string::from_printf (m_ctxt
,
5479 m_value
->get_debug_string ());
5482 /* Implementation of recording::memento::write_reproducer for string literal
5486 recording::memento_of_new_string_literal::write_reproducer (reproducer
&r
)
5488 const char *id
= r
.make_identifier (this, "rvalue");
5489 r
.write (" gcc_jit_rvalue *%s =\n"
5490 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
5491 " %s); /* const char *value */\n",
5493 r
.get_identifier (get_context ()),
5494 m_value
->get_debug_string ());
5497 /* The implementation of class
5498 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
5500 /* The constructor for
5501 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
5503 recording::memento_of_new_rvalue_from_vector::
5504 memento_of_new_rvalue_from_vector (context
*ctxt
,
5508 : rvalue (ctxt
, loc
, type
),
5509 m_vector_type (type
),
5512 for (unsigned i
= 0; i
< type
->get_num_units (); i
++)
5513 m_elements
.safe_push (elements
[i
]);
5516 /* Implementation of pure virtual hook recording::memento::replay_into
5517 for recording::memento_of_new_rvalue_from_vector. */
5520 recording::memento_of_new_rvalue_from_vector::replay_into (replayer
*r
)
5522 auto_vec
<playback::rvalue
*> playback_elements
;
5523 playback_elements
.create (m_elements
.length ());
5524 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
5525 playback_elements
.safe_push (m_elements
[i
]->playback_rvalue ());
5527 set_playback_obj (r
->new_rvalue_from_vector (playback_location (r
, m_loc
),
5528 m_type
->playback_type (),
5529 playback_elements
));
5532 /* Implementation of pure virtual hook recording::rvalue::visit_children
5533 for recording::memento_of_new_rvalue_from_vector. */
5536 recording::memento_of_new_rvalue_from_vector::visit_children (rvalue_visitor
*v
)
5538 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
5539 v
->visit (m_elements
[i
]);
5542 /* Implementation of recording::memento::make_debug_string for
5546 recording::memento_of_new_rvalue_from_vector::make_debug_string ()
5548 comma_separated_string
elements (m_elements
, get_precedence ());
5550 /* Now build a string. */
5551 string
*result
= string::from_printf (m_ctxt
,
5553 elements
.as_char_ptr ());
5559 /* Implementation of recording::memento::write_reproducer for
5563 recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer
&r
)
5565 const char *id
= r
.make_identifier (this, "vector");
5566 const char *elements_id
= r
.make_tmp_identifier ("elements_for_", this);
5567 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
5569 m_elements
.length ());
5570 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
5571 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_elements
[i
]));
5573 r
.write (" gcc_jit_rvalue *%s =\n"
5574 " gcc_jit_context_new_rvalue_from_vector (%s, /* gcc_jit_context *ctxt */\n"
5575 " %s, /* gcc_jit_location *loc */\n"
5576 " %s, /* gcc_jit_type *vec_type */\n"
5577 " %i, /* size_t num_elements */ \n"
5578 " %s); /* gcc_jit_rvalue **elements*/\n",
5580 r
.get_identifier (get_context ()),
5581 r
.get_identifier (m_loc
),
5582 r
.get_identifier (m_vector_type
),
5583 m_elements
.length (),
5588 recording::ctor::visit_children (rvalue_visitor
*v
)
5590 for (unsigned int i
= 0; i
< m_values
.length (); i
++)
5591 v
->visit (m_values
[i
]);
5595 recording::ctor::make_debug_string ()
5597 //Make a compound literal-ish
5600 pp_string (&pp
, "(");
5601 pp_string (&pp
, m_type
->get_debug_string ());
5602 pp_string (&pp
, ") {");
5604 size_t field_n
= m_fields
.length ();
5605 size_t values_n
= m_values
.length ();
5607 if (!field_n
&& !values_n
)
5609 else if (!field_n
&& values_n
)
5611 for (size_t i
= 0; i
< values_n
; i
++)
5614 pp_string (&pp
, m_values
[i
]->get_debug_string ());
5616 pp_string (&pp
, "0");
5617 if (i
+ 1 != values_n
)
5618 pp_string (&pp
, ", ");
5621 else if (field_n
&& values_n
)
5623 for (size_t i
= 0; i
< values_n
; i
++)
5625 pp_string (&pp
, ".");
5626 pp_string (&pp
, m_fields
[i
]->get_debug_string ());
5627 pp_string (&pp
, "=");
5629 pp_string (&pp
, m_values
[i
]->get_debug_string ());
5631 pp_string (&pp
, "0");
5632 if (i
+ 1 != values_n
)
5633 pp_string (&pp
, ", ");
5636 /* m_fields are never populated with m_values empty. */
5638 pp_string (&pp
, "}");
5640 return new_string (pp_formatted_text (&pp
));
5644 recording::ctor::write_reproducer (reproducer
&r
)
5646 const char *id
= r
.make_identifier (this, "rvalue");
5647 type
*type
= get_type ();
5649 r
.write (" gcc_jit_rvalue *%s;\n", id
);
5650 r
.write (" {\n"); /* Open scope for locals. */
5652 if (type
->is_union ())
5654 if (m_values
.length () == 0)
5655 r
.write (" gcc_jit_rvalue *value = NULL;\n");
5657 r
.write (" gcc_jit_rvalue *value = %s;\n",
5658 r
.get_identifier (m_values
[0]));
5660 if (m_fields
.length () == 0)
5661 r
.write (" gcc_jit_field *field = NULL;\n");
5663 r
.write (" gcc_jit_field *field = %s;\n",
5664 r
.get_identifier (m_fields
[0]));
5668 /* Write the array of values. */
5669 if (m_values
.length () == 0)
5670 r
.write (" gcc_jit_rvalue **values = NULL;\n");
5673 r
.write (" gcc_jit_rvalue *values[] = {\n");
5674 for (size_t i
= 0; i
< m_values
.length (); i
++)
5675 r
.write (" %s,\n", r
.get_identifier (m_values
[i
]));
5678 /* Write the array of fields. */
5679 if (m_fields
.length () == 0)
5680 r
.write (" gcc_jit_field **fields = NULL;\n");
5683 r
.write (" gcc_jit_field *fields[] = {\n");
5684 for (size_t i
= 0; i
< m_fields
.length (); i
++)
5685 r
.write (" %s,\n", r
.get_identifier (m_fields
[i
]));
5689 if (type
->is_array ())
5692 " gcc_jit_context_new_array_constructor (%s,\n"
5693 " %s, /* gcc_jit_location *loc */\n"
5694 " %s, /* gcc_jit_type *type */\n"
5695 " %i, /* int num_values */\n"
5698 r
.get_identifier (get_context ()),
5699 r
.get_identifier (m_loc
),
5700 r
.get_identifier_as_type (get_type ()),
5701 m_values
.length ());
5702 else if (type
->is_struct ())
5705 " gcc_jit_context_new_struct_constructor (%s,\n"
5707 " %s, /* gcc_jit_type *type */\n"
5708 " %i, /* int num_values */\n"
5712 r
.get_identifier (get_context ()),
5713 r
.get_identifier (m_loc
),
5714 r
.get_identifier_as_type (get_type ()),
5715 m_values
.length ());
5716 else if (type
->is_union ())
5719 " gcc_jit_context_new_union_constructor (%s,\n"
5721 " %s, /* gcc_jit_type *type */\n"
5725 r
.get_identifier (get_context ()),
5726 r
.get_identifier (m_loc
),
5727 r
.get_identifier_as_type (get_type ()));
5731 r
.write (" }\n"); /* Close scope for locals. */
5735 recording::ctor::replay_into (replayer
*r
)
5737 auto_vec
<playback::rvalue
*> playback_values
;
5738 auto_vec
<playback::field
*> playback_fields
;
5740 int n
= m_values
.length ();
5742 type
*type
= get_type ();
5744 /* Handle arrays, and return. */
5745 if (type
->is_array ())
5747 playback_values
.reserve (n
, false);
5749 for (int i
= 0; i
< n
; i
++)
5751 /* null m_values element indicates zero ctor. */
5752 playback_values
.quick_push (m_values
[i
] ?
5753 m_values
[i
]->playback_rvalue () :
5756 set_playback_obj (r
->new_ctor (playback_location (r
, m_loc
),
5757 get_type ()->playback_type (),
5762 /* ... else handle unions and structs. */
5764 playback_values
.reserve (n
, false);
5765 playback_fields
.reserve (n
, false);
5767 for (int i
= 0; i
< n
; i
++)
5769 /* null m_values element indicates zero ctor. */
5770 playback_values
.quick_push (m_values
[i
] ?
5771 m_values
[i
]->playback_rvalue () :
5773 playback_fields
.quick_push (m_fields
[i
]->playback_field ());
5776 set_playback_obj (r
->new_ctor (playback_location (r
, m_loc
),
5777 get_type ()->playback_type (),
5782 /* The implementation of class gcc::jit::recording::unary_op. */
5784 /* Implementation of pure virtual hook recording::memento::replay_into
5785 for recording::unary_op. */
5788 recording::unary_op::replay_into (replayer
*r
)
5790 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
5792 get_type ()->playback_type (),
5793 m_a
->playback_rvalue ()));
5796 /* Implementation of pure virtual hook recording::rvalue::visit_children
5797 for recording::unary_op. */
5799 recording::unary_op::visit_children (rvalue_visitor
*v
)
5804 /* Implementation of recording::memento::make_debug_string for
5807 static const char * const unary_op_strings
[] = {
5808 "-", /* GCC_JIT_UNARY_OP_MINUS */
5809 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
5810 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
5811 "abs ", /* GCC_JIT_UNARY_OP_ABS */
5815 recording::unary_op::make_debug_string ()
5817 return string::from_printf (m_ctxt
,
5819 unary_op_strings
[m_op
],
5820 m_a
->get_debug_string ());
5823 const char * const unary_op_reproducer_strings
[] = {
5824 "GCC_JIT_UNARY_OP_MINUS",
5825 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
5826 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
5827 "GCC_JIT_UNARY_OP_ABS"
5830 /* Implementation of recording::memento::write_reproducer for unary ops. */
5833 recording::unary_op::write_reproducer (reproducer
&r
)
5835 const char *id
= r
.make_identifier (this, "rvalue");
5836 r
.write (" gcc_jit_rvalue *%s =\n"
5837 " gcc_jit_context_new_unary_op (%s,\n"
5838 " %s, /* gcc_jit_location *loc */\n"
5839 " %s, /* enum gcc_jit_unary_op op */\n"
5840 " %s, /* gcc_jit_type *result_type */\n"
5841 " %s); /* gcc_jit_rvalue *a */\n",
5843 r
.get_identifier (get_context ()),
5844 r
.get_identifier (m_loc
),
5845 unary_op_reproducer_strings
[m_op
],
5846 r
.get_identifier_as_type (get_type ()),
5847 r
.get_identifier_as_rvalue (m_a
));
5850 /* The implementation of class gcc::jit::recording::binary_op. */
5852 /* Implementation of pure virtual hook recording::memento::replay_into
5853 for recording::binary_op. */
5856 recording::binary_op::replay_into (replayer
*r
)
5858 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
5860 get_type ()->playback_type (),
5861 m_a
->playback_rvalue (),
5862 m_b
->playback_rvalue ()));
5865 /* Implementation of pure virtual hook recording::rvalue::visit_children
5866 for recording::binary_op. */
5868 recording::binary_op::visit_children (rvalue_visitor
*v
)
5874 /* Implementation of recording::memento::make_debug_string for
5877 static const char * const binary_op_strings
[] = {
5878 "+", /* GCC_JIT_BINARY_OP_PLUS */
5879 "-", /* GCC_JIT_BINARY_OP_MINUS */
5880 "*", /* GCC_JIT_BINARY_OP_MULT */
5881 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
5882 "%", /* GCC_JIT_BINARY_OP_MODULO */
5883 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
5884 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
5885 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
5886 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
5887 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
5888 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
5889 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
5893 recording::binary_op::make_debug_string ()
5895 enum precedence prec
= get_precedence ();
5896 return string::from_printf (m_ctxt
,
5898 m_a
->get_debug_string_parens (prec
),
5899 binary_op_strings
[m_op
],
5900 m_b
->get_debug_string_parens (prec
));
5903 const char * const binary_op_reproducer_strings
[] = {
5904 "GCC_JIT_BINARY_OP_PLUS",
5905 "GCC_JIT_BINARY_OP_MINUS",
5906 "GCC_JIT_BINARY_OP_MULT",
5907 "GCC_JIT_BINARY_OP_DIVIDE",
5908 "GCC_JIT_BINARY_OP_MODULO",
5909 "GCC_JIT_BINARY_OP_BITWISE_AND",
5910 "GCC_JIT_BINARY_OP_BITWISE_XOR",
5911 "GCC_JIT_BINARY_OP_BITWISE_OR",
5912 "GCC_JIT_BINARY_OP_LOGICAL_AND",
5913 "GCC_JIT_BINARY_OP_LOGICAL_OR",
5914 "GCC_JIT_BINARY_OP_LSHIFT",
5915 "GCC_JIT_BINARY_OP_RSHIFT"
5918 /* Implementation of recording::memento::write_reproducer for binary ops. */
5921 recording::binary_op::write_reproducer (reproducer
&r
)
5923 const char *id
= r
.make_identifier (this, "rvalue");
5924 r
.write (" gcc_jit_rvalue *%s =\n"
5925 " gcc_jit_context_new_binary_op (%s,\n"
5926 " %s, /* gcc_jit_location *loc */\n"
5927 " %s, /* enum gcc_jit_binary_op op */\n"
5928 " %s, /* gcc_jit_type *result_type */\n"
5929 " %s, /* gcc_jit_rvalue *a */\n"
5930 " %s); /* gcc_jit_rvalue *b */\n",
5932 r
.get_identifier (get_context ()),
5933 r
.get_identifier (m_loc
),
5934 binary_op_reproducer_strings
[m_op
],
5935 r
.get_identifier_as_type (get_type ()),
5936 r
.get_identifier_as_rvalue (m_a
),
5937 r
.get_identifier_as_rvalue (m_b
));
5940 namespace recording
{
5941 static const enum precedence binary_op_precedence
[] = {
5942 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_PLUS */
5943 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_MINUS */
5945 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MULT */
5946 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_DIVIDE */
5947 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MODULO */
5949 PRECEDENCE_BITWISE_AND
, /* GCC_JIT_BINARY_OP_BITWISE_AND */
5950 PRECEDENCE_BITWISE_XOR
, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
5951 PRECEDENCE_BITWISE_IOR
, /* GCC_JIT_BINARY_OP_BITWISE_OR */
5952 PRECEDENCE_LOGICAL_AND
, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
5953 PRECEDENCE_LOGICAL_OR
, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
5954 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_LSHIFT */
5955 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_RSHIFT */
5957 } /* namespace recording */
5959 enum recording::precedence
5960 recording::binary_op::get_precedence () const
5962 return binary_op_precedence
[m_op
];
5965 /* The implementation of class gcc::jit::recording::comparison. */
5967 /* Implementation of recording::memento::make_debug_string for
5970 static const char * const comparison_strings
[] =
5972 "==", /* GCC_JIT_COMPARISON_EQ */
5973 "!=", /* GCC_JIT_COMPARISON_NE */
5974 "<", /* GCC_JIT_COMPARISON_LT */
5975 "<=", /* GCC_JIT_COMPARISON_LE */
5976 ">", /* GCC_JIT_COMPARISON_GT */
5977 ">=", /* GCC_JIT_COMPARISON_GE */
5981 recording::comparison::make_debug_string ()
5983 enum precedence prec
= get_precedence ();
5984 return string::from_printf (m_ctxt
,
5986 m_a
->get_debug_string_parens (prec
),
5987 comparison_strings
[m_op
],
5988 m_b
->get_debug_string_parens (prec
));
5991 /* A table of enum gcc_jit_comparison values expressed in string
5994 static const char * const comparison_reproducer_strings
[] =
5996 "GCC_JIT_COMPARISON_EQ",
5997 "GCC_JIT_COMPARISON_NE",
5998 "GCC_JIT_COMPARISON_LT",
5999 "GCC_JIT_COMPARISON_LE",
6000 "GCC_JIT_COMPARISON_GT",
6001 "GCC_JIT_COMPARISON_GE"
6004 /* Implementation of recording::memento::write_reproducer for comparisons. */
6007 recording::comparison::write_reproducer (reproducer
&r
)
6009 const char *id
= r
.make_identifier (this, "rvalue");
6010 r
.write (" gcc_jit_rvalue *%s =\n"
6011 " gcc_jit_context_new_comparison (%s,\n"
6012 " %s, /* gcc_jit_location *loc */\n"
6013 " %s, /* enum gcc_jit_comparison op */\n"
6014 " %s, /* gcc_jit_rvalue *a */\n"
6015 " %s); /* gcc_jit_rvalue *b */\n",
6017 r
.get_identifier (get_context ()),
6018 r
.get_identifier (m_loc
),
6019 comparison_reproducer_strings
[m_op
],
6020 r
.get_identifier_as_rvalue (m_a
),
6021 r
.get_identifier_as_rvalue (m_b
));
6024 /* Implementation of pure virtual hook recording::memento::replay_into
6025 for recording::comparison. */
6028 recording::comparison::replay_into (replayer
*r
)
6030 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
6032 m_a
->playback_rvalue (),
6033 m_b
->playback_rvalue (),
6034 m_type
->playback_type ()));
6037 /* Implementation of pure virtual hook recording::rvalue::visit_children
6038 for recording::comparison. */
6041 recording::comparison::visit_children (rvalue_visitor
*v
)
6047 namespace recording
{
6048 static const enum precedence comparison_precedence
[] =
6050 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_EQ */
6051 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_NE */
6053 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LT */
6054 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LE */
6055 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GT */
6056 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GE */
6058 } /* namespace recording */
6060 enum recording::precedence
6061 recording::comparison::get_precedence () const
6063 return comparison_precedence
[m_op
];
6066 /* Implementation of pure virtual hook recording::memento::replay_into
6067 for recording::cast. */
6070 recording::cast::replay_into (replayer
*r
)
6072 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
6073 m_rvalue
->playback_rvalue (),
6074 get_type ()->playback_type ()));
6077 /* Implementation of pure virtual hook recording::rvalue::visit_children
6078 for recording::cast. */
6080 recording::cast::visit_children (rvalue_visitor
*v
)
6082 v
->visit (m_rvalue
);
6085 /* Implementation of recording::memento::make_debug_string for
6089 recording::cast::make_debug_string ()
6091 enum precedence prec
= get_precedence ();
6092 return string::from_printf (m_ctxt
,
6094 get_type ()->get_debug_string (),
6095 m_rvalue
->get_debug_string_parens (prec
));
6098 /* Implementation of recording::memento::write_reproducer for casts. */
6101 recording::cast::write_reproducer (reproducer
&r
)
6103 const char *id
= r
.make_identifier (this, "rvalue");
6104 r
.write (" gcc_jit_rvalue *%s =\n"
6105 " gcc_jit_context_new_cast (%s,\n"
6106 " %s, /* gcc_jit_location *loc */\n"
6107 " %s, /* gcc_jit_rvalue *rvalue */\n"
6108 " %s); /* gcc_jit_type *type */\n",
6110 r
.get_identifier (get_context ()),
6111 r
.get_identifier (m_loc
),
6112 r
.get_identifier_as_rvalue (m_rvalue
),
6113 r
.get_identifier_as_type (get_type ()));
6116 /* Implementation of pure virtual hook recording::memento::replay_into
6117 for recording::bitcast. */
6120 recording::bitcast::replay_into (replayer
*r
)
6122 set_playback_obj (r
->new_bitcast (playback_location (r
, m_loc
),
6123 m_rvalue
->playback_rvalue (),
6124 get_type ()->playback_type ()));
6127 /* Implementation of pure virtual hook recording::rvalue::visit_children
6128 for recording::bitcast. */
6130 recording::bitcast::visit_children (rvalue_visitor
*v
)
6132 v
->visit (m_rvalue
);
6135 /* Implementation of recording::memento::make_debug_string for
6139 recording::bitcast::make_debug_string ()
6141 enum precedence prec
= get_precedence ();
6142 return string::from_printf (m_ctxt
,
6144 m_rvalue
->get_debug_string_parens (prec
),
6145 get_type ()->get_debug_string ());
6148 /* Implementation of recording::memento::write_reproducer for casts. */
6151 recording::bitcast::write_reproducer (reproducer
&r
)
6153 const char *id
= r
.make_identifier (this, "rvalue");
6154 r
.write (" gcc_jit_rvalue *%s =\n"
6155 " gcc_jit_context_new_bitcast (%s,\n"
6156 " %s, /* gcc_jit_location *loc */\n"
6157 " %s, /* gcc_jit_rvalue *rvalue */\n"
6158 " %s); /* gcc_jit_type *type */\n",
6160 r
.get_identifier (get_context ()),
6161 r
.get_identifier (m_loc
),
6162 r
.get_identifier_as_rvalue (m_rvalue
),
6163 r
.get_identifier_as_type (get_type ()));
6166 /* The implementation of class gcc::jit::recording::base_call. */
6168 /* The constructor for gcc::jit::recording::base_call. */
6170 recording::base_call::base_call (context
*ctxt
,
6175 : rvalue (ctxt
, loc
, type_
),
6177 m_require_tail_call (0)
6179 for (int i
= 0; i
< numargs
; i
++)
6180 m_args
.safe_push (args
[i
]);
6183 /* Subroutine for use by call and call_though_ptr's write_reproducer
6187 recording::base_call::write_reproducer_tail_call (reproducer
&r
,
6190 if (m_require_tail_call
)
6192 r
.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
6193 " %i); /* int require_tail_call*/\n",
6199 /* The implementation of class gcc::jit::recording::call. */
6201 /* The constructor for gcc::jit::recording::call. */
6203 recording::call::call (recording::context
*ctxt
,
6204 recording::location
*loc
,
6205 recording::function
*func
,
6208 : base_call (ctxt
, loc
, func
->get_return_type (), numargs
, args
),
6213 /* Implementation of pure virtual hook recording::memento::replay_into
6214 for recording::call. */
6217 recording::call::replay_into (replayer
*r
)
6219 auto_vec
<playback::rvalue
*> playback_args
;
6220 playback_args
.create (m_args
.length ());
6221 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6222 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
6224 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
6225 m_func
->playback_function (),
6227 m_require_tail_call
));
6230 /* Implementation of pure virtual hook recording::rvalue::visit_children
6231 for recording::call. */
6234 recording::call::visit_children (rvalue_visitor
*v
)
6236 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6237 v
->visit (m_args
[i
]);
6240 /* Implementation of recording::memento::make_debug_string for
6244 recording::call::make_debug_string ()
6246 /* First, build a buffer for the arguments. */
6247 comma_separated_string
args (m_args
, get_precedence ());
6249 /* ...and use it to get the string for the call as a whole. */
6250 string
*result
= string::from_printf (m_ctxt
,
6252 m_func
->get_debug_string (),
6253 args
.as_char_ptr ());
6259 recording::call::write_reproducer (reproducer
&r
)
6261 const char *id
= r
.make_identifier (this, "call");
6262 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
6263 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
6266 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6267 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
6269 r
.write (" gcc_jit_rvalue *%s =\n"
6270 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
6271 " %s, /* gcc_jit_location *loc */\n"
6272 " %s, /* gcc_jit_function *func */\n"
6273 " %i, /* int numargs */ \n"
6274 " %s); /* gcc_jit_rvalue **args*/\n",
6276 r
.get_identifier (get_context ()),
6277 r
.get_identifier (m_loc
),
6278 r
.get_identifier (m_func
),
6281 write_reproducer_tail_call (r
, id
);
6284 /* The implementation of class gcc::jit::recording::call_through_ptr. */
6286 /* The constructor for recording::call_through_ptr. */
6288 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
6289 recording::location
*loc
,
6290 recording::rvalue
*fn_ptr
,
6293 : base_call (ctxt
, loc
,
6294 fn_ptr
->get_type ()->dereference ()
6295 ->as_a_function_type ()->get_return_type (),
6301 /* Implementation of pure virtual hook recording::memento::replay_into
6302 for recording::call_through_ptr. */
6305 recording::call_through_ptr::replay_into (replayer
*r
)
6307 auto_vec
<playback::rvalue
*> playback_args
;
6308 playback_args
.create (m_args
.length ());
6309 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6310 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
6312 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
6313 m_fn_ptr
->playback_rvalue (),
6315 m_require_tail_call
));
6318 /* Implementation of pure virtual hook recording::rvalue::visit_children
6319 for recording::call_through_ptr. */
6322 recording::call_through_ptr::visit_children (rvalue_visitor
*v
)
6324 v
->visit (m_fn_ptr
);
6325 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6326 v
->visit (m_args
[i
]);
6329 /* Implementation of recording::memento::make_debug_string for
6330 calls through function ptrs. */
6333 recording::call_through_ptr::make_debug_string ()
6335 enum precedence prec
= get_precedence ();
6336 /* First, build a buffer for the arguments. */
6337 /* Calculate length of said buffer. */
6338 size_t sz
= 1; /* nil terminator */
6339 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6341 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
6342 sz
+= 2; /* ", " separator */
6345 /* Now allocate and populate the buffer. */
6346 char *argbuf
= new char[sz
];
6349 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6351 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
6352 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
6353 if (i
+ 1 < m_args
.length ())
6355 strcpy (argbuf
+ len
, ", ");
6361 /* ...and use it to get the string for the call as a whole. */
6362 string
*result
= string::from_printf (m_ctxt
,
6364 m_fn_ptr
->get_debug_string_parens (prec
),
6372 /* Implementation of recording::memento::write_reproducer for
6373 call_through_ptr. */
6376 recording::call_through_ptr::write_reproducer (reproducer
&r
)
6378 const char *id
= r
.make_identifier (this, "call");
6379 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
6380 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
6383 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6384 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
6386 r
.write (" gcc_jit_rvalue *%s =\n"
6387 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
6388 " %s, /* gcc_jit_location *loc */\n"
6389 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
6390 " %i, /* int numargs */ \n"
6391 " %s); /* gcc_jit_rvalue **args*/\n",
6393 r
.get_identifier (get_context ()),
6394 r
.get_identifier (m_loc
),
6395 r
.get_identifier_as_rvalue (m_fn_ptr
),
6398 write_reproducer_tail_call (r
, id
);
6401 /* The implementation of class gcc::jit::recording::array_access. */
6403 /* Implementation of pure virtual hook recording::memento::replay_into
6404 for recording::array_access. */
6407 recording::array_access::replay_into (replayer
*r
)
6410 r
->new_array_access (playback_location (r
, m_loc
),
6411 m_ptr
->playback_rvalue (),
6412 m_index
->playback_rvalue ()));
6415 /* Implementation of pure virtual hook recording::rvalue::visit_children
6416 for recording::array_access. */
6419 recording::array_access::visit_children (rvalue_visitor
*v
)
6425 /* Implementation of recording::memento::make_debug_string for
6429 recording::array_access::make_debug_string ()
6431 enum precedence prec
= get_precedence ();
6432 return string::from_printf (m_ctxt
,
6434 m_ptr
->get_debug_string_parens (prec
),
6435 m_index
->get_debug_string_parens (prec
));
6438 /* Implementation of recording::memento::write_reproducer for
6442 recording::array_access::write_reproducer (reproducer
&r
)
6444 const char *id
= r
.make_identifier (this, "lvalue");
6445 r
.write (" gcc_jit_lvalue *%s = \n"
6446 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
6447 " %s, /*gcc_jit_location *loc */\n"
6448 " %s, /* gcc_jit_rvalue *ptr */\n"
6449 " %s); /* gcc_jit_rvalue *index */\n",
6451 r
.get_identifier (get_context ()),
6452 r
.get_identifier (m_loc
),
6453 r
.get_identifier_as_rvalue (m_ptr
),
6454 r
.get_identifier_as_rvalue (m_index
));
6457 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
6459 /* Implementation of pure virtual hook recording::memento::replay_into
6460 for recording::access_field_of_lvalue. */
6463 recording::access_field_of_lvalue::replay_into (replayer
*r
)
6466 m_lvalue
->playback_lvalue ()
6467 ->access_field (playback_location (r
, m_loc
),
6468 m_field
->playback_field ()));
6472 /* Implementation of pure virtual hook recording::rvalue::visit_children
6473 for recording::access_field_of_lvalue. */
6476 recording::access_field_of_lvalue::visit_children (rvalue_visitor
*v
)
6478 v
->visit (m_lvalue
);
6481 /* Implementation of recording::memento::make_debug_string for
6482 accessing a field of an lvalue. */
6485 recording::access_field_of_lvalue::make_debug_string ()
6487 enum precedence prec
= get_precedence ();
6488 return string::from_printf (m_ctxt
,
6490 m_lvalue
->get_debug_string_parens (prec
),
6491 m_field
->get_debug_string ());
6494 /* Implementation of recording::memento::write_reproducer for
6495 access_field_of_lvalue. */
6498 recording::access_field_of_lvalue::write_reproducer (reproducer
&r
)
6500 const char *id
= r
.make_identifier (this, "lvalue");
6501 r
.write (" gcc_jit_lvalue *%s = \n"
6502 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
6503 " %s, /*gcc_jit_location *loc */\n"
6506 r
.get_identifier_as_lvalue (m_lvalue
),
6507 r
.get_identifier (m_loc
),
6508 r
.get_identifier (m_field
));
6511 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
6513 /* Implementation of pure virtual hook recording::memento::replay_into
6514 for recording::access_field_rvalue. */
6517 recording::access_field_rvalue::replay_into (replayer
*r
)
6520 m_rvalue
->playback_rvalue ()
6521 ->access_field (playback_location (r
, m_loc
),
6522 m_field
->playback_field ()));
6525 /* Implementation of pure virtual hook recording::rvalue::visit_children
6526 for recording::access_field_rvalue. */
6529 recording::access_field_rvalue::visit_children (rvalue_visitor
*v
)
6531 v
->visit (m_rvalue
);
6534 /* Implementation of recording::memento::make_debug_string for
6535 accessing a field of an rvalue. */
6538 recording::access_field_rvalue::make_debug_string ()
6540 enum precedence prec
= get_precedence ();
6541 return string::from_printf (m_ctxt
,
6543 m_rvalue
->get_debug_string_parens (prec
),
6544 m_field
->get_debug_string ());
6547 /* Implementation of recording::memento::write_reproducer for
6548 access_field_rvalue. */
6551 recording::access_field_rvalue::write_reproducer (reproducer
&r
)
6553 const char *id
= r
.make_identifier (this, "rvalue");
6554 r
.write (" gcc_jit_rvalue *%s = \n"
6555 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
6556 " %s, /*gcc_jit_location *loc */\n"
6559 r
.get_identifier_as_rvalue (m_rvalue
),
6560 r
.get_identifier (m_loc
),
6561 r
.get_identifier (m_field
));
6564 /* The implementation of class
6565 gcc::jit::recording::dereference_field_rvalue. */
6567 /* Implementation of pure virtual hook recording::memento::replay_into
6568 for recording::dereference_field_rvalue. */
6571 recording::dereference_field_rvalue::replay_into (replayer
*r
)
6574 m_rvalue
->playback_rvalue ()->
6575 dereference_field (playback_location (r
, m_loc
),
6576 m_field
->playback_field ()));
6579 /* Implementation of pure virtual hook recording::rvalue::visit_children
6580 for recording::dereference_field_rvalue. */
6583 recording::dereference_field_rvalue::visit_children (rvalue_visitor
*v
)
6585 v
->visit (m_rvalue
);
6588 /* Implementation of recording::memento::make_debug_string for
6589 dereferencing a field of an rvalue. */
6592 recording::dereference_field_rvalue::make_debug_string ()
6594 enum precedence prec
= get_precedence ();
6595 return string::from_printf (m_ctxt
,
6597 m_rvalue
->get_debug_string_parens (prec
),
6598 m_field
->get_debug_string ());
6601 /* Implementation of recording::memento::write_reproducer for
6602 dereference_field_rvalue. */
6605 recording::dereference_field_rvalue::write_reproducer (reproducer
&r
)
6607 const char *id
= r
.make_identifier (this, "lvalue");
6608 r
.write (" gcc_jit_lvalue *%s=\n"
6609 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
6610 " %s, /* gcc_jit_location *loc */\n"
6611 " %s); /* gcc_jit_field *field */\n",
6613 r
.get_identifier_as_rvalue (m_rvalue
),
6614 r
.get_identifier (m_loc
),
6615 r
.get_identifier (m_field
));
6618 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
6620 /* Implementation of pure virtual hook recording::memento::replay_into
6621 for recording::dereference_rvalue. */
6624 recording::dereference_rvalue::replay_into (replayer
*r
)
6627 m_rvalue
->playback_rvalue ()->
6628 dereference (playback_location (r
, m_loc
)));
6631 /* Implementation of pure virtual hook recording::rvalue::visit_children
6632 for recording::dereference_rvalue. */
6635 recording::dereference_rvalue::visit_children (rvalue_visitor
*v
)
6637 v
->visit (m_rvalue
);
6640 /* Implementation of recording::memento::make_debug_string for
6641 dereferencing an rvalue. */
6644 recording::dereference_rvalue::make_debug_string ()
6646 enum precedence prec
= get_precedence ();
6647 return string::from_printf (m_ctxt
,
6649 m_rvalue
->get_debug_string_parens (prec
));
6652 /* Implementation of recording::memento::write_reproducer for
6653 dereference_rvalue. */
6656 recording::dereference_rvalue::write_reproducer (reproducer
&r
)
6658 const char *id
= r
.make_identifier (this, "dereference");
6659 r
.write (" gcc_jit_lvalue *%s =\n"
6660 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
6661 " %s); /* gcc_jit_location *loc */\n",
6663 r
.get_identifier_as_rvalue (m_rvalue
),
6664 r
.get_identifier (m_loc
));
6667 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
6669 /* Implementation of pure virtual hook recording::memento::replay_into
6670 for recording::get_address_of_lvalue. */
6673 recording::get_address_of_lvalue::replay_into (replayer
*r
)
6676 m_lvalue
->playback_lvalue ()->
6677 get_address (playback_location (r
, m_loc
)));
6680 /* Implementation of pure virtual hook recording::rvalue::visit_children
6681 for recording::get_address_of_lvalue. */
6684 recording::get_address_of_lvalue::visit_children (rvalue_visitor
*v
)
6686 v
->visit (m_lvalue
);
6689 /* Implementation of recording::memento::make_debug_string for
6690 getting the address of an lvalue. */
6693 recording::get_address_of_lvalue::make_debug_string ()
6695 enum precedence prec
= get_precedence ();
6696 return string::from_printf (m_ctxt
,
6698 m_lvalue
->get_debug_string_parens (prec
));
6701 /* Implementation of recording::memento::write_reproducer for
6702 get_address_of_lvalue. */
6705 recording::get_address_of_lvalue::write_reproducer (reproducer
&r
)
6707 const char *id
= r
.make_identifier (this, "address_of");
6708 r
.write (" gcc_jit_rvalue *%s =\n"
6709 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
6710 " %s); /* gcc_jit_location *loc */\n",
6712 r
.get_identifier_as_lvalue (m_lvalue
),
6713 r
.get_identifier (m_loc
));
6716 /* The implementation of class gcc::jit::recording::function_pointer. */
6718 /* Implementation of pure virtual hook recording::memento::replay_into
6719 for recording::function_pointer. */
6722 recording::function_pointer::replay_into (replayer
*r
)
6725 m_fn
->playback_function ()->
6726 get_address (playback_location (r
, m_loc
)));
6730 recording::function_pointer::visit_children (rvalue_visitor
*)
6735 /* Implementation of recording::memento::make_debug_string for
6736 getting the address of an lvalue. */
6739 recording::function_pointer::make_debug_string ()
6741 return string::from_printf (m_ctxt
,
6743 m_fn
->get_debug_string ());
6746 /* Implementation of recording::memento::write_reproducer for
6747 function_pointer. */
6750 recording::function_pointer::write_reproducer (reproducer
&r
)
6752 const char *id
= r
.make_identifier (this, "address_of");
6753 r
.write (" gcc_jit_rvalue *%s =\n"
6754 " gcc_jit_function_get_address (%s, /* gcc_jit_function *fn */\n"
6755 " %s); /* gcc_jit_location *loc */\n",
6757 r
.get_identifier (m_fn
),
6758 r
.get_identifier (m_loc
));
6761 /* The implementation of class gcc::jit::recording::local. */
6763 /* Implementation of pure virtual hook recording::memento::replay_into
6764 for recording::local. */
6767 recording::local::replay_into (replayer
*r
)
6769 playback::lvalue
*obj
= m_func
->playback_function ()
6770 ->new_local (playback_location (r
, m_loc
),
6771 m_type
->playback_type (),
6772 playback_string (m_name
),
6773 m_string_attributes
);
6775 if (m_reg_name
!= NULL
)
6776 obj
->set_register_name (m_reg_name
->c_str ());
6778 if (m_alignment
!= 0)
6779 obj
->set_alignment (m_alignment
);
6781 set_playback_obj (obj
);
6784 /* Override the default implementation of
6785 recording::memento::write_to_dump for locals by writing
6787 for use at the top of the function body as if it were a
6791 recording::local::write_to_dump (dump
&d
)
6793 if (d
.update_locations ())
6794 m_loc
= d
.make_location ();
6795 d
.write (" %s %s;\n",
6796 m_type
->get_debug_string (),
6797 get_debug_string ());
6801 recording::local::write_reproducer (reproducer
&r
)
6803 const char *id
= r
.make_identifier (this, "local");
6804 r
.write (" gcc_jit_lvalue *%s =\n"
6805 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
6806 " %s, /* gcc_jit_location *loc */\n"
6807 " %s, /* gcc_jit_type *type */\n"
6808 " %s); /* const char *name */\n",
6810 r
.get_identifier (m_func
),
6811 r
.get_identifier (m_loc
),
6812 r
.get_identifier_as_type (m_type
),
6813 m_name
->get_debug_string ());
6816 /* The implementation of class gcc::jit::recording::statement. */
6818 /* We poison the default implementation of
6819 gcc::jit::recording::statement::get_successor_blocks
6820 since this vfunc must only ever be called on terminator
6823 vec
<recording::block
*>
6824 recording::statement::get_successor_blocks () const
6826 /* The base class implementation is for non-terminating statements,
6827 and thus should never be called. */
6829 vec
<block
*> result
;
6834 /* Extend the default implementation of
6835 recording::memento::write_to_dump for statements by (if requested)
6836 updating the location of the statement to the current location in
6840 recording::statement::write_to_dump (dump
&d
)
6842 memento::write_to_dump (d
);
6843 if (d
.update_locations ())
6844 m_loc
= d
.make_location ();
6847 /* The implementation of class gcc::jit::recording::eval. */
6849 /* Implementation of pure virtual hook recording::memento::replay_into
6850 for recording::eval. */
6853 recording::eval::replay_into (replayer
*r
)
6855 playback_block (get_block ())
6856 ->add_eval (playback_location (r
),
6857 m_rvalue
->playback_rvalue ());
6860 /* Implementation of recording::memento::make_debug_string for
6861 an eval statement. */
6864 recording::eval::make_debug_string ()
6866 return string::from_printf (m_ctxt
,
6868 m_rvalue
->get_debug_string ());
6871 /* Implementation of recording::memento::write_reproducer for
6875 recording::eval::write_reproducer (reproducer
&r
)
6877 r
.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
6878 " %s, /* gcc_jit_location *loc */\n"
6879 " %s); /* gcc_jit_rvalue *rvalue */\n",
6880 r
.get_identifier (get_block ()),
6881 r
.get_identifier (get_loc ()),
6882 r
.get_identifier_as_rvalue (m_rvalue
));
6885 /* The implementation of class gcc::jit::recording::assignment. */
6887 /* Implementation of pure virtual hook recording::memento::replay_into
6888 for recording::assignment. */
6891 recording::assignment::replay_into (replayer
*r
)
6893 playback_block (get_block ())
6894 ->add_assignment (playback_location (r
),
6895 m_lvalue
->playback_lvalue (),
6896 m_rvalue
->playback_rvalue ());
6899 /* Implementation of recording::memento::make_debug_string for
6900 an assignment statement. */
6903 recording::assignment::make_debug_string ()
6905 return string::from_printf (m_ctxt
,
6907 m_lvalue
->get_debug_string (),
6908 m_rvalue
->get_debug_string ());
6911 /* Implementation of recording::memento::write_reproducer for
6912 assignment statements. */
6915 recording::assignment::write_reproducer (reproducer
&r
)
6917 r
.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
6918 " %s, /* gcc_jit_location *loc */\n"
6919 " %s, /* gcc_jit_lvalue *lvalue */\n"
6920 " %s); /* gcc_jit_rvalue *rvalue */\n",
6921 r
.get_identifier (get_block ()),
6922 r
.get_identifier (get_loc ()),
6923 r
.get_identifier_as_lvalue (m_lvalue
),
6924 r
.get_identifier_as_rvalue (m_rvalue
));
6927 /* The implementation of class gcc::jit::recording::assignment_op. */
6929 /* Implementation of pure virtual hook recording::memento::replay_into
6930 for recording::assignment_op. */
6933 recording::assignment_op::replay_into (replayer
*r
)
6935 playback::type
*result_type
=
6936 m_lvalue
->playback_lvalue ()->get_type ();
6938 playback::rvalue
*binary_op
=
6939 r
->new_binary_op (playback_location (r
),
6942 m_lvalue
->playback_rvalue (),
6943 m_rvalue
->playback_rvalue ());
6945 playback_block (get_block ())
6946 ->add_assignment (playback_location (r
),
6947 m_lvalue
->playback_lvalue (),
6951 /* Implementation of recording::memento::make_debug_string for
6952 an assignment_op statement. */
6955 recording::assignment_op::make_debug_string ()
6957 return string::from_printf (m_ctxt
,
6959 m_lvalue
->get_debug_string (),
6960 binary_op_strings
[m_op
],
6961 m_rvalue
->get_debug_string ());
6964 /* Implementation of recording::memento::write_reproducer for
6965 assignment_op statements. */
6968 recording::assignment_op::write_reproducer (reproducer
&r
)
6970 r
.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
6971 " %s, /* gcc_jit_location *loc */\n"
6972 " %s, /* gcc_jit_lvalue *lvalue */\n"
6973 " %s, /* enum gcc_jit_binary_op op */\n"
6974 " %s); /* gcc_jit_rvalue *rvalue */\n",
6975 r
.get_identifier (get_block ()),
6976 r
.get_identifier (get_loc ()),
6977 r
.get_identifier_as_lvalue (m_lvalue
),
6978 binary_op_reproducer_strings
[m_op
],
6979 r
.get_identifier_as_rvalue (m_rvalue
));
6982 /* The implementation of class gcc::jit::recording::comment. */
6984 /* Implementation of pure virtual hook recording::memento::replay_into
6985 for recording::comment. */
6988 recording::comment::replay_into (replayer
*r
)
6990 playback_block (get_block ())
6991 ->add_comment (playback_location (r
),
6995 /* Implementation of recording::memento::make_debug_string for
6996 a comment "statement". */
6999 recording::comment::make_debug_string ()
7001 return string::from_printf (m_ctxt
,
7006 /* Implementation of recording::memento::write_reproducer for
7010 recording::comment::write_reproducer (reproducer
&r
)
7012 r
.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
7013 " %s, /* gcc_jit_location *loc */\n"
7014 " %s); /* const char *text */\n",
7015 r
.get_identifier (get_block ()),
7016 r
.get_identifier (get_loc ()),
7017 m_text
->get_debug_string ());
7020 /* The implementation of class gcc::jit::recording::conditional. */
7022 /* Implementation of pure virtual hook recording::memento::replay_into
7023 for recording::conditional. */
7026 recording::conditional::replay_into (replayer
*r
)
7028 playback_block (get_block ())
7029 ->add_conditional (playback_location (r
),
7030 m_boolval
->playback_rvalue (),
7031 playback_block (m_on_true
),
7032 playback_block (m_on_false
));
7035 /* Override the poisoned default implementation of
7036 gcc::jit::recording::statement::get_successor_blocks
7038 A conditional jump has 2 successor blocks. */
7040 vec
<recording::block
*>
7041 recording::conditional::get_successor_blocks () const
7043 vec
<block
*> result
;
7045 result
.quick_push (m_on_true
);
7046 result
.quick_push (m_on_false
);
7050 /* Implementation of recording::memento::make_debug_string for
7051 a conditional jump statement. */
7054 recording::conditional::make_debug_string ()
7057 return string::from_printf (m_ctxt
,
7058 "if (%s) goto %s; else goto %s;",
7059 m_boolval
->get_debug_string (),
7060 m_on_true
->get_debug_string (),
7061 m_on_false
->get_debug_string ());
7063 return string::from_printf (m_ctxt
,
7065 m_boolval
->get_debug_string (),
7066 m_on_true
->get_debug_string ());
7069 /* Implementation of recording::memento::write_reproducer for
7070 conditional statements. */
7073 recording::conditional::write_reproducer (reproducer
&r
)
7075 r
.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
7076 " %s, /* gcc_jit_location *loc */\n"
7077 " %s, /* gcc_jit_rvalue *boolval */\n"
7078 " %s, /* gcc_jit_block *on_true */\n"
7079 " %s); /* gcc_jit_block *on_false */\n",
7080 r
.get_identifier (get_block ()),
7081 r
.get_identifier (get_loc ()),
7082 r
.get_identifier_as_rvalue (m_boolval
),
7083 r
.get_identifier (m_on_true
),
7084 r
.get_identifier (m_on_false
));
7087 /* The implementation of class gcc::jit::recording::jump. */
7089 /* Implementation of pure virtual hook recording::memento::replay_into
7090 for recording::jump. */
7093 recording::jump::replay_into (replayer
*r
)
7095 playback_block (get_block ())
7096 ->add_jump (playback_location (r
),
7097 m_target
->playback_block ());
7100 /* Override the poisoned default implementation of
7101 gcc::jit::recording::statement::get_successor_blocks
7103 An unconditional jump has 1 successor block. */
7105 vec
<recording::block
*>
7106 recording::jump::get_successor_blocks () const
7108 vec
<block
*> result
;
7110 result
.quick_push (m_target
);
7114 /* Implementation of recording::memento::make_debug_string for
7115 a unconditional jump statement. */
7118 recording::jump::make_debug_string ()
7120 return string::from_printf (m_ctxt
,
7122 m_target
->get_debug_string ());
7125 /* Implementation of recording::memento::write_reproducer for
7129 recording::jump::write_reproducer (reproducer
&r
)
7131 r
.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
7132 " %s, /* gcc_jit_location *loc */\n"
7133 " %s); /* gcc_jit_block *target */\n",
7134 r
.get_identifier (get_block ()),
7135 r
.get_identifier (get_loc ()),
7136 r
.get_identifier (m_target
));
7139 /* The implementation of class gcc::jit::recording::return_. */
7141 /* Implementation of pure virtual hook recording::memento::replay_into
7142 for recording::return_. */
7145 recording::return_::replay_into (replayer
*r
)
7147 playback_block (get_block ())
7148 ->add_return (playback_location (r
),
7149 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
7152 /* Override the poisoned default implementation of
7153 gcc::jit::recording::statement::get_successor_blocks
7155 A return statement has no successor block. */
7157 vec
<recording::block
*>
7158 recording::return_::get_successor_blocks () const
7160 vec
<block
*> result
;
7165 /* Implementation of recording::memento::make_debug_string for
7166 a return statement (covers both those with and without rvalues). */
7169 recording::return_::make_debug_string ()
7172 return string::from_printf (m_ctxt
,
7174 m_rvalue
->get_debug_string ());
7176 return string::from_printf (m_ctxt
,
7180 /* Implementation of recording::memento::write_reproducer for
7181 return statements. */
7184 recording::return_::write_reproducer (reproducer
&r
)
7187 r
.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
7188 " %s, /* gcc_jit_location *loc */\n"
7189 " %s); /* gcc_jit_rvalue *rvalue */\n",
7190 r
.get_identifier (get_block ()),
7191 r
.get_identifier (get_loc ()),
7192 r
.get_identifier_as_rvalue (m_rvalue
));
7194 r
.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
7195 " %s); /* gcc_jit_location *loc */\n",
7196 r
.get_identifier (get_block ()),
7197 r
.get_identifier (get_loc ()));
7200 /* The implementation of class gcc::jit::recording::case_. */
7203 recording::case_::write_reproducer (reproducer
&r
)
7205 const char *id
= r
.make_identifier (this, "case");
7207 " gcc_jit_case *%s = \n"
7208 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
7209 " %s, /* gcc_jit_rvalue *min_value */\n"
7210 " %s, /* gcc_jit_rvalue *max_value */\n"
7211 " %s); /* gcc_jit_block *dest_block */\n";
7214 r
.get_identifier (get_context ()),
7215 r
.get_identifier_as_rvalue (m_min_value
),
7216 r
.get_identifier_as_rvalue (m_max_value
),
7217 r
.get_identifier (m_dest_block
));
7221 recording::case_::make_debug_string ()
7223 return string::from_printf (get_context (),
7224 "case %s ... %s: goto %s;",
7225 m_min_value
->get_debug_string (),
7226 m_max_value
->get_debug_string (),
7227 m_dest_block
->get_debug_string ());
7230 /* The implementation of class gcc::jit::recording::switch_. */
7232 /* gcc::jit::recording::switch_'s constructor. */
7234 recording::switch_::switch_ (block
*b
,
7237 block
*default_block
,
7240 : statement (b
, loc
),
7242 m_default_block (default_block
)
7244 m_cases
.reserve_exact (num_cases
);
7245 for (int i
= 0; i
< num_cases
; i
++)
7246 m_cases
.quick_push (cases
[i
]);
7249 /* Implementation of pure virtual hook recording::memento::replay_into
7250 for recording::switch_. */
7253 recording::switch_::replay_into (replayer
*r
)
7255 auto_vec
<playback::case_
> pcases
;
7257 recording::case_
*rcase
;
7258 pcases
.reserve_exact (m_cases
.length ());
7259 FOR_EACH_VEC_ELT (m_cases
, i
, rcase
)
7261 playback::case_
pcase (rcase
->get_min_value ()->playback_rvalue (),
7262 rcase
->get_max_value ()->playback_rvalue (),
7263 rcase
->get_dest_block ()->playback_block ());
7264 pcases
.safe_push (pcase
);
7266 playback_block (get_block ())
7267 ->add_switch (playback_location (r
),
7268 m_expr
->playback_rvalue (),
7269 m_default_block
->playback_block (),
7273 /* Override the poisoned default implementation of
7274 gcc::jit::recording::statement::get_successor_blocks
7276 A switch statement has (NUM_CASES + 1) successor blocks. */
7278 vec
<recording::block
*>
7279 recording::switch_::get_successor_blocks () const
7281 vec
<block
*> result
;
7282 result
.create (m_cases
.length () + 1);
7283 result
.quick_push (m_default_block
);
7286 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
7287 result
.quick_push (c
->get_dest_block ());
7291 /* Implementation of recording::memento::make_debug_string for
7292 a switch statement. */
7295 recording::switch_::make_debug_string ()
7297 auto_vec
<char> cases_str
;
7300 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
7302 size_t len
= strlen (c
->get_debug_string ());
7303 unsigned idx
= cases_str
.length ();
7304 cases_str
.safe_grow (idx
+ 1 + len
, true);
7305 cases_str
[idx
] = ' ';
7306 memcpy (&(cases_str
[idx
+ 1]),
7307 c
->get_debug_string (),
7310 cases_str
.safe_push ('\0');
7312 return string::from_printf (m_ctxt
,
7313 "switch (%s) {default: goto %s;%s}",
7314 m_expr
->get_debug_string (),
7315 m_default_block
->get_debug_string (),
7319 /* Implementation of recording::memento::write_reproducer for
7320 switch statements. */
7323 recording::switch_::write_reproducer (reproducer
&r
)
7325 r
.make_identifier (this, "switch");
7328 const char *cases_id
=
7329 r
.make_tmp_identifier ("cases_for", this);
7330 r
.write (" gcc_jit_case *%s[%i] = {\n",
7333 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
7334 r
.write (" %s,\n", r
.get_identifier (c
));
7337 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
7338 " %s, /* gcc_jit_location *loc */\n"
7339 " %s, /* gcc_jit_rvalue *expr */\n"
7340 " %s, /* gcc_jit_block *default_block */\n"
7341 " %i, /* int num_cases */\n"
7342 " %s); /* gcc_jit_case **cases */\n";
7344 r
.get_identifier (get_block ()),
7345 r
.get_identifier (get_loc ()),
7346 r
.get_identifier_as_rvalue (m_expr
),
7347 r
.get_identifier (m_default_block
),
7352 /* class asm_operand : public memento. */
7354 recording::asm_operand::asm_operand (extended_asm
*ext_asm
,
7355 string
*asm_symbolic_name
,
7357 : memento (ext_asm
->get_context ()),
7358 m_ext_asm (ext_asm
),
7359 m_asm_symbolic_name (asm_symbolic_name
),
7360 m_constraint (constraint
)
7365 recording::asm_operand::print (pretty_printer
*pp
) const
7367 if (m_asm_symbolic_name
)
7369 pp_character (pp
, '[');
7370 pp_string (pp
, m_asm_symbolic_name
->c_str ());
7371 pp_character (pp
, ']');
7374 pp_string (pp
, m_constraint
->get_debug_string ());
7375 /* Subclass will add lvalue/rvalue. */
7379 recording::asm_operand::make_debug_string ()
7383 return m_ctxt
->new_string (pp_formatted_text (&pp
), false);
7386 /* class output_asm_operand : public asm_operand. */
7389 recording::output_asm_operand::write_reproducer (reproducer
&r
)
7392 " gcc_jit_extended_asm_add_output_operand (%s, /* gcc_jit_extended_asm *ext_asm */\n"
7393 " %s, /* const char *asm_symbolic_name */\n"
7394 " %s, /* const char *constraint */\n"
7395 " %s); /* gcc_jit_lvalue *dest */\n";
7397 r
.get_identifier (m_ext_asm
),
7398 (m_asm_symbolic_name
7399 ? m_asm_symbolic_name
->get_debug_string () : "NULL"),
7400 m_constraint
->get_debug_string (),
7401 r
.get_identifier (m_dest
));
7405 recording::output_asm_operand::print (pretty_printer
*pp
) const
7407 asm_operand::print (pp
);
7408 pp_string (pp
, " (");
7409 pp_string (pp
, m_dest
->get_debug_string ());
7410 pp_string (pp
, ")");
7413 /* class input_asm_operand : public asm_operand. */
7416 recording::input_asm_operand::write_reproducer (reproducer
&r
)
7419 " gcc_jit_extended_asm_add_input_operand (%s, /* gcc_jit_extended_asm *ext_asm */\n"
7420 " %s, /* const char *asm_symbolic_name */\n"
7421 " %s, /* const char *constraint */\n"
7422 " %s); /* gcc_jit_rvalue *src */\n";
7424 r
.get_identifier (m_ext_asm
),
7425 (m_asm_symbolic_name
7426 ? m_asm_symbolic_name
->get_debug_string () : "NULL"),
7427 m_constraint
->get_debug_string (),
7428 r
.get_identifier_as_rvalue (m_src
));
7432 recording::input_asm_operand::print (pretty_printer
*pp
) const
7434 asm_operand::print (pp
);
7435 pp_string (pp
, " (");
7436 pp_string (pp
, m_src
->get_debug_string ());
7437 pp_string (pp
, ")");
7440 /* The implementation of class gcc::jit::recording::extended_asm. */
7443 recording::extended_asm::add_output_operand (const char *asm_symbolic_name
,
7444 const char *constraint
,
7447 output_asm_operand
*op
7448 = new output_asm_operand (this,
7449 new_string (asm_symbolic_name
),
7450 new_string (constraint
),
7452 m_ctxt
->record (op
);
7453 m_output_ops
.safe_push (op
);
7457 recording::extended_asm::add_input_operand (const char *asm_symbolic_name
,
7458 const char *constraint
,
7461 input_asm_operand
*op
7462 = new input_asm_operand (this,
7463 new_string (asm_symbolic_name
),
7464 new_string (constraint
),
7466 m_ctxt
->record (op
);
7467 m_input_ops
.safe_push (op
);
7471 recording::extended_asm::add_clobber (const char *victim
)
7473 m_clobbers
.safe_push (new_string (victim
));
7476 /* Implementation of recording::memento::replay_into
7477 for recording::extended_asm. */
7480 recording::extended_asm::replay_into (replayer
*r
)
7482 auto_vec
<playback::asm_operand
> playback_output_ops
;
7483 auto_vec
<playback::asm_operand
> playback_input_ops
;
7484 auto_vec
<const char *> playback_clobbers
;
7485 auto_vec
<playback::block
*> playback_goto_blocks
;
7487 /* Populate outputs. */
7489 output_asm_operand
*rec_asm_op
;
7491 FOR_EACH_VEC_ELT (m_output_ops
, i
, rec_asm_op
)
7493 playback::asm_operand playback_asm_op
7494 (rec_asm_op
->get_symbolic_name (),
7495 rec_asm_op
->get_constraint (),
7496 rec_asm_op
->get_lvalue ()->playback_lvalue ()->as_tree ());
7497 playback_output_ops
.safe_push (playback_asm_op
);
7501 /* Populate inputs. */
7503 input_asm_operand
*rec_asm_op
;
7505 FOR_EACH_VEC_ELT (m_input_ops
, i
, rec_asm_op
)
7507 playback::asm_operand playback_asm_op
7508 (rec_asm_op
->get_symbolic_name (),
7509 rec_asm_op
->get_constraint (),
7510 rec_asm_op
->get_rvalue ()->playback_rvalue ()->as_tree ());
7511 playback_input_ops
.safe_push (playback_asm_op
);
7515 /* Populate clobbers. */
7517 string
*rec_clobber
;
7519 FOR_EACH_VEC_ELT (m_clobbers
, i
, rec_clobber
)
7520 playback_clobbers
.safe_push (rec_clobber
->c_str ());
7523 /* Populate playback blocks if an "asm goto". */
7524 maybe_populate_playback_blocks (&playback_goto_blocks
);
7526 playback_block (get_block ())
7527 ->add_extended_asm (playback_location (r
),
7528 m_asm_template
->c_str (),
7529 m_is_volatile
, m_is_inline
,
7530 &playback_output_ops
,
7531 &playback_input_ops
,
7533 &playback_goto_blocks
);
7536 /* Implementation of recording::memento::make_debug_string for
7537 an extended_asm "statement". */
7540 recording::extended_asm::make_debug_string ()
7543 pp_string (&pp
, "asm ");
7545 pp_string (&pp
, "volatile ");
7547 pp_string (&pp
, "inline ");
7549 pp_string (&pp
, "goto ");
7550 pp_character (&pp
, '(');
7551 pp_string (&pp
, m_asm_template
->get_debug_string ());
7552 pp_string (&pp
, " : ");
7555 output_asm_operand
*asm_op
;
7556 FOR_EACH_VEC_ELT (m_output_ops
, i
, asm_op
)
7559 pp_string (&pp
, ", ");
7560 asm_op
->print (&pp
);
7563 pp_string (&pp
, " : ");
7565 input_asm_operand
*asm_op
;
7566 FOR_EACH_VEC_ELT (m_input_ops
, i
, asm_op
)
7569 pp_string (&pp
, ", ");
7570 asm_op
->print (&pp
);
7573 pp_string (&pp
, " : ");
7574 string
*rec_clobber
;
7575 FOR_EACH_VEC_ELT (m_clobbers
, i
, rec_clobber
)
7578 pp_string (&pp
, ", ");
7579 pp_string (&pp
, rec_clobber
->get_debug_string ());
7581 maybe_print_gotos (&pp
);
7582 pp_character (&pp
, ')');
7583 return new_string (pp_formatted_text (&pp
));
7587 recording::extended_asm::write_flags (reproducer
&r
)
7590 r
.write (" gcc_jit_extended_asm_set_volatile_flag (%s, 1);\n",
7591 r
.get_identifier (this));
7593 r
.write (" gcc_jit_extended_asm_set_inline_flag (%s, 1);\n",
7594 r
.get_identifier (this));
7598 recording::extended_asm::write_clobbers (reproducer
&r
)
7602 FOR_EACH_VEC_ELT (m_clobbers
, i
, clobber
)
7603 r
.write (" gcc_jit_extended_asm_add_clobber (%s, %s);\n",
7604 r
.get_identifier (this),
7605 clobber
->get_debug_string ());
7608 /* Implementation of recording::memento::write_reproducer for
7609 extended_asm_simple. */
7612 recording::extended_asm_simple::write_reproducer (reproducer
&r
)
7614 const char *id
= r
.make_identifier (this, "extended_asm");
7615 r
.write (" gcc_jit_extended_asm *%s =\n"
7616 " gcc_jit_block_add_extended_asm (%s, /*gcc_jit_block *block */\n"
7617 " %s, /* gcc_jit_location *loc */\n"
7618 " %s); /* const char *asm_template */\n",
7620 r
.get_identifier (get_block ()),
7621 r
.get_identifier (get_loc ()),
7622 m_asm_template
->get_debug_string ());
7628 recording::extended_asm::
7629 maybe_populate_playback_blocks (auto_vec
<playback::block
*> *)
7631 /* Do nothing; not an "asm goto". */
7634 /* The implementation of class gcc::jit::recording::extended_asm_goto. */
7636 /* recording::extended_asm_goto's ctor. */
7638 recording::extended_asm_goto::extended_asm_goto (block
*b
,
7640 string
*asm_template
,
7641 int num_goto_blocks
,
7642 block
**goto_blocks
,
7643 block
*fallthrough_block
)
7644 : extended_asm (b
, loc
, asm_template
),
7645 m_goto_blocks (num_goto_blocks
),
7646 m_fallthrough_block (fallthrough_block
)
7648 for (int i
= 0; i
< num_goto_blocks
; i
++)
7649 m_goto_blocks
.quick_push (goto_blocks
[i
]);
7652 /* Implementation of recording::memento::replay_into
7653 for recording::extended_asm_goto. */
7656 recording::extended_asm_goto::replay_into (replayer
*r
)
7658 /* Chain up to base class impl. */
7659 recording::extended_asm::replay_into (r
);
7661 /* ...and potentially add a goto for the fallthrough. */
7662 if (m_fallthrough_block
)
7663 playback_block (get_block ())
7664 ->add_jump (playback_location (r
),
7665 m_fallthrough_block
->playback_block ());
7668 /* Implementation of recording::memento::write_reproducer for
7669 extended_asm_goto. */
7672 recording::extended_asm_goto::write_reproducer (reproducer
&r
)
7674 const char *id
= r
.make_identifier (this, "extended_asm");
7675 const char *blocks_id
= r
.make_tmp_identifier ("blocks_for", this);
7676 r
.write (" gcc_jit_block *%s[%i] = {\n",
7678 m_goto_blocks
.length ());
7681 FOR_EACH_VEC_ELT (m_goto_blocks
, i
, b
)
7682 r
.write (" %s,\n", r
.get_identifier (b
));
7684 r
.write (" gcc_jit_extended_asm *%s =\n"
7685 " gcc_jit_block_end_with_extended_asm_goto (%s, /*gcc_jit_block *block */\n"
7686 " %s, /* gcc_jit_location *loc */\n"
7687 " %s, /* const char *asm_template */\n"
7688 " %i, /* int num_goto_blocks */\n"
7689 " %s, /* gcc_jit_block **goto_blocks */\n"
7690 " %s); /* gcc_jit_block *fallthrough_block */\n",
7692 r
.get_identifier (get_block ()),
7693 r
.get_identifier (get_loc ()),
7694 m_asm_template
->get_debug_string (),
7695 m_goto_blocks
.length (),
7697 (m_fallthrough_block
7698 ? r
.get_identifier (m_fallthrough_block
)
7704 /* Override the poisoned default implementation of
7705 gcc::jit::recording::statement::get_successor_blocks
7707 An extended_asm_goto can jump to the m_goto_blocks, and to
7708 the (optional) m_fallthrough_block. */
7710 vec
<recording::block
*>
7711 recording::extended_asm_goto::get_successor_blocks () const
7713 vec
<block
*> result
;
7714 result
.create (m_goto_blocks
.length () + 1);
7715 if (m_fallthrough_block
)
7716 result
.quick_push (m_fallthrough_block
);
7717 result
.splice (m_goto_blocks
);
7721 /* Vfunc for use by recording::extended_asm::make_debug_string. */
7724 recording::extended_asm_goto::maybe_print_gotos (pretty_printer
*pp
) const
7726 pp_string (pp
, " : ");
7729 FOR_EACH_VEC_ELT (m_goto_blocks
, i
, b
)
7732 pp_string (pp
, ", ");
7733 pp_string (pp
, b
->get_debug_string ());
7735 /* Non-C syntax here. */
7736 if (m_fallthrough_block
)
7737 pp_printf (pp
, " [fallthrough: %s]",
7738 m_fallthrough_block
->get_debug_string ());
7741 /* Vfunc for use by recording::extended_asm::replay_into. */
7744 recording::extended_asm_goto::
7745 maybe_populate_playback_blocks (auto_vec
<playback::block
*> *out
)
7749 FOR_EACH_VEC_ELT (m_goto_blocks
, i
, b
)
7750 out
->safe_push (b
->playback_block ());
7753 /* class top_level_asm : public memento. */
7755 recording::top_level_asm::top_level_asm (context
*ctxt
,
7760 m_asm_stmts (asm_stmts
)
7764 /* Implementation of recording::memento::replay_into for top-level asm. */
7767 recording::top_level_asm::replay_into (replayer
*r
)
7769 r
->add_top_level_asm (m_asm_stmts
->c_str ());
7772 /* Implementation of recording::memento::make_debug_string for
7776 recording::top_level_asm::make_debug_string ()
7778 return string::from_printf (m_ctxt
, "asm (%s)",
7779 m_asm_stmts
->get_debug_string ());
7782 /* Override the default implementation of
7783 recording::memento::write_to_dump.
7784 Don't indent the string. */
7787 recording::top_level_asm::write_to_dump (dump
&d
)
7789 d
.write ("%s;\n", get_debug_string ());
7792 /* Implementation of recording::memento::write_reproducer for top-level asm. */
7795 recording::top_level_asm::write_reproducer (reproducer
&r
)
7797 r
.write (" gcc_jit_context_add_top_level_asm (%s, /* gcc_jit_context *ctxt */\n"
7798 " %s, /* gcc_jit_location *loc */\n"
7799 " %s); /* const char *asm_stmts */\n",
7800 r
.get_identifier (get_context ()),
7801 r
.get_identifier (m_loc
),
7802 m_asm_stmts
->get_debug_string ());
7806 recording::global_init_rvalue::replay_into (replayer
*r
)
7808 r
->global_set_init_rvalue (m_variable
->playback_lvalue (),
7809 m_init
->playback_rvalue ());
7813 recording::global_init_rvalue::write_reproducer (reproducer
&r
)
7816 " gcc_jit_global_set_initializer_rvalue (%s, /* lvalue *global */\n"
7817 " %s);/* rvalue *init */\n",
7818 r
.get_identifier (m_variable
),
7819 r
.get_identifier_as_rvalue (m_init
));
7823 recording::global_init_rvalue::write_to_dump (dump
&d
)
7825 d
.write ("%s;\n", get_debug_string ());
7829 recording::global_init_rvalue::make_debug_string ()
7831 return string::from_printf (m_ctxt
, "%s = %s",
7832 m_variable
->get_debug_string (),
7833 m_init
->get_debug_string ());
7842 /* Strips type down to array, vector or base type (whichever comes first)
7844 Also saves 'ptr_depth' and sets 'flags' for array or vector types. */
7847 strip_and_count (recording::type
*type_to_strip
,
7851 recording::type
*t
= type_to_strip
;
7856 gcc_unreachable (); /* Should only happen on corrupt input. */
7858 recording::type
*pointed_to_type
= t
->is_pointer ();
7859 if (pointed_to_type
!= NULL
)
7862 t
= pointed_to_type
;
7866 recording::type
*array_el
= t
->is_array ();
7867 if (array_el
!= NULL
)
7869 flags
= STRIP_FLAG_ARR
;
7873 recording::type
*vec
= t
->dyn_cast_vector_type ();
7876 flags
= STRIP_FLAG_VEC
;
7880 /* unqualified () returns 'this' on base types. */
7881 recording::type
*next
= t
->unqualified ();
7892 /* Strip qualifiers and count pointer depth, returning true
7893 if the types' base type and pointer depth are
7894 the same, otherwise false.
7896 For array and vector types the number of element also
7899 Do not call this directly. Call 'types_kinda_same'. */
7901 types_kinda_same_internal (recording::type
*a
, recording::type
*b
)
7903 int ptr_depth_a
= 0;
7904 int ptr_depth_b
= 0;
7905 recording::type
*base_a
;
7906 recording::type
*base_b
;
7908 strip_flags flags_a
= STRIP_FLAG_NONE
;
7909 strip_flags flags_b
= STRIP_FLAG_NONE
;
7911 base_a
= strip_and_count (a
, ptr_depth_a
, flags_a
);
7912 base_b
= strip_and_count (b
, ptr_depth_b
, flags_b
);
7914 if (ptr_depth_a
!= ptr_depth_b
)
7917 if (base_a
== base_b
)
7920 if (flags_a
!= flags_b
)
7923 /* If the "base type" is an array or vector we might need to
7925 if (flags_a
== STRIP_FLAG_ARR
)
7927 recording::array_type
*arr_a
=
7928 static_cast<recording::array_type
*> (base_a
);
7929 recording::array_type
*arr_b
=
7930 static_cast<recording::array_type
*> (base_b
);
7932 if (arr_a
->num_elements () != arr_b
->num_elements ())
7935 /* is_array returns element type. */
7936 recording::type
*el_a
= arr_a
->is_array ();
7937 recording::type
*el_b
= arr_b
->is_array ();
7942 return types_kinda_same_internal (el_a
, el_b
);
7944 if (flags_a
== STRIP_FLAG_VEC
)
7946 recording::vector_type
*arr_a
=
7947 static_cast<recording::vector_type
*> (base_a
);
7948 recording::vector_type
*arr_b
=
7949 static_cast<recording::vector_type
*> (base_b
);
7951 if (arr_a
->get_num_units () != arr_b
->get_num_units ())
7954 recording::type
*el_a
= arr_a
->get_element_type ();
7955 recording::type
*el_b
= arr_b
->get_element_type ();
7960 return types_kinda_same_internal (el_a
, el_b
);
7966 } // namespace gcc::jit