1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2023 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"
38 dump::dump (recording::context
&ctxt
,
40 bool update_locations
)
42 m_filename (filename
),
43 m_update_locations (update_locations
),
47 m_file
= fopen (filename
, "w");
50 "error opening dump file %s for writing: %s",
59 int err
= fclose (m_file
);
61 m_ctxt
.add_error (NULL
,
62 "error closing dump file %s: %s",
68 /* Write the given message to the dump, using printf-formatting
69 conventions, updating the line/column within the dump.
71 Emit an error on the context if a failure occurs. */
74 dump::write (const char *fmt
, ...)
80 /* If there was an error opening the file, we've already reported it.
81 Don't attempt further work. */
86 len
= vasprintf (&buf
, fmt
, ap
);
89 if (buf
== NULL
|| len
< 0)
91 m_ctxt
.add_error (NULL
, "malloc failure writing to dumpfile %s",
96 if (fwrite (buf
, strlen (buf
), 1, m_file
) != 1)
97 m_ctxt
.add_error (NULL
, "error writing to dump file %s",
100 /* Flush after each line, to ease debugging crashes. */
103 /* Update line/column: */
104 for (const char *ptr
= buf
; *ptr
; ptr
++)
118 /* Construct a gcc::jit::recording::location instance for the current
119 location within the dump. */
121 recording::location
*
122 dump::make_location () const
124 return m_ctxt
.new_location (m_filename
, m_line
, m_column
,
125 /* We need to flag such locations as *not*
126 created by the user, so that
127 reproducer::get_identifier can cope with
128 them appearing *after* the memento that
133 /* A collection of allocations, all of which can be released together, to
134 avoid needing to track and release them individually. */
142 xstrdup_printf (const char *, ...)
143 ATTRIBUTE_RETURNS_NONNULL
147 xstrdup_printf_va (const char *, va_list ap
)
148 ATTRIBUTE_RETURNS_NONNULL
152 auto_vec
<void *> m_buffers
;
155 /* allocator's destructor. Call "free" on all of the allocations. */
157 allocator::~allocator ()
161 FOR_EACH_VEC_ELT (m_buffers
, i
, buffer
)
165 /* Formatted printing, allocating to a buffer (or exiting the process if
166 the allocation fails).
168 The buffer exists until the allocator is cleaned up, and is freed at
169 that point, so the caller doesn't need to track the result. */
172 allocator::xstrdup_printf (const char *fmt
, ...)
177 result
= xstrdup_printf_va (fmt
, ap
);
182 /* Formatted printing, allocating to a buffer (or exiting the process if
183 the allocation fails).
185 The buffer exists until the allocator is cleaned up, and is freed at
186 that point, so the caller doesn't need to track the result. */
189 allocator::xstrdup_printf_va (const char *fmt
, va_list ap
)
191 char *result
= xvasprintf (fmt
, ap
);
192 m_buffers
.safe_push (result
);
196 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
197 implementing gcc_jit_context_dump_reproducer_to_file. */
199 class reproducer
: public dump
202 reproducer (recording::context
&ctxt
,
203 const char *filename
);
206 write_params (const vec
<recording::context
*> &contexts
);
209 write_args (const vec
<recording::context
*> &contexts
);
212 make_identifier (recording::memento
*m
, const char *prefix
);
215 make_tmp_identifier (const char *prefix
, recording::memento
*m
);
218 get_identifier (recording::context
*ctxt
);
221 get_identifier (recording::memento
*m
);
224 get_identifier_as_rvalue (recording::rvalue
*m
);
227 get_identifier_as_lvalue (recording::lvalue
*m
);
230 get_identifier_as_type (recording::type
*m
);
233 xstrdup_printf (const char *, ...)
234 ATTRIBUTE_RETURNS_NONNULL
238 const char * ensure_identifier_is_unique (const char *candidate
, void *ptr
);
241 hash_map
<recording::memento
*, const char *> m_map_memento_to_identifier
;
243 struct hash_traits
: public string_hash
245 static void remove (const char *) {}
247 hash_set
<const char *, false, hash_traits
> m_set_identifiers
;
248 allocator m_allocator
;
251 /* gcc::jit::reproducer's constructor. */
253 reproducer::reproducer (recording::context
&ctxt
,
254 const char *filename
) :
255 dump (ctxt
, filename
, 0),
256 m_map_memento_to_identifier (),
257 m_set_identifiers (),
262 /* Write out a list of contexts as a set of parameters within a
263 C function declaration. */
266 reproducer::write_params (const vec
<recording::context
*> &contexts
)
269 recording::context
*ctxt
;
270 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
272 write ("gcc_jit_context *%s",
273 get_identifier (ctxt
));
274 if (i
< contexts
.length () - 1)
280 /* Write out a list of contexts as a set of arguments within a call
284 reproducer::write_args (const vec
<recording::context
*> &contexts
)
287 recording::context
*ctxt
;
288 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
291 get_identifier (ctxt
));
292 if (i
< contexts
.length () - 1)
298 /* Ensure that STR is a valid C identifier by overwriting
299 any invalid chars in-place with underscores.
301 This doesn't special-case the first character. */
304 convert_to_identifier (char *str
)
306 for (char *p
= str
; *p
; p
++)
311 /* Given CANDIDATE, a possible C identifier for use in a reproducer,
312 ensure that it is unique within the generated source file by
313 appending PTR to it if necessary. Return the resulting string.
315 The reproducer will eventually clean up the buffer in its dtor. */
318 reproducer::ensure_identifier_is_unique (const char *candidate
, void *ptr
)
320 if (m_set_identifiers
.contains (candidate
))
321 candidate
= m_allocator
.xstrdup_printf ("%s_%p", candidate
, ptr
);
322 gcc_assert (!m_set_identifiers
.contains (candidate
));
323 m_set_identifiers
.add (candidate
);
327 /* Generate a C identifier for the given memento, associating the generated
328 buffer with the memento (for future calls to get_identifier et al).
330 The reproducer will eventually clean up the buffer in its dtor. */
332 reproducer::make_identifier (recording::memento
*m
, const char *prefix
)
335 if (strlen (m
->get_debug_string ()) < 100)
337 char *buf
= m_allocator
.xstrdup_printf ("%s_%s",
339 m
->get_debug_string ());
340 convert_to_identifier (buf
);
344 result
= m_allocator
.xstrdup_printf ("%s_%p",
346 result
= ensure_identifier_is_unique (result
, m
);
347 m_map_memento_to_identifier
.put (m
, result
);
351 /* Generate a C identifier for a temporary variable.
352 The reproducer will eventually clean up the buffer in its dtor. */
355 reproducer::make_tmp_identifier (const char *prefix
, recording::memento
*m
)
357 return m_allocator
.xstrdup_printf ("%s_%s",
358 prefix
, get_identifier (m
));
361 /* Generate a C identifier for the given context.
362 The reproducer will eventually clean up the buffer in its dtor. */
365 reproducer::get_identifier (recording::context
*ctxt
)
367 return m_allocator
.xstrdup_printf ("ctxt_%p",
371 /* Locate the C identifier for the given memento, which is assumed to
372 have already been created via make_identifier. */
375 reproducer::get_identifier (recording::memento
*m
)
380 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
381 and hence these locations appear in the context's memento list
382 out-of-order: they appear in the context's memento list *after*
383 the memento that refers to them. For this case, it's simplest to
384 pretend that they're NULL when writing out the code to recreate the
385 memento that uses them. */
386 if (recording::location
*loc
= m
->dyn_cast_location ())
387 if (!loc
->created_by_user ())
390 const char **slot
= m_map_memento_to_identifier
.get (m
);
393 get_context ().add_error (NULL
,
394 "unable to find identifier for %p: %s",
396 m
->get_debug_string ());
402 /* Locate the C identifier for the given rvalue, wrapping it within
403 a gcc_*_as_rvalue upcast if necessary. */
406 reproducer::get_identifier_as_rvalue (recording::rvalue
*m
)
408 return m
->access_as_rvalue (*this);
411 /* Locate the C identifier for the given lvalue, wrapping it within
412 a gcc_*_as_lvalue upcast if necessary. */
415 reproducer::get_identifier_as_lvalue (recording::lvalue
*m
)
417 return m
->access_as_lvalue (*this);
420 /* Locate the C identifier for the given type, wrapping it within
421 a gcc_*_as_type upcast if necessary. */
424 reproducer::get_identifier_as_type (recording::type
*m
)
426 return m
->access_as_type (*this);
429 /* Formatted printing, allocating to a buffer (or exiting the process if
430 the allocation fails).
432 The buffer exists until the allocator is cleaned up, and is freed at
433 that point, so the caller doesn't need to track the result.
435 Note that we can't use ggc_printf since we're not within the compiler
436 proper (when within gcc_jit_context_dump_reproducer_to_file). */
439 reproducer::xstrdup_printf (const char *fmt
, ...)
444 result
= m_allocator
.xstrdup_printf_va (fmt
, ap
);
449 /* A helper class for implementing make_debug_string, for building
450 a temporary string from a vec of rvalues. */
452 class comma_separated_string
455 comma_separated_string (const auto_vec
<recording::rvalue
*> &rvalues
,
456 enum recording::precedence prec
);
457 ~comma_separated_string ();
459 const char *as_char_ptr () const { return m_buf
; }
465 /* comma_separated_string's ctor
468 comma_separated_string::comma_separated_string
469 (const auto_vec
<recording::rvalue
*> &rvalues
,
470 enum recording::precedence prec
)
473 /* Calculate length of said buffer. */
474 size_t sz
= 1; /* nil terminator */
475 for (unsigned i
= 0; i
< rvalues
.length (); i
++)
477 sz
+= strlen (rvalues
[i
]->get_debug_string_parens (prec
));
478 sz
+= 2; /* ", " separator */
481 /* Now allocate and populate the buffer. */
482 m_buf
= new char[sz
];
485 for (unsigned i
= 0; i
< rvalues
.length (); i
++)
487 strcpy (m_buf
+ len
, rvalues
[i
]->get_debug_string_parens (prec
));
488 len
+= strlen (rvalues
[i
]->get_debug_string_parens (prec
));
489 if (i
+ 1 < rvalues
.length ())
491 strcpy (m_buf
+ len
, ", ");
498 /* comma_separated_string's dtor. */
500 comma_separated_string::~comma_separated_string ()
505 /**********************************************************************
507 **********************************************************************/
509 /* Get the playback::location for the given recording::location,
510 handling a NULL input with a NULL output. */
513 recording::playback_location (replayer
*r
, recording::location
*loc
)
516 return loc
->playback_location (r
);
521 /* Get a const char * for the given recording::string
522 handling a NULL input with a NULL output. */
525 recording::playback_string (recording::string
*str
)
528 return str
->c_str ();
533 /* Get the playback::block for the given recording::block,
534 handling a NULL input with a NULL output. */
537 recording::playback_block (recording::block
*b
)
540 return b
->playback_block ();
545 /* Methods of cc::jit::recording::context. */
547 /* The constructor for gcc::jit::recording::context, used by
548 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
550 recording::context::context (context
*parent_ctxt
)
552 m_parent_ctxt (parent_ctxt
),
553 m_toplevel_ctxt (m_parent_ctxt
? m_parent_ctxt
->m_toplevel_ctxt
: this),
556 m_first_error_str (NULL
),
557 m_owns_first_error_str (false),
558 m_last_error_str (NULL
),
559 m_owns_last_error_str (false),
565 m_builtins_manager(NULL
)
569 /* Inherit options from parent. */
570 for (unsigned i
= 0; i
< ARRAY_SIZE (m_str_options
); i
++)
572 const char *parent_opt
= parent_ctxt
->m_str_options
[i
];
573 m_str_options
[i
] = parent_opt
? xstrdup (parent_opt
) : NULL
;
575 memcpy (m_int_options
,
576 parent_ctxt
->m_int_options
,
577 sizeof (m_int_options
));
578 memcpy (m_bool_options
,
579 parent_ctxt
->m_bool_options
,
580 sizeof (m_bool_options
));
581 memcpy (m_inner_bool_options
,
582 parent_ctxt
->m_inner_bool_options
,
583 sizeof (m_inner_bool_options
));
584 set_logger (parent_ctxt
->get_logger ());
588 memset (m_str_options
, 0, sizeof (m_str_options
));
589 memset (m_int_options
, 0, sizeof (m_int_options
));
590 memset (m_bool_options
, 0, sizeof (m_bool_options
));
591 memset (m_inner_bool_options
, 0, sizeof (m_inner_bool_options
));
592 m_inner_bool_options
[INNER_BOOL_OPTION_PRINT_ERRORS_TO_STDERR
] = true;
595 memset (m_basic_types
, 0, sizeof (m_basic_types
));
598 /* The destructor for gcc::jit::recording::context, implicitly used by
599 gcc_jit_context_release. */
601 recording::context::~context ()
603 JIT_LOG_SCOPE (get_logger ());
606 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
611 for (i
= 0; i
< GCC_JIT_NUM_STR_OPTIONS
; ++i
)
612 free (m_str_options
[i
]);
615 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
617 FOR_EACH_VEC_ELT (m_driver_options
, i
, optname
)
620 if (m_builtins_manager
)
621 delete m_builtins_manager
;
623 if (m_owns_first_error_str
)
624 free (m_first_error_str
);
626 if (m_owns_last_error_str
)
627 if (m_last_error_str
!= m_first_error_str
)
628 free (m_last_error_str
);
631 /* Add the given mememto to the list of those tracked by this
632 gcc::jit::recording::context, so that e.g. it can be deleted
633 when this context is released. */
636 recording::context::record (memento
*m
)
640 m_mementos
.safe_push (m
);
643 /* Replay this context (and any parents) into the given replayer. */
646 recording::context::replay_into (replayer
*r
)
648 JIT_LOG_SCOPE (get_logger ());
652 /* If we have a parent context, we must replay it. This will
653 recursively walk backwards up the historical tree, then replay things
654 forwards "in historical order", starting with the ultimate parent
655 context, until we reach the "this" context.
657 Note that we fully replay the parent, then fully replay the child,
658 which means that inter-context references can only exist from child
659 to parent, not the other way around.
661 All of this replaying is suboptimal - it would be better to do the
662 work for the parent context *once*, rather than replaying the parent
663 every time we replay each child. However, fixing this requires deep
664 surgery to lifetime-management: we'd need every context family tree
665 to have its own GC heap, and to initialize the GCC code to use that
666 heap (with a mutex on such a heap). */
668 m_parent_ctxt
->replay_into (r
);
670 if (r
->errors_occurred ())
673 /* Replay this context's saved operations into r. */
674 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
676 /* Disabled low-level debugging, here if we need it: print what
678 Note that the calls to get_debug_string might lead to more
679 mementos being created for the strings.
680 This can also be used to exercise the debug_string
683 printf ("context %p replaying (%p): %s\n",
684 (void *)this, (void *)m
, m
->get_debug_string ());
688 if (r
->errors_occurred ())
693 /* During a playback, we associate objects from the recording with
694 their counterparts during this playback.
696 For simplicity, we store this within the recording objects.
698 The following method cleans away these associations, to ensure that
699 we never have out-of-date associations lingering on subsequent
700 playbacks (the objects pointed to are GC-managed, but the
701 recording objects don't own refs to them). */
704 recording::context::disassociate_from_playback ()
706 JIT_LOG_SCOPE (get_logger ());
711 m_parent_ctxt
->disassociate_from_playback ();
713 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
715 m
->set_playback_obj (NULL
);
719 /* Create a recording::string instance and add it to this context's list
722 This creates a fresh copy of the given 0-terminated buffer. */
725 recording::context::new_string (const char *text
, bool escaped
)
730 recording::string
*result
= new string (this, text
, escaped
);
735 /* Create a recording::location instance and add it to this context's
738 Implements the post-error-checking part of
739 gcc_jit_context_new_location. */
741 recording::location
*
742 recording::context::new_location (const char *filename
,
745 bool created_by_user
)
747 recording::location
*result
=
748 new recording::location (this,
749 new_string (filename
),
756 /* If we haven't seen this enum value yet, create a recording::type
757 instance and add it to this context's list of mementos.
759 If we have seen it before, reuse our cached value, so that repeated
760 calls on the context give the same object.
762 If we have a parent context, the cache is within the ultimate
765 Implements the post-error-checking part of
766 gcc_jit_context_get_type. */
769 recording::context::get_type (enum gcc_jit_types kind
)
771 if (!m_basic_types
[kind
])
774 m_basic_types
[kind
] = m_parent_ctxt
->get_type (kind
);
777 recording::type
*result
= new memento_of_get_type (this, kind
);
779 m_basic_types
[kind
] = result
;
783 return m_basic_types
[kind
];
786 /* Get a recording::type instance for the given size and signedness.
787 This is implemented in terms of recording::context::get_type
790 Implements the post-error-checking part of
791 gcc_jit_context_get_int_type. */
794 recording::context::get_int_type (int num_bytes
, int is_signed
)
796 /* We can't use a switch here since some of the values are macros affected
797 by options; e.g. i386.h has
798 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
799 Compare with tree.cc's make_or_reuse_type. Note that the _SIZE macros
800 are in bits, rather than bytes.
802 const int num_bits
= num_bytes
* 8;
803 if (num_bits
== INT_TYPE_SIZE
)
804 return get_type (is_signed
806 : GCC_JIT_TYPE_UNSIGNED_INT
);
807 if (num_bits
== CHAR_TYPE_SIZE
)
808 return get_type (is_signed
809 ? GCC_JIT_TYPE_SIGNED_CHAR
810 : GCC_JIT_TYPE_UNSIGNED_CHAR
);
811 if (num_bits
== SHORT_TYPE_SIZE
)
812 return get_type (is_signed
814 : GCC_JIT_TYPE_UNSIGNED_SHORT
);
815 if (num_bits
== LONG_TYPE_SIZE
)
816 return get_type (is_signed
818 : GCC_JIT_TYPE_UNSIGNED_LONG
);
819 if (num_bits
== LONG_LONG_TYPE_SIZE
)
820 return get_type (is_signed
821 ? GCC_JIT_TYPE_LONG_LONG
822 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
824 return get_type (is_signed
825 ? GCC_JIT_TYPE_INT128_T
826 : GCC_JIT_TYPE_UINT128_T
);
828 /* Some other size, not corresponding to the C int types. */
829 /* To be written: support arbitrary other sizes, sharing by
830 memoizing at the recording::context level? */
834 /* Create a recording::type instance and add it to this context's list
837 Implements the post-error-checking part of
838 gcc_jit_context_new_array_type. */
841 recording::context::new_array_type (recording::location
*loc
,
842 recording::type
*element_type
,
845 if (struct_
*s
= element_type
->dyn_cast_struct ())
846 if (!s
->get_fields ())
849 "cannot create an array of type %s"
850 " until the fields have been set",
851 s
->get_name ()->c_str ());
854 recording::type
*result
=
855 new recording::array_type (this, loc
, element_type
, num_elements
);
860 /* Create a recording::field instance and add it to this context's list
863 Implements the post-error-checking part of
864 gcc_jit_context_new_field. */
867 recording::context::new_field (recording::location
*loc
,
868 recording::type
*type
,
871 recording::field
*result
=
872 new recording::field (this, loc
, type
, new_string (name
));
877 /* Create a recording::bitfield instance and add it to this context's list
880 Implements the post-error-checking part of
881 gcc_jit_context_new_bitfield. */
884 recording::context::new_bitfield (recording::location
*loc
,
885 recording::type
*type
,
889 recording::field
*result
=
890 new recording::bitfield (this, loc
, type
, width
, new_string (name
));
895 /* Create a recording::struct_ instance and add it to this context's
896 list of mementos and list of compound types.
898 Implements the post-error-checking part of
899 gcc_jit_context_new_struct_type. */
902 recording::context::new_struct_type (recording::location
*loc
,
905 recording::struct_
*result
= new struct_ (this, loc
, new_string (name
));
907 m_compound_types
.safe_push (result
);
911 /* Create a recording::union_ instance and add it to this context's
912 list of mementos and list of compound types.
914 Implements the first post-error-checking part of
915 gcc_jit_context_new_union_type. */
918 recording::context::new_union_type (recording::location
*loc
,
921 recording::union_
*result
= new union_ (this, loc
, new_string (name
));
923 m_compound_types
.safe_push (result
);
927 /* Create a recording::function_type instance and add it to this context's
930 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
932 recording::function_type
*
933 recording::context::new_function_type (recording::type
*return_type
,
935 recording::type
**param_types
,
938 recording::function_type
*fn_type
939 = new function_type (this,
948 /* Create a recording::type instance and add it to this context's list
951 Implements the post-error-checking part of
952 gcc_jit_context_new_function_ptr_type. */
955 recording::context::new_function_ptr_type (recording::location
*, /* unused loc */
956 recording::type
*return_type
,
958 recording::type
**param_types
,
961 recording::function_type
*fn_type
962 = new_function_type (return_type
,
967 /* Return a pointer-type to the function type. */
968 return fn_type
->get_pointer ();
971 /* Create a recording::param instance and add it to this context's list
974 Implements the post-error-checking part of
975 gcc_jit_context_new_param. */
978 recording::context::new_param (recording::location
*loc
,
979 recording::type
*type
,
982 recording::param
*result
= new recording::param (this, loc
, type
, new_string (name
));
987 /* Create a recording::function instance and add it to this context's list
988 of mementos and list of functions.
990 Implements the post-error-checking part of
991 gcc_jit_context_new_function. */
993 recording::function
*
994 recording::context::new_function (recording::location
*loc
,
995 enum gcc_jit_function_kind kind
,
996 recording::type
*return_type
,
999 recording::param
**params
,
1001 enum built_in_function builtin_id
)
1003 recording::function
*result
=
1004 new recording::function (this,
1005 loc
, kind
, return_type
,
1007 num_params
, params
, is_variadic
,
1010 m_functions
.safe_push (result
);
1015 /* Locate the builtins_manager (if any) for this family of contexts,
1016 creating it if it doesn't exist already.
1018 All of the recording contexts in a family share one builtins_manager:
1019 if we have a child context, follow the parent links to get the
1020 ultimate ancestor context, and look for it/store it there. */
1023 recording::context::get_builtins_manager ()
1026 return m_parent_ctxt
->get_builtins_manager ();
1028 if (!m_builtins_manager
)
1029 m_builtins_manager
= new builtins_manager (this);
1031 return m_builtins_manager
;
1034 /* Get a recording::function instance, which is lazily-created and added
1035 to the context's lists of mementos.
1037 Implements the post-error-checking part of
1038 gcc_jit_context_get_builtin_function. */
1040 recording::function
*
1041 recording::context::get_builtin_function (const char *name
)
1043 builtins_manager
*bm
= get_builtins_manager ();
1044 return bm
->get_builtin_function (name
);
1047 /* Create a recording::global instance and add it to this context's list
1050 Implements the post-error-checking part of
1051 gcc_jit_context_new_global. */
1054 recording::context::new_global (recording::location
*loc
,
1055 enum gcc_jit_global_kind kind
,
1056 recording::type
*type
,
1059 recording::global
*result
=
1060 new recording::global (this, loc
, kind
, type
, new_string (name
));
1062 m_globals
.safe_push (result
);
1068 recording::context::new_global_init_rvalue (lvalue
*variable
,
1071 recording::global_init_rvalue
*obj
=
1072 new recording::global_init_rvalue (this, variable
, init
);
1075 global
*gbl
= (global
*) variable
;
1076 gbl
->set_rvalue_init (init
); /* Needed by the global for write dump. */
1079 /* Create a recording::memento_of_new_string_literal instance and add it
1080 to this context's list of mementos.
1082 Implements the post-error-checking part of
1083 gcc_jit_context_new_string_literal. */
1086 recording::context::new_string_literal (const char *value
)
1088 recording::rvalue
*result
=
1089 new memento_of_new_string_literal (this, NULL
, new_string (value
));
1094 /* Create a recording::memento_of_new_rvalue_from_vector instance and add it
1095 to this context's list of mementos.
1097 Implements the post-error-checking part of
1098 gcc_jit_context_new_rvalue_from_vector. */
1101 recording::context::new_rvalue_from_vector (location
*loc
,
1105 recording::rvalue
*result
1106 = new memento_of_new_rvalue_from_vector (this, loc
, type
, elements
);
1112 recording::context::new_ctor (recording::location
*loc
,
1113 recording::type
*type
,
1118 recording::ctor
*result
= new ctor (this, loc
, type
);
1120 /* Short cut for zero init. */
1127 bool is_struct_or_union
= type
->is_struct () || type
->is_union ();
1129 /* We need to copy fields and values into result's auto_vec:s.
1130 Both for structs and unions and only values for arrays. */
1131 if (type
->is_array () != NULL
)
1133 result
->m_values
.reserve (num_values
, false);
1135 for (size_t i
= 0; i
< num_values
; i
++)
1136 result
->m_values
.quick_push (values
[i
]);
1138 else if (is_struct_or_union
&& fields
)
1140 /* ctor values are paired with user specified fields. */
1142 result
->m_values
.reserve (num_values
, false);
1143 result
->m_fields
.reserve (num_values
, false);
1145 for (size_t i
= 0; i
< num_values
; i
++)
1147 result
->m_values
.quick_push (values
[i
]);
1148 result
->m_fields
.quick_push (fields
[i
]);
1151 else if (is_struct_or_union
&& !fields
)
1153 /* ctor values are in definition order one by one,
1154 so take the fields from the type object. */
1156 result
->m_values
.reserve (num_values
, false);
1157 result
->m_fields
.reserve (num_values
, false);
1159 compound_type
*ct
= reinterpret_cast<compound_type
*>(type
);
1160 recording::fields
*fields
= ct
->get_fields ();
1162 /* The entry point checks that num_values is not greater than
1163 the amount of fields in 'fields'. */
1164 for (size_t i
= 0; i
< num_values
; i
++)
1166 result
->m_values
.quick_push (values
[i
]);
1167 result
->m_fields
.quick_push (fields
->get_field (i
));
1177 /* Create a recording::unary_op instance and add it to this context's
1180 Implements the post-error-checking part of
1181 gcc_jit_context_new_unary_op. */
1184 recording::context::new_unary_op (recording::location
*loc
,
1185 enum gcc_jit_unary_op op
,
1186 recording::type
*result_type
,
1187 recording::rvalue
*a
)
1189 recording::rvalue
*result
=
1190 new unary_op (this, loc
, op
, result_type
, a
);
1195 /* Create a recording::binary_op instance and add it to this context's
1198 Implements the post-error-checking part of
1199 gcc_jit_context_new_binary_op. */
1202 recording::context::new_binary_op (recording::location
*loc
,
1203 enum gcc_jit_binary_op op
,
1204 recording::type
*result_type
,
1205 recording::rvalue
*a
,
1206 recording::rvalue
*b
)
1208 recording::rvalue
*result
=
1209 new binary_op (this, loc
, op
, result_type
, a
, b
);
1214 /* Create a recording::comparison instance and add it to this context's
1217 Implements the post-error-checking part of
1218 gcc_jit_context_new_comparison. */
1221 recording::context::new_comparison (recording::location
*loc
,
1222 enum gcc_jit_comparison op
,
1223 recording::rvalue
*a
,
1224 recording::rvalue
*b
)
1226 recording::rvalue
*result
= new comparison (this, loc
, op
, a
, b
);
1231 /* Create a recording::cast instance and add it to this context's list
1234 Implements the post-error-checking part of
1235 gcc_jit_context_new_cast. */
1238 recording::context::new_cast (recording::location
*loc
,
1239 recording::rvalue
*expr
,
1240 recording::type
*type_
)
1242 recording::rvalue
*result
= new cast (this, loc
, expr
, type_
);
1247 /* Create a recording::bitcast instance and add it to this context's list
1250 Implements the post-error-checking part of
1251 gcc_jit_context_new_bitcast. */
1254 recording::context::new_bitcast (location
*loc
,
1258 recording::rvalue
*result
= new bitcast (this, loc
, expr
, type_
);
1263 /* Create a recording::call instance and add it to this context's list
1266 Implements the post-error-checking part of
1267 gcc_jit_context_new_call. */
1270 recording::context::new_call (recording::location
*loc
,
1272 int numargs
, recording::rvalue
**args
)
1274 recording::rvalue
*result
= new call (this, loc
, func
, numargs
, args
);
1279 /* Create a recording::call_through_ptr instance and add it to this
1280 context's list of mementos.
1282 Implements the post-error-checking part of
1283 gcc_jit_context_new_call_through_ptr. */
1286 recording::context::new_call_through_ptr (recording::location
*loc
,
1287 recording::rvalue
*fn_ptr
,
1289 recording::rvalue
**args
)
1291 recording::rvalue
*result
= new call_through_ptr (this, loc
, fn_ptr
, numargs
, args
);
1296 /* Create a recording::array_access instance and add it to this context's list
1299 Implements the post-error-checking part of
1300 gcc_jit_context_new_array_access. */
1303 recording::context::new_array_access (recording::location
*loc
,
1304 recording::rvalue
*ptr
,
1305 recording::rvalue
*index
)
1307 recording::lvalue
*result
= new array_access (this, loc
, ptr
, index
);
1312 /* Create a recording::case_ instance and add it to this context's list
1315 Implements the post-error-checking part of
1316 gcc_jit_context_new_case. */
1319 recording::context::new_case (recording::rvalue
*min_value
,
1320 recording::rvalue
*max_value
,
1321 recording::block
*block
)
1323 recording::case_
*result
= new case_ (this, min_value
, max_value
, block
);
1328 /* Set the given string option for this context, or add an error if
1329 it's not recognized.
1331 Implements the post-error-checking part of
1332 gcc_jit_context_set_str_option. */
1335 recording::context::set_str_option (enum gcc_jit_str_option opt
,
1338 if (opt
< 0 || opt
>= GCC_JIT_NUM_STR_OPTIONS
)
1341 "unrecognized (enum gcc_jit_str_option) value: %i", opt
);
1344 free (m_str_options
[opt
]);
1345 m_str_options
[opt
] = value
? xstrdup (value
) : NULL
;
1346 log_str_option (opt
);
1349 /* Set the given integer option for this context, or add an error if
1350 it's not recognized.
1352 Implements the post-error-checking part of
1353 gcc_jit_context_set_int_option. */
1356 recording::context::set_int_option (enum gcc_jit_int_option opt
,
1359 if (opt
< 0 || opt
>= GCC_JIT_NUM_INT_OPTIONS
)
1362 "unrecognized (enum gcc_jit_int_option) value: %i", opt
);
1365 m_int_options
[opt
] = value
;
1366 log_int_option (opt
);
1369 /* Set the given boolean option for this context, or add an error if
1370 it's not recognized.
1372 Implements the post-error-checking part of
1373 gcc_jit_context_set_bool_option. */
1376 recording::context::set_bool_option (enum gcc_jit_bool_option opt
,
1379 if (opt
< 0 || opt
>= GCC_JIT_NUM_BOOL_OPTIONS
)
1382 "unrecognized (enum gcc_jit_bool_option) value: %i", opt
);
1385 m_bool_options
[opt
] = value
? true : false;
1386 log_bool_option (opt
);
1390 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt
,
1393 gcc_assert (inner_opt
>= 0 && inner_opt
< NUM_INNER_BOOL_OPTIONS
);
1394 m_inner_bool_options
[inner_opt
] = value
? true : false;
1395 log_inner_bool_option (inner_opt
);
1399 /* Add the given optname to this context's list of extra options.
1401 Implements the post-error-checking part of
1402 gcc_jit_context_add_command_line_option. */
1405 recording::context::add_command_line_option (const char *optname
)
1407 m_command_line_options
.safe_push (xstrdup (optname
));
1410 /* Add any user-provided extra options, starting with any from
1412 Called by playback::context::make_fake_args. */
1415 recording::context::append_command_line_options (vec
<char *> *argvec
)
1418 m_parent_ctxt
->append_command_line_options (argvec
);
1422 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1423 argvec
->safe_push (xstrdup (optname
));
1426 /* Add the given optname to this context's list of extra driver options. */
1429 recording::context::add_driver_option (const char *optname
)
1431 m_driver_options
.safe_push (xstrdup (optname
));
1434 /* Add any user-provided driver options, starting with any from
1436 Called by playback::context::invoke_driver. */
1439 recording::context::append_driver_options (auto_string_vec
*argvec
)
1442 m_parent_ctxt
->append_driver_options (argvec
);
1447 FOR_EACH_VEC_ELT (m_driver_options
, i
, optname
)
1448 argvec
->safe_push (xstrdup (optname
));
1451 /* Add the given dumpname/out_ptr pair to this context's list of requested
1454 Implements the post-error-checking part of
1455 gcc_jit_context_enable_dump. */
1458 recording::context::enable_dump (const char *dumpname
,
1462 gcc_assert (dumpname
);
1463 gcc_assert (out_ptr
);
1465 d
.m_dumpname
= dumpname
;
1466 d
.m_out_ptr
= out_ptr
;
1468 m_requested_dumps
.safe_push (d
);
1471 /* Validate this context, and if it passes, compile it to memory
1474 Implements the post-error-checking part of
1475 gcc_jit_context_compile. */
1478 recording::context::compile ()
1480 JIT_LOG_SCOPE (get_logger ());
1486 if (errors_occurred ())
1489 /* Set up a compile_to_memory playback context. */
1490 ::gcc::jit::playback::compile_to_memory
replayer (this);
1493 replayer
.compile ();
1495 /* Get the jit::result (or NULL) from the
1496 compile_to_memory playback context. */
1497 return replayer
.get_result_obj ();
1500 /* Validate this context, and if it passes, compile it to a file
1503 Implements the post-error-checking part of
1504 gcc_jit_context_compile_to_file. */
1507 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind
,
1508 const char *output_path
)
1510 JIT_LOG_SCOPE (get_logger ());
1516 if (errors_occurred ())
1519 /* Set up a compile_to_file playback context. */
1520 ::gcc::jit::playback::compile_to_file
replayer (this,
1525 replayer
.compile ();
1528 /* Format the given error using printf's conventions, print
1529 it to stderr, and add it to the context. */
1532 recording::context::add_error (location
*loc
, const char *fmt
, ...)
1536 add_error_va (loc
, fmt
, ap
);
1540 /* Format the given error using printf's conventions, print
1541 it to stderr, and add it to the context. */
1544 recording::context::add_error_va (location
*loc
, const char *fmt
, va_list ap
)
1551 JIT_LOG_SCOPE (get_logger ());
1553 len
= vasprintf (&malloced_msg
, fmt
, ap
);
1554 if (malloced_msg
== NULL
|| len
< 0)
1556 errmsg
= "out of memory generating error message";
1557 has_ownership
= false;
1561 errmsg
= malloced_msg
;
1562 has_ownership
= true;
1565 get_logger ()->log ("error %i: %s", m_error_count
, errmsg
);
1567 const char *ctxt_progname
=
1568 get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
1570 ctxt_progname
= "libgccjit.so";
1572 bool print_errors_to_stderr
=
1573 get_inner_bool_option (INNER_BOOL_OPTION_PRINT_ERRORS_TO_STDERR
);
1574 if (print_errors_to_stderr
)
1577 fprintf (stderr
, "%s: %s: error: %s\n",
1579 loc
->get_debug_string (),
1582 fprintf (stderr
, "%s: error: %s\n",
1589 m_first_error_str
= const_cast <char *> (errmsg
);
1590 m_owns_first_error_str
= has_ownership
;
1593 if (m_owns_last_error_str
)
1594 if (m_last_error_str
!= m_first_error_str
)
1595 free (m_last_error_str
);
1596 m_last_error_str
= const_cast <char *> (errmsg
);
1597 m_owns_last_error_str
= has_ownership
;
1602 /* Get the message for the first error that occurred on this context, or
1603 NULL if no errors have occurred on it.
1605 Implements the post-error-checking part of
1606 gcc_jit_context_get_first_error. */
1609 recording::context::get_first_error () const
1611 return m_first_error_str
;
1614 /* Get the message for the last error that occurred on this context, or
1615 NULL if no errors have occurred on it.
1617 Implements the post-error-checking part of
1618 gcc_jit_context_get_last_error. */
1621 recording::context::get_last_error () const
1623 return m_last_error_str
;
1626 /* Lazily generate and record a recording::type representing an opaque
1627 struct named "FILE".
1629 For use if client code tries to dereference the result of
1630 get_type (GCC_JIT_TYPE_FILE_PTR). */
1633 recording::context::get_opaque_FILE_type ()
1636 m_FILE_type
= new_struct_type (NULL
, "FILE");
1640 /* Dump a C-like representation of the given context to the given path.
1641 If UPDATE_LOCATIONS is true, update the locations within the
1642 context's mementos to point to the dumpfile.
1644 Implements the post-error-checking part of
1645 gcc_jit_context_dump_to_file. */
1648 recording::context::dump_to_file (const char *path
, bool update_locations
)
1651 dump
d (*this, path
, update_locations
);
1653 /* Forward declaration of structs and unions. */
1655 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1657 d
.write ("%s;\n\n", st
->get_debug_string ());
1660 /* Content of structs, where set. */
1661 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1662 if (st
->get_fields ())
1664 st
->get_fields ()->write_to_dump (d
);
1670 FOR_EACH_VEC_ELT (m_globals
, i
, g
)
1672 g
->write_to_dump (d
);
1674 if (!m_globals
.is_empty ())
1678 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1680 fn
->write_to_dump (d
);
1684 FOR_EACH_VEC_ELT (m_top_level_asms
, i
, tla
)
1685 tla
->write_to_dump (d
);
1688 static const char * const
1689 str_option_reproducer_strings
[GCC_JIT_NUM_STR_OPTIONS
] = {
1690 "GCC_JIT_STR_OPTION_PROGNAME"
1693 static const char * const
1694 int_option_reproducer_strings
[GCC_JIT_NUM_INT_OPTIONS
] = {
1695 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1698 static const char * const
1699 bool_option_reproducer_strings
[GCC_JIT_NUM_BOOL_OPTIONS
] = {
1700 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1701 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1702 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1703 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1704 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1705 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1706 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1707 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1710 static const char * const
1711 inner_bool_option_reproducer_strings
[NUM_INNER_BOOL_OPTIONS
] = {
1712 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1713 "gcc_jit_context_set_bool_use_external_driver",
1714 "gcc_jit_context_set_bool_print_errors_to_stderr",
1717 /* Write the current value of all options to the log file (if any). */
1720 recording::context::log_all_options () const
1727 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1728 log_str_option ((enum gcc_jit_str_option
)opt_idx
);
1730 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1731 log_int_option ((enum gcc_jit_int_option
)opt_idx
);
1733 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1734 log_bool_option ((enum gcc_jit_bool_option
)opt_idx
);
1735 for (opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1736 log_inner_bool_option ((enum inner_bool_option
)opt_idx
);
1739 /* Write the current value of the given string option to the
1740 log file (if any). */
1743 recording::context::log_str_option (enum gcc_jit_str_option opt
) const
1745 gcc_assert (opt
< GCC_JIT_NUM_STR_OPTIONS
);
1748 if (m_str_options
[opt
])
1750 str_option_reproducer_strings
[opt
],
1751 m_str_options
[opt
]);
1754 str_option_reproducer_strings
[opt
]);
1758 /* Write the current value of the given int option to the
1759 log file (if any). */
1762 recording::context::log_int_option (enum gcc_jit_int_option opt
) const
1764 gcc_assert (opt
< GCC_JIT_NUM_INT_OPTIONS
);
1767 int_option_reproducer_strings
[opt
],
1768 m_int_options
[opt
]);
1771 /* Write the current value of the given bool option to the
1772 log file (if any). */
1775 recording::context::log_bool_option (enum gcc_jit_bool_option opt
) const
1777 gcc_assert (opt
< GCC_JIT_NUM_BOOL_OPTIONS
);
1780 bool_option_reproducer_strings
[opt
],
1781 m_bool_options
[opt
] ? "true" : "false");
1784 /* Write the current value of the given "inner" bool option to the
1785 log file (if any). */
1788 recording::context::log_inner_bool_option (enum inner_bool_option opt
) const
1790 gcc_assert (opt
< NUM_INNER_BOOL_OPTIONS
);
1793 inner_bool_option_reproducer_strings
[opt
],
1794 m_inner_bool_options
[opt
] ? "true" : "false");
1797 /* Write C source code to PATH that attempts to replay the API
1798 calls made to this context (and its parents), for use in
1799 minimizing test cases for libgccjit.
1801 Implements the post-error-checking part of
1802 gcc_jit_context_dump_reproducer_to_file. */
1805 recording::context::dump_reproducer_to_file (const char *path
)
1807 JIT_LOG_SCOPE (get_logger ());
1808 reproducer
r (*this, path
);
1810 /* Generate the "ancestry" of this context, as a list. */
1811 auto_vec
<context
*> ascending_contexts
;
1812 for (context
*ctxt
= this; ctxt
; ctxt
= ctxt
->m_parent_ctxt
)
1813 ascending_contexts
.safe_push (ctxt
);
1815 /* Reverse the list, giving a list of contexts from
1816 top-most parent context down through to youngest child context.
1817 We will use this list as the parameters of the functions in
1818 our generated file. */
1819 unsigned num_ctxts
= ascending_contexts
.length ();
1820 auto_vec
<context
*> contexts (num_ctxts
);
1821 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1822 contexts
.safe_push (ascending_contexts
[num_ctxts
- (i
+ 1)]);
1824 /* contexts[0] should be the top-level context. */
1825 gcc_assert (contexts
[0]);
1826 gcc_assert (contexts
[0]->m_toplevel_ctxt
== contexts
[0]);
1828 /* The final element in contexts should be "this". */
1829 gcc_assert (contexts
[contexts
.length () - 1] == this);
1830 gcc_assert (contexts
[contexts
.length () - 1]->m_toplevel_ctxt
1833 r
.write ("/* This code was autogenerated by"
1834 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1835 print_version (r
.get_file (), " ", false);
1837 r
.write ("#include <libgccjit.h>\n\n");
1838 r
.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1839 r
.write ("static void\nset_options (");
1840 r
.write_params (contexts
);
1842 r
.write ("static void\ncreate_code (");
1843 r
.write_params (contexts
);
1845 r
.write ("int\nmain (int argc, const char **argv)\n");
1847 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1848 r
.write (" gcc_jit_context *%s;\n",
1849 r
.get_identifier (contexts
[i
]));
1850 r
.write (" gcc_jit_result *result;\n"
1853 /* Create the contexts.
1854 The top-level context is acquired from a clean slate, the others as
1855 children of the prior context. */
1856 r
.write (" %s = gcc_jit_context_acquire ();\n",
1857 r
.get_identifier (contexts
[0]));
1858 for (unsigned i
= 1; i
< num_ctxts
; i
++)
1859 r
.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1860 r
.get_identifier (contexts
[i
]),
1861 r
.get_identifier (contexts
[i
- 1]));
1862 r
.write (" set_options (");
1863 r
.write_args (contexts
);
1865 r
.write (" create_code (");
1866 r
.write_args (contexts
);
1869 r
.write (" result = gcc_jit_context_compile (%s);\n",
1870 r
.get_identifier (this));
1872 for (unsigned i
= num_ctxts
; i
> 0; i
--)
1873 r
.write (" gcc_jit_context_release (%s);\n",
1874 r
.get_identifier (contexts
[i
- 1]));
1876 r
.write (" gcc_jit_result_release (result);\n"
1880 /* Define (char *) variables for use in calls to
1881 gcc_jit_context_enable_dump. */
1882 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1884 if (m_requested_dumps
.length ())
1886 r
.write ("/* Requested dumps for %s. */\n",
1887 r
.get_identifier (contexts
[ctxt_idx
]));
1888 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1889 r
.write ("static char *dump_%p;\n",
1890 (void *)&m_requested_dumps
[i
]);
1895 /* Write out values of options. */
1896 r
.write ("static void\nset_options (");
1897 r
.write_params (contexts
);
1899 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1904 r
.write (" /* Set options for %s. */\n",
1905 r
.get_identifier (contexts
[ctxt_idx
]));
1907 r
.write (" /* String options. */\n");
1908 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1910 r
.write (" gcc_jit_context_set_str_option (%s,\n"
1912 r
.get_identifier (contexts
[ctxt_idx
]),
1913 str_option_reproducer_strings
[opt_idx
]);
1914 if (m_str_options
[opt_idx
])
1915 r
.write (" \"%s\");\n",
1916 m_str_options
[opt_idx
]);
1918 r
.write (" NULL);\n");
1920 r
.write (" /* Int options. */\n");
1921 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1922 r
.write (" gcc_jit_context_set_int_option (%s,\n"
1925 r
.get_identifier (contexts
[ctxt_idx
]),
1926 int_option_reproducer_strings
[opt_idx
],
1927 m_int_options
[opt_idx
]);
1928 r
.write (" /* Boolean options. */\n");
1929 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1930 r
.write (" gcc_jit_context_set_bool_option (%s,\n"
1933 r
.get_identifier (contexts
[ctxt_idx
]),
1934 bool_option_reproducer_strings
[opt_idx
],
1935 m_bool_options
[opt_idx
]);
1936 for (int opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1937 r
.write (" %s (%s, %i);\n",
1938 inner_bool_option_reproducer_strings
[opt_idx
],
1939 r
.get_identifier (contexts
[ctxt_idx
]),
1940 m_inner_bool_options
[opt_idx
]);
1942 if (!m_command_line_options
.is_empty ())
1946 r
.write (" /* User-provided command-line options. */\n");
1947 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1948 r
.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1949 r
.get_identifier (contexts
[ctxt_idx
]),
1953 if (!m_driver_options
.is_empty ())
1957 r
.write (" /* User-provided driver options. */\n");
1958 FOR_EACH_VEC_ELT (m_driver_options
, i
, optname
)
1959 r
.write (" gcc_jit_context_add_driver_option (%s, \"%s\");\n",
1960 r
.get_identifier (contexts
[ctxt_idx
]),
1964 if (m_requested_dumps
.length ())
1966 r
.write (" /* Requested dumps. */\n");
1967 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1968 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1970 r
.write (" gcc_jit_context_enable_dump (%s,\n"
1973 r
.get_identifier (contexts
[ctxt_idx
]),
1974 m_requested_dumps
[i
].m_dumpname
,
1975 (void *)&m_requested_dumps
[i
]);
1981 r
.write ("static void\ncreate_code (");
1982 r
.write_params (contexts
);
1985 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1992 r
.write (" /* Replay of API calls for %s. */\n",
1993 r
.get_identifier (contexts
[ctxt_idx
]));
1994 FOR_EACH_VEC_ELT (contexts
[ctxt_idx
]->m_mementos
, i
, m
)
1995 m
->write_reproducer (r
);
2000 /* Copy the requested dumps within this context and all ancestors into
2004 recording::context::get_all_requested_dumps (vec
<recording::requested_dump
> *out
)
2007 m_parent_ctxt
->get_all_requested_dumps (out
);
2009 out
->reserve (m_requested_dumps
.length ());
2010 out
->splice (m_requested_dumps
);
2013 /* Create a recording::top_level_asm instance and add it to this
2014 context's list of mementos and to m_top_level_asms.
2016 Implements the post-error-checking part of
2017 gcc_jit_context_add_top_level_asm. */
2020 recording::context::add_top_level_asm (recording::location
*loc
,
2021 const char *asm_stmts
)
2023 recording::top_level_asm
*asm_obj
2024 = new recording::top_level_asm (this, loc
, new_string (asm_stmts
));
2026 m_top_level_asms
.safe_push (asm_obj
);
2029 /* This is a pre-compilation check for the context (and any parents).
2031 Detect errors within the context, adding errors if any are found. */
2034 recording::context::validate ()
2036 JIT_LOG_SCOPE (get_logger ());
2039 m_parent_ctxt
->validate ();
2043 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
2047 /* The implementation of class gcc::jit::recording::memento. */
2049 /* Get a (const char *) debug description of the given memento, by
2050 calling the pure-virtual make_debug_string hook, caching the
2053 It is intended that this should only be called in debugging and
2054 error-handling paths, so this doesn't need to be particularly
2058 recording::memento::get_debug_string ()
2060 if (!m_debug_string
)
2061 m_debug_string
= make_debug_string ();
2062 return m_debug_string
->c_str ();
2065 /* Default implementation of recording::memento::write_to_dump, writing
2066 an indented form of the memento's debug string to the dump. */
2069 recording::memento::write_to_dump (dump
&d
)
2071 d
.write(" %s\n", get_debug_string ());
2074 /* The implementation of class gcc::jit::recording::string. */
2076 /* Constructor for gcc::jit::recording::string::string, allocating a
2077 copy of the given text using new char[]. */
2079 recording::string::string (context
*ctxt
, const char *text
, bool escaped
)
2083 m_len
= strlen (text
);
2084 m_buffer
= new char[m_len
+ 1];
2085 strcpy (m_buffer
, text
);
2088 /* Destructor for gcc::jit::recording::string::string. */
2090 recording::string::~string ()
2095 /* Function for making gcc::jit::recording::string instances on a
2096 context via printf-style formatting.
2098 It is intended that this should only be called in debugging and
2099 error-handling paths, so this doesn't need to be particularly
2100 optimized, hence the double-copy of the string is acceptable. */
2103 recording::string::from_printf (context
*ctxt
, const char *fmt
, ...)
2108 recording::string
*result
;
2111 len
= vasprintf (&buf
, fmt
, ap
);
2114 if (buf
== NULL
|| len
< 0)
2116 ctxt
->add_error (NULL
, "malloc failure");
2120 result
= ctxt
->new_string (buf
);
2125 /* Implementation of recording::memento::make_debug_string for strings,
2126 wrapping the given string in quotes and escaping as necessary. */
2129 recording::string::make_debug_string ()
2131 /* Avoid infinite recursion into strings when logging all mementos:
2132 don't re-escape strings: */
2136 /* Wrap in quotes and do escaping etc */
2138 size_t sz
= (1 /* opening quote */
2139 + (m_len
* 2) /* each char might get escaped */
2140 + 1 /* closing quote */
2141 + 1); /* nil termintator */
2142 char *tmp
= new char[sz
];
2145 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
2146 APPEND('"'); /* opening quote */
2147 for (size_t i
= 0; i
< m_len
; i
++)
2149 char ch
= m_buffer
[i
];
2170 APPEND('"'); /* closing quote */
2172 tmp
[len
] = '\0'; /* nil termintator */
2174 string
*result
= m_ctxt
->new_string (tmp
, true);
2180 /* Implementation of recording::memento::write_reproducer for strings. */
2183 recording::string::write_reproducer (reproducer
&)
2188 /* The implementation of class gcc::jit::recording::location. */
2190 /* Implementation of recording::memento::replay_into for locations.
2192 Create a new playback::location and store it into the
2193 recording::location's m_playback_obj field. */
2196 recording::location::replay_into (replayer
*r
)
2198 m_playback_obj
= r
->new_location (this,
2199 m_filename
->c_str (),
2204 /* Implementation of recording::memento::make_debug_string for locations,
2205 turning them into the usual form:
2206 FILENAME:LINE:COLUMN
2207 like we do when emitting diagnostics. */
2210 recording::location::make_debug_string ()
2212 return string::from_printf (m_ctxt
,
2214 m_filename
->c_str (), m_line
, m_column
);
2217 /* Implementation of recording::memento::write_reproducer for locations. */
2220 recording::location::write_reproducer (reproducer
&r
)
2222 const char *id
= r
.make_identifier (this, "loc");
2223 r
.write (" gcc_jit_location *%s =\n"
2224 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
2225 " %s, /* const char *filename */\n"
2226 " %i, /* int line */\n"
2227 " %i);/* int column */\n",
2229 r
.get_identifier (get_context ()),
2230 m_filename
->get_debug_string (),
2234 /* The implementation of class gcc::jit::recording::type. */
2236 /* Given a type T, get the type T*.
2238 If this doesn't already exist, generate a new memento_of_get_pointer
2239 instance and add it to this type's context's list of mementos.
2241 Otherwise, use the cached type.
2243 Implements the post-error-checking part of
2244 gcc_jit_type_get_pointer. */
2247 recording::type::get_pointer ()
2249 if (!m_pointer_to_this_type
)
2251 m_pointer_to_this_type
= new memento_of_get_pointer (this);
2252 m_ctxt
->record (m_pointer_to_this_type
);
2254 return m_pointer_to_this_type
;
2257 /* Given a type T, get the type const T.
2259 Implements the post-error-checking part of
2260 gcc_jit_type_get_const. */
2263 recording::type::get_const ()
2265 recording::type
*result
= new memento_of_get_const (this);
2266 m_ctxt
->record (result
);
2270 /* Given a type T, get the type restrict T.
2272 Implements the post-error-checking part of
2273 gcc_jit_type_get_restrict. */
2276 recording::type::get_restrict ()
2278 recording::type
*result
= new memento_of_get_restrict (this);
2279 m_ctxt
->record (result
);
2283 /* Given a type T, get the type volatile T.
2285 Implements the post-error-checking part of
2286 gcc_jit_type_get_volatile. */
2289 recording::type::get_volatile ()
2291 recording::type
*result
= new memento_of_get_volatile (this);
2292 m_ctxt
->record (result
);
2296 /* Given a type, get an aligned version of the type.
2298 Implements the post-error-checking part of
2299 gcc_jit_type_get_aligned. */
2302 recording::type::get_aligned (size_t alignment_in_bytes
)
2304 recording::type
*result
2305 = new memento_of_get_aligned (this, alignment_in_bytes
);
2306 m_ctxt
->record (result
);
2310 /* Given a type, get a vector version of the type.
2312 Implements the post-error-checking part of
2313 gcc_jit_type_get_vector. */
2316 recording::type::get_vector (size_t num_units
)
2318 recording::type
*result
2319 = new vector_type (this, num_units
);
2320 m_ctxt
->record (result
);
2325 recording::type::access_as_type (reproducer
&r
)
2327 return r
.get_identifier (this);
2330 /* Override of default implementation of
2331 recording::type::get_size.
2333 Return the size in bytes. This is in use for global
2337 recording::memento_of_get_type::get_size ()
2342 case GCC_JIT_TYPE_VOID
:
2344 case GCC_JIT_TYPE_BOOL
:
2345 case GCC_JIT_TYPE_CHAR
:
2346 case GCC_JIT_TYPE_SIGNED_CHAR
:
2347 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2349 case GCC_JIT_TYPE_SHORT
:
2350 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2351 size
= SHORT_TYPE_SIZE
;
2353 case GCC_JIT_TYPE_INT
:
2354 case GCC_JIT_TYPE_UNSIGNED_INT
:
2355 size
= INT_TYPE_SIZE
;
2357 case GCC_JIT_TYPE_LONG
:
2358 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2359 size
= LONG_TYPE_SIZE
;
2361 case GCC_JIT_TYPE_LONG_LONG
:
2362 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2363 size
= LONG_LONG_TYPE_SIZE
;
2365 case GCC_JIT_TYPE_UINT8_T
:
2366 case GCC_JIT_TYPE_INT8_T
:
2369 case GCC_JIT_TYPE_UINT16_T
:
2370 case GCC_JIT_TYPE_INT16_T
:
2373 case GCC_JIT_TYPE_UINT32_T
:
2374 case GCC_JIT_TYPE_INT32_T
:
2377 case GCC_JIT_TYPE_UINT64_T
:
2378 case GCC_JIT_TYPE_INT64_T
:
2381 case GCC_JIT_TYPE_UINT128_T
:
2382 case GCC_JIT_TYPE_INT128_T
:
2385 case GCC_JIT_TYPE_FLOAT
:
2386 size
= FLOAT_TYPE_SIZE
;
2388 case GCC_JIT_TYPE_DOUBLE
:
2389 size
= DOUBLE_TYPE_SIZE
;
2391 case GCC_JIT_TYPE_LONG_DOUBLE
:
2392 size
= LONG_DOUBLE_TYPE_SIZE
;
2394 case GCC_JIT_TYPE_SIZE_T
:
2395 size
= MAX_BITS_PER_WORD
;
2398 /* As this function is called by
2399 'gcc_jit_global_set_initializer' and
2400 'recording::global::write_reproducer' possible types are only
2401 integrals and are covered by the previous cases. */
2405 return size
/ BITS_PER_UNIT
;
2408 /* Implementation of pure virtual hook recording::type::dereference for
2409 recording::memento_of_get_type. */
2412 recording::memento_of_get_type::dereference ()
2416 default: gcc_unreachable ();
2418 case GCC_JIT_TYPE_VOID
:
2421 case GCC_JIT_TYPE_VOID_PTR
:
2422 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
2424 case GCC_JIT_TYPE_BOOL
:
2425 case GCC_JIT_TYPE_CHAR
:
2426 case GCC_JIT_TYPE_SIGNED_CHAR
:
2427 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2428 case GCC_JIT_TYPE_SHORT
:
2429 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2430 case GCC_JIT_TYPE_INT
:
2431 case GCC_JIT_TYPE_UNSIGNED_INT
:
2432 case GCC_JIT_TYPE_LONG
:
2433 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2434 case GCC_JIT_TYPE_LONG_LONG
:
2435 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2436 case GCC_JIT_TYPE_UINT8_T
:
2437 case GCC_JIT_TYPE_UINT16_T
:
2438 case GCC_JIT_TYPE_UINT32_T
:
2439 case GCC_JIT_TYPE_UINT64_T
:
2440 case GCC_JIT_TYPE_UINT128_T
:
2441 case GCC_JIT_TYPE_INT8_T
:
2442 case GCC_JIT_TYPE_INT16_T
:
2443 case GCC_JIT_TYPE_INT32_T
:
2444 case GCC_JIT_TYPE_INT64_T
:
2445 case GCC_JIT_TYPE_INT128_T
:
2446 case GCC_JIT_TYPE_FLOAT
:
2447 case GCC_JIT_TYPE_DOUBLE
:
2448 case GCC_JIT_TYPE_LONG_DOUBLE
:
2449 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2450 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2451 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2452 /* Not a pointer: */
2455 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2456 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
2458 case GCC_JIT_TYPE_SIZE_T
:
2459 /* Not a pointer: */
2462 case GCC_JIT_TYPE_FILE_PTR
:
2463 /* Give the client code back an opaque "struct FILE". */
2464 return m_ctxt
->get_opaque_FILE_type ();
2468 /* Implementation of pure virtual hook recording::type::is_int for
2469 recording::memento_of_get_type. */
2472 recording::memento_of_get_type::is_int () const
2476 default: gcc_unreachable ();
2478 case GCC_JIT_TYPE_VOID
:
2481 case GCC_JIT_TYPE_VOID_PTR
:
2484 case GCC_JIT_TYPE_BOOL
:
2487 case GCC_JIT_TYPE_CHAR
:
2488 case GCC_JIT_TYPE_SIGNED_CHAR
:
2489 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2490 case GCC_JIT_TYPE_SHORT
:
2491 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2492 case GCC_JIT_TYPE_INT
:
2493 case GCC_JIT_TYPE_UNSIGNED_INT
:
2494 case GCC_JIT_TYPE_LONG
:
2495 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2496 case GCC_JIT_TYPE_LONG_LONG
:
2497 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2498 case GCC_JIT_TYPE_UINT8_T
:
2499 case GCC_JIT_TYPE_UINT16_T
:
2500 case GCC_JIT_TYPE_UINT32_T
:
2501 case GCC_JIT_TYPE_UINT64_T
:
2502 case GCC_JIT_TYPE_UINT128_T
:
2503 case GCC_JIT_TYPE_INT8_T
:
2504 case GCC_JIT_TYPE_INT16_T
:
2505 case GCC_JIT_TYPE_INT32_T
:
2506 case GCC_JIT_TYPE_INT64_T
:
2507 case GCC_JIT_TYPE_INT128_T
:
2510 case GCC_JIT_TYPE_FLOAT
:
2511 case GCC_JIT_TYPE_DOUBLE
:
2512 case GCC_JIT_TYPE_LONG_DOUBLE
:
2515 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2518 case GCC_JIT_TYPE_SIZE_T
:
2521 case GCC_JIT_TYPE_FILE_PTR
:
2524 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2525 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2526 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2531 /* Implementation of pure virtual hook recording::type::is_signed for
2532 recording::memento_of_get_type. */
2535 recording::memento_of_get_type::is_signed () const
2539 default: gcc_unreachable ();
2541 case GCC_JIT_TYPE_SIGNED_CHAR
:
2542 case GCC_JIT_TYPE_CHAR
:
2543 case GCC_JIT_TYPE_SHORT
:
2544 case GCC_JIT_TYPE_INT
:
2545 case GCC_JIT_TYPE_LONG
:
2546 case GCC_JIT_TYPE_LONG_LONG
:
2547 case GCC_JIT_TYPE_INT8_T
:
2548 case GCC_JIT_TYPE_INT16_T
:
2549 case GCC_JIT_TYPE_INT32_T
:
2550 case GCC_JIT_TYPE_INT64_T
:
2551 case GCC_JIT_TYPE_INT128_T
:
2554 case GCC_JIT_TYPE_VOID
:
2555 case GCC_JIT_TYPE_VOID_PTR
:
2556 case GCC_JIT_TYPE_BOOL
:
2557 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2558 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2559 case GCC_JIT_TYPE_UNSIGNED_INT
:
2560 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2561 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2562 case GCC_JIT_TYPE_UINT8_T
:
2563 case GCC_JIT_TYPE_UINT16_T
:
2564 case GCC_JIT_TYPE_UINT32_T
:
2565 case GCC_JIT_TYPE_UINT64_T
:
2566 case GCC_JIT_TYPE_UINT128_T
:
2568 case GCC_JIT_TYPE_FLOAT
:
2569 case GCC_JIT_TYPE_DOUBLE
:
2570 case GCC_JIT_TYPE_LONG_DOUBLE
:
2572 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2574 case GCC_JIT_TYPE_SIZE_T
:
2576 case GCC_JIT_TYPE_FILE_PTR
:
2578 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2579 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2580 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2585 /* Implementation of pure virtual hook recording::type::is_float for
2586 recording::memento_of_get_type. */
2589 recording::memento_of_get_type::is_float () const
2593 default: gcc_unreachable ();
2595 case GCC_JIT_TYPE_VOID
:
2598 case GCC_JIT_TYPE_VOID_PTR
:
2601 case GCC_JIT_TYPE_BOOL
:
2604 case GCC_JIT_TYPE_CHAR
:
2605 case GCC_JIT_TYPE_SIGNED_CHAR
:
2606 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2607 case GCC_JIT_TYPE_SHORT
:
2608 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2609 case GCC_JIT_TYPE_INT
:
2610 case GCC_JIT_TYPE_UNSIGNED_INT
:
2611 case GCC_JIT_TYPE_LONG
:
2612 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2613 case GCC_JIT_TYPE_LONG_LONG
:
2614 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2615 case GCC_JIT_TYPE_UINT8_T
:
2616 case GCC_JIT_TYPE_UINT16_T
:
2617 case GCC_JIT_TYPE_UINT32_T
:
2618 case GCC_JIT_TYPE_UINT64_T
:
2619 case GCC_JIT_TYPE_UINT128_T
:
2620 case GCC_JIT_TYPE_INT8_T
:
2621 case GCC_JIT_TYPE_INT16_T
:
2622 case GCC_JIT_TYPE_INT32_T
:
2623 case GCC_JIT_TYPE_INT64_T
:
2624 case GCC_JIT_TYPE_INT128_T
:
2627 case GCC_JIT_TYPE_FLOAT
:
2628 case GCC_JIT_TYPE_DOUBLE
:
2629 case GCC_JIT_TYPE_LONG_DOUBLE
:
2632 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2635 case GCC_JIT_TYPE_SIZE_T
:
2638 case GCC_JIT_TYPE_FILE_PTR
:
2641 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2642 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2643 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2648 /* Implementation of pure virtual hook recording::type::is_bool for
2649 recording::memento_of_get_type. */
2652 recording::memento_of_get_type::is_bool () const
2656 default: gcc_unreachable ();
2658 case GCC_JIT_TYPE_VOID
:
2661 case GCC_JIT_TYPE_VOID_PTR
:
2664 case GCC_JIT_TYPE_BOOL
:
2667 case GCC_JIT_TYPE_CHAR
:
2668 case GCC_JIT_TYPE_SIGNED_CHAR
:
2669 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2670 case GCC_JIT_TYPE_SHORT
:
2671 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2672 case GCC_JIT_TYPE_INT
:
2673 case GCC_JIT_TYPE_UNSIGNED_INT
:
2674 case GCC_JIT_TYPE_LONG
:
2675 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2676 case GCC_JIT_TYPE_LONG_LONG
:
2677 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2678 case GCC_JIT_TYPE_UINT8_T
:
2679 case GCC_JIT_TYPE_UINT16_T
:
2680 case GCC_JIT_TYPE_UINT32_T
:
2681 case GCC_JIT_TYPE_UINT64_T
:
2682 case GCC_JIT_TYPE_UINT128_T
:
2683 case GCC_JIT_TYPE_INT8_T
:
2684 case GCC_JIT_TYPE_INT16_T
:
2685 case GCC_JIT_TYPE_INT32_T
:
2686 case GCC_JIT_TYPE_INT64_T
:
2687 case GCC_JIT_TYPE_INT128_T
:
2690 case GCC_JIT_TYPE_FLOAT
:
2691 case GCC_JIT_TYPE_DOUBLE
:
2692 case GCC_JIT_TYPE_LONG_DOUBLE
:
2695 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2698 case GCC_JIT_TYPE_SIZE_T
:
2701 case GCC_JIT_TYPE_FILE_PTR
:
2704 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2705 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2706 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2711 /* Implementation of pure virtual hook recording::memento::replay_into
2712 for recording::memento_of_get_type. */
2715 recording::memento_of_get_type::replay_into (replayer
*r
)
2717 set_playback_obj (r
->get_type (m_kind
));
2720 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2722 /* Descriptive strings for each of enum gcc_jit_types. */
2724 static const char * const get_type_strings
[] = {
2725 "void", /* GCC_JIT_TYPE_VOID */
2726 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2728 "bool", /* GCC_JIT_TYPE_BOOL */
2730 "char", /* GCC_JIT_TYPE_CHAR */
2731 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2732 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2734 "short", /* GCC_JIT_TYPE_SHORT */
2735 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2737 "int", /* GCC_JIT_TYPE_INT */
2738 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2740 "long", /* GCC_JIT_TYPE_LONG */
2741 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2743 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2744 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2746 "float", /* GCC_JIT_TYPE_FLOAT */
2747 "double", /* GCC_JIT_TYPE_DOUBLE */
2748 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2750 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2752 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2754 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2756 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2757 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2758 "complex long double", /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2760 "__uint8_t", /* GCC_JIT_TYPE_UINT8_T */
2761 "__uint16_t", /* GCC_JIT_TYPE_UINT16_T */
2762 "__uint32_t", /* GCC_JIT_TYPE_UINT32_T */
2763 "__uint64_t", /* GCC_JIT_TYPE_UINT64_T */
2764 "__uint128_t", /* GCC_JIT_TYPE_UINT128_T */
2765 "__int8_t", /* GCC_JIT_TYPE_INT8_T */
2766 "__int16_t", /* GCC_JIT_TYPE_INT16_T */
2767 "__int32_t", /* GCC_JIT_TYPE_INT32_T */
2768 "__int64_t", /* GCC_JIT_TYPE_INT64_T */
2769 "__int128_t", /* GCC_JIT_TYPE_INT128_T */
2773 /* Implementation of recording::memento::make_debug_string for
2774 results of get_type, using a simple table of type names. */
2777 recording::memento_of_get_type::make_debug_string ()
2779 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
2782 static const char * const get_type_enum_strings
[] = {
2783 "GCC_JIT_TYPE_VOID",
2784 "GCC_JIT_TYPE_VOID_PTR",
2785 "GCC_JIT_TYPE_BOOL",
2786 "GCC_JIT_TYPE_CHAR",
2787 "GCC_JIT_TYPE_SIGNED_CHAR",
2788 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2789 "GCC_JIT_TYPE_SHORT",
2790 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2792 "GCC_JIT_TYPE_UNSIGNED_INT",
2793 "GCC_JIT_TYPE_LONG",
2794 "GCC_JIT_TYPE_UNSIGNED_LONG",
2795 "GCC_JIT_TYPE_LONG_LONG",
2796 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2797 "GCC_JIT_TYPE_FLOAT",
2798 "GCC_JIT_TYPE_DOUBLE",
2799 "GCC_JIT_TYPE_LONG_DOUBLE",
2800 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2801 "GCC_JIT_TYPE_SIZE_T",
2802 "GCC_JIT_TYPE_FILE_PTR",
2803 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2804 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2805 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE",
2806 "GCC_JIT_TYPE_UINT8_T",
2807 "GCC_JIT_TYPE_UINT16_T",
2808 "GCC_JIT_TYPE_UINT32_T",
2809 "GCC_JIT_TYPE_UINT64_T",
2810 "GCC_JIT_TYPE_UINT128_T",
2811 "GCC_JIT_TYPE_INT8_T",
2812 "GCC_JIT_TYPE_INT16_T",
2813 "GCC_JIT_TYPE_INT32_T",
2814 "GCC_JIT_TYPE_INT64_T",
2815 "GCC_JIT_TYPE_INT128_T",
2819 recording::memento_of_get_type::write_reproducer (reproducer
&r
)
2821 const char *id
= r
.make_identifier (this, "type");
2822 r
.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2824 r
.get_identifier (get_context ()),
2825 get_type_enum_strings
[m_kind
]);
2828 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2830 /* Override of default implementation of
2831 recording::type::get_size for get_pointer. */
2834 recording::memento_of_get_pointer::get_size ()
2836 return POINTER_SIZE
/ BITS_PER_UNIT
;
2839 /* Override of default implementation of
2840 recording::type::accepts_writes_from for get_pointer.
2842 Require a pointer type, and allowing writes to
2843 (const T *) from a (T*), but not the other way around. */
2846 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
2848 /* Must be a pointer type: */
2849 type
*rtype_points_to
= rtype
->is_pointer ();
2850 if (!rtype_points_to
)
2853 /* It's OK to assign to a (const T *) from a (T *). */
2854 if (m_other_type
->unqualified ()->accepts_writes_from (rtype_points_to
))
2859 /* It's OK to assign to a (volatile const T *) from a (volatile const T *). */
2860 return m_other_type
->is_same_type_as (rtype_points_to
);
2863 /* Implementation of pure virtual hook recording::memento::replay_into
2864 for recording::memento_of_get_pointer. */
2867 recording::memento_of_get_pointer::replay_into (replayer
*)
2869 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
2872 /* Implementation of recording::memento::make_debug_string for
2873 results of get_pointer, adding " *" to the underlying type,
2874 with special-casing to handle function pointer types. */
2877 recording::memento_of_get_pointer::make_debug_string ()
2879 /* Special-case function pointer types, to put the "*" in parens between
2880 the return type and the params (for one level of dereferencing, at
2882 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2883 return fn_type
->make_debug_string_with_ptr ();
2885 return string::from_printf (m_ctxt
,
2886 "%s *", m_other_type
->get_debug_string ());
2889 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2892 recording::memento_of_get_pointer::write_reproducer (reproducer
&r
)
2894 /* We need to special-case function pointer types; see the notes in
2895 recording::function_type::write_deferred_reproducer. */
2896 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2898 fn_type
->write_deferred_reproducer (r
, this);
2902 const char *id
= r
.make_identifier (this, "type");
2903 r
.write (" gcc_jit_type *%s =\n"
2904 " gcc_jit_type_get_pointer (%s);\n",
2906 r
.get_identifier_as_type (m_other_type
));
2909 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2911 /* Implementation of pure virtual hook recording::memento::replay_into
2912 for recording::memento_of_get_const. */
2915 recording::memento_of_get_const::replay_into (replayer
*)
2917 set_playback_obj (m_other_type
->playback_type ()->get_const ());
2920 /* Implementation of recording::memento::make_debug_string for
2921 results of get_const, prepending "const ". */
2924 recording::memento_of_get_const::make_debug_string ()
2926 return string::from_printf (m_ctxt
,
2927 "const %s", m_other_type
->get_debug_string ());
2930 /* Implementation of recording::memento::write_reproducer for const types. */
2933 recording::memento_of_get_const::write_reproducer (reproducer
&r
)
2935 const char *id
= r
.make_identifier (this, "type");
2936 r
.write (" gcc_jit_type *%s =\n"
2937 " gcc_jit_type_get_const (%s);\n",
2939 r
.get_identifier_as_type (m_other_type
));
2942 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2944 /* Implementation of pure virtual hook recording::memento::replay_into
2945 for recording::memento_of_get_volatile. */
2948 recording::memento_of_get_volatile::replay_into (replayer
*)
2950 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
2953 /* Implementation of recording::memento::make_debug_string for
2954 results of get_volatile, prepending "volatile ". */
2957 recording::memento_of_get_volatile::make_debug_string ()
2959 return string::from_printf (m_ctxt
,
2960 "volatile %s", m_other_type
->get_debug_string ());
2963 /* Implementation of recording::memento::write_reproducer for volatile
2967 recording::memento_of_get_volatile::write_reproducer (reproducer
&r
)
2969 const char *id
= r
.make_identifier (this, "type");
2970 r
.write (" gcc_jit_type *%s =\n"
2971 " gcc_jit_type_get_volatile (%s);\n",
2973 r
.get_identifier_as_type (m_other_type
));
2976 /* The implementation of class gcc::jit::recording::memento_of_get_restrict. */
2978 /* Implementation of pure virtual hook recording::memento::replay_into
2979 for recording::memento_of_get_restrict. */
2982 recording::memento_of_get_restrict::replay_into (replayer
*)
2984 set_playback_obj (m_other_type
->playback_type ()->get_restrict ());
2987 /* Implementation of recording::memento::make_debug_string for
2988 results of get_restrict, prepending "restrict ". */
2991 recording::memento_of_get_restrict::make_debug_string ()
2993 return string::from_printf (m_ctxt
,
2994 "restrict %s", m_other_type
->get_debug_string ());
2997 /* Implementation of recording::memento::write_reproducer for restrict
3001 recording::memento_of_get_restrict::write_reproducer (reproducer
&r
)
3003 const char *id
= r
.make_identifier (this, "type");
3004 r
.write (" gcc_jit_type *%s =\n"
3005 " gcc_jit_type_get_restrict (%s);\n",
3007 r
.get_identifier_as_type (m_other_type
));
3010 /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
3012 /* Implementation of pure virtual hook recording::memento::replay_into
3013 for recording::memento_of_get_aligned. */
3016 recording::memento_of_get_aligned::replay_into (replayer
*)
3019 (m_other_type
->playback_type ()->get_aligned (m_alignment_in_bytes
));
3022 /* Implementation of recording::memento::make_debug_string for
3023 results of get_aligned. */
3026 recording::memento_of_get_aligned::make_debug_string ()
3028 return string::from_printf (m_ctxt
,
3029 "%s __attribute__((aligned(%zi)))",
3030 m_other_type
->get_debug_string (),
3031 m_alignment_in_bytes
);
3034 /* Implementation of recording::memento::write_reproducer for aligned
3038 recording::memento_of_get_aligned::write_reproducer (reproducer
&r
)
3040 const char *id
= r
.make_identifier (this, "type");
3041 r
.write (" gcc_jit_type *%s =\n"
3042 " gcc_jit_type_get_aligned (%s, %zi);\n",
3044 r
.get_identifier_as_type (m_other_type
),
3045 m_alignment_in_bytes
);
3048 /* The implementation of class gcc::jit::recording::vector_type. */
3050 /* Implementation of pure virtual hook recording::memento::replay_into
3051 for recording::vector_type. */
3054 recording::vector_type::replay_into (replayer
*)
3057 (m_other_type
->playback_type ()->get_vector (m_num_units
));
3060 /* Implementation of recording::memento::make_debug_string for
3061 results of get_vector. */
3064 recording::vector_type::make_debug_string ()
3066 return string::from_printf
3068 "%s __attribute__((vector_size(sizeof (%s) * %zi)))",
3069 m_other_type
->get_debug_string (),
3070 m_other_type
->get_debug_string (),
3074 /* Implementation of recording::memento::write_reproducer for vector types. */
3077 recording::vector_type::write_reproducer (reproducer
&r
)
3079 const char *id
= r
.make_identifier (this, "type");
3080 r
.write (" gcc_jit_type *%s =\n"
3081 " gcc_jit_type_get_vector (%s, %zi);\n",
3083 r
.get_identifier_as_type (m_other_type
),
3087 /* The implementation of class gcc::jit::recording::array_type */
3089 /* Implementation of pure virtual hook recording::type::dereference for
3090 recording::array_type. */
3093 recording::array_type::dereference ()
3095 return m_element_type
;
3098 /* Implementation of pure virtual hook recording::memento::replay_into
3099 for recording::array_type. */
3102 recording::array_type::replay_into (replayer
*r
)
3104 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
3105 m_element_type
->playback_type (),
3109 /* Implementation of recording::memento::make_debug_string for
3110 results of new_array_type. */
3113 recording::array_type::make_debug_string ()
3115 return string::from_printf (m_ctxt
,
3117 m_element_type
->get_debug_string (),
3121 /* Implementation of recording::memento::write_reproducer for array
3125 recording::array_type::write_reproducer (reproducer
&r
)
3127 const char *id
= r
.make_identifier (this, "array_type");
3128 r
.write (" gcc_jit_type *%s =\n"
3129 " gcc_jit_context_new_array_type (%s,\n"
3130 " %s, /* gcc_jit_location *loc */\n"
3131 " %s, /* gcc_jit_type *element_type */\n"
3132 " %i); /* int num_elements */\n",
3134 r
.get_identifier (get_context ()),
3135 r
.get_identifier (m_loc
),
3136 r
.get_identifier_as_type (m_element_type
),
3140 /* The implementation of class gcc::jit::recording::function_type */
3142 /* Constructor for gcc::jit::recording::function_type. */
3144 recording::function_type::function_type (context
*ctxt
,
3150 m_return_type (return_type
),
3152 m_is_variadic (is_variadic
)
3154 for (int i
= 0; i
< num_params
; i
++)
3155 m_param_types
.safe_push (param_types
[i
]);
3158 /* Implementation of pure virtual hook recording::type::dereference for
3159 recording::function_type. */
3162 recording::function_type::dereference ()
3167 /* Implementation of virtual hook recording::type::is_same_type_as for
3168 recording::function_type.
3170 We override this to avoid requiring identity of function pointer types,
3171 so that if client code has obtained the same signature in
3172 different ways (e.g. via gcc_jit_context_new_function_ptr_type
3173 vs gcc_jit_function_get_address), the different function_type
3174 instances are treated as compatible.
3176 We can't use type::accepts_writes_from for this as we need a stronger
3177 notion of "sameness": if we have a fn_ptr type that has args that are
3178 themselves fn_ptr types, then those args still need to match exactly.
3180 Alternatively, we could consolidate attempts to create identical
3181 function_type instances so that pointer equality works, but that runs
3182 into issues about the lifetimes of the cache (w.r.t. nested contexts). */
3185 recording::function_type::is_same_type_as (type
*other
)
3189 function_type
*other_fn_type
= other
->dyn_cast_function_type ();
3193 /* Everything must match. */
3195 if (!m_return_type
->is_same_type_as (other_fn_type
->m_return_type
))
3198 if (m_param_types
.length () != other_fn_type
->m_param_types
.length ())
3203 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
3204 if (!param_type
->is_same_type_as (other_fn_type
->m_param_types
[i
]))
3207 if (m_is_variadic
!= other_fn_type
->m_is_variadic
)
3210 /* Passed all tests. */
3214 /* Implementation of pure virtual hook recording::memento::replay_into
3215 for recording::function_type. */
3218 recording::function_type::replay_into (replayer
*r
)
3220 /* Convert m_param_types to a vec of playback type. */
3221 auto_vec
<playback::type
*> param_types
;
3223 recording::type
*type
;
3224 param_types
.create (m_param_types
.length ());
3225 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
3226 param_types
.safe_push (type
->playback_type ());
3228 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
3233 /* Special-casing for make_debug_string for get_pointer results for
3234 handling (one level) of pointers to functions. */
3237 recording::function_type::make_debug_string_with_ptr ()
3239 return make_debug_string_with ("(*) ");
3242 /* Implementation of recording::memento::make_debug_string for
3243 results of new_function_type. */
3246 recording::function_type::make_debug_string ()
3248 return make_debug_string_with ("");
3251 /* Build a debug string representation of the form:
3253 RESULT_TYPE INSERT (PARAM_TYPES)
3255 for use when handling 0 and 1 level of indirection to this
3259 recording::function_type::make_debug_string_with (const char *insert
)
3261 /* First, build a buffer for the arguments. */
3262 /* Calculate length of said buffer. */
3263 size_t sz
= 1; /* nil terminator */
3264 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
3266 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
3267 sz
+= 2; /* ", " separator */
3270 sz
+= 5; /* ", ..." separator and ellipsis */
3272 /* Now allocate and populate the buffer. */
3273 char *argbuf
= new char[sz
];
3276 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
3278 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
3279 len
+= strlen (m_param_types
[i
]->get_debug_string ());
3280 if (i
+ 1 < m_param_types
.length ())
3282 strcpy (argbuf
+ len
, ", ");
3288 if (m_param_types
.length ())
3290 strcpy (argbuf
+ len
, ", ");
3293 strcpy (argbuf
+ len
, "...");
3298 /* ...and use it to get the string for the call as a whole. */
3299 string
*result
= string::from_printf (m_ctxt
,
3301 m_return_type
->get_debug_string (),
3310 /* Implementation of recording::memento::write_reproducer for function
3314 recording::function_type::write_reproducer (reproducer
&)
3316 /* see notes below. */
3319 /* There's a get_pointer within context::new_function_ptr_type:
3320 the type received by client code isn't the memento for the
3321 function_type, but instead the result of get_pointer on it.
3323 Hence we can't directly write a reproducer that gives function_type.
3324 Instead we special-case things within get_pointer, detecting this
3325 case, calling the following function. */
3328 recording::function_type::write_deferred_reproducer (reproducer
&r
,
3331 gcc_assert (ptr_type
);
3332 r
.make_identifier (this, "function_type");
3333 const char *ptr_id
= r
.make_identifier (ptr_type
, "ptr_to");
3334 const char *param_types_id
= r
.make_tmp_identifier ("params_for", this);
3335 r
.write (" gcc_jit_type *%s[%i] = {\n",
3337 m_param_types
.length ());
3340 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
3341 r
.write (" %s,\n", r
.get_identifier_as_type (param_type
));
3343 r
.write (" gcc_jit_type *%s =\n"
3344 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
3345 " %s, /* gcc_jit_location *loc */\n"
3346 " %s, /* gcc_jit_type *return_type */\n"
3347 " %i, /* int num_params */\n"
3348 " %s, /* gcc_jit_type **param_types */\n"
3349 " %i); /* int is_variadic */\n",
3351 r
.get_identifier (get_context ()),
3352 "NULL", /* location is not stored */
3353 r
.get_identifier_as_type (m_return_type
),
3354 m_param_types
.length (),
3359 /* The implementation of class gcc::jit::recording::field. */
3361 /* Implementation of pure virtual hook recording::memento::replay_into
3362 for recording::field. */
3365 recording::field::replay_into (replayer
*r
)
3367 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
3368 m_type
->playback_type (),
3369 playback_string (m_name
)));
3372 /* Override the default implementation of
3373 recording::memento::write_to_dump. Dump each field
3374 by dumping a line of the form:
3376 so that we can build up a struct/union field by field. */
3379 recording::field::write_to_dump (dump
&d
)
3381 d
.write (" %s %s;\n",
3382 m_type
->get_debug_string (),
3386 /* Implementation of recording::memento::make_debug_string for
3387 results of new_field. */
3390 recording::field::make_debug_string ()
3395 /* Implementation of recording::memento::write_reproducer for fields. */
3398 recording::field::write_reproducer (reproducer
&r
)
3400 const char *id
= r
.make_identifier (this, "field");
3401 r
.write(" gcc_jit_field *%s =\n"
3402 " gcc_jit_context_new_field (%s,\n"
3403 " %s, /* gcc_jit_location *loc */\n"
3404 " %s, /* gcc_jit_type *type, */\n"
3405 " %s); /* const char *name */\n",
3407 r
.get_identifier (get_context ()),
3408 r
.get_identifier (m_loc
),
3409 r
.get_identifier_as_type (m_type
),
3410 m_name
->get_debug_string ());
3413 /* The implementation of class gcc::jit::recording::bitfield. */
3415 /* Implementation of pure virtual hook recording::memento::replay_into
3416 for recording::bitfield. */
3419 recording::bitfield::replay_into (replayer
*r
)
3421 set_playback_obj (r
->new_bitfield (playback_location (r
, m_loc
),
3422 m_type
->playback_type (),
3424 playback_string (m_name
)));
3427 /* Override the default implementation of
3428 recording::memento::write_to_dump. Dump each bit field
3429 by dumping a line of the form:
3431 so that we can build up a struct/union field by field. */
3434 recording::bitfield::write_to_dump (dump
&d
)
3436 d
.write (" %s %s:%d;\n",
3437 m_type
->get_debug_string (),
3442 /* Implementation of recording::memento::make_debug_string for
3443 results of new_bitfield. */
3446 recording::bitfield::make_debug_string ()
3448 return string::from_printf (m_ctxt
,
3450 m_name
->c_str (), m_width
);
3453 /* Implementation of recording::memento::write_reproducer for bitfields. */
3456 recording::bitfield::write_reproducer (reproducer
&r
)
3458 const char *id
= r
.make_identifier (this, "bitfield");
3459 r
.write (" gcc_jit_field *%s =\n"
3460 " gcc_jit_context_new_bitfield (%s,\n"
3461 " %s, /* gcc_jit_location *loc */\n"
3462 " %s, /* gcc_jit_type *type, */\n"
3463 " %d, /* int width, */\n"
3464 " %s); /* const char *name */\n",
3466 r
.get_identifier (get_context ()),
3467 r
.get_identifier (m_loc
),
3468 r
.get_identifier_as_type (m_type
),
3470 m_name
->get_debug_string ());
3473 /* The implementation of class gcc::jit::recording::compound_type */
3475 /* The constructor for gcc::jit::recording::compound_type. */
3477 recording::compound_type::compound_type (context
*ctxt
,
3487 /* Set the fields of a compound type.
3489 Implements the post-error-checking part of
3490 gcc_jit_struct_set_fields, and is also used by
3491 gcc_jit_context_new_union_type. */
3494 recording::compound_type::set_fields (location
*loc
,
3496 field
**field_array
)
3499 gcc_assert (m_fields
== NULL
);
3501 m_fields
= new fields (this, num_fields
, field_array
);
3502 m_ctxt
->record (m_fields
);
3505 /* Implementation of pure virtual hook recording::type::dereference for
3506 recording::compound_type. */
3509 recording::compound_type::dereference ()
3511 return NULL
; /* not a pointer */
3514 /* The implementation of class gcc::jit::recording::struct_. */
3516 /* The constructor for gcc::jit::recording::struct_. */
3518 recording::struct_::struct_ (context
*ctxt
,
3521 : compound_type (ctxt
, loc
, name
)
3525 /* Implementation of pure virtual hook recording::memento::replay_into
3526 for recording::struct_. */
3529 recording::struct_::replay_into (replayer
*r
)
3532 r
->new_compound_type (playback_location (r
, get_loc ()),
3533 get_name ()->c_str (),
3534 true /* is_struct */));
3538 recording::struct_::access_as_type (reproducer
&r
)
3540 return r
.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
3541 r
.get_identifier (this));
3544 /* Implementation of recording::memento::make_debug_string for
3548 recording::struct_::make_debug_string ()
3550 return string::from_printf (m_ctxt
,
3551 "struct %s", get_name ()->c_str ());
3555 recording::struct_::write_reproducer (reproducer
&r
)
3557 const char *id
= r
.make_identifier (this, "struct");
3558 r
.write (" gcc_jit_struct *%s =\n"
3559 " gcc_jit_context_new_opaque_struct (%s,\n"
3560 " %s, /* gcc_jit_location *loc */\n"
3561 " %s); /* const char *name */\n",
3563 r
.get_identifier (get_context ()),
3564 r
.get_identifier (get_loc ()),
3565 get_name ()->get_debug_string ());
3568 /* The implementation of class gcc::jit::recording::union_. */
3570 /* The constructor for gcc::jit::recording::union_. */
3572 recording::union_::union_ (context
*ctxt
,
3575 : compound_type (ctxt
, loc
, name
)
3579 /* Implementation of pure virtual hook recording::memento::replay_into
3580 for recording::union_. */
3583 recording::union_::replay_into (replayer
*r
)
3586 r
->new_compound_type (playback_location (r
, get_loc ()),
3587 get_name ()->c_str (),
3588 false /* is_struct */));
3591 /* Implementation of recording::memento::make_debug_string for
3595 recording::union_::make_debug_string ()
3597 return string::from_printf (m_ctxt
,
3598 "union %s", get_name ()->c_str ());
3601 /* Implementation of recording::memento::write_reproducer for unions. */
3604 recording::union_::write_reproducer (reproducer
&r
)
3606 const char *id
= r
.make_identifier (this, "union");
3608 const char *fields_id
= r
.make_tmp_identifier ("fields_for", this);
3609 r
.write (" gcc_jit_field *%s[%i] = {\n",
3611 get_fields ()->length ());
3612 for (int i
= 0; i
< get_fields ()->length (); i
++)
3613 r
.write (" %s,\n", r
.get_identifier (get_fields ()->get_field (i
)));
3616 r
.write (" gcc_jit_type *%s =\n"
3617 " gcc_jit_context_new_union_type (%s,\n"
3618 " %s, /* gcc_jit_location *loc */\n"
3619 " %s, /* const char *name */\n"
3620 " %i, /* int num_fields */\n"
3621 " %s); /* gcc_jit_field **fields */\n",
3623 r
.get_identifier (get_context ()),
3624 r
.get_identifier (get_loc ()),
3625 get_name ()->get_debug_string (),
3626 get_fields ()->length (),
3630 /* The implementation of class gcc::jit::recording::fields. */
3632 /* The constructor for gcc::jit::recording::fields. */
3634 recording::fields::fields (compound_type
*struct_or_union
,
3637 : memento (struct_or_union
->m_ctxt
),
3638 m_struct_or_union (struct_or_union
),
3641 for (int i
= 0; i
< num_fields
; i
++)
3643 gcc_assert (fields
[i
]->get_container () == NULL
);
3644 fields
[i
]->set_container (m_struct_or_union
);
3645 m_fields
.safe_push (fields
[i
]);
3649 /* Implementation of pure virtual hook recording::memento::replay_into
3650 for recording::fields. */
3653 recording::fields::replay_into (replayer
*)
3655 auto_vec
<playback::field
*> playback_fields
;
3656 playback_fields
.create (m_fields
.length ());
3657 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
3658 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
3659 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
3662 /* Override the default implementation of
3663 recording::memento::write_to_dump by writing a union/struct
3664 declaration of this form:
3676 recording::fields::write_to_dump (dump
&d
)
3681 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
3682 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
3683 f
->write_to_dump (d
);
3687 /* Implementation of recording::memento::write_reproducer for the fields
3691 recording::fields::write_reproducer (reproducer
&r
)
3693 if (m_struct_or_union
)
3694 if (m_struct_or_union
->dyn_cast_struct () == NULL
)
3695 /* We have a union; the fields have already been written by
3696 union::write_reproducer. */
3699 const char *fields_id
= r
.make_identifier (this, "fields");
3700 r
.write (" gcc_jit_field *%s[%i] = {\n",
3702 m_fields
.length ());
3705 FOR_EACH_VEC_ELT (m_fields
, i
, field
)
3706 r
.write (" %s,\n", r
.get_identifier (field
));
3709 r
.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
3710 " %s, /* gcc_jit_location *loc */\n"
3711 " %i, /* int num_fields */\n"
3712 " %s); /* gcc_jit_field **fields */\n",
3713 r
.get_identifier (m_struct_or_union
),
3714 r
.get_identifier ((memento
*)NULL
),
3719 /* Implementation of recording::memento::make_debug_string for
3723 recording::fields::make_debug_string ()
3725 return string::from_printf (m_ctxt
,
3729 /* The implementation of class gcc::jit::recording::rvalue. */
3731 /* Create a recording::access_field_rvalue instance and add it to
3732 the rvalue's context's list of mementos.
3734 Implements the post-error-checking part of
3735 gcc_jit_rvalue_access_field. */
3738 recording::rvalue::access_field (recording::location
*loc
,
3741 recording::rvalue
*result
=
3742 new access_field_rvalue (m_ctxt
, loc
, this, field
);
3743 m_ctxt
->record (result
);
3747 /* Create a recording::dereference_field_rvalue instance and add it to
3748 the rvalue's context's list of mementos.
3750 Implements the post-error-checking part of
3751 gcc_jit_rvalue_dereference_field. */
3754 recording::rvalue::dereference_field (recording::location
*loc
,
3757 recording::lvalue
*result
=
3758 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
3759 m_ctxt
->record (result
);
3763 /* Create a recording::dereference_rvalue instance and add it to the
3764 rvalue's context's list of mementos.
3766 Implements the post-error-checking part of
3767 gcc_jit_rvalue_dereference. */
3770 recording::rvalue::dereference (recording::location
*loc
)
3772 recording::lvalue
*result
=
3773 new dereference_rvalue (m_ctxt
, loc
, this);
3774 m_ctxt
->record (result
);
3778 /* An rvalue visitor, for validating that every rvalue within an expression
3779 trees within "STMT" has the correct scope (e.g. no access to locals
3780 of a different function). */
3782 class rvalue_usage_validator
: public recording::rvalue_visitor
3785 rvalue_usage_validator (const char *api_funcname
,
3786 recording::context
*ctxt
,
3787 recording::statement
*stmt
);
3790 visit (recording::rvalue
*rvalue
) final override
;
3793 const char *m_api_funcname
;
3794 recording::context
*m_ctxt
;
3795 recording::statement
*m_stmt
;
3798 /* The trivial constructor for rvalue_usage_validator. */
3800 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname
,
3801 recording::context
*ctxt
,
3802 recording::statement
*stmt
)
3803 : m_api_funcname (api_funcname
),
3809 /* Verify that the given rvalue is in the correct scope. */
3812 rvalue_usage_validator::visit (recording::rvalue
*rvalue
)
3814 gcc_assert (m_stmt
->get_block ());
3815 recording::function
*stmt_scope
= m_stmt
->get_block ()->get_function ();
3817 /* Most rvalues don't have a scope (only locals and params). */
3818 if (rvalue
->get_scope ())
3820 if (rvalue
->get_scope () != stmt_scope
)
3822 (rvalue
->get_loc (),
3824 " rvalue %s (type: %s)"
3825 " has scope limited to function %s"
3826 " but was used within function %s"
3827 " (in statement: %s)",
3829 rvalue
->get_debug_string (),
3830 rvalue
->get_type ()->get_debug_string (),
3831 rvalue
->get_scope ()->get_debug_string (),
3832 stmt_scope
->get_debug_string (),
3833 m_stmt
->get_debug_string ());
3837 if (rvalue
->dyn_cast_param ())
3839 (rvalue
->get_loc (),
3841 " param %s (type: %s)"
3842 " was used within function %s"
3843 " (in statement: %s)"
3844 " but is not associated with any function",
3846 rvalue
->get_debug_string (),
3847 rvalue
->get_type ()->get_debug_string (),
3848 stmt_scope
->get_debug_string (),
3849 m_stmt
->get_debug_string ());
3853 /* Verify that it's valid to use this rvalue (and all expressions
3854 in the tree below it) within the given statement.
3856 For example, we must reject attempts to use a local from one
3857 function within a different function here, or we'll get
3858 an ICE deep inside toplev::main. */
3861 recording::rvalue::verify_valid_within_stmt (const char *api_funcname
, statement
*s
)
3863 rvalue_usage_validator
v (api_funcname
,
3867 /* Verify that it's OK to use this rvalue within s. */
3870 /* Traverse the expression tree below "this", verifying all rvalues
3872 visit_children (&v
);
3875 /* Set the scope of this rvalue to be the given function. This can only
3876 be done once on a given rvalue. */
3879 recording::rvalue::set_scope (function
*scope
)
3882 gcc_assert (m_scope
== NULL
);
3887 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3889 Instances of rvalue don't need an upcast call. */
3892 recording::rvalue::access_as_rvalue (reproducer
&r
)
3894 return r
.get_identifier (this);
3897 /* Return a debug string for the given rvalue, wrapping it in parentheses
3898 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3899 stronger precedence that this rvalue's precedence.
3913 since MULT has strong precedence than PLUS and MINUS, whereas for:
3925 since PLUS has weaker precedence than MULT and DIVIDE. */
3928 recording::rvalue::get_debug_string_parens (enum precedence outer_prec
)
3930 enum precedence this_prec
= get_precedence ();
3932 /* If this_prec has stronger precedence than outer_prec, we don't
3933 need to wrap this in parens within the outer debug string.
3934 Stronger precedences occur earlier than weaker within the enum,
3935 so this is a less than test. Equal precedences don't need
3937 if (this_prec
<= outer_prec
)
3938 return get_debug_string();
3940 /* Otherwise, we need parentheses. */
3942 /* Lazily-build and cache m_parenthesized_string. */
3943 if (!m_parenthesized_string
)
3945 const char *debug_string
= get_debug_string ();
3946 m_parenthesized_string
= string::from_printf (get_context (),
3950 gcc_assert (m_parenthesized_string
);
3951 return m_parenthesized_string
->c_str ();
3955 /* The implementation of class gcc::jit::recording::lvalue. */
3957 /* Create a recording::new_access_field_of_lvalue instance and add it to
3958 the lvalue's context's list of mementos.
3960 Implements the post-error-checking part of
3961 gcc_jit_lvalue_access_field. */
3964 recording::lvalue::access_field (recording::location
*loc
,
3967 recording::lvalue
*result
=
3968 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
3969 m_ctxt
->record (result
);
3973 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3974 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3978 recording::lvalue::access_as_rvalue (reproducer
&r
)
3980 return r
.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3981 r
.get_identifier (this));
3984 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3985 Instances of lvalue don't need to be upcast. */
3988 recording::lvalue::access_as_lvalue (reproducer
&r
)
3990 return r
.get_identifier (this);
3993 /* Create a recording::get_address_of_lvalue instance and add it to
3994 the lvalue's context's list of mementos.
3996 Implements the post-error-checking part of
3997 gcc_jit_lvalue_get_address. */
4000 recording::lvalue::get_address (recording::location
*loc
)
4002 recording::rvalue
*result
=
4003 new get_address_of_lvalue (m_ctxt
, loc
, this);
4004 m_ctxt
->record (result
);
4009 recording::lvalue::set_tls_model (enum gcc_jit_tls_model model
)
4011 m_tls_model
= model
;
4014 void recording::lvalue::set_link_section (const char *name
)
4016 m_link_section
= new_string (name
);
4019 void recording::lvalue::set_register_name (const char *reg_name
)
4021 m_reg_name
= new_string (reg_name
);
4024 void recording::lvalue::set_alignment (unsigned bytes
)
4026 m_alignment
= bytes
;
4029 /* The implementation of class gcc::jit::recording::param. */
4031 /* Implementation of pure virtual hook recording::memento::replay_into
4032 for recording::param. */
4035 recording::param::replay_into (replayer
*r
)
4037 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
4038 m_type
->playback_type (),
4042 /* Implementation of recording::rvalue::access_as_rvalue for params.
4043 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
4047 recording::param::access_as_rvalue (reproducer
&r
)
4049 return r
.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
4050 r
.get_identifier (this));
4053 /* Implementation of recording::lvalue::access_as_lvalue for params.
4054 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
4058 recording::param::access_as_lvalue (reproducer
&r
)
4060 return r
.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
4061 r
.get_identifier (this));
4064 /* Implementation of recording::memento::write_reproducer for params. */
4067 recording::param::write_reproducer (reproducer
&r
)
4069 const char *id
= r
.make_identifier (this, "param");
4070 r
.write (" gcc_jit_param *%s =\n"
4071 " gcc_jit_context_new_param (%s,\n"
4072 " %s, /* gcc_jit_location *loc */\n"
4073 " %s, /*gcc_jit_type *type */\n"
4074 " %s); /* const char *name */\n",
4076 r
.get_identifier (get_context ()),
4077 r
.get_identifier (m_loc
),
4078 r
.get_identifier_as_type (m_type
),
4079 m_name
->get_debug_string ());
4082 /* The implementation of class gcc::jit::recording::function. */
4084 /* gcc::jit::recording::function's constructor. */
4086 recording::function::function (context
*ctxt
,
4087 recording::location
*loc
,
4088 enum gcc_jit_function_kind kind
,
4090 recording::string
*name
,
4092 recording::param
**params
,
4094 enum built_in_function builtin_id
)
4098 m_return_type (return_type
),
4101 m_is_variadic (is_variadic
),
4102 m_builtin_id (builtin_id
),
4105 m_fn_ptr_type (NULL
)
4107 for (int i
= 0; i
< num_params
; i
++)
4109 param
*param
= params
[i
];
4112 /* Associate each param with this function.
4114 Verify that the param doesn't already have a function. */
4115 if (param
->get_scope ())
4117 /* We've already rejected attempts to reuse a param between
4118 different functions (within gcc_jit_context_new_function), so
4119 if the param *does* already have a function, it must be being
4120 reused within the params array for this function. We must
4121 produce an error for this reuse (blocking the compile), since
4122 otherwise we'd have an ICE later on. */
4123 gcc_assert (this == param
->get_scope ());
4126 "gcc_jit_context_new_function:"
4127 " parameter %s (type: %s)"
4128 " is used more than once when creating function %s",
4129 param
->get_debug_string (),
4130 param
->get_type ()->get_debug_string (),
4135 /* The normal, non-error case: associate this function with the
4137 param
->set_scope (this);
4140 m_params
.safe_push (param
);
4144 /* Implementation of pure virtual hook recording::memento::replay_into
4145 for recording::function. */
4148 recording::function::replay_into (replayer
*r
)
4150 /* Convert m_params to a vec of playback param. */
4151 auto_vec
<playback::param
*> params
;
4153 recording::param
*param
;
4154 params
.create (m_params
.length ());
4155 FOR_EACH_VEC_ELT (m_params
, i
, param
)
4156 params
.safe_push (param
->playback_param ());
4158 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
4160 m_return_type
->playback_type (),
4167 /* Create a recording::local instance and add it to
4168 the functions's context's list of mementos, and to the function's
4171 Implements the post-error-checking part of
4172 gcc_jit_function_new_local. */
4175 recording::function::new_local (recording::location
*loc
,
4179 local
*result
= new local (this, loc
, type
, new_string (name
));
4180 m_ctxt
->record (result
);
4181 m_locals
.safe_push (result
);
4185 /* Create a recording::block instance and add it to
4186 the functions's context's list of mementos, and to the function's
4189 Implements the post-error-checking part of
4190 gcc_jit_function_new_block. */
4193 recording::function::new_block (const char *name
)
4195 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
4197 recording::block
*result
=
4198 new recording::block (this, m_blocks
.length (), new_string (name
));
4199 m_ctxt
->record (result
);
4200 m_blocks
.safe_push (result
);
4204 /* Override the default implementation of
4205 recording::memento::write_to_dump by dumping a C-like
4206 representation of the function; either like a prototype
4207 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
4208 all other kinds of function. */
4211 recording::function::write_to_dump (dump
&d
)
4215 default: gcc_unreachable ();
4216 case GCC_JIT_FUNCTION_EXPORTED
:
4217 case GCC_JIT_FUNCTION_IMPORTED
:
4218 d
.write ("extern ");
4220 case GCC_JIT_FUNCTION_INTERNAL
:
4221 d
.write ("static ");
4223 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
4224 d
.write ("static inline ");
4227 d
.write ("%s\n", m_return_type
->get_debug_string ());
4229 if (d
.update_locations ())
4230 m_loc
= d
.make_location ();
4232 d
.write ("%s (", get_debug_string ());
4235 recording::param
*param
;
4236 FOR_EACH_VEC_ELT (m_params
, i
, param
)
4241 param
->get_type ()->get_debug_string (),
4242 param
->get_debug_string ());
4245 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
4247 d
.write ("; /* (imported) */\n\n");
4257 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
4258 var
->write_to_dump (d
);
4259 if (m_locals
.length ())
4262 /* Write each block: */
4263 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
4267 b
->write_to_dump (d
);
4274 /* Pre-compilation validation of a function, for those things we can't
4275 check until the context is (supposedly) fully-populated. */
4278 recording::function::validate ()
4280 /* Complain about empty functions with non-void return type. */
4281 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
4282 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
4283 if (m_blocks
.length () == 0)
4284 m_ctxt
->add_error (m_loc
,
4285 "function %s returns non-void (type: %s)"
4286 " but has no blocks",
4287 get_debug_string (),
4288 m_return_type
->get_debug_string ());
4290 /* Check that all blocks are terminated. */
4291 int num_invalid_blocks
= 0;
4296 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
4297 if (!b
->validate ())
4298 num_invalid_blocks
++;
4301 /* Check that all blocks are reachable. */
4302 if (!m_ctxt
->get_inner_bool_option
4303 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS
)
4304 && m_blocks
.length () > 0 && num_invalid_blocks
== 0)
4306 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
4307 flag, starting at the initial block. */
4308 auto_vec
<block
*> worklist (m_blocks
.length ());
4309 worklist
.safe_push (m_blocks
[0]);
4310 while (worklist
.length () > 0)
4312 block
*b
= worklist
.pop ();
4313 b
->m_is_reachable
= true;
4315 /* Add successor blocks that aren't yet marked to the worklist. */
4316 /* We checked that each block has a terminating statement above . */
4317 vec
<block
*> successors
= b
->get_successor_blocks ();
4320 FOR_EACH_VEC_ELT (successors
, i
, succ
)
4321 if (!succ
->m_is_reachable
)
4322 worklist
.safe_push (succ
);
4323 successors
.release ();
4326 /* Now complain about any blocks that haven't been marked. */
4330 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
4331 if (!b
->m_is_reachable
)
4332 m_ctxt
->add_error (b
->get_loc (),
4333 "unreachable block: %s",
4334 b
->get_debug_string ());
4339 /* Implements the post-error-checking part of
4340 gcc_jit_function_dump_to_dot. */
4343 recording::function::dump_to_dot (const char *path
)
4345 FILE *fp
= fopen (path
, "w");
4349 pretty_printer the_pp
;
4350 the_pp
.buffer
->stream
= fp
;
4352 pretty_printer
*pp
= &the_pp
;
4354 pp_printf (pp
, "digraph %s", get_debug_string ());
4355 pp_string (pp
, " {\n");
4361 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
4362 b
->dump_to_dot (pp
);
4369 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
4370 b
->dump_edges_to_dot (pp
);
4373 pp_string (pp
, "}\n");
4378 /* Implements the post-error-checking part of
4379 gcc_jit_function_get_address. */
4382 recording::function::get_address (recording::location
*loc
)
4384 /* Lazily create and cache the function pointer type. */
4387 /* Make a recording::function_type for this function. */
4388 auto_vec
<recording::type
*> param_types (m_params
.length ());
4390 recording::param
*param
;
4391 FOR_EACH_VEC_ELT (m_params
, i
, param
)
4392 param_types
.safe_push (param
->get_type ());
4393 recording::function_type
*fn_type
4394 = m_ctxt
->new_function_type (m_return_type
,
4396 param_types
.address (),
4398 m_fn_ptr_type
= fn_type
->get_pointer ();
4400 gcc_assert (m_fn_ptr_type
);
4402 rvalue
*result
= new function_pointer (get_context (), loc
, this, m_fn_ptr_type
);
4403 m_ctxt
->record (result
);
4407 /* Implementation of recording::memento::make_debug_string for
4411 recording::function::make_debug_string ()
4416 /* A table of enum gcc_jit_function_kind values expressed in string
4419 static const char * const names_of_function_kinds
[] = {
4420 "GCC_JIT_FUNCTION_EXPORTED",
4421 "GCC_JIT_FUNCTION_INTERNAL",
4422 "GCC_JIT_FUNCTION_IMPORTED",
4423 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
4426 /* Implementation of recording::memento::write_reproducer for functions. */
4429 recording::function::write_reproducer (reproducer
&r
)
4431 const char *id
= r
.make_identifier (this, "func");
4435 r
.write (" gcc_jit_function *%s =\n"
4436 " gcc_jit_context_get_builtin_function (%s,\n"
4439 r
.get_identifier (get_context ()),
4440 m_name
->get_debug_string ());
4443 const char *params_id
= r
.make_tmp_identifier ("params_for", this);
4444 r
.write (" gcc_jit_param *%s[%i] = {\n",
4446 m_params
.length ());
4449 FOR_EACH_VEC_ELT (m_params
, i
, param
)
4450 r
.write (" %s,\n", r
.get_identifier (param
));
4452 r
.write (" gcc_jit_function *%s =\n"
4453 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
4454 " %s, /* gcc_jit_location *loc */\n"
4455 " %s, /* enum gcc_jit_function_kind kind */\n"
4456 " %s, /* gcc_jit_type *return_type */\n"
4457 " %s, /* const char *name */\n"
4458 " %i, /* int num_params */\n"
4459 " %s, /* gcc_jit_param **params */\n"
4460 " %i); /* int is_variadic */\n",
4462 r
.get_identifier (get_context ()),
4463 r
.get_identifier (m_loc
),
4464 names_of_function_kinds
[m_kind
],
4465 r
.get_identifier_as_type (m_return_type
),
4466 m_name
->get_debug_string (),
4473 /* The implementation of class gcc::jit::recording::block. */
4475 /* Create a recording::eval instance and add it to
4476 the block's context's list of mementos, and to the block's
4479 Implements the heart of gcc_jit_block_add_eval. */
4481 recording::statement
*
4482 recording::block::add_eval (recording::location
*loc
,
4483 recording::rvalue
*rvalue
)
4485 statement
*result
= new eval (this, loc
, rvalue
);
4486 m_ctxt
->record (result
);
4487 m_statements
.safe_push (result
);
4491 /* Create a recording::assignment instance and add it to
4492 the block's context's list of mementos, and to the block's
4495 Implements the heart of gcc_jit_block_add_assignment. */
4497 recording::statement
*
4498 recording::block::add_assignment (recording::location
*loc
,
4499 recording::lvalue
*lvalue
,
4500 recording::rvalue
*rvalue
)
4502 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
4503 m_ctxt
->record (result
);
4504 m_statements
.safe_push (result
);
4508 /* Create a recording::assignment_op instance and add it to
4509 the block's context's list of mementos, and to the block's
4512 Implements the heart of gcc_jit_block_add_assignment_op. */
4514 recording::statement
*
4515 recording::block::add_assignment_op (recording::location
*loc
,
4516 recording::lvalue
*lvalue
,
4517 enum gcc_jit_binary_op op
,
4518 recording::rvalue
*rvalue
)
4520 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
4521 m_ctxt
->record (result
);
4522 m_statements
.safe_push (result
);
4526 /* Create a recording::comment instance and add it to
4527 the block's context's list of mementos, and to the block's
4530 Implements the heart of gcc_jit_block_add_comment. */
4532 recording::statement
*
4533 recording::block::add_comment (recording::location
*loc
,
4536 statement
*result
= new comment (this, loc
, new_string (text
));
4537 m_ctxt
->record (result
);
4538 m_statements
.safe_push (result
);
4542 /* Create a recording::extended_asm_simple instance and add it to
4543 the block's context's list of mementos, and to the block's
4546 Implements the heart of gcc_jit_block_add_extended_asm. */
4548 recording::extended_asm
*
4549 recording::block::add_extended_asm (location
*loc
,
4550 const char *asm_template
)
4552 extended_asm
*result
4553 = new extended_asm_simple (this, loc
, new_string (asm_template
));
4554 m_ctxt
->record (result
);
4555 m_statements
.safe_push (result
);
4559 /* Create a recording::end_with_conditional instance and add it to
4560 the block's context's list of mementos, and to the block's
4563 Implements the heart of gcc_jit_block_end_with_conditional. */
4565 recording::statement
*
4566 recording::block::end_with_conditional (recording::location
*loc
,
4567 recording::rvalue
*boolval
,
4568 recording::block
*on_true
,
4569 recording::block
*on_false
)
4571 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
4572 m_ctxt
->record (result
);
4573 m_statements
.safe_push (result
);
4574 m_has_been_terminated
= true;
4578 /* Create a recording::end_with_jump instance and add it to
4579 the block's context's list of mementos, and to the block's
4582 Implements the heart of gcc_jit_block_end_with_jump. */
4584 recording::statement
*
4585 recording::block::end_with_jump (recording::location
*loc
,
4586 recording::block
*target
)
4588 statement
*result
= new jump (this, loc
, target
);
4589 m_ctxt
->record (result
);
4590 m_statements
.safe_push (result
);
4591 m_has_been_terminated
= true;
4595 /* Create a recording::end_with_return instance and add it to
4596 the block's context's list of mementos, and to the block's
4599 Implements the post-error-checking parts of
4600 gcc_jit_block_end_with_return and
4601 gcc_jit_block_end_with_void_return. */
4603 recording::statement
*
4604 recording::block::end_with_return (recording::location
*loc
,
4605 recording::rvalue
*rvalue
)
4607 /* This is used by both gcc_jit_function_add_return and
4608 gcc_jit_function_add_void_return; rvalue will be non-NULL for
4609 the former and NULL for the latter. */
4610 statement
*result
= new return_ (this, loc
, rvalue
);
4611 m_ctxt
->record (result
);
4612 m_statements
.safe_push (result
);
4613 m_has_been_terminated
= true;
4617 /* Create a recording::switch_ instance and add it to
4618 the block's context's list of mementos, and to the block's
4621 Implements the heart of gcc_jit_block_end_with_switch. */
4623 recording::statement
*
4624 recording::block::end_with_switch (recording::location
*loc
,
4625 recording::rvalue
*expr
,
4626 recording::block
*default_block
,
4628 recording::case_
**cases
)
4630 statement
*result
= new switch_ (this, loc
,
4635 m_ctxt
->record (result
);
4636 m_statements
.safe_push (result
);
4637 m_has_been_terminated
= true;
4641 /* Create a recording::extended_asm_goto instance and add it to
4642 the block's context's list of mementos, and to the block's
4645 Implements the heart of gcc_jit_block_end_with_extended_asm_goto. */
4648 recording::extended_asm
*
4649 recording::block::end_with_extended_asm_goto (location
*loc
,
4650 const char *asm_template
,
4651 int num_goto_blocks
,
4652 block
**goto_blocks
,
4653 block
*fallthrough_block
)
4655 extended_asm
*result
4656 = new extended_asm_goto (this, loc
, new_string (asm_template
),
4657 num_goto_blocks
, goto_blocks
,
4659 m_ctxt
->record (result
);
4660 m_statements
.safe_push (result
);
4661 m_has_been_terminated
= true;
4665 /* Override the default implementation of
4666 recording::memento::write_to_dump for blocks by writing
4667 an unindented block name as a label, followed by the indented
4677 recording::block::write_to_dump (dump
&d
)
4679 d
.write ("%s:\n", get_debug_string ());
4683 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
4684 s
->write_to_dump (d
);
4687 /* Validate a block by ensuring that it has been terminated. */
4690 recording::block::validate ()
4692 /* Check for termination. */
4693 if (!has_been_terminated ())
4695 statement
*stmt
= get_last_statement ();
4696 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
4697 m_func
->get_context ()->add_error (loc
,
4698 "unterminated block in %s: %s",
4699 m_func
->get_debug_string (),
4700 get_debug_string ());
4707 /* Get the source-location of a block by using that of the first
4708 statement within it, if any. */
4710 recording::location
*
4711 recording::block::get_loc () const
4713 recording::statement
*stmt
= get_first_statement ();
4715 return stmt
->get_loc ();
4720 /* Get the first statement within a block, if any. */
4722 recording::statement
*
4723 recording::block::get_first_statement () const
4725 if (m_statements
.length ())
4726 return m_statements
[0];
4731 /* Get the last statement within a block, if any. */
4733 recording::statement
*
4734 recording::block::get_last_statement () const
4736 if (m_statements
.length ())
4737 return m_statements
[m_statements
.length () - 1];
4742 /* Assuming that this block has been terminated, get the successor blocks
4743 as a vector. Ownership of the vector transfers to the caller, which
4744 must call its release () method.
4746 Used when validating functions, and when dumping dot representations
4749 vec
<recording::block
*>
4750 recording::block::get_successor_blocks () const
4752 gcc_assert (m_has_been_terminated
);
4753 statement
*last_statement
= get_last_statement ();
4754 gcc_assert (last_statement
);
4755 return last_statement
->get_successor_blocks ();
4758 /* Implementation of pure virtual hook recording::memento::replay_into
4759 for recording::block. */
4762 recording::block::replay_into (replayer
*)
4764 set_playback_obj (m_func
->playback_function ()
4765 ->new_block (playback_string (m_name
)));
4768 /* Implementation of recording::memento::make_debug_string for
4772 recording::block::make_debug_string ()
4777 return string::from_printf (m_ctxt
,
4778 "<UNNAMED BLOCK %p>",
4782 /* Implementation of recording::memento::write_reproducer for blocks. */
4785 recording::block::write_reproducer (reproducer
&r
)
4787 const char *id
= r
.make_identifier (this, "block");
4788 r
.write (" gcc_jit_block *%s =\n"
4789 " gcc_jit_function_new_block (%s, %s);\n",
4791 r
.get_identifier (m_func
),
4792 m_name
? m_name
->get_debug_string () : "NULL");
4795 /* Disable warnings about missing quoting in GCC diagnostics for
4796 the pp_printf calls. Their format strings deliberately don't
4797 follow GCC diagnostic conventions. */
4799 # pragma GCC diagnostic push
4800 # pragma GCC diagnostic ignored "-Wformat-diag"
4803 /* Dump a block in graphviz form into PP, capturing the block name (if
4804 any) and the statements. */
4807 recording::block::dump_to_dot (pretty_printer
*pp
)
4811 "[shape=record,style=filled,fillcolor=white,label=\"{"),
4813 pp_write_text_to_stream (pp
);
4816 pp_string (pp
, m_name
->c_str ());
4817 pp_string (pp
, ":");
4819 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
4824 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
4826 pp_string (pp
, s
->get_debug_string ());
4828 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
4836 /* Dump the out-edges of the block in graphviz form into PP. */
4839 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
4841 vec
<block
*> successors
= get_successor_blocks ();
4844 FOR_EACH_VEC_ELT (successors
, i
, succ
)
4846 "\tblock_%d:s -> block_%d:n;\n",
4847 m_index
, succ
->m_index
);
4848 successors
.release ();
4852 # pragma GCC diagnostic pop
4855 namespace recording
{
4856 static const enum tls_model tls_models
[] = {
4857 TLS_MODEL_NONE
, /* GCC_JIT_TLS_MODEL_NONE */
4858 TLS_MODEL_GLOBAL_DYNAMIC
, /* GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC */
4859 TLS_MODEL_LOCAL_DYNAMIC
, /* GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC */
4860 TLS_MODEL_INITIAL_EXEC
, /* GCC_JIT_TLS_MODEL_INITIAL_EXEC */
4861 TLS_MODEL_LOCAL_EXEC
, /* GCC_JIT_TLS_MODEL_LOCAL_EXEC */
4863 } /* namespace recording */
4865 /* The implementation of class gcc::jit::recording::global. */
4867 /* Implementation of pure virtual hook recording::memento::replay_into
4868 for recording::global. */
4871 recording::global::replay_into (replayer
*r
)
4873 playback::lvalue
*global
= m_initializer
4874 ? r
->new_global_initialized (playback_location (r
, m_loc
),
4876 m_type
->playback_type (),
4877 m_type
->dereference ()->get_size (),
4878 m_initializer_num_bytes
4879 / m_type
->dereference ()->get_size (),
4881 playback_string (m_name
),
4883 : r
->new_global (playback_location (r
, m_loc
),
4885 m_type
->playback_type (),
4886 playback_string (m_name
),
4889 if (m_tls_model
!= GCC_JIT_TLS_MODEL_NONE
)
4890 global
->set_tls_model (recording::tls_models
[m_tls_model
]);
4892 if (m_link_section
!= NULL
)
4893 global
->set_link_section (m_link_section
->c_str ());
4895 if (m_reg_name
!= NULL
)
4896 global
->set_register_name (m_reg_name
->c_str ());
4898 if (m_alignment
!= 0)
4899 global
->set_alignment (m_alignment
);
4901 set_playback_obj (global
);
4904 /* Override the default implementation of
4905 recording::memento::write_to_dump for globals.
4906 This will be of the form:
4908 GCC_JIT_GLOBAL_EXPORTED:
4912 GCC_JIT_GLOBAL_INTERNAL:
4914 e.g. "static int foo;"
4916 GCC_JIT_GLOBAL_IMPORTED:
4918 e.g. "extern int foo;"
4920 These are written to the top of the dump by
4921 recording::context::dump_to_file. */
4924 recording::global::write_to_dump (dump
&d
)
4926 if (d
.update_locations ())
4927 m_loc
= d
.make_location ();
4934 case GCC_JIT_GLOBAL_EXPORTED
:
4937 case GCC_JIT_GLOBAL_INTERNAL
:
4938 d
.write ("static ");
4941 case GCC_JIT_GLOBAL_IMPORTED
:
4942 d
.write ("extern ");
4947 m_type
->get_debug_string (),
4948 get_debug_string ());
4950 if (!m_initializer
&& !m_rvalue_init
)
4954 else if (m_initializer
)
4957 const unsigned char *p
= (const unsigned char *)m_initializer
;
4958 for (size_t i
= 0; i
< m_initializer_num_bytes
; i
++)
4960 d
.write ("0x%x, ", p
[i
]);
4966 else if (m_rvalue_init
)
4969 d
.write (m_rvalue_init
->get_debug_string ());
4976 /* A table of enum gcc_jit_global_kind values expressed in string
4979 static const char * const global_kind_reproducer_strings
[] = {
4980 "GCC_JIT_GLOBAL_EXPORTED",
4981 "GCC_JIT_GLOBAL_INTERNAL",
4982 "GCC_JIT_GLOBAL_IMPORTED"
4985 template <typename T
>
4987 recording::global::write_initializer_reproducer (const char *id
, reproducer
&r
)
4989 const char *init_id
= r
.make_tmp_identifier ("init_for", this);
4990 r
.write (" %s %s[] =\n {",
4991 m_type
->dereference ()->get_debug_string (),
4994 const T
*p
= (const T
*)m_initializer
;
4995 for (size_t i
= 0; i
< m_initializer_num_bytes
/ sizeof (T
); i
++)
4997 r
.write ("%" PRIu64
", ", (uint64_t)p
[i
]);
5002 r
.write (" gcc_jit_global_set_initializer (%s, %s, sizeof (%s));\n",
5003 id
, init_id
, init_id
);
5006 /* Implementation of recording::memento::write_reproducer for globals. */
5008 static const char * const tls_model_enum_strings
[] = {
5009 "GCC_JIT_TLS_MODEL_NONE",
5010 "GCC_JIT_TLS_MODEL_GLOBAL_DYNAMIC",
5011 "GCC_JIT_TLS_MODEL_LOCAL_DYNAMIC",
5012 "GCC_JIT_TLS_MODEL_INITIAL_EXEC",
5013 "GCC_JIT_TLS_MODEL_LOCAL_EXEC",
5017 recording::global::write_reproducer (reproducer
&r
)
5019 const char *id
= r
.make_identifier (this, "block");
5020 r
.write (" gcc_jit_lvalue *%s =\n"
5021 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
5022 " %s, /* gcc_jit_location *loc */\n"
5023 " %s, /* enum gcc_jit_global_kind kind */\n"
5024 " %s, /* gcc_jit_type *type */\n"
5025 " %s); /* const char *name */\n",
5027 r
.get_identifier (get_context ()),
5028 r
.get_identifier (m_loc
),
5029 global_kind_reproducer_strings
[m_kind
],
5030 r
.get_identifier_as_type (get_type ()),
5031 m_name
->get_debug_string ());
5033 if (m_tls_model
!= GCC_JIT_TLS_MODEL_NONE
)
5034 r
.write (" gcc_jit_lvalue_set_tls_model (%s, /* gcc_jit_lvalue *lvalue */\n"
5035 " %s); /* enum gcc_jit_tls_model model */\n",
5037 tls_model_enum_strings
[m_tls_model
]);
5039 if (m_link_section
!= NULL
)
5040 r
.write (" gcc_jit_lvalue_set_link_section (%s, /* gcc_jit_lvalue *lvalue */\n"
5041 " \"%s\"); /* */\n",
5043 m_link_section
->c_str ());
5046 switch (m_type
->dereference ()->get_size ())
5049 write_initializer_reproducer
<uint8_t> (id
, r
);
5052 write_initializer_reproducer
<uint16_t> (id
, r
);
5055 write_initializer_reproducer
<uint32_t> (id
, r
);
5058 write_initializer_reproducer
<uint64_t> (id
, r
);
5061 /* This function is serving on sizes returned by 'get_size',
5062 these are all covered by the previous cases. */
5067 /* The implementation of the various const-handling classes:
5068 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
5070 /* Explicit specialization of the various mementos we're interested in. */
5071 template class recording::memento_of_new_rvalue_from_const
<int>;
5072 template class recording::memento_of_new_rvalue_from_const
<long>;
5073 template class recording::memento_of_new_rvalue_from_const
<double>;
5074 template class recording::memento_of_new_rvalue_from_const
<void *>;
5076 /* Implementation of the pure virtual hook recording::memento::replay_into
5077 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
5079 template <typename HOST_TYPE
>
5082 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
5085 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
5089 /* The make_debug_string and write_reproducer methods vary between the
5091 memento_of_new_rvalue_from_const <HOST_TYPE>
5092 classes, so we explicitly write specializations of them.
5094 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
5095 namespaces are written out explicitly, which is why most of this file
5096 doesn't abbreviate things by entering the "recording" namespace.
5098 However, these specializations are required to be in the same namespace
5099 as the template, hence we now have to enter the gcc::jit::recording
5105 /* The make_debug_string specialization for <int>, which renders it as
5106 (TARGET_TYPE)LITERAL
5112 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
5114 return string::from_printf (m_ctxt
,
5116 m_type
->get_debug_string (),
5120 /* The get_wide_int specialization for <int>. */
5124 memento_of_new_rvalue_from_const
<int>::get_wide_int (wide_int
*out
) const
5126 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
5130 /* The write_reproducer specialization for <int>. */
5134 memento_of_new_rvalue_from_const
<int>::write_reproducer (reproducer
&r
)
5136 const char *id
= r
.make_identifier (this, "rvalue");
5137 r
.write (" gcc_jit_rvalue *%s =\n"
5138 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
5139 " %s, /* gcc_jit_type *numeric_type */\n"
5140 " %i); /* int value */\n",
5142 r
.get_identifier (get_context ()),
5143 r
.get_identifier_as_type (m_type
),
5147 /* The make_debug_string specialization for <long>, rendering it as
5148 (TARGET_TYPE)LITERAL
5154 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
5156 return string::from_printf (m_ctxt
,
5158 m_type
->get_debug_string (),
5162 /* The get_wide_int specialization for <long>. */
5166 memento_of_new_rvalue_from_const
<long>::get_wide_int (wide_int
*out
) const
5168 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
5172 /* The write_reproducer specialization for <long>. */
5176 recording::memento_of_new_rvalue_from_const
<long>::write_reproducer (reproducer
&r
)
5178 const char *id
= r
.make_identifier (this, "rvalue");
5180 /* We have to special-case LONG_MIN, since e.g.
5181 -9223372036854775808L
5183 -(9223372036854775808L)
5185 error: integer constant is so large that it is unsigned [-Werror]
5186 Workaround this by writing (LONG_MIN + 1) - 1. */
5187 if (m_value
== LONG_MIN
)
5189 r
.write (" gcc_jit_rvalue *%s =\n"
5190 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
5191 " %s, /* gcc_jit_type *numeric_type */\n"
5192 " %ldL - 1); /* long value */\n",
5194 r
.get_identifier (get_context ()),
5195 r
.get_identifier_as_type (m_type
),
5200 r
.write (" gcc_jit_rvalue *%s =\n"
5201 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
5202 " %s, /* gcc_jit_type *numeric_type */\n"
5203 " %ldL); /* long value */\n",
5205 r
.get_identifier (get_context ()),
5206 r
.get_identifier_as_type (m_type
),
5210 /* The make_debug_string specialization for <double>, rendering it as
5211 (TARGET_TYPE)LITERAL
5217 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
5219 return string::from_printf (m_ctxt
,
5221 m_type
->get_debug_string (),
5225 /* The get_wide_int specialization for <double>. */
5229 memento_of_new_rvalue_from_const
<double>::get_wide_int (wide_int
*) const
5234 /* The write_reproducer specialization for <double>. */
5238 recording::memento_of_new_rvalue_from_const
<double>::write_reproducer (reproducer
&r
)
5240 const char *id
= r
.make_identifier (this, "rvalue");
5241 r
.write (" gcc_jit_rvalue *%s =\n"
5242 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
5243 " %s, /* gcc_jit_type *numeric_type */\n"
5244 " %f); /* double value */\n",
5246 r
.get_identifier (get_context ()),
5247 r
.get_identifier_as_type (m_type
),
5251 /* The make_debug_string specialization for <void *>, rendering it as
5256 Zero is rendered as NULL e.g.
5261 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
5263 if (m_value
!= NULL
)
5264 return string::from_printf (m_ctxt
,
5266 m_type
->get_debug_string (), m_value
);
5268 return string::from_printf (m_ctxt
,
5270 m_type
->get_debug_string ());
5273 /* The get_wide_int specialization for <void *>. */
5277 memento_of_new_rvalue_from_const
<void *>::get_wide_int (wide_int
*) const
5282 /* Implementation of recording::memento::write_reproducer for <void *>
5287 memento_of_new_rvalue_from_const
<void *>::write_reproducer (reproducer
&r
)
5289 const char *id
= r
.make_identifier (this, "rvalue");
5291 r
.write (" gcc_jit_rvalue *%s =\n"
5292 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
5293 " %s, /* gcc_jit_type *pointer_type */\n"
5294 " (void *)%p); /* void *value */\n",
5296 r
.get_identifier (get_context ()),
5297 r
.get_identifier_as_type (m_type
),
5300 r
.write (" gcc_jit_rvalue *%s =\n"
5301 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
5302 " %s); /* gcc_jit_type *pointer_type */\n",
5304 r
.get_identifier (get_context ()),
5305 r
.get_identifier_as_type (m_type
));
5308 /* We're done specializing make_debug_string and write_reproducer, so we
5309 can exit the gcc::jit::recording namespace. */
5311 } // namespace recording
5313 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
5315 /* Implementation of pure virtual hook recording::memento::replay_into
5316 for recording::memento_of_new_string_literal. */
5319 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
5321 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
5324 /* Implementation of recording::memento::make_debug_string for
5328 recording::memento_of_new_string_literal::make_debug_string ()
5330 return string::from_printf (m_ctxt
,
5332 m_value
->get_debug_string ());
5335 /* Implementation of recording::memento::write_reproducer for string literal
5339 recording::memento_of_new_string_literal::write_reproducer (reproducer
&r
)
5341 const char *id
= r
.make_identifier (this, "rvalue");
5342 r
.write (" gcc_jit_rvalue *%s =\n"
5343 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
5344 " %s); /* const char *value */\n",
5346 r
.get_identifier (get_context ()),
5347 m_value
->get_debug_string ());
5350 /* The implementation of class
5351 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
5353 /* The constructor for
5354 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
5356 recording::memento_of_new_rvalue_from_vector::
5357 memento_of_new_rvalue_from_vector (context
*ctxt
,
5361 : rvalue (ctxt
, loc
, type
),
5362 m_vector_type (type
),
5365 for (unsigned i
= 0; i
< type
->get_num_units (); i
++)
5366 m_elements
.safe_push (elements
[i
]);
5369 /* Implementation of pure virtual hook recording::memento::replay_into
5370 for recording::memento_of_new_rvalue_from_vector. */
5373 recording::memento_of_new_rvalue_from_vector::replay_into (replayer
*r
)
5375 auto_vec
<playback::rvalue
*> playback_elements
;
5376 playback_elements
.create (m_elements
.length ());
5377 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
5378 playback_elements
.safe_push (m_elements
[i
]->playback_rvalue ());
5380 set_playback_obj (r
->new_rvalue_from_vector (playback_location (r
, m_loc
),
5381 m_type
->playback_type (),
5382 playback_elements
));
5385 /* Implementation of pure virtual hook recording::rvalue::visit_children
5386 for recording::memento_of_new_rvalue_from_vector. */
5389 recording::memento_of_new_rvalue_from_vector::visit_children (rvalue_visitor
*v
)
5391 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
5392 v
->visit (m_elements
[i
]);
5395 /* Implementation of recording::memento::make_debug_string for
5399 recording::memento_of_new_rvalue_from_vector::make_debug_string ()
5401 comma_separated_string
elements (m_elements
, get_precedence ());
5403 /* Now build a string. */
5404 string
*result
= string::from_printf (m_ctxt
,
5406 elements
.as_char_ptr ());
5412 /* Implementation of recording::memento::write_reproducer for
5416 recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer
&r
)
5418 const char *id
= r
.make_identifier (this, "vector");
5419 const char *elements_id
= r
.make_tmp_identifier ("elements_for_", this);
5420 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
5422 m_elements
.length ());
5423 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
5424 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_elements
[i
]));
5426 r
.write (" gcc_jit_rvalue *%s =\n"
5427 " gcc_jit_context_new_rvalue_from_vector (%s, /* gcc_jit_context *ctxt */\n"
5428 " %s, /* gcc_jit_location *loc */\n"
5429 " %s, /* gcc_jit_type *vec_type */\n"
5430 " %i, /* size_t num_elements */ \n"
5431 " %s); /* gcc_jit_rvalue **elements*/\n",
5433 r
.get_identifier (get_context ()),
5434 r
.get_identifier (m_loc
),
5435 r
.get_identifier (m_vector_type
),
5436 m_elements
.length (),
5441 recording::ctor::visit_children (rvalue_visitor
*v
)
5443 for (unsigned int i
= 0; i
< m_values
.length (); i
++)
5444 v
->visit (m_values
[i
]);
5448 recording::ctor::make_debug_string ()
5450 //Make a compound literal-ish
5453 pp_string (&pp
, "(");
5454 pp_string (&pp
, m_type
->get_debug_string ());
5455 pp_string (&pp
, ") {");
5457 size_t field_n
= m_fields
.length ();
5458 size_t values_n
= m_values
.length ();
5460 if (!field_n
&& !values_n
)
5462 else if (!field_n
&& values_n
)
5464 for (size_t i
= 0; i
< values_n
; i
++)
5467 pp_string (&pp
, m_values
[i
]->get_debug_string ());
5469 pp_string (&pp
, "0");
5470 if (i
+ 1 != values_n
)
5471 pp_string (&pp
, ", ");
5474 else if (field_n
&& values_n
)
5476 for (size_t i
= 0; i
< values_n
; i
++)
5478 pp_string (&pp
, ".");
5479 pp_string (&pp
, m_fields
[i
]->get_debug_string ());
5480 pp_string (&pp
, "=");
5482 pp_string (&pp
, m_values
[i
]->get_debug_string ());
5484 pp_string (&pp
, "0");
5485 if (i
+ 1 != values_n
)
5486 pp_string (&pp
, ", ");
5489 /* m_fields are never populated with m_values empty. */
5491 pp_string (&pp
, "}");
5493 return new_string (pp_formatted_text (&pp
));
5497 recording::ctor::write_reproducer (reproducer
&r
)
5499 const char *id
= r
.make_identifier (this, "rvalue");
5500 type
*type
= get_type ();
5502 r
.write (" gcc_jit_rvalue *%s;\n", id
);
5503 r
.write (" {\n"); /* Open scope for locals. */
5505 if (type
->is_union ())
5507 if (m_values
.length () == 0)
5508 r
.write (" gcc_jit_rvalue *value = NULL;\n");
5510 r
.write (" gcc_jit_rvalue *value = %s;\n",
5511 r
.get_identifier (m_values
[0]));
5513 if (m_fields
.length () == 0)
5514 r
.write (" gcc_jit_field *field = NULL;\n");
5516 r
.write (" gcc_jit_field *field = %s;\n",
5517 r
.get_identifier (m_fields
[0]));
5521 /* Write the array of values. */
5522 if (m_values
.length () == 0)
5523 r
.write (" gcc_jit_rvalue **values = NULL;\n");
5526 r
.write (" gcc_jit_rvalue *values[] = {\n");
5527 for (size_t i
= 0; i
< m_values
.length (); i
++)
5528 r
.write (" %s,\n", r
.get_identifier (m_values
[i
]));
5531 /* Write the array of fields. */
5532 if (m_fields
.length () == 0)
5533 r
.write (" gcc_jit_field **fields = NULL;\n");
5536 r
.write (" gcc_jit_field *fields[] = {\n");
5537 for (size_t i
= 0; i
< m_fields
.length (); i
++)
5538 r
.write (" %s,\n", r
.get_identifier (m_fields
[i
]));
5542 if (type
->is_array ())
5545 " gcc_jit_context_new_array_constructor (%s,\n"
5546 " %s, /* gcc_jit_location *loc */\n"
5547 " %s, /* gcc_jit_type *type */\n"
5548 " %i, /* int num_values */\n"
5551 r
.get_identifier (get_context ()),
5552 r
.get_identifier (m_loc
),
5553 r
.get_identifier_as_type (get_type ()),
5554 m_values
.length ());
5555 else if (type
->is_struct ())
5558 " gcc_jit_context_new_struct_constructor (%s,\n"
5560 " %s, /* gcc_jit_type *type */\n"
5561 " %i, /* int num_values */\n"
5565 r
.get_identifier (get_context ()),
5566 r
.get_identifier (m_loc
),
5567 r
.get_identifier_as_type (get_type ()),
5568 m_values
.length ());
5569 else if (type
->is_union ())
5572 " gcc_jit_context_new_union_constructor (%s,\n"
5574 " %s, /* gcc_jit_type *type */\n"
5578 r
.get_identifier (get_context ()),
5579 r
.get_identifier (m_loc
),
5580 r
.get_identifier_as_type (get_type ()));
5584 r
.write (" }\n"); /* Close scope for locals. */
5588 recording::ctor::replay_into (replayer
*r
)
5590 auto_vec
<playback::rvalue
*> playback_values
;
5591 auto_vec
<playback::field
*> playback_fields
;
5593 int n
= m_values
.length ();
5595 type
*type
= get_type ();
5597 /* Handle arrays, and return. */
5598 if (type
->is_array ())
5600 playback_values
.reserve (n
, false);
5602 for (int i
= 0; i
< n
; i
++)
5604 /* null m_values element indicates zero ctor. */
5605 playback_values
.quick_push (m_values
[i
] ?
5606 m_values
[i
]->playback_rvalue () :
5609 set_playback_obj (r
->new_ctor (playback_location (r
, m_loc
),
5610 get_type ()->playback_type (),
5615 /* ... else handle unions and structs. */
5617 playback_values
.reserve (n
, false);
5618 playback_fields
.reserve (n
, false);
5620 for (int i
= 0; i
< n
; i
++)
5622 /* null m_values element indicates zero ctor. */
5623 playback_values
.quick_push (m_values
[i
] ?
5624 m_values
[i
]->playback_rvalue () :
5626 playback_fields
.quick_push (m_fields
[i
]->playback_field ());
5629 set_playback_obj (r
->new_ctor (playback_location (r
, m_loc
),
5630 get_type ()->playback_type (),
5635 /* The implementation of class gcc::jit::recording::unary_op. */
5637 /* Implementation of pure virtual hook recording::memento::replay_into
5638 for recording::unary_op. */
5641 recording::unary_op::replay_into (replayer
*r
)
5643 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
5645 get_type ()->playback_type (),
5646 m_a
->playback_rvalue ()));
5649 /* Implementation of pure virtual hook recording::rvalue::visit_children
5650 for recording::unary_op. */
5652 recording::unary_op::visit_children (rvalue_visitor
*v
)
5657 /* Implementation of recording::memento::make_debug_string for
5660 static const char * const unary_op_strings
[] = {
5661 "-", /* GCC_JIT_UNARY_OP_MINUS */
5662 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
5663 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
5664 "abs ", /* GCC_JIT_UNARY_OP_ABS */
5668 recording::unary_op::make_debug_string ()
5670 return string::from_printf (m_ctxt
,
5672 unary_op_strings
[m_op
],
5673 m_a
->get_debug_string ());
5676 const char * const unary_op_reproducer_strings
[] = {
5677 "GCC_JIT_UNARY_OP_MINUS",
5678 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
5679 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
5680 "GCC_JIT_UNARY_OP_ABS"
5683 /* Implementation of recording::memento::write_reproducer for unary ops. */
5686 recording::unary_op::write_reproducer (reproducer
&r
)
5688 const char *id
= r
.make_identifier (this, "rvalue");
5689 r
.write (" gcc_jit_rvalue *%s =\n"
5690 " gcc_jit_context_new_unary_op (%s,\n"
5691 " %s, /* gcc_jit_location *loc */\n"
5692 " %s, /* enum gcc_jit_unary_op op */\n"
5693 " %s, /* gcc_jit_type *result_type */\n"
5694 " %s); /* gcc_jit_rvalue *a */\n",
5696 r
.get_identifier (get_context ()),
5697 r
.get_identifier (m_loc
),
5698 unary_op_reproducer_strings
[m_op
],
5699 r
.get_identifier_as_type (get_type ()),
5700 r
.get_identifier_as_rvalue (m_a
));
5703 /* The implementation of class gcc::jit::recording::binary_op. */
5705 /* Implementation of pure virtual hook recording::memento::replay_into
5706 for recording::binary_op. */
5709 recording::binary_op::replay_into (replayer
*r
)
5711 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
5713 get_type ()->playback_type (),
5714 m_a
->playback_rvalue (),
5715 m_b
->playback_rvalue ()));
5718 /* Implementation of pure virtual hook recording::rvalue::visit_children
5719 for recording::binary_op. */
5721 recording::binary_op::visit_children (rvalue_visitor
*v
)
5727 /* Implementation of recording::memento::make_debug_string for
5730 static const char * const binary_op_strings
[] = {
5731 "+", /* GCC_JIT_BINARY_OP_PLUS */
5732 "-", /* GCC_JIT_BINARY_OP_MINUS */
5733 "*", /* GCC_JIT_BINARY_OP_MULT */
5734 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
5735 "%", /* GCC_JIT_BINARY_OP_MODULO */
5736 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
5737 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
5738 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
5739 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
5740 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
5741 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
5742 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
5746 recording::binary_op::make_debug_string ()
5748 enum precedence prec
= get_precedence ();
5749 return string::from_printf (m_ctxt
,
5751 m_a
->get_debug_string_parens (prec
),
5752 binary_op_strings
[m_op
],
5753 m_b
->get_debug_string_parens (prec
));
5756 const char * const binary_op_reproducer_strings
[] = {
5757 "GCC_JIT_BINARY_OP_PLUS",
5758 "GCC_JIT_BINARY_OP_MINUS",
5759 "GCC_JIT_BINARY_OP_MULT",
5760 "GCC_JIT_BINARY_OP_DIVIDE",
5761 "GCC_JIT_BINARY_OP_MODULO",
5762 "GCC_JIT_BINARY_OP_BITWISE_AND",
5763 "GCC_JIT_BINARY_OP_BITWISE_XOR",
5764 "GCC_JIT_BINARY_OP_BITWISE_OR",
5765 "GCC_JIT_BINARY_OP_LOGICAL_AND",
5766 "GCC_JIT_BINARY_OP_LOGICAL_OR",
5767 "GCC_JIT_BINARY_OP_LSHIFT",
5768 "GCC_JIT_BINARY_OP_RSHIFT"
5771 /* Implementation of recording::memento::write_reproducer for binary ops. */
5774 recording::binary_op::write_reproducer (reproducer
&r
)
5776 const char *id
= r
.make_identifier (this, "rvalue");
5777 r
.write (" gcc_jit_rvalue *%s =\n"
5778 " gcc_jit_context_new_binary_op (%s,\n"
5779 " %s, /* gcc_jit_location *loc */\n"
5780 " %s, /* enum gcc_jit_binary_op op */\n"
5781 " %s, /* gcc_jit_type *result_type */\n"
5782 " %s, /* gcc_jit_rvalue *a */\n"
5783 " %s); /* gcc_jit_rvalue *b */\n",
5785 r
.get_identifier (get_context ()),
5786 r
.get_identifier (m_loc
),
5787 binary_op_reproducer_strings
[m_op
],
5788 r
.get_identifier_as_type (get_type ()),
5789 r
.get_identifier_as_rvalue (m_a
),
5790 r
.get_identifier_as_rvalue (m_b
));
5793 namespace recording
{
5794 static const enum precedence binary_op_precedence
[] = {
5795 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_PLUS */
5796 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_MINUS */
5798 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MULT */
5799 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_DIVIDE */
5800 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MODULO */
5802 PRECEDENCE_BITWISE_AND
, /* GCC_JIT_BINARY_OP_BITWISE_AND */
5803 PRECEDENCE_BITWISE_XOR
, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
5804 PRECEDENCE_BITWISE_IOR
, /* GCC_JIT_BINARY_OP_BITWISE_OR */
5805 PRECEDENCE_LOGICAL_AND
, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
5806 PRECEDENCE_LOGICAL_OR
, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
5807 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_LSHIFT */
5808 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_RSHIFT */
5810 } /* namespace recording */
5812 enum recording::precedence
5813 recording::binary_op::get_precedence () const
5815 return binary_op_precedence
[m_op
];
5818 /* The implementation of class gcc::jit::recording::comparison. */
5820 /* Implementation of recording::memento::make_debug_string for
5823 static const char * const comparison_strings
[] =
5825 "==", /* GCC_JIT_COMPARISON_EQ */
5826 "!=", /* GCC_JIT_COMPARISON_NE */
5827 "<", /* GCC_JIT_COMPARISON_LT */
5828 "<=", /* GCC_JIT_COMPARISON_LE */
5829 ">", /* GCC_JIT_COMPARISON_GT */
5830 ">=", /* GCC_JIT_COMPARISON_GE */
5834 recording::comparison::make_debug_string ()
5836 enum precedence prec
= get_precedence ();
5837 return string::from_printf (m_ctxt
,
5839 m_a
->get_debug_string_parens (prec
),
5840 comparison_strings
[m_op
],
5841 m_b
->get_debug_string_parens (prec
));
5844 /* A table of enum gcc_jit_comparison values expressed in string
5847 static const char * const comparison_reproducer_strings
[] =
5849 "GCC_JIT_COMPARISON_EQ",
5850 "GCC_JIT_COMPARISON_NE",
5851 "GCC_JIT_COMPARISON_LT",
5852 "GCC_JIT_COMPARISON_LE",
5853 "GCC_JIT_COMPARISON_GT",
5854 "GCC_JIT_COMPARISON_GE"
5857 /* Implementation of recording::memento::write_reproducer for comparisons. */
5860 recording::comparison::write_reproducer (reproducer
&r
)
5862 const char *id
= r
.make_identifier (this, "rvalue");
5863 r
.write (" gcc_jit_rvalue *%s =\n"
5864 " gcc_jit_context_new_comparison (%s,\n"
5865 " %s, /* gcc_jit_location *loc */\n"
5866 " %s, /* enum gcc_jit_comparison op */\n"
5867 " %s, /* gcc_jit_rvalue *a */\n"
5868 " %s); /* gcc_jit_rvalue *b */\n",
5870 r
.get_identifier (get_context ()),
5871 r
.get_identifier (m_loc
),
5872 comparison_reproducer_strings
[m_op
],
5873 r
.get_identifier_as_rvalue (m_a
),
5874 r
.get_identifier_as_rvalue (m_b
));
5877 /* Implementation of pure virtual hook recording::memento::replay_into
5878 for recording::comparison. */
5881 recording::comparison::replay_into (replayer
*r
)
5883 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
5885 m_a
->playback_rvalue (),
5886 m_b
->playback_rvalue (),
5887 m_type
->playback_type ()));
5890 /* Implementation of pure virtual hook recording::rvalue::visit_children
5891 for recording::comparison. */
5894 recording::comparison::visit_children (rvalue_visitor
*v
)
5900 namespace recording
{
5901 static const enum precedence comparison_precedence
[] =
5903 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_EQ */
5904 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_NE */
5906 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LT */
5907 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LE */
5908 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GT */
5909 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GE */
5911 } /* namespace recording */
5913 enum recording::precedence
5914 recording::comparison::get_precedence () const
5916 return comparison_precedence
[m_op
];
5919 /* Implementation of pure virtual hook recording::memento::replay_into
5920 for recording::cast. */
5923 recording::cast::replay_into (replayer
*r
)
5925 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
5926 m_rvalue
->playback_rvalue (),
5927 get_type ()->playback_type ()));
5930 /* Implementation of pure virtual hook recording::rvalue::visit_children
5931 for recording::cast. */
5933 recording::cast::visit_children (rvalue_visitor
*v
)
5935 v
->visit (m_rvalue
);
5938 /* Implementation of recording::memento::make_debug_string for
5942 recording::cast::make_debug_string ()
5944 enum precedence prec
= get_precedence ();
5945 return string::from_printf (m_ctxt
,
5947 get_type ()->get_debug_string (),
5948 m_rvalue
->get_debug_string_parens (prec
));
5951 /* Implementation of recording::memento::write_reproducer for casts. */
5954 recording::cast::write_reproducer (reproducer
&r
)
5956 const char *id
= r
.make_identifier (this, "rvalue");
5957 r
.write (" gcc_jit_rvalue *%s =\n"
5958 " gcc_jit_context_new_cast (%s,\n"
5959 " %s, /* gcc_jit_location *loc */\n"
5960 " %s, /* gcc_jit_rvalue *rvalue */\n"
5961 " %s); /* gcc_jit_type *type */\n",
5963 r
.get_identifier (get_context ()),
5964 r
.get_identifier (m_loc
),
5965 r
.get_identifier_as_rvalue (m_rvalue
),
5966 r
.get_identifier_as_type (get_type ()));
5969 /* Implementation of pure virtual hook recording::memento::replay_into
5970 for recording::bitcast. */
5973 recording::bitcast::replay_into (replayer
*r
)
5975 set_playback_obj (r
->new_bitcast (playback_location (r
, m_loc
),
5976 m_rvalue
->playback_rvalue (),
5977 get_type ()->playback_type ()));
5980 /* Implementation of pure virtual hook recording::rvalue::visit_children
5981 for recording::bitcast. */
5983 recording::bitcast::visit_children (rvalue_visitor
*v
)
5985 v
->visit (m_rvalue
);
5988 /* Implementation of recording::memento::make_debug_string for
5992 recording::bitcast::make_debug_string ()
5994 enum precedence prec
= get_precedence ();
5995 return string::from_printf (m_ctxt
,
5997 m_rvalue
->get_debug_string_parens (prec
),
5998 get_type ()->get_debug_string ());
6001 /* Implementation of recording::memento::write_reproducer for casts. */
6004 recording::bitcast::write_reproducer (reproducer
&r
)
6006 const char *id
= r
.make_identifier (this, "rvalue");
6007 r
.write (" gcc_jit_rvalue *%s =\n"
6008 " gcc_jit_context_new_bitcast (%s,\n"
6009 " %s, /* gcc_jit_location *loc */\n"
6010 " %s, /* gcc_jit_rvalue *rvalue */\n"
6011 " %s); /* gcc_jit_type *type */\n",
6013 r
.get_identifier (get_context ()),
6014 r
.get_identifier (m_loc
),
6015 r
.get_identifier_as_rvalue (m_rvalue
),
6016 r
.get_identifier_as_type (get_type ()));
6019 /* The implementation of class gcc::jit::recording::base_call. */
6021 /* The constructor for gcc::jit::recording::base_call. */
6023 recording::base_call::base_call (context
*ctxt
,
6028 : rvalue (ctxt
, loc
, type_
),
6030 m_require_tail_call (0)
6032 for (int i
= 0; i
< numargs
; i
++)
6033 m_args
.safe_push (args
[i
]);
6036 /* Subroutine for use by call and call_though_ptr's write_reproducer
6040 recording::base_call::write_reproducer_tail_call (reproducer
&r
,
6043 if (m_require_tail_call
)
6045 r
.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
6046 " %i); /* int require_tail_call*/\n",
6052 /* The implementation of class gcc::jit::recording::call. */
6054 /* The constructor for gcc::jit::recording::call. */
6056 recording::call::call (recording::context
*ctxt
,
6057 recording::location
*loc
,
6058 recording::function
*func
,
6061 : base_call (ctxt
, loc
, func
->get_return_type (), numargs
, args
),
6066 /* Implementation of pure virtual hook recording::memento::replay_into
6067 for recording::call. */
6070 recording::call::replay_into (replayer
*r
)
6072 auto_vec
<playback::rvalue
*> playback_args
;
6073 playback_args
.create (m_args
.length ());
6074 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6075 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
6077 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
6078 m_func
->playback_function (),
6080 m_require_tail_call
));
6083 /* Implementation of pure virtual hook recording::rvalue::visit_children
6084 for recording::call. */
6087 recording::call::visit_children (rvalue_visitor
*v
)
6089 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6090 v
->visit (m_args
[i
]);
6093 /* Implementation of recording::memento::make_debug_string for
6097 recording::call::make_debug_string ()
6099 /* First, build a buffer for the arguments. */
6100 comma_separated_string
args (m_args
, get_precedence ());
6102 /* ...and use it to get the string for the call as a whole. */
6103 string
*result
= string::from_printf (m_ctxt
,
6105 m_func
->get_debug_string (),
6106 args
.as_char_ptr ());
6112 recording::call::write_reproducer (reproducer
&r
)
6114 const char *id
= r
.make_identifier (this, "call");
6115 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
6116 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
6119 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6120 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
6122 r
.write (" gcc_jit_rvalue *%s =\n"
6123 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
6124 " %s, /* gcc_jit_location *loc */\n"
6125 " %s, /* gcc_jit_function *func */\n"
6126 " %i, /* int numargs */ \n"
6127 " %s); /* gcc_jit_rvalue **args*/\n",
6129 r
.get_identifier (get_context ()),
6130 r
.get_identifier (m_loc
),
6131 r
.get_identifier (m_func
),
6134 write_reproducer_tail_call (r
, id
);
6137 /* The implementation of class gcc::jit::recording::call_through_ptr. */
6139 /* The constructor for recording::call_through_ptr. */
6141 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
6142 recording::location
*loc
,
6143 recording::rvalue
*fn_ptr
,
6146 : base_call (ctxt
, loc
,
6147 fn_ptr
->get_type ()->dereference ()
6148 ->as_a_function_type ()->get_return_type (),
6154 /* Implementation of pure virtual hook recording::memento::replay_into
6155 for recording::call_through_ptr. */
6158 recording::call_through_ptr::replay_into (replayer
*r
)
6160 auto_vec
<playback::rvalue
*> playback_args
;
6161 playback_args
.create (m_args
.length ());
6162 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6163 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
6165 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
6166 m_fn_ptr
->playback_rvalue (),
6168 m_require_tail_call
));
6171 /* Implementation of pure virtual hook recording::rvalue::visit_children
6172 for recording::call_through_ptr. */
6175 recording::call_through_ptr::visit_children (rvalue_visitor
*v
)
6177 v
->visit (m_fn_ptr
);
6178 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6179 v
->visit (m_args
[i
]);
6182 /* Implementation of recording::memento::make_debug_string for
6183 calls through function ptrs. */
6186 recording::call_through_ptr::make_debug_string ()
6188 enum precedence prec
= get_precedence ();
6189 /* First, build a buffer for the arguments. */
6190 /* Calculate length of said buffer. */
6191 size_t sz
= 1; /* nil terminator */
6192 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6194 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
6195 sz
+= 2; /* ", " separator */
6198 /* Now allocate and populate the buffer. */
6199 char *argbuf
= new char[sz
];
6202 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6204 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
6205 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
6206 if (i
+ 1 < m_args
.length ())
6208 strcpy (argbuf
+ len
, ", ");
6214 /* ...and use it to get the string for the call as a whole. */
6215 string
*result
= string::from_printf (m_ctxt
,
6217 m_fn_ptr
->get_debug_string_parens (prec
),
6225 /* Implementation of recording::memento::write_reproducer for
6226 call_through_ptr. */
6229 recording::call_through_ptr::write_reproducer (reproducer
&r
)
6231 const char *id
= r
.make_identifier (this, "call");
6232 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
6233 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
6236 for (unsigned i
= 0; i
< m_args
.length (); i
++)
6237 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
6239 r
.write (" gcc_jit_rvalue *%s =\n"
6240 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
6241 " %s, /* gcc_jit_location *loc */\n"
6242 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
6243 " %i, /* int numargs */ \n"
6244 " %s); /* gcc_jit_rvalue **args*/\n",
6246 r
.get_identifier (get_context ()),
6247 r
.get_identifier (m_loc
),
6248 r
.get_identifier_as_rvalue (m_fn_ptr
),
6251 write_reproducer_tail_call (r
, id
);
6254 /* The implementation of class gcc::jit::recording::array_access. */
6256 /* Implementation of pure virtual hook recording::memento::replay_into
6257 for recording::array_access. */
6260 recording::array_access::replay_into (replayer
*r
)
6263 r
->new_array_access (playback_location (r
, m_loc
),
6264 m_ptr
->playback_rvalue (),
6265 m_index
->playback_rvalue ()));
6268 /* Implementation of pure virtual hook recording::rvalue::visit_children
6269 for recording::array_access. */
6272 recording::array_access::visit_children (rvalue_visitor
*v
)
6278 /* Implementation of recording::memento::make_debug_string for
6282 recording::array_access::make_debug_string ()
6284 enum precedence prec
= get_precedence ();
6285 return string::from_printf (m_ctxt
,
6287 m_ptr
->get_debug_string_parens (prec
),
6288 m_index
->get_debug_string_parens (prec
));
6291 /* Implementation of recording::memento::write_reproducer for
6295 recording::array_access::write_reproducer (reproducer
&r
)
6297 const char *id
= r
.make_identifier (this, "lvalue");
6298 r
.write (" gcc_jit_lvalue *%s = \n"
6299 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
6300 " %s, /*gcc_jit_location *loc */\n"
6301 " %s, /* gcc_jit_rvalue *ptr */\n"
6302 " %s); /* gcc_jit_rvalue *index */\n",
6304 r
.get_identifier (get_context ()),
6305 r
.get_identifier (m_loc
),
6306 r
.get_identifier_as_rvalue (m_ptr
),
6307 r
.get_identifier_as_rvalue (m_index
));
6310 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
6312 /* Implementation of pure virtual hook recording::memento::replay_into
6313 for recording::access_field_of_lvalue. */
6316 recording::access_field_of_lvalue::replay_into (replayer
*r
)
6319 m_lvalue
->playback_lvalue ()
6320 ->access_field (playback_location (r
, m_loc
),
6321 m_field
->playback_field ()));
6325 /* Implementation of pure virtual hook recording::rvalue::visit_children
6326 for recording::access_field_of_lvalue. */
6329 recording::access_field_of_lvalue::visit_children (rvalue_visitor
*v
)
6331 v
->visit (m_lvalue
);
6334 /* Implementation of recording::memento::make_debug_string for
6335 accessing a field of an lvalue. */
6338 recording::access_field_of_lvalue::make_debug_string ()
6340 enum precedence prec
= get_precedence ();
6341 return string::from_printf (m_ctxt
,
6343 m_lvalue
->get_debug_string_parens (prec
),
6344 m_field
->get_debug_string ());
6347 /* Implementation of recording::memento::write_reproducer for
6348 access_field_of_lvalue. */
6351 recording::access_field_of_lvalue::write_reproducer (reproducer
&r
)
6353 const char *id
= r
.make_identifier (this, "lvalue");
6354 r
.write (" gcc_jit_lvalue *%s = \n"
6355 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
6356 " %s, /*gcc_jit_location *loc */\n"
6359 r
.get_identifier_as_lvalue (m_lvalue
),
6360 r
.get_identifier (m_loc
),
6361 r
.get_identifier (m_field
));
6364 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
6366 /* Implementation of pure virtual hook recording::memento::replay_into
6367 for recording::access_field_rvalue. */
6370 recording::access_field_rvalue::replay_into (replayer
*r
)
6373 m_rvalue
->playback_rvalue ()
6374 ->access_field (playback_location (r
, m_loc
),
6375 m_field
->playback_field ()));
6378 /* Implementation of pure virtual hook recording::rvalue::visit_children
6379 for recording::access_field_rvalue. */
6382 recording::access_field_rvalue::visit_children (rvalue_visitor
*v
)
6384 v
->visit (m_rvalue
);
6387 /* Implementation of recording::memento::make_debug_string for
6388 accessing a field of an rvalue. */
6391 recording::access_field_rvalue::make_debug_string ()
6393 enum precedence prec
= get_precedence ();
6394 return string::from_printf (m_ctxt
,
6396 m_rvalue
->get_debug_string_parens (prec
),
6397 m_field
->get_debug_string ());
6400 /* Implementation of recording::memento::write_reproducer for
6401 access_field_rvalue. */
6404 recording::access_field_rvalue::write_reproducer (reproducer
&r
)
6406 const char *id
= r
.make_identifier (this, "rvalue");
6407 r
.write (" gcc_jit_rvalue *%s = \n"
6408 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
6409 " %s, /*gcc_jit_location *loc */\n"
6412 r
.get_identifier_as_rvalue (m_rvalue
),
6413 r
.get_identifier (m_loc
),
6414 r
.get_identifier (m_field
));
6417 /* The implementation of class
6418 gcc::jit::recording::dereference_field_rvalue. */
6420 /* Implementation of pure virtual hook recording::memento::replay_into
6421 for recording::dereference_field_rvalue. */
6424 recording::dereference_field_rvalue::replay_into (replayer
*r
)
6427 m_rvalue
->playback_rvalue ()->
6428 dereference_field (playback_location (r
, m_loc
),
6429 m_field
->playback_field ()));
6432 /* Implementation of pure virtual hook recording::rvalue::visit_children
6433 for recording::dereference_field_rvalue. */
6436 recording::dereference_field_rvalue::visit_children (rvalue_visitor
*v
)
6438 v
->visit (m_rvalue
);
6441 /* Implementation of recording::memento::make_debug_string for
6442 dereferencing a field of an rvalue. */
6445 recording::dereference_field_rvalue::make_debug_string ()
6447 enum precedence prec
= get_precedence ();
6448 return string::from_printf (m_ctxt
,
6450 m_rvalue
->get_debug_string_parens (prec
),
6451 m_field
->get_debug_string ());
6454 /* Implementation of recording::memento::write_reproducer for
6455 dereference_field_rvalue. */
6458 recording::dereference_field_rvalue::write_reproducer (reproducer
&r
)
6460 const char *id
= r
.make_identifier (this, "lvalue");
6461 r
.write (" gcc_jit_lvalue *%s=\n"
6462 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
6463 " %s, /* gcc_jit_location *loc */\n"
6464 " %s); /* gcc_jit_field *field */\n",
6466 r
.get_identifier_as_rvalue (m_rvalue
),
6467 r
.get_identifier (m_loc
),
6468 r
.get_identifier (m_field
));
6471 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
6473 /* Implementation of pure virtual hook recording::memento::replay_into
6474 for recording::dereference_rvalue. */
6477 recording::dereference_rvalue::replay_into (replayer
*r
)
6480 m_rvalue
->playback_rvalue ()->
6481 dereference (playback_location (r
, m_loc
)));
6484 /* Implementation of pure virtual hook recording::rvalue::visit_children
6485 for recording::dereference_rvalue. */
6488 recording::dereference_rvalue::visit_children (rvalue_visitor
*v
)
6490 v
->visit (m_rvalue
);
6493 /* Implementation of recording::memento::make_debug_string for
6494 dereferencing an rvalue. */
6497 recording::dereference_rvalue::make_debug_string ()
6499 enum precedence prec
= get_precedence ();
6500 return string::from_printf (m_ctxt
,
6502 m_rvalue
->get_debug_string_parens (prec
));
6505 /* Implementation of recording::memento::write_reproducer for
6506 dereference_rvalue. */
6509 recording::dereference_rvalue::write_reproducer (reproducer
&r
)
6511 const char *id
= r
.make_identifier (this, "dereference");
6512 r
.write (" gcc_jit_lvalue *%s =\n"
6513 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
6514 " %s); /* gcc_jit_location *loc */\n",
6516 r
.get_identifier_as_rvalue (m_rvalue
),
6517 r
.get_identifier (m_loc
));
6520 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
6522 /* Implementation of pure virtual hook recording::memento::replay_into
6523 for recording::get_address_of_lvalue. */
6526 recording::get_address_of_lvalue::replay_into (replayer
*r
)
6529 m_lvalue
->playback_lvalue ()->
6530 get_address (playback_location (r
, m_loc
)));
6533 /* Implementation of pure virtual hook recording::rvalue::visit_children
6534 for recording::get_address_of_lvalue. */
6537 recording::get_address_of_lvalue::visit_children (rvalue_visitor
*v
)
6539 v
->visit (m_lvalue
);
6542 /* Implementation of recording::memento::make_debug_string for
6543 getting the address of an lvalue. */
6546 recording::get_address_of_lvalue::make_debug_string ()
6548 enum precedence prec
= get_precedence ();
6549 return string::from_printf (m_ctxt
,
6551 m_lvalue
->get_debug_string_parens (prec
));
6554 /* Implementation of recording::memento::write_reproducer for
6555 get_address_of_lvalue. */
6558 recording::get_address_of_lvalue::write_reproducer (reproducer
&r
)
6560 const char *id
= r
.make_identifier (this, "address_of");
6561 r
.write (" gcc_jit_rvalue *%s =\n"
6562 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
6563 " %s); /* gcc_jit_location *loc */\n",
6565 r
.get_identifier_as_lvalue (m_lvalue
),
6566 r
.get_identifier (m_loc
));
6569 /* The implementation of class gcc::jit::recording::function_pointer. */
6571 /* Implementation of pure virtual hook recording::memento::replay_into
6572 for recording::function_pointer. */
6575 recording::function_pointer::replay_into (replayer
*r
)
6578 m_fn
->playback_function ()->
6579 get_address (playback_location (r
, m_loc
)));
6583 recording::function_pointer::visit_children (rvalue_visitor
*)
6588 /* Implementation of recording::memento::make_debug_string for
6589 getting the address of an lvalue. */
6592 recording::function_pointer::make_debug_string ()
6594 return string::from_printf (m_ctxt
,
6596 m_fn
->get_debug_string ());
6599 /* Implementation of recording::memento::write_reproducer for
6600 function_pointer. */
6603 recording::function_pointer::write_reproducer (reproducer
&r
)
6605 const char *id
= r
.make_identifier (this, "address_of");
6606 r
.write (" gcc_jit_rvalue *%s =\n"
6607 " gcc_jit_function_get_address (%s, /* gcc_jit_function *fn */\n"
6608 " %s); /* gcc_jit_location *loc */\n",
6610 r
.get_identifier (m_fn
),
6611 r
.get_identifier (m_loc
));
6614 /* The implementation of class gcc::jit::recording::local. */
6616 /* Implementation of pure virtual hook recording::memento::replay_into
6617 for recording::local. */
6620 recording::local::replay_into (replayer
*r
)
6622 playback::lvalue
*obj
= m_func
->playback_function ()
6623 ->new_local (playback_location (r
, m_loc
),
6624 m_type
->playback_type (),
6625 playback_string (m_name
));
6627 if (m_reg_name
!= NULL
)
6628 obj
->set_register_name (m_reg_name
->c_str ());
6630 if (m_alignment
!= 0)
6631 obj
->set_alignment (m_alignment
);
6633 set_playback_obj (obj
);
6636 /* Override the default implementation of
6637 recording::memento::write_to_dump for locals by writing
6639 for use at the top of the function body as if it were a
6643 recording::local::write_to_dump (dump
&d
)
6645 if (d
.update_locations ())
6646 m_loc
= d
.make_location ();
6647 d
.write(" %s %s;\n",
6648 m_type
->get_debug_string (),
6649 get_debug_string ());
6653 recording::local::write_reproducer (reproducer
&r
)
6655 const char *id
= r
.make_identifier (this, "local");
6656 r
.write (" gcc_jit_lvalue *%s =\n"
6657 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
6658 " %s, /* gcc_jit_location *loc */\n"
6659 " %s, /* gcc_jit_type *type */\n"
6660 " %s); /* const char *name */\n",
6662 r
.get_identifier (m_func
),
6663 r
.get_identifier (m_loc
),
6664 r
.get_identifier_as_type (m_type
),
6665 m_name
->get_debug_string ());
6668 /* The implementation of class gcc::jit::recording::statement. */
6670 /* We poison the default implementation of
6671 gcc::jit::recording::statement::get_successor_blocks
6672 since this vfunc must only ever be called on terminator
6675 vec
<recording::block
*>
6676 recording::statement::get_successor_blocks () const
6678 /* The base class implementation is for non-terminating statements,
6679 and thus should never be called. */
6681 vec
<block
*> result
;
6686 /* Extend the default implementation of
6687 recording::memento::write_to_dump for statements by (if requested)
6688 updating the location of the statement to the current location in
6692 recording::statement::write_to_dump (dump
&d
)
6694 memento::write_to_dump (d
);
6695 if (d
.update_locations ())
6696 m_loc
= d
.make_location ();
6699 /* The implementation of class gcc::jit::recording::eval. */
6701 /* Implementation of pure virtual hook recording::memento::replay_into
6702 for recording::eval. */
6705 recording::eval::replay_into (replayer
*r
)
6707 playback_block (get_block ())
6708 ->add_eval (playback_location (r
),
6709 m_rvalue
->playback_rvalue ());
6712 /* Implementation of recording::memento::make_debug_string for
6713 an eval statement. */
6716 recording::eval::make_debug_string ()
6718 return string::from_printf (m_ctxt
,
6720 m_rvalue
->get_debug_string ());
6723 /* Implementation of recording::memento::write_reproducer for
6727 recording::eval::write_reproducer (reproducer
&r
)
6729 r
.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
6730 " %s, /* gcc_jit_location *loc */\n"
6731 " %s); /* gcc_jit_rvalue *rvalue */\n",
6732 r
.get_identifier (get_block ()),
6733 r
.get_identifier (get_loc ()),
6734 r
.get_identifier_as_rvalue (m_rvalue
));
6737 /* The implementation of class gcc::jit::recording::assignment. */
6739 /* Implementation of pure virtual hook recording::memento::replay_into
6740 for recording::assignment. */
6743 recording::assignment::replay_into (replayer
*r
)
6745 playback_block (get_block ())
6746 ->add_assignment (playback_location (r
),
6747 m_lvalue
->playback_lvalue (),
6748 m_rvalue
->playback_rvalue ());
6751 /* Implementation of recording::memento::make_debug_string for
6752 an assignment statement. */
6755 recording::assignment::make_debug_string ()
6757 return string::from_printf (m_ctxt
,
6759 m_lvalue
->get_debug_string (),
6760 m_rvalue
->get_debug_string ());
6763 /* Implementation of recording::memento::write_reproducer for
6764 assignment statements. */
6767 recording::assignment::write_reproducer (reproducer
&r
)
6769 r
.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
6770 " %s, /* gcc_jit_location *loc */\n"
6771 " %s, /* gcc_jit_lvalue *lvalue */\n"
6772 " %s); /* gcc_jit_rvalue *rvalue */\n",
6773 r
.get_identifier (get_block ()),
6774 r
.get_identifier (get_loc ()),
6775 r
.get_identifier_as_lvalue (m_lvalue
),
6776 r
.get_identifier_as_rvalue (m_rvalue
));
6779 /* The implementation of class gcc::jit::recording::assignment_op. */
6781 /* Implementation of pure virtual hook recording::memento::replay_into
6782 for recording::assignment_op. */
6785 recording::assignment_op::replay_into (replayer
*r
)
6787 playback::type
*result_type
=
6788 m_lvalue
->playback_lvalue ()->get_type ();
6790 playback::rvalue
*binary_op
=
6791 r
->new_binary_op (playback_location (r
),
6794 m_lvalue
->playback_rvalue (),
6795 m_rvalue
->playback_rvalue ());
6797 playback_block (get_block ())
6798 ->add_assignment (playback_location (r
),
6799 m_lvalue
->playback_lvalue (),
6803 /* Implementation of recording::memento::make_debug_string for
6804 an assignment_op statement. */
6807 recording::assignment_op::make_debug_string ()
6809 return string::from_printf (m_ctxt
,
6811 m_lvalue
->get_debug_string (),
6812 binary_op_strings
[m_op
],
6813 m_rvalue
->get_debug_string ());
6816 /* Implementation of recording::memento::write_reproducer for
6817 assignment_op statements. */
6820 recording::assignment_op::write_reproducer (reproducer
&r
)
6822 r
.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
6823 " %s, /* gcc_jit_location *loc */\n"
6824 " %s, /* gcc_jit_lvalue *lvalue */\n"
6825 " %s, /* enum gcc_jit_binary_op op */\n"
6826 " %s); /* gcc_jit_rvalue *rvalue */\n",
6827 r
.get_identifier (get_block ()),
6828 r
.get_identifier (get_loc ()),
6829 r
.get_identifier_as_lvalue (m_lvalue
),
6830 binary_op_reproducer_strings
[m_op
],
6831 r
.get_identifier_as_rvalue (m_rvalue
));
6834 /* The implementation of class gcc::jit::recording::comment. */
6836 /* Implementation of pure virtual hook recording::memento::replay_into
6837 for recording::comment. */
6840 recording::comment::replay_into (replayer
*r
)
6842 playback_block (get_block ())
6843 ->add_comment (playback_location (r
),
6847 /* Implementation of recording::memento::make_debug_string for
6848 a comment "statement". */
6851 recording::comment::make_debug_string ()
6853 return string::from_printf (m_ctxt
,
6858 /* Implementation of recording::memento::write_reproducer for
6862 recording::comment::write_reproducer (reproducer
&r
)
6864 r
.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
6865 " %s, /* gcc_jit_location *loc */\n"
6866 " %s); /* const char *text */\n",
6867 r
.get_identifier (get_block ()),
6868 r
.get_identifier (get_loc ()),
6869 m_text
->get_debug_string ());
6872 /* The implementation of class gcc::jit::recording::conditional. */
6874 /* Implementation of pure virtual hook recording::memento::replay_into
6875 for recording::conditional. */
6878 recording::conditional::replay_into (replayer
*r
)
6880 playback_block (get_block ())
6881 ->add_conditional (playback_location (r
),
6882 m_boolval
->playback_rvalue (),
6883 playback_block (m_on_true
),
6884 playback_block (m_on_false
));
6887 /* Override the poisoned default implementation of
6888 gcc::jit::recording::statement::get_successor_blocks
6890 A conditional jump has 2 successor blocks. */
6892 vec
<recording::block
*>
6893 recording::conditional::get_successor_blocks () const
6895 vec
<block
*> result
;
6897 result
.quick_push (m_on_true
);
6898 result
.quick_push (m_on_false
);
6902 /* Implementation of recording::memento::make_debug_string for
6903 a conditional jump statement. */
6906 recording::conditional::make_debug_string ()
6909 return string::from_printf (m_ctxt
,
6910 "if (%s) goto %s; else goto %s;",
6911 m_boolval
->get_debug_string (),
6912 m_on_true
->get_debug_string (),
6913 m_on_false
->get_debug_string ());
6915 return string::from_printf (m_ctxt
,
6917 m_boolval
->get_debug_string (),
6918 m_on_true
->get_debug_string ());
6921 /* Implementation of recording::memento::write_reproducer for
6922 conditional statements. */
6925 recording::conditional::write_reproducer (reproducer
&r
)
6927 r
.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
6928 " %s, /* gcc_jit_location *loc */\n"
6929 " %s, /* gcc_jit_rvalue *boolval */\n"
6930 " %s, /* gcc_jit_block *on_true */\n"
6931 " %s); /* gcc_jit_block *on_false */\n",
6932 r
.get_identifier (get_block ()),
6933 r
.get_identifier (get_loc ()),
6934 r
.get_identifier_as_rvalue (m_boolval
),
6935 r
.get_identifier (m_on_true
),
6936 r
.get_identifier (m_on_false
));
6939 /* The implementation of class gcc::jit::recording::jump. */
6941 /* Implementation of pure virtual hook recording::memento::replay_into
6942 for recording::jump. */
6945 recording::jump::replay_into (replayer
*r
)
6947 playback_block (get_block ())
6948 ->add_jump (playback_location (r
),
6949 m_target
->playback_block ());
6952 /* Override the poisoned default implementation of
6953 gcc::jit::recording::statement::get_successor_blocks
6955 An unconditional jump has 1 successor block. */
6957 vec
<recording::block
*>
6958 recording::jump::get_successor_blocks () const
6960 vec
<block
*> result
;
6962 result
.quick_push (m_target
);
6966 /* Implementation of recording::memento::make_debug_string for
6967 a unconditional jump statement. */
6970 recording::jump::make_debug_string ()
6972 return string::from_printf (m_ctxt
,
6974 m_target
->get_debug_string ());
6977 /* Implementation of recording::memento::write_reproducer for
6981 recording::jump::write_reproducer (reproducer
&r
)
6983 r
.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
6984 " %s, /* gcc_jit_location *loc */\n"
6985 " %s); /* gcc_jit_block *target */\n",
6986 r
.get_identifier (get_block ()),
6987 r
.get_identifier (get_loc ()),
6988 r
.get_identifier (m_target
));
6991 /* The implementation of class gcc::jit::recording::return_. */
6993 /* Implementation of pure virtual hook recording::memento::replay_into
6994 for recording::return_. */
6997 recording::return_::replay_into (replayer
*r
)
6999 playback_block (get_block ())
7000 ->add_return (playback_location (r
),
7001 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
7004 /* Override the poisoned default implementation of
7005 gcc::jit::recording::statement::get_successor_blocks
7007 A return statement has no successor block. */
7009 vec
<recording::block
*>
7010 recording::return_::get_successor_blocks () const
7012 vec
<block
*> result
;
7017 /* Implementation of recording::memento::make_debug_string for
7018 a return statement (covers both those with and without rvalues). */
7021 recording::return_::make_debug_string ()
7024 return string::from_printf (m_ctxt
,
7026 m_rvalue
->get_debug_string ());
7028 return string::from_printf (m_ctxt
,
7032 /* Implementation of recording::memento::write_reproducer for
7033 return statements. */
7036 recording::return_::write_reproducer (reproducer
&r
)
7039 r
.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
7040 " %s, /* gcc_jit_location *loc */\n"
7041 " %s); /* gcc_jit_rvalue *rvalue */\n",
7042 r
.get_identifier (get_block ()),
7043 r
.get_identifier (get_loc ()),
7044 r
.get_identifier_as_rvalue (m_rvalue
));
7046 r
.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
7047 " %s); /* gcc_jit_location *loc */\n",
7048 r
.get_identifier (get_block ()),
7049 r
.get_identifier (get_loc ()));
7052 /* The implementation of class gcc::jit::recording::case_. */
7055 recording::case_::write_reproducer (reproducer
&r
)
7057 const char *id
= r
.make_identifier (this, "case");
7059 " gcc_jit_case *%s = \n"
7060 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
7061 " %s, /* gcc_jit_rvalue *min_value */\n"
7062 " %s, /* gcc_jit_rvalue *max_value */\n"
7063 " %s); /* gcc_jit_block *dest_block */\n";
7066 r
.get_identifier (get_context ()),
7067 r
.get_identifier_as_rvalue (m_min_value
),
7068 r
.get_identifier_as_rvalue (m_max_value
),
7069 r
.get_identifier (m_dest_block
));
7073 recording::case_::make_debug_string ()
7075 return string::from_printf (get_context (),
7076 "case %s ... %s: goto %s;",
7077 m_min_value
->get_debug_string (),
7078 m_max_value
->get_debug_string (),
7079 m_dest_block
->get_debug_string ());
7082 /* The implementation of class gcc::jit::recording::switch_. */
7084 /* gcc::jit::recording::switch_'s constructor. */
7086 recording::switch_::switch_ (block
*b
,
7089 block
*default_block
,
7092 : statement (b
, loc
),
7094 m_default_block (default_block
)
7096 m_cases
.reserve_exact (num_cases
);
7097 for (int i
= 0; i
< num_cases
; i
++)
7098 m_cases
.quick_push (cases
[i
]);
7101 /* Implementation of pure virtual hook recording::memento::replay_into
7102 for recording::switch_. */
7105 recording::switch_::replay_into (replayer
*r
)
7107 auto_vec
<playback::case_
> pcases
;
7109 recording::case_
*rcase
;
7110 pcases
.reserve_exact (m_cases
.length ());
7111 FOR_EACH_VEC_ELT (m_cases
, i
, rcase
)
7113 playback::case_
pcase (rcase
->get_min_value ()->playback_rvalue (),
7114 rcase
->get_max_value ()->playback_rvalue (),
7115 rcase
->get_dest_block ()->playback_block ());
7116 pcases
.safe_push (pcase
);
7118 playback_block (get_block ())
7119 ->add_switch (playback_location (r
),
7120 m_expr
->playback_rvalue (),
7121 m_default_block
->playback_block (),
7125 /* Override the poisoned default implementation of
7126 gcc::jit::recording::statement::get_successor_blocks
7128 A switch statement has (NUM_CASES + 1) successor blocks. */
7130 vec
<recording::block
*>
7131 recording::switch_::get_successor_blocks () const
7133 vec
<block
*> result
;
7134 result
.create (m_cases
.length () + 1);
7135 result
.quick_push (m_default_block
);
7138 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
7139 result
.quick_push (c
->get_dest_block ());
7143 /* Implementation of recording::memento::make_debug_string for
7144 a switch statement. */
7147 recording::switch_::make_debug_string ()
7149 auto_vec
<char> cases_str
;
7152 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
7154 size_t len
= strlen (c
->get_debug_string ());
7155 unsigned idx
= cases_str
.length ();
7156 cases_str
.safe_grow (idx
+ 1 + len
, true);
7157 cases_str
[idx
] = ' ';
7158 memcpy (&(cases_str
[idx
+ 1]),
7159 c
->get_debug_string (),
7162 cases_str
.safe_push ('\0');
7164 return string::from_printf (m_ctxt
,
7165 "switch (%s) {default: goto %s;%s}",
7166 m_expr
->get_debug_string (),
7167 m_default_block
->get_debug_string (),
7171 /* Implementation of recording::memento::write_reproducer for
7172 switch statements. */
7175 recording::switch_::write_reproducer (reproducer
&r
)
7177 r
.make_identifier (this, "switch");
7180 const char *cases_id
=
7181 r
.make_tmp_identifier ("cases_for", this);
7182 r
.write (" gcc_jit_case *%s[%i] = {\n",
7185 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
7186 r
.write (" %s,\n", r
.get_identifier (c
));
7189 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
7190 " %s, /* gcc_jit_location *loc */\n"
7191 " %s, /* gcc_jit_rvalue *expr */\n"
7192 " %s, /* gcc_jit_block *default_block */\n"
7193 " %i, /* int num_cases */\n"
7194 " %s); /* gcc_jit_case **cases */\n";
7196 r
.get_identifier (get_block ()),
7197 r
.get_identifier (get_loc ()),
7198 r
.get_identifier_as_rvalue (m_expr
),
7199 r
.get_identifier (m_default_block
),
7204 /* class asm_operand : public memento. */
7206 recording::asm_operand::asm_operand (extended_asm
*ext_asm
,
7207 string
*asm_symbolic_name
,
7209 : memento (ext_asm
->get_context ()),
7210 m_ext_asm (ext_asm
),
7211 m_asm_symbolic_name (asm_symbolic_name
),
7212 m_constraint (constraint
)
7217 recording::asm_operand::print (pretty_printer
*pp
) const
7219 if (m_asm_symbolic_name
)
7221 pp_character (pp
, '[');
7222 pp_string (pp
, m_asm_symbolic_name
->c_str ());
7223 pp_character (pp
, ']');
7226 pp_string (pp
, m_constraint
->get_debug_string ());
7227 /* Subclass will add lvalue/rvalue. */
7231 recording::asm_operand::make_debug_string ()
7235 return m_ctxt
->new_string (pp_formatted_text (&pp
), false);
7238 /* class output_asm_operand : public asm_operand. */
7241 recording::output_asm_operand::write_reproducer (reproducer
&r
)
7244 " gcc_jit_extended_asm_add_output_operand (%s, /* gcc_jit_extended_asm *ext_asm */\n"
7245 " %s, /* const char *asm_symbolic_name */\n"
7246 " %s, /* const char *constraint */\n"
7247 " %s); /* gcc_jit_lvalue *dest */\n";
7249 r
.get_identifier (m_ext_asm
),
7250 (m_asm_symbolic_name
7251 ? m_asm_symbolic_name
->get_debug_string () : "NULL"),
7252 m_constraint
->get_debug_string (),
7253 r
.get_identifier (m_dest
));
7257 recording::output_asm_operand::print (pretty_printer
*pp
) const
7259 asm_operand::print (pp
);
7260 pp_string (pp
, " (");
7261 pp_string (pp
, m_dest
->get_debug_string ());
7262 pp_string (pp
, ")");
7265 /* class input_asm_operand : public asm_operand. */
7268 recording::input_asm_operand::write_reproducer (reproducer
&r
)
7271 " gcc_jit_extended_asm_add_input_operand (%s, /* gcc_jit_extended_asm *ext_asm */\n"
7272 " %s, /* const char *asm_symbolic_name */\n"
7273 " %s, /* const char *constraint */\n"
7274 " %s); /* gcc_jit_rvalue *src */\n";
7276 r
.get_identifier (m_ext_asm
),
7277 (m_asm_symbolic_name
7278 ? m_asm_symbolic_name
->get_debug_string () : "NULL"),
7279 m_constraint
->get_debug_string (),
7280 r
.get_identifier_as_rvalue (m_src
));
7284 recording::input_asm_operand::print (pretty_printer
*pp
) const
7286 asm_operand::print (pp
);
7287 pp_string (pp
, " (");
7288 pp_string (pp
, m_src
->get_debug_string ());
7289 pp_string (pp
, ")");
7292 /* The implementation of class gcc::jit::recording::extended_asm. */
7295 recording::extended_asm::add_output_operand (const char *asm_symbolic_name
,
7296 const char *constraint
,
7299 output_asm_operand
*op
7300 = new output_asm_operand (this,
7301 new_string (asm_symbolic_name
),
7302 new_string (constraint
),
7304 m_ctxt
->record (op
);
7305 m_output_ops
.safe_push (op
);
7309 recording::extended_asm::add_input_operand (const char *asm_symbolic_name
,
7310 const char *constraint
,
7313 input_asm_operand
*op
7314 = new input_asm_operand (this,
7315 new_string (asm_symbolic_name
),
7316 new_string (constraint
),
7318 m_ctxt
->record (op
);
7319 m_input_ops
.safe_push (op
);
7323 recording::extended_asm::add_clobber (const char *victim
)
7325 m_clobbers
.safe_push (new_string (victim
));
7328 /* Implementation of recording::memento::replay_into
7329 for recording::extended_asm. */
7332 recording::extended_asm::replay_into (replayer
*r
)
7334 auto_vec
<playback::asm_operand
> playback_output_ops
;
7335 auto_vec
<playback::asm_operand
> playback_input_ops
;
7336 auto_vec
<const char *> playback_clobbers
;
7337 auto_vec
<playback::block
*> playback_goto_blocks
;
7339 /* Populate outputs. */
7341 output_asm_operand
*rec_asm_op
;
7343 FOR_EACH_VEC_ELT (m_output_ops
, i
, rec_asm_op
)
7345 playback::asm_operand playback_asm_op
7346 (rec_asm_op
->get_symbolic_name (),
7347 rec_asm_op
->get_constraint (),
7348 rec_asm_op
->get_lvalue ()->playback_lvalue ()->as_tree ());
7349 playback_output_ops
.safe_push (playback_asm_op
);
7353 /* Populate inputs. */
7355 input_asm_operand
*rec_asm_op
;
7357 FOR_EACH_VEC_ELT (m_input_ops
, i
, rec_asm_op
)
7359 playback::asm_operand playback_asm_op
7360 (rec_asm_op
->get_symbolic_name (),
7361 rec_asm_op
->get_constraint (),
7362 rec_asm_op
->get_rvalue ()->playback_rvalue ()->as_tree ());
7363 playback_input_ops
.safe_push (playback_asm_op
);
7367 /* Populate clobbers. */
7369 string
*rec_clobber
;
7371 FOR_EACH_VEC_ELT (m_clobbers
, i
, rec_clobber
)
7372 playback_clobbers
.safe_push (rec_clobber
->c_str ());
7375 /* Populate playback blocks if an "asm goto". */
7376 maybe_populate_playback_blocks (&playback_goto_blocks
);
7378 playback_block (get_block ())
7379 ->add_extended_asm (playback_location (r
),
7380 m_asm_template
->c_str (),
7381 m_is_volatile
, m_is_inline
,
7382 &playback_output_ops
,
7383 &playback_input_ops
,
7385 &playback_goto_blocks
);
7388 /* Implementation of recording::memento::make_debug_string for
7389 an extended_asm "statement". */
7392 recording::extended_asm::make_debug_string ()
7395 pp_string (&pp
, "asm ");
7397 pp_string (&pp
, "volatile ");
7399 pp_string (&pp
, "inline ");
7401 pp_string (&pp
, "goto ");
7402 pp_character (&pp
, '(');
7403 pp_string (&pp
, m_asm_template
->get_debug_string ());
7404 pp_string (&pp
, " : ");
7407 output_asm_operand
*asm_op
;
7408 FOR_EACH_VEC_ELT (m_output_ops
, i
, asm_op
)
7411 pp_string (&pp
, ", ");
7412 asm_op
->print (&pp
);
7415 pp_string (&pp
, " : ");
7417 input_asm_operand
*asm_op
;
7418 FOR_EACH_VEC_ELT (m_input_ops
, i
, asm_op
)
7421 pp_string (&pp
, ", ");
7422 asm_op
->print (&pp
);
7425 pp_string (&pp
, " : ");
7426 string
*rec_clobber
;
7427 FOR_EACH_VEC_ELT (m_clobbers
, i
, rec_clobber
)
7430 pp_string (&pp
, ", ");
7431 pp_string (&pp
, rec_clobber
->get_debug_string ());
7433 maybe_print_gotos (&pp
);
7434 pp_character (&pp
, ')');
7435 return new_string (pp_formatted_text (&pp
));
7439 recording::extended_asm::write_flags (reproducer
&r
)
7442 r
.write (" gcc_jit_extended_asm_set_volatile_flag (%s, 1);\n",
7443 r
.get_identifier (this));
7445 r
.write (" gcc_jit_extended_asm_set_inline_flag (%s, 1);\n",
7446 r
.get_identifier (this));
7450 recording::extended_asm::write_clobbers (reproducer
&r
)
7454 FOR_EACH_VEC_ELT (m_clobbers
, i
, clobber
)
7455 r
.write (" gcc_jit_extended_asm_add_clobber (%s, %s);\n",
7456 r
.get_identifier (this),
7457 clobber
->get_debug_string ());
7460 /* Implementation of recording::memento::write_reproducer for
7461 extended_asm_simple. */
7464 recording::extended_asm_simple::write_reproducer (reproducer
&r
)
7466 const char *id
= r
.make_identifier (this, "extended_asm");
7467 r
.write (" gcc_jit_extended_asm *%s =\n"
7468 " gcc_jit_block_add_extended_asm (%s, /*gcc_jit_block *block */\n"
7469 " %s, /* gcc_jit_location *loc */\n"
7470 " %s); /* const char *asm_template */\n",
7472 r
.get_identifier (get_block ()),
7473 r
.get_identifier (get_loc ()),
7474 m_asm_template
->get_debug_string ());
7480 recording::extended_asm::
7481 maybe_populate_playback_blocks (auto_vec
<playback::block
*> *)
7483 /* Do nothing; not an "asm goto". */
7486 /* The implementation of class gcc::jit::recording::extended_asm_goto. */
7488 /* recording::extended_asm_goto's ctor. */
7490 recording::extended_asm_goto::extended_asm_goto (block
*b
,
7492 string
*asm_template
,
7493 int num_goto_blocks
,
7494 block
**goto_blocks
,
7495 block
*fallthrough_block
)
7496 : extended_asm (b
, loc
, asm_template
),
7497 m_goto_blocks (num_goto_blocks
),
7498 m_fallthrough_block (fallthrough_block
)
7500 for (int i
= 0; i
< num_goto_blocks
; i
++)
7501 m_goto_blocks
.quick_push (goto_blocks
[i
]);
7504 /* Implementation of recording::memento::replay_into
7505 for recording::extended_asm_goto. */
7508 recording::extended_asm_goto::replay_into (replayer
*r
)
7510 /* Chain up to base class impl. */
7511 recording::extended_asm::replay_into (r
);
7513 /* ...and potentially add a goto for the fallthrough. */
7514 if (m_fallthrough_block
)
7515 playback_block (get_block ())
7516 ->add_jump (playback_location (r
),
7517 m_fallthrough_block
->playback_block ());
7520 /* Implementation of recording::memento::write_reproducer for
7521 extended_asm_goto. */
7524 recording::extended_asm_goto::write_reproducer (reproducer
&r
)
7526 const char *id
= r
.make_identifier (this, "extended_asm");
7527 const char *blocks_id
= r
.make_tmp_identifier ("blocks_for", this);
7528 r
.write (" gcc_jit_block *%s[%i] = {\n",
7530 m_goto_blocks
.length ());
7533 FOR_EACH_VEC_ELT (m_goto_blocks
, i
, b
)
7534 r
.write (" %s,\n", r
.get_identifier (b
));
7536 r
.write (" gcc_jit_extended_asm *%s =\n"
7537 " gcc_jit_block_end_with_extended_asm_goto (%s, /*gcc_jit_block *block */\n"
7538 " %s, /* gcc_jit_location *loc */\n"
7539 " %s, /* const char *asm_template */\n"
7540 " %i, /* int num_goto_blocks */\n"
7541 " %s, /* gcc_jit_block **goto_blocks */\n"
7542 " %s); /* gcc_jit_block *fallthrough_block */\n",
7544 r
.get_identifier (get_block ()),
7545 r
.get_identifier (get_loc ()),
7546 m_asm_template
->get_debug_string (),
7547 m_goto_blocks
.length (),
7549 (m_fallthrough_block
7550 ? r
.get_identifier (m_fallthrough_block
)
7556 /* Override the poisoned default implementation of
7557 gcc::jit::recording::statement::get_successor_blocks
7559 An extended_asm_goto can jump to the m_goto_blocks, and to
7560 the (optional) m_fallthrough_block. */
7562 vec
<recording::block
*>
7563 recording::extended_asm_goto::get_successor_blocks () const
7565 vec
<block
*> result
;
7566 result
.create (m_goto_blocks
.length () + 1);
7567 if (m_fallthrough_block
)
7568 result
.quick_push (m_fallthrough_block
);
7569 result
.splice (m_goto_blocks
);
7573 /* Vfunc for use by recording::extended_asm::make_debug_string. */
7576 recording::extended_asm_goto::maybe_print_gotos (pretty_printer
*pp
) const
7578 pp_string (pp
, " : ");
7581 FOR_EACH_VEC_ELT (m_goto_blocks
, i
, b
)
7584 pp_string (pp
, ", ");
7585 pp_string (pp
, b
->get_debug_string ());
7587 /* Non-C syntax here. */
7588 if (m_fallthrough_block
)
7589 pp_printf (pp
, " [fallthrough: %s]",
7590 m_fallthrough_block
->get_debug_string ());
7593 /* Vfunc for use by recording::extended_asm::replay_into. */
7596 recording::extended_asm_goto::
7597 maybe_populate_playback_blocks (auto_vec
<playback::block
*> *out
)
7601 FOR_EACH_VEC_ELT (m_goto_blocks
, i
, b
)
7602 out
->safe_push (b
->playback_block ());
7605 /* class top_level_asm : public memento. */
7607 recording::top_level_asm::top_level_asm (context
*ctxt
,
7612 m_asm_stmts (asm_stmts
)
7616 /* Implementation of recording::memento::replay_into for top-level asm. */
7619 recording::top_level_asm::replay_into (replayer
*r
)
7621 r
->add_top_level_asm (m_asm_stmts
->c_str ());
7624 /* Implementation of recording::memento::make_debug_string for
7628 recording::top_level_asm::make_debug_string ()
7630 return string::from_printf (m_ctxt
, "asm (%s)",
7631 m_asm_stmts
->get_debug_string ());
7634 /* Override the default implementation of
7635 recording::memento::write_to_dump.
7636 Don't indent the string. */
7639 recording::top_level_asm::write_to_dump (dump
&d
)
7641 d
.write ("%s;\n", get_debug_string ());
7644 /* Implementation of recording::memento::write_reproducer for top-level asm. */
7647 recording::top_level_asm::write_reproducer (reproducer
&r
)
7649 r
.write (" gcc_jit_context_add_top_level_asm (%s, /* gcc_jit_context *ctxt */\n"
7650 " %s, /* gcc_jit_location *loc */\n"
7651 " %s); /* const char *asm_stmts */\n",
7652 r
.get_identifier (get_context ()),
7653 r
.get_identifier (m_loc
),
7654 m_asm_stmts
->get_debug_string ());
7658 recording::global_init_rvalue::replay_into (replayer
*r
)
7660 r
->global_set_init_rvalue (m_variable
->playback_lvalue (),
7661 m_init
->playback_rvalue ());
7665 recording::global_init_rvalue::write_reproducer (reproducer
&r
)
7668 " gcc_jit_global_set_initializer_rvalue (%s, /* lvalue *global */\n"
7669 " %s);/* rvalue *init */\n",
7670 r
.get_identifier (m_variable
),
7671 r
.get_identifier_as_rvalue (m_init
));
7675 recording::global_init_rvalue::write_to_dump (dump
&d
)
7677 d
.write ("%s;\n", get_debug_string ());
7681 recording::global_init_rvalue::make_debug_string ()
7683 return string::from_printf (m_ctxt
, "%s = %s",
7684 m_variable
->get_debug_string (),
7685 m_init
->get_debug_string ());
7694 /* Strips type down to array, vector or base type (whichever comes first)
7696 Also saves 'ptr_depth' and sets 'flags' for array or vector types. */
7699 strip_and_count (recording::type
*type_to_strip
,
7703 recording::type
*t
= type_to_strip
;
7708 gcc_unreachable (); /* Should only happen on corrupt input. */
7710 recording::type
*pointed_to_type
= t
->is_pointer ();
7711 if (pointed_to_type
!= NULL
)
7714 t
= pointed_to_type
;
7718 recording::type
*array_el
= t
->is_array ();
7719 if (array_el
!= NULL
)
7721 flags
= STRIP_FLAG_ARR
;
7725 recording::type
*vec
= t
->dyn_cast_vector_type ();
7728 flags
= STRIP_FLAG_VEC
;
7732 /* unqualified () returns 'this' on base types. */
7733 recording::type
*next
= t
->unqualified ();
7744 /* Strip qualifiers and count pointer depth, returning true
7745 if the types' base type and pointer depth are
7746 the same, otherwise false.
7748 For array and vector types the number of element also
7751 Do not call this directly. Call 'types_kinda_same'. */
7753 types_kinda_same_internal (recording::type
*a
, recording::type
*b
)
7755 int ptr_depth_a
= 0;
7756 int ptr_depth_b
= 0;
7757 recording::type
*base_a
;
7758 recording::type
*base_b
;
7760 strip_flags flags_a
= STRIP_FLAG_NONE
;
7761 strip_flags flags_b
= STRIP_FLAG_NONE
;
7763 base_a
= strip_and_count (a
, ptr_depth_a
, flags_a
);
7764 base_b
= strip_and_count (b
, ptr_depth_b
, flags_b
);
7766 if (ptr_depth_a
!= ptr_depth_b
)
7769 if (base_a
== base_b
)
7772 if (flags_a
!= flags_b
)
7775 /* If the "base type" is an array or vector we might need to
7777 if (flags_a
== STRIP_FLAG_ARR
)
7779 recording::array_type
*arr_a
=
7780 static_cast<recording::array_type
*> (base_a
);
7781 recording::array_type
*arr_b
=
7782 static_cast<recording::array_type
*> (base_b
);
7784 if (arr_a
->num_elements () != arr_b
->num_elements ())
7787 /* is_array returns element type. */
7788 recording::type
*el_a
= arr_a
->is_array ();
7789 recording::type
*el_b
= arr_b
->is_array ();
7794 return types_kinda_same_internal (el_a
, el_b
);
7796 if (flags_a
== STRIP_FLAG_VEC
)
7798 recording::vector_type
*arr_a
=
7799 static_cast<recording::vector_type
*> (base_a
);
7800 recording::vector_type
*arr_b
=
7801 static_cast<recording::vector_type
*> (base_b
);
7803 if (arr_a
->get_num_units () != arr_b
->get_num_units ())
7806 recording::type
*el_a
= arr_a
->get_element_type ();
7807 recording::type
*el_b
= arr_b
->get_element_type ();
7812 return types_kinda_same_internal (el_a
, el_b
);
7818 } // namespace gcc::jit