1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2020 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GCC is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
25 #include "pretty-print.h"
30 #include "jit-builtins.h"
31 #include "jit-recording.h"
32 #include "jit-playback.h"
39 dump::dump (recording::context
&ctxt
,
41 bool update_locations
)
43 m_filename (filename
),
44 m_update_locations (update_locations
),
48 m_file
= fopen (filename
, "w");
51 "error opening dump file %s for writing: %s",
60 int err
= fclose (m_file
);
62 m_ctxt
.add_error (NULL
,
63 "error closing dump file %s: %s",
69 /* Write the given message to the dump, using printf-formatting
70 conventions, updating the line/column within the dump.
72 Emit an error on the context if a failure occurs. */
75 dump::write (const char *fmt
, ...)
81 /* If there was an error opening the file, we've already reported it.
82 Don't attempt further work. */
87 len
= vasprintf (&buf
, fmt
, ap
);
90 if (buf
== NULL
|| len
< 0)
92 m_ctxt
.add_error (NULL
, "malloc failure writing to dumpfile %s",
97 if (fwrite (buf
, strlen (buf
), 1, m_file
) != 1)
98 m_ctxt
.add_error (NULL
, "error writing to dump file %s",
101 /* Flush after each line, to ease debugging crashes. */
104 /* Update line/column: */
105 for (const char *ptr
= buf
; *ptr
; ptr
++)
119 /* Construct a gcc::jit::recording::location instance for the current
120 location within the dump. */
122 recording::location
*
123 dump::make_location () const
125 return m_ctxt
.new_location (m_filename
, m_line
, m_column
,
126 /* We need to flag such locations as *not*
127 created by the user, so that
128 reproducer::get_identifier can cope with
129 them appearing *after* the memento that
134 /* A collection of allocations, all of which can be released together, to
135 avoid needing to track and release them individually. */
143 xstrdup_printf (const char *, ...)
144 ATTRIBUTE_RETURNS_NONNULL
148 xstrdup_printf_va (const char *, va_list ap
)
149 ATTRIBUTE_RETURNS_NONNULL
153 auto_vec
<void *> m_buffers
;
156 /* allocator's destructor. Call "free" on all of the allocations. */
158 allocator::~allocator ()
162 FOR_EACH_VEC_ELT (m_buffers
, i
, buffer
)
166 /* Formatted printing, allocating to a buffer (or exiting the process if
167 the allocation fails).
169 The buffer exists until the allocator is cleaned up, and is freed at
170 that point, so the caller doesn't need to track the result. */
173 allocator::xstrdup_printf (const char *fmt
, ...)
178 result
= xstrdup_printf_va (fmt
, ap
);
183 /* Formatted printing, allocating to a buffer (or exiting the process if
184 the allocation fails).
186 The buffer exists until the allocator is cleaned up, and is freed at
187 that point, so the caller doesn't need to track the result. */
190 allocator::xstrdup_printf_va (const char *fmt
, va_list ap
)
192 char *result
= xvasprintf (fmt
, ap
);
193 m_buffers
.safe_push (result
);
197 /* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
198 implementing gcc_jit_context_dump_reproducer_to_file. */
200 class reproducer
: public dump
203 reproducer (recording::context
&ctxt
,
204 const char *filename
);
207 write_params (const vec
<recording::context
*> &contexts
);
210 write_args (const vec
<recording::context
*> &contexts
);
213 make_identifier (recording::memento
*m
, const char *prefix
);
216 make_tmp_identifier (const char *prefix
, recording::memento
*m
);
219 get_identifier (recording::context
*ctxt
);
222 get_identifier (recording::memento
*m
);
225 get_identifier_as_rvalue (recording::rvalue
*m
);
228 get_identifier_as_lvalue (recording::lvalue
*m
);
231 get_identifier_as_type (recording::type
*m
);
234 xstrdup_printf (const char *, ...)
235 ATTRIBUTE_RETURNS_NONNULL
239 const char * ensure_identifier_is_unique (const char *candidate
, void *ptr
);
242 hash_map
<recording::memento
*, const char *> m_map_memento_to_identifier
;
244 struct hash_traits
: public string_hash
246 static void remove (const char *) {}
248 hash_set
<const char *, false, hash_traits
> m_set_identifiers
;
249 allocator m_allocator
;
252 /* gcc::jit::reproducer's constructor. */
254 reproducer::reproducer (recording::context
&ctxt
,
255 const char *filename
) :
256 dump (ctxt
, filename
, 0),
257 m_map_memento_to_identifier (),
258 m_set_identifiers (),
263 /* Write out a list of contexts as a set of parameters within a
264 C function declaration. */
267 reproducer::write_params (const vec
<recording::context
*> &contexts
)
270 recording::context
*ctxt
;
271 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
273 write ("gcc_jit_context *%s",
274 get_identifier (ctxt
));
275 if (i
< contexts
.length () - 1)
281 /* Write out a list of contexts as a set of arguments within a call
285 reproducer::write_args (const vec
<recording::context
*> &contexts
)
288 recording::context
*ctxt
;
289 FOR_EACH_VEC_ELT (contexts
, i
, ctxt
)
292 get_identifier (ctxt
));
293 if (i
< contexts
.length () - 1)
299 /* Ensure that STR is a valid C identifier by overwriting
300 any invalid chars in-place with underscores.
302 This doesn't special-case the first character. */
305 convert_to_identifier (char *str
)
307 for (char *p
= str
; *p
; p
++)
312 /* Given CANDIDATE, a possible C identifier for use in a reproducer,
313 ensure that it is unique within the generated source file by
314 appending PTR to it if necessary. Return the resulting string.
316 The reproducer will eventually clean up the buffer in its dtor. */
319 reproducer::ensure_identifier_is_unique (const char *candidate
, void *ptr
)
321 if (m_set_identifiers
.contains (candidate
))
322 candidate
= m_allocator
.xstrdup_printf ("%s_%p", candidate
, ptr
);
323 gcc_assert (!m_set_identifiers
.contains (candidate
));
324 m_set_identifiers
.add (candidate
);
328 /* Generate a C identifier for the given memento, associating the generated
329 buffer with the memento (for future calls to get_identifier et al).
331 The reproducer will eventually clean up the buffer in its dtor. */
333 reproducer::make_identifier (recording::memento
*m
, const char *prefix
)
336 if (strlen (m
->get_debug_string ()) < 100)
338 char *buf
= m_allocator
.xstrdup_printf ("%s_%s",
340 m
->get_debug_string ());
341 convert_to_identifier (buf
);
345 result
= m_allocator
.xstrdup_printf ("%s_%p",
347 result
= ensure_identifier_is_unique (result
, m
);
348 m_map_memento_to_identifier
.put (m
, result
);
352 /* Generate a C identifier for a temporary variable.
353 The reproducer will eventually clean up the buffer in its dtor. */
356 reproducer::make_tmp_identifier (const char *prefix
, recording::memento
*m
)
358 return m_allocator
.xstrdup_printf ("%s_%s",
359 prefix
, get_identifier (m
));
362 /* Generate a C identifier for the given context.
363 The reproducer will eventually clean up the buffer in its dtor. */
366 reproducer::get_identifier (recording::context
*ctxt
)
368 return m_allocator
.xstrdup_printf ("ctxt_%p",
372 /* Locate the C identifier for the given memento, which is assumed to
373 have already been created via make_identifier. */
376 reproducer::get_identifier (recording::memento
*m
)
381 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
382 and hence these locations appear in the context's memento list
383 out-of-order: they appear in the context's memento list *after*
384 the memento that refers to them. For this case, it's simplest to
385 pretend that they're NULL when writing out the code to recreate the
386 memento that uses them. */
387 if (recording::location
*loc
= m
->dyn_cast_location ())
388 if (!loc
->created_by_user ())
391 const char **slot
= m_map_memento_to_identifier
.get (m
);
394 get_context ().add_error (NULL
,
395 "unable to find identifier for %p: %s",
397 m
->get_debug_string ());
403 /* Locate the C identifier for the given rvalue, wrapping it within
404 a gcc_*_as_rvalue upcast if necessary. */
407 reproducer::get_identifier_as_rvalue (recording::rvalue
*m
)
409 return m
->access_as_rvalue (*this);
412 /* Locate the C identifier for the given lvalue, wrapping it within
413 a gcc_*_as_lvalue upcast if necessary. */
416 reproducer::get_identifier_as_lvalue (recording::lvalue
*m
)
418 return m
->access_as_lvalue (*this);
421 /* Locate the C identifier for the given type, wrapping it within
422 a gcc_*_as_type upcast if necessary. */
425 reproducer::get_identifier_as_type (recording::type
*m
)
427 return m
->access_as_type (*this);
430 /* Formatted printing, allocating to a buffer (or exiting the process if
431 the allocation fails).
433 The buffer exists until the allocator is cleaned up, and is freed at
434 that point, so the caller doesn't need to track the result.
436 Note that we can't use ggc_printf since we're not within the compiler
437 proper (when within gcc_jit_context_dump_reproducer_to_file). */
440 reproducer::xstrdup_printf (const char *fmt
, ...)
445 result
= m_allocator
.xstrdup_printf_va (fmt
, ap
);
450 /* A helper class for implementing make_debug_string, for building
451 a temporary string from a vec of rvalues. */
453 class comma_separated_string
456 comma_separated_string (const auto_vec
<recording::rvalue
*> &rvalues
,
457 enum recording::precedence prec
);
458 ~comma_separated_string ();
460 const char *as_char_ptr () const { return m_buf
; }
466 /* comma_separated_string's ctor
469 comma_separated_string::comma_separated_string
470 (const auto_vec
<recording::rvalue
*> &rvalues
,
471 enum recording::precedence prec
)
474 /* Calculate length of said buffer. */
475 size_t sz
= 1; /* nil terminator */
476 for (unsigned i
= 0; i
< rvalues
.length (); i
++)
478 sz
+= strlen (rvalues
[i
]->get_debug_string_parens (prec
));
479 sz
+= 2; /* ", " separator */
482 /* Now allocate and populate the buffer. */
483 m_buf
= new char[sz
];
486 for (unsigned i
= 0; i
< rvalues
.length (); i
++)
488 strcpy (m_buf
+ len
, rvalues
[i
]->get_debug_string_parens (prec
));
489 len
+= strlen (rvalues
[i
]->get_debug_string_parens (prec
));
490 if (i
+ 1 < rvalues
.length ())
492 strcpy (m_buf
+ len
, ", ");
499 /* comma_separated_string's dtor. */
501 comma_separated_string::~comma_separated_string ()
506 /**********************************************************************
508 **********************************************************************/
510 /* Get the playback::location for the given recording::location,
511 handling a NULL input with a NULL output. */
514 recording::playback_location (replayer
*r
, recording::location
*loc
)
517 return loc
->playback_location (r
);
522 /* Get a const char * for the given recording::string
523 handling a NULL input with a NULL output. */
526 recording::playback_string (recording::string
*str
)
529 return str
->c_str ();
534 /* Get the playback::block for the given recording::block,
535 handling a NULL input with a NULL output. */
538 recording::playback_block (recording::block
*b
)
541 return b
->playback_block ();
546 /* Methods of cc::jit::recording::context. */
548 /* The constructor for gcc::jit::recording::context, used by
549 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
551 recording::context::context (context
*parent_ctxt
)
553 m_parent_ctxt (parent_ctxt
),
554 m_toplevel_ctxt (m_parent_ctxt
? m_parent_ctxt
->m_toplevel_ctxt
: this),
557 m_first_error_str (NULL
),
558 m_owns_first_error_str (false),
559 m_last_error_str (NULL
),
560 m_owns_last_error_str (false),
566 m_builtins_manager(NULL
)
570 /* Inherit options from parent. */
572 i
< sizeof (m_str_options
) / sizeof (m_str_options
[0]);
575 const char *parent_opt
= parent_ctxt
->m_str_options
[i
];
576 m_str_options
[i
] = parent_opt
? xstrdup (parent_opt
) : NULL
;
578 memcpy (m_int_options
,
579 parent_ctxt
->m_int_options
,
580 sizeof (m_int_options
));
581 memcpy (m_bool_options
,
582 parent_ctxt
->m_bool_options
,
583 sizeof (m_bool_options
));
584 memcpy (m_inner_bool_options
,
585 parent_ctxt
->m_inner_bool_options
,
586 sizeof (m_inner_bool_options
));
587 set_logger (parent_ctxt
->get_logger ());
591 memset (m_str_options
, 0, sizeof (m_str_options
));
592 memset (m_int_options
, 0, sizeof (m_int_options
));
593 memset (m_bool_options
, 0, sizeof (m_bool_options
));
594 memset (m_inner_bool_options
, 0, sizeof (m_inner_bool_options
));
597 memset (m_basic_types
, 0, sizeof (m_basic_types
));
600 /* The destructor for gcc::jit::recording::context, implicitly used by
601 gcc_jit_context_release. */
603 recording::context::~context ()
605 JIT_LOG_SCOPE (get_logger ());
608 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
613 for (i
= 0; i
< GCC_JIT_NUM_STR_OPTIONS
; ++i
)
614 free (m_str_options
[i
]);
617 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
619 FOR_EACH_VEC_ELT (m_driver_options
, i
, optname
)
622 if (m_builtins_manager
)
623 delete m_builtins_manager
;
625 if (m_owns_first_error_str
)
626 free (m_first_error_str
);
628 if (m_owns_last_error_str
)
629 if (m_last_error_str
!= m_first_error_str
)
630 free (m_last_error_str
);
633 /* Add the given mememto to the list of those tracked by this
634 gcc::jit::recording::context, so that e.g. it can be deleted
635 when this context is released. */
638 recording::context::record (memento
*m
)
642 m_mementos
.safe_push (m
);
645 /* Replay this context (and any parents) into the given replayer. */
648 recording::context::replay_into (replayer
*r
)
650 JIT_LOG_SCOPE (get_logger ());
654 /* If we have a parent context, we must replay it. This will
655 recursively walk backwards up the historical tree, then replay things
656 forwards "in historical order", starting with the ultimate parent
657 context, until we reach the "this" context.
659 Note that we fully replay the parent, then fully replay the child,
660 which means that inter-context references can only exist from child
661 to parent, not the other way around.
663 All of this replaying is suboptimal - it would be better to do the
664 work for the parent context *once*, rather than replaying the parent
665 every time we replay each child. However, fixing this requires deep
666 surgery to lifetime-management: we'd need every context family tree
667 to have its own GC heap, and to initialize the GCC code to use that
668 heap (with a mutex on such a heap). */
670 m_parent_ctxt
->replay_into (r
);
672 if (r
->errors_occurred ())
675 /* Replay this context's saved operations into r. */
676 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
678 /* Disabled low-level debugging, here if we need it: print what
680 Note that the calls to get_debug_string might lead to more
681 mementos being created for the strings.
682 This can also be used to exercise the debug_string
685 printf ("context %p replaying (%p): %s\n",
686 (void *)this, (void *)m
, m
->get_debug_string ());
690 if (r
->errors_occurred ())
695 /* During a playback, we associate objects from the recording with
696 their counterparts during this playback.
698 For simplicity, we store this within the recording objects.
700 The following method cleans away these associations, to ensure that
701 we never have out-of-date associations lingering on subsequent
702 playbacks (the objects pointed to are GC-managed, but the
703 recording objects don't own refs to them). */
706 recording::context::disassociate_from_playback ()
708 JIT_LOG_SCOPE (get_logger ());
713 m_parent_ctxt
->disassociate_from_playback ();
715 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
717 m
->set_playback_obj (NULL
);
721 /* Create a recording::string instance and add it to this context's list
724 This creates a fresh copy of the given 0-terminated buffer. */
727 recording::context::new_string (const char *text
)
732 recording::string
*result
= new string (this, text
);
737 /* Create a recording::location instance and add it to this context's
740 Implements the post-error-checking part of
741 gcc_jit_context_new_location. */
743 recording::location
*
744 recording::context::new_location (const char *filename
,
747 bool created_by_user
)
749 recording::location
*result
=
750 new recording::location (this,
751 new_string (filename
),
758 /* If we haven't seen this enum value yet, create a recording::type
759 instance and add it to this context's list of mementos.
761 If we have seen it before, reuse our cached value, so that repeated
762 calls on the context give the same object.
764 If we have a parent context, the cache is within the ultimate
767 Implements the post-error-checking part of
768 gcc_jit_context_get_type. */
771 recording::context::get_type (enum gcc_jit_types kind
)
773 if (!m_basic_types
[kind
])
776 m_basic_types
[kind
] = m_parent_ctxt
->get_type (kind
);
779 recording::type
*result
= new memento_of_get_type (this, kind
);
781 m_basic_types
[kind
] = result
;
785 return m_basic_types
[kind
];
788 /* Get a recording::type instance for the given size and signedness.
789 This is implemented in terms of recording::context::get_type
792 Implements the post-error-checking part of
793 gcc_jit_context_get_int_type. */
796 recording::context::get_int_type (int num_bytes
, int is_signed
)
798 /* We can't use a switch here since some of the values are macros affected
799 by options; e.g. i386.h has
800 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
801 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
802 are in bits, rather than bytes.
804 const int num_bits
= num_bytes
* 8;
805 if (num_bits
== INT_TYPE_SIZE
)
806 return get_type (is_signed
808 : GCC_JIT_TYPE_UNSIGNED_INT
);
809 if (num_bits
== CHAR_TYPE_SIZE
)
810 return get_type (is_signed
811 ? GCC_JIT_TYPE_SIGNED_CHAR
812 : GCC_JIT_TYPE_UNSIGNED_CHAR
);
813 if (num_bits
== SHORT_TYPE_SIZE
)
814 return get_type (is_signed
816 : GCC_JIT_TYPE_UNSIGNED_SHORT
);
817 if (num_bits
== LONG_TYPE_SIZE
)
818 return get_type (is_signed
820 : GCC_JIT_TYPE_UNSIGNED_LONG
);
821 if (num_bits
== LONG_LONG_TYPE_SIZE
)
822 return get_type (is_signed
823 ? GCC_JIT_TYPE_LONG_LONG
824 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
826 /* Some other size, not corresponding to the C int types. */
827 /* To be written: support arbitrary other sizes, sharing by
828 memoizing at the recording::context level? */
832 /* Create a recording::type instance and add it to this context's list
835 Implements the post-error-checking part of
836 gcc_jit_context_new_array_type. */
839 recording::context::new_array_type (recording::location
*loc
,
840 recording::type
*element_type
,
843 if (struct_
*s
= element_type
->dyn_cast_struct ())
844 if (!s
->get_fields ())
847 "cannot create an array of type %s"
848 " until the fields have been set",
849 s
->get_name ()->c_str ());
852 recording::type
*result
=
853 new recording::array_type (this, loc
, element_type
, num_elements
);
858 /* Create a recording::field instance and add it to this context's list
861 Implements the post-error-checking part of
862 gcc_jit_context_new_field. */
865 recording::context::new_field (recording::location
*loc
,
866 recording::type
*type
,
869 recording::field
*result
=
870 new recording::field (this, loc
, type
, new_string (name
));
875 /* Create a recording::bitfield instance and add it to this context's list
878 Implements the post-error-checking part of
879 gcc_jit_context_new_bitfield. */
882 recording::context::new_bitfield (recording::location
*loc
,
883 recording::type
*type
,
887 recording::field
*result
=
888 new recording::bitfield (this, loc
, type
, width
, new_string (name
));
893 /* Create a recording::struct_ instance and add it to this context's
894 list of mementos and list of compound types.
896 Implements the post-error-checking part of
897 gcc_jit_context_new_struct_type. */
900 recording::context::new_struct_type (recording::location
*loc
,
903 recording::struct_
*result
= new struct_ (this, loc
, new_string (name
));
905 m_compound_types
.safe_push (result
);
909 /* Create a recording::union_ instance and add it to this context's
910 list of mementos and list of compound types.
912 Implements the first post-error-checking part of
913 gcc_jit_context_new_union_type. */
916 recording::context::new_union_type (recording::location
*loc
,
919 recording::union_
*result
= new union_ (this, loc
, new_string (name
));
921 m_compound_types
.safe_push (result
);
925 /* Create a recording::function_type instance and add it to this context's
928 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
930 recording::function_type
*
931 recording::context::new_function_type (recording::type
*return_type
,
933 recording::type
**param_types
,
936 recording::function_type
*fn_type
937 = new function_type (this,
946 /* Create a recording::type instance and add it to this context's list
949 Implements the post-error-checking part of
950 gcc_jit_context_new_function_ptr_type. */
953 recording::context::new_function_ptr_type (recording::location
*, /* unused loc */
954 recording::type
*return_type
,
956 recording::type
**param_types
,
959 recording::function_type
*fn_type
960 = new_function_type (return_type
,
965 /* Return a pointer-type to the function type. */
966 return fn_type
->get_pointer ();
969 /* Create a recording::param instance and add it to this context's list
972 Implements the post-error-checking part of
973 gcc_jit_context_new_param. */
976 recording::context::new_param (recording::location
*loc
,
977 recording::type
*type
,
980 recording::param
*result
= new recording::param (this, loc
, type
, new_string (name
));
985 /* Create a recording::function instance and add it to this context's list
986 of mementos and list of functions.
988 Implements the post-error-checking part of
989 gcc_jit_context_new_function. */
991 recording::function
*
992 recording::context::new_function (recording::location
*loc
,
993 enum gcc_jit_function_kind kind
,
994 recording::type
*return_type
,
997 recording::param
**params
,
999 enum built_in_function builtin_id
)
1001 recording::function
*result
=
1002 new recording::function (this,
1003 loc
, kind
, return_type
,
1005 num_params
, params
, is_variadic
,
1008 m_functions
.safe_push (result
);
1013 /* Locate the builtins_manager (if any) for this family of contexts,
1014 creating it if it doesn't exist already.
1016 All of the recording contexts in a family share one builtins_manager:
1017 if we have a child context, follow the parent links to get the
1018 ultimate ancestor context, and look for it/store it there. */
1021 recording::context::get_builtins_manager ()
1024 return m_parent_ctxt
->get_builtins_manager ();
1026 if (!m_builtins_manager
)
1027 m_builtins_manager
= new builtins_manager (this);
1029 return m_builtins_manager
;
1032 /* Get a recording::function instance, which is lazily-created and added
1033 to the context's lists of mementos.
1035 Implements the post-error-checking part of
1036 gcc_jit_context_get_builtin_function. */
1038 recording::function
*
1039 recording::context::get_builtin_function (const char *name
)
1041 builtins_manager
*bm
= get_builtins_manager ();
1042 return bm
->get_builtin_function (name
);
1045 /* Create a recording::global instance and add it to this context's list
1048 Implements the post-error-checking part of
1049 gcc_jit_context_new_global. */
1052 recording::context::new_global (recording::location
*loc
,
1053 enum gcc_jit_global_kind kind
,
1054 recording::type
*type
,
1057 recording::global
*result
=
1058 new recording::global (this, loc
, kind
, type
, new_string (name
));
1060 m_globals
.safe_push (result
);
1065 /* Create a recording::memento_of_new_string_literal instance and add it
1066 to this context's list of mementos.
1068 Implements the post-error-checking part of
1069 gcc_jit_context_new_string_literal. */
1072 recording::context::new_string_literal (const char *value
)
1074 recording::rvalue
*result
=
1075 new memento_of_new_string_literal (this, NULL
, new_string (value
));
1080 /* Create a recording::memento_of_new_rvalue_from_vector instance and add it
1081 to this context's list of mementos.
1083 Implements the post-error-checking part of
1084 gcc_jit_context_new_rvalue_from_vector. */
1087 recording::context::new_rvalue_from_vector (location
*loc
,
1091 recording::rvalue
*result
1092 = new memento_of_new_rvalue_from_vector (this, loc
, type
, elements
);
1097 /* Create a recording::unary_op instance and add it to this context's
1100 Implements the post-error-checking part of
1101 gcc_jit_context_new_unary_op. */
1104 recording::context::new_unary_op (recording::location
*loc
,
1105 enum gcc_jit_unary_op op
,
1106 recording::type
*result_type
,
1107 recording::rvalue
*a
)
1109 recording::rvalue
*result
=
1110 new unary_op (this, loc
, op
, result_type
, a
);
1115 /* Create a recording::binary_op instance and add it to this context's
1118 Implements the post-error-checking part of
1119 gcc_jit_context_new_binary_op. */
1122 recording::context::new_binary_op (recording::location
*loc
,
1123 enum gcc_jit_binary_op op
,
1124 recording::type
*result_type
,
1125 recording::rvalue
*a
,
1126 recording::rvalue
*b
)
1128 recording::rvalue
*result
=
1129 new binary_op (this, loc
, op
, result_type
, a
, b
);
1134 /* Create a recording::comparison instance and add it to this context's
1137 Implements the post-error-checking part of
1138 gcc_jit_context_new_comparison. */
1141 recording::context::new_comparison (recording::location
*loc
,
1142 enum gcc_jit_comparison op
,
1143 recording::rvalue
*a
,
1144 recording::rvalue
*b
)
1146 recording::rvalue
*result
= new comparison (this, loc
, op
, a
, b
);
1151 /* Create a recording::cast instance and add it to this context's list
1154 Implements the post-error-checking part of
1155 gcc_jit_context_new_cast. */
1158 recording::context::new_cast (recording::location
*loc
,
1159 recording::rvalue
*expr
,
1160 recording::type
*type_
)
1162 recording::rvalue
*result
= new cast (this, loc
, expr
, type_
);
1167 /* Create a recording::call instance and add it to this context's list
1170 Implements the post-error-checking part of
1171 gcc_jit_context_new_call. */
1174 recording::context::new_call (recording::location
*loc
,
1176 int numargs
, recording::rvalue
**args
)
1178 recording::rvalue
*result
= new call (this, loc
, func
, numargs
, args
);
1183 /* Create a recording::call_through_ptr instance and add it to this
1184 context's list of mementos.
1186 Implements the post-error-checking part of
1187 gcc_jit_context_new_call_through_ptr. */
1190 recording::context::new_call_through_ptr (recording::location
*loc
,
1191 recording::rvalue
*fn_ptr
,
1193 recording::rvalue
**args
)
1195 recording::rvalue
*result
= new call_through_ptr (this, loc
, fn_ptr
, numargs
, args
);
1200 /* Create a recording::array_access instance and add it to this context's list
1203 Implements the post-error-checking part of
1204 gcc_jit_context_new_array_access. */
1207 recording::context::new_array_access (recording::location
*loc
,
1208 recording::rvalue
*ptr
,
1209 recording::rvalue
*index
)
1211 recording::lvalue
*result
= new array_access (this, loc
, ptr
, index
);
1216 /* Create a recording::case_ instance and add it to this context's list
1219 Implements the post-error-checking part of
1220 gcc_jit_context_new_case. */
1223 recording::context::new_case (recording::rvalue
*min_value
,
1224 recording::rvalue
*max_value
,
1225 recording::block
*block
)
1227 recording::case_
*result
= new case_ (this, min_value
, max_value
, block
);
1232 /* Set the given string option for this context, or add an error if
1233 it's not recognized.
1235 Implements the post-error-checking part of
1236 gcc_jit_context_set_str_option. */
1239 recording::context::set_str_option (enum gcc_jit_str_option opt
,
1242 if (opt
< 0 || opt
>= GCC_JIT_NUM_STR_OPTIONS
)
1245 "unrecognized (enum gcc_jit_str_option) value: %i", opt
);
1248 free (m_str_options
[opt
]);
1249 m_str_options
[opt
] = value
? xstrdup (value
) : NULL
;
1250 log_str_option (opt
);
1253 /* Set the given integer option for this context, or add an error if
1254 it's not recognized.
1256 Implements the post-error-checking part of
1257 gcc_jit_context_set_int_option. */
1260 recording::context::set_int_option (enum gcc_jit_int_option opt
,
1263 if (opt
< 0 || opt
>= GCC_JIT_NUM_INT_OPTIONS
)
1266 "unrecognized (enum gcc_jit_int_option) value: %i", opt
);
1269 m_int_options
[opt
] = value
;
1270 log_int_option (opt
);
1273 /* Set the given boolean option for this context, or add an error if
1274 it's not recognized.
1276 Implements the post-error-checking part of
1277 gcc_jit_context_set_bool_option. */
1280 recording::context::set_bool_option (enum gcc_jit_bool_option opt
,
1283 if (opt
< 0 || opt
>= GCC_JIT_NUM_BOOL_OPTIONS
)
1286 "unrecognized (enum gcc_jit_bool_option) value: %i", opt
);
1289 m_bool_options
[opt
] = value
? true : false;
1290 log_bool_option (opt
);
1294 recording::context::set_inner_bool_option (enum inner_bool_option inner_opt
,
1297 gcc_assert (inner_opt
>= 0 && inner_opt
< NUM_INNER_BOOL_OPTIONS
);
1298 m_inner_bool_options
[inner_opt
] = value
? true : false;
1299 log_inner_bool_option (inner_opt
);
1303 /* Add the given optname to this context's list of extra options.
1305 Implements the post-error-checking part of
1306 gcc_jit_context_add_command_line_option. */
1309 recording::context::add_command_line_option (const char *optname
)
1311 m_command_line_options
.safe_push (xstrdup (optname
));
1314 /* Add any user-provided extra options, starting with any from
1316 Called by playback::context::make_fake_args. */
1319 recording::context::append_command_line_options (vec
<char *> *argvec
)
1322 m_parent_ctxt
->append_command_line_options (argvec
);
1326 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1327 argvec
->safe_push (xstrdup (optname
));
1330 /* Add the given optname to this context's list of extra driver options. */
1333 recording::context::add_driver_option (const char *optname
)
1335 m_driver_options
.safe_push (xstrdup (optname
));
1338 /* Add any user-provided driver options, starting with any from
1340 Called by playback::context::invoke_driver. */
1343 recording::context::append_driver_options (auto_string_vec
*argvec
)
1346 m_parent_ctxt
->append_driver_options (argvec
);
1351 FOR_EACH_VEC_ELT (m_driver_options
, i
, optname
)
1352 argvec
->safe_push (xstrdup (optname
));
1355 /* Add the given dumpname/out_ptr pair to this context's list of requested
1358 Implements the post-error-checking part of
1359 gcc_jit_context_enable_dump. */
1362 recording::context::enable_dump (const char *dumpname
,
1366 gcc_assert (dumpname
);
1367 gcc_assert (out_ptr
);
1369 d
.m_dumpname
= dumpname
;
1370 d
.m_out_ptr
= out_ptr
;
1372 m_requested_dumps
.safe_push (d
);
1375 /* Validate this context, and if it passes, compile it to memory
1378 Implements the post-error-checking part of
1379 gcc_jit_context_compile. */
1382 recording::context::compile ()
1384 JIT_LOG_SCOPE (get_logger ());
1390 if (errors_occurred ())
1393 /* Set up a compile_to_memory playback context. */
1394 ::gcc::jit::playback::compile_to_memory
replayer (this);
1397 replayer
.compile ();
1399 /* Get the jit::result (or NULL) from the
1400 compile_to_memory playback context. */
1401 return replayer
.get_result_obj ();
1404 /* Validate this context, and if it passes, compile it to a file
1407 Implements the post-error-checking part of
1408 gcc_jit_context_compile_to_file. */
1411 recording::context::compile_to_file (enum gcc_jit_output_kind output_kind
,
1412 const char *output_path
)
1414 JIT_LOG_SCOPE (get_logger ());
1420 if (errors_occurred ())
1423 /* Set up a compile_to_file playback context. */
1424 ::gcc::jit::playback::compile_to_file
replayer (this,
1429 replayer
.compile ();
1432 /* Format the given error using printf's conventions, print
1433 it to stderr, and add it to the context. */
1436 recording::context::add_error (location
*loc
, const char *fmt
, ...)
1440 add_error_va (loc
, fmt
, ap
);
1444 /* Format the given error using printf's conventions, print
1445 it to stderr, and add it to the context. */
1448 recording::context::add_error_va (location
*loc
, const char *fmt
, va_list ap
)
1455 JIT_LOG_SCOPE (get_logger ());
1457 len
= vasprintf (&malloced_msg
, fmt
, ap
);
1458 if (malloced_msg
== NULL
|| len
< 0)
1460 errmsg
= "out of memory generating error message";
1461 has_ownership
= false;
1465 errmsg
= malloced_msg
;
1466 has_ownership
= true;
1469 get_logger ()->log ("error %i: %s", m_error_count
, errmsg
);
1471 const char *ctxt_progname
=
1472 get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
1474 ctxt_progname
= "libgccjit.so";
1477 fprintf (stderr
, "%s: %s: error: %s\n",
1479 loc
->get_debug_string (),
1482 fprintf (stderr
, "%s: error: %s\n",
1488 m_first_error_str
= const_cast <char *> (errmsg
);
1489 m_owns_first_error_str
= has_ownership
;
1492 if (m_owns_last_error_str
)
1493 if (m_last_error_str
!= m_first_error_str
)
1494 free (m_last_error_str
);
1495 m_last_error_str
= const_cast <char *> (errmsg
);
1496 m_owns_last_error_str
= has_ownership
;
1501 /* Get the message for the first error that occurred on this context, or
1502 NULL if no errors have occurred on it.
1504 Implements the post-error-checking part of
1505 gcc_jit_context_get_first_error. */
1508 recording::context::get_first_error () const
1510 return m_first_error_str
;
1513 /* Get the message for the last error that occurred on this context, or
1514 NULL if no errors have occurred on it.
1516 Implements the post-error-checking part of
1517 gcc_jit_context_get_last_error. */
1520 recording::context::get_last_error () const
1522 return m_last_error_str
;
1525 /* Lazily generate and record a recording::type representing an opaque
1526 struct named "FILE".
1528 For use if client code tries to dereference the result of
1529 get_type (GCC_JIT_TYPE_FILE_PTR). */
1532 recording::context::get_opaque_FILE_type ()
1535 m_FILE_type
= new_struct_type (NULL
, "FILE");
1539 /* Dump a C-like representation of the given context to the given path.
1540 If UPDATE_LOCATIONS is true, update the locations within the
1541 context's mementos to point to the dumpfile.
1543 Implements the post-error-checking part of
1544 gcc_jit_context_dump_to_file. */
1547 recording::context::dump_to_file (const char *path
, bool update_locations
)
1550 dump
d (*this, path
, update_locations
);
1552 /* Forward declaration of structs and unions. */
1554 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1556 d
.write ("%s;\n\n", st
->get_debug_string ());
1559 /* Content of structs, where set. */
1560 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1561 if (st
->get_fields ())
1563 st
->get_fields ()->write_to_dump (d
);
1569 FOR_EACH_VEC_ELT (m_globals
, i
, g
)
1571 g
->write_to_dump (d
);
1573 if (!m_globals
.is_empty ())
1577 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1579 fn
->write_to_dump (d
);
1583 static const char * const
1584 str_option_reproducer_strings
[GCC_JIT_NUM_STR_OPTIONS
] = {
1585 "GCC_JIT_STR_OPTION_PROGNAME"
1588 static const char * const
1589 int_option_reproducer_strings
[GCC_JIT_NUM_INT_OPTIONS
] = {
1590 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1593 static const char * const
1594 bool_option_reproducer_strings
[GCC_JIT_NUM_BOOL_OPTIONS
] = {
1595 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1596 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1597 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1598 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1599 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1600 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1601 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1602 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1605 static const char * const
1606 inner_bool_option_reproducer_strings
[NUM_INNER_BOOL_OPTIONS
] = {
1607 "gcc_jit_context_set_bool_allow_unreachable_blocks",
1608 "gcc_jit_context_set_bool_use_external_driver"
1611 /* Write the current value of all options to the log file (if any). */
1614 recording::context::log_all_options () const
1621 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1622 log_str_option ((enum gcc_jit_str_option
)opt_idx
);
1624 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1625 log_int_option ((enum gcc_jit_int_option
)opt_idx
);
1627 for (opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1628 log_bool_option ((enum gcc_jit_bool_option
)opt_idx
);
1629 for (opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1630 log_inner_bool_option ((enum inner_bool_option
)opt_idx
);
1633 /* Write the current value of the given string option to the
1634 log file (if any). */
1637 recording::context::log_str_option (enum gcc_jit_str_option opt
) const
1639 gcc_assert (opt
< GCC_JIT_NUM_STR_OPTIONS
);
1642 if (m_str_options
[opt
])
1644 str_option_reproducer_strings
[opt
],
1645 m_str_options
[opt
]);
1648 str_option_reproducer_strings
[opt
]);
1652 /* Write the current value of the given int option to the
1653 log file (if any). */
1656 recording::context::log_int_option (enum gcc_jit_int_option opt
) const
1658 gcc_assert (opt
< GCC_JIT_NUM_INT_OPTIONS
);
1661 int_option_reproducer_strings
[opt
],
1662 m_int_options
[opt
]);
1665 /* Write the current value of the given bool option to the
1666 log file (if any). */
1669 recording::context::log_bool_option (enum gcc_jit_bool_option opt
) const
1671 gcc_assert (opt
< GCC_JIT_NUM_BOOL_OPTIONS
);
1674 bool_option_reproducer_strings
[opt
],
1675 m_bool_options
[opt
] ? "true" : "false");
1678 /* Write the current value of the given "inner" bool option to the
1679 log file (if any). */
1682 recording::context::log_inner_bool_option (enum inner_bool_option opt
) const
1684 gcc_assert (opt
< NUM_INNER_BOOL_OPTIONS
);
1687 inner_bool_option_reproducer_strings
[opt
],
1688 m_inner_bool_options
[opt
] ? "true" : "false");
1691 /* Write C source code to PATH that attempts to replay the API
1692 calls made to this context (and its parents), for use in
1693 minimizing test cases for libgccjit.
1695 Implements the post-error-checking part of
1696 gcc_jit_context_dump_reproducer_to_file. */
1699 recording::context::dump_reproducer_to_file (const char *path
)
1701 JIT_LOG_SCOPE (get_logger ());
1702 reproducer
r (*this, path
);
1704 /* Generate the "ancestry" of this context, as a list. */
1705 auto_vec
<context
*> ascending_contexts
;
1706 for (context
*ctxt
= this; ctxt
; ctxt
= ctxt
->m_parent_ctxt
)
1707 ascending_contexts
.safe_push (ctxt
);
1709 /* Reverse the list, giving a list of contexts from
1710 top-most parent context down through to youngest child context.
1711 We will use this list as the parameters of the functions in
1712 our generated file. */
1713 unsigned num_ctxts
= ascending_contexts
.length ();
1714 auto_vec
<context
*> contexts (num_ctxts
);
1715 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1716 contexts
.safe_push (ascending_contexts
[num_ctxts
- (i
+ 1)]);
1718 /* contexts[0] should be the top-level context. */
1719 gcc_assert (contexts
[0]);
1720 gcc_assert (contexts
[0]->m_toplevel_ctxt
== contexts
[0]);
1722 /* The final element in contexts should be "this". */
1723 gcc_assert (contexts
[contexts
.length () - 1] == this);
1724 gcc_assert (contexts
[contexts
.length () - 1]->m_toplevel_ctxt
1727 r
.write ("/* This code was autogenerated by"
1728 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1729 print_version (r
.get_file (), " ", false);
1731 r
.write ("#include <libgccjit.h>\n\n");
1732 r
.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n");
1733 r
.write ("static void\nset_options (");
1734 r
.write_params (contexts
);
1736 r
.write ("static void\ncreate_code (");
1737 r
.write_params (contexts
);
1739 r
.write ("int\nmain (int argc, const char **argv)\n");
1741 for (unsigned i
= 0; i
< num_ctxts
; i
++)
1742 r
.write (" gcc_jit_context *%s;\n",
1743 r
.get_identifier (contexts
[i
]));
1744 r
.write (" gcc_jit_result *result;\n"
1747 /* Create the contexts.
1748 The top-level context is acquired from a clean slate, the others as
1749 children of the prior context. */
1750 r
.write (" %s = gcc_jit_context_acquire ();\n",
1751 r
.get_identifier (contexts
[0]));
1752 for (unsigned i
= 1; i
< num_ctxts
; i
++)
1753 r
.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1754 r
.get_identifier (contexts
[i
]),
1755 r
.get_identifier (contexts
[i
- 1]));
1756 r
.write (" set_options (");
1757 r
.write_args (contexts
);
1759 r
.write (" create_code (");
1760 r
.write_args (contexts
);
1763 r
.write (" result = gcc_jit_context_compile (%s);\n",
1764 r
.get_identifier (this));
1766 for (unsigned i
= num_ctxts
; i
> 0; i
--)
1767 r
.write (" gcc_jit_context_release (%s);\n",
1768 r
.get_identifier (contexts
[i
- 1]));
1770 r
.write (" gcc_jit_result_release (result);\n"
1774 /* Define (char *) variables for use in calls to
1775 gcc_jit_context_enable_dump. */
1776 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1778 if (m_requested_dumps
.length ())
1780 r
.write ("/* Requested dumps for %s. */\n",
1781 r
.get_identifier (contexts
[ctxt_idx
]));
1782 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1783 r
.write ("static char *dump_%p;\n",
1784 (void *)&m_requested_dumps
[i
]);
1789 /* Write out values of options. */
1790 r
.write ("static void\nset_options (");
1791 r
.write_params (contexts
);
1793 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1798 r
.write (" /* Set options for %s. */\n",
1799 r
.get_identifier (contexts
[ctxt_idx
]));
1801 r
.write (" /* String options. */\n");
1802 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_STR_OPTIONS
; opt_idx
++)
1804 r
.write (" gcc_jit_context_set_str_option (%s,\n"
1806 r
.get_identifier (contexts
[ctxt_idx
]),
1807 str_option_reproducer_strings
[opt_idx
]);
1808 if (m_str_options
[opt_idx
])
1809 r
.write (" \"%s\");\n",
1810 m_str_options
[opt_idx
]);
1812 r
.write (" NULL);\n");
1814 r
.write (" /* Int options. */\n");
1815 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_INT_OPTIONS
; opt_idx
++)
1816 r
.write (" gcc_jit_context_set_int_option (%s,\n"
1819 r
.get_identifier (contexts
[ctxt_idx
]),
1820 int_option_reproducer_strings
[opt_idx
],
1821 m_int_options
[opt_idx
]);
1822 r
.write (" /* Boolean options. */\n");
1823 for (int opt_idx
= 0; opt_idx
< GCC_JIT_NUM_BOOL_OPTIONS
; opt_idx
++)
1824 r
.write (" gcc_jit_context_set_bool_option (%s,\n"
1827 r
.get_identifier (contexts
[ctxt_idx
]),
1828 bool_option_reproducer_strings
[opt_idx
],
1829 m_bool_options
[opt_idx
]);
1830 for (int opt_idx
= 0; opt_idx
< NUM_INNER_BOOL_OPTIONS
; opt_idx
++)
1831 r
.write (" %s (%s, %i);\n",
1832 inner_bool_option_reproducer_strings
[opt_idx
],
1833 r
.get_identifier (contexts
[ctxt_idx
]),
1834 m_inner_bool_options
[opt_idx
]);
1836 if (!m_command_line_options
.is_empty ())
1840 r
.write (" /* User-provided command-line options. */\n");
1841 FOR_EACH_VEC_ELT (m_command_line_options
, i
, optname
)
1842 r
.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n",
1843 r
.get_identifier (contexts
[ctxt_idx
]),
1847 if (!m_driver_options
.is_empty ())
1851 r
.write (" /* User-provided driver options. */\n");
1852 FOR_EACH_VEC_ELT (m_driver_options
, i
, optname
)
1853 r
.write (" gcc_jit_context_add_driver_option (%s, \"%s\");\n",
1854 r
.get_identifier (contexts
[ctxt_idx
]),
1858 if (m_requested_dumps
.length ())
1860 r
.write (" /* Requested dumps. */\n");
1861 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1862 for (unsigned i
= 0; i
< m_requested_dumps
.length (); i
++)
1864 r
.write (" gcc_jit_context_enable_dump (%s,\n"
1867 r
.get_identifier (contexts
[ctxt_idx
]),
1868 m_requested_dumps
[i
].m_dumpname
,
1869 (void *)&m_requested_dumps
[i
]);
1875 r
.write ("static void\ncreate_code (");
1876 r
.write_params (contexts
);
1879 for (unsigned ctxt_idx
= 0; ctxt_idx
< num_ctxts
; ctxt_idx
++)
1886 r
.write (" /* Replay of API calls for %s. */\n",
1887 r
.get_identifier (contexts
[ctxt_idx
]));
1888 FOR_EACH_VEC_ELT (contexts
[ctxt_idx
]->m_mementos
, i
, m
)
1889 m
->write_reproducer (r
);
1894 /* Copy the requested dumps within this context and all ancestors into
1898 recording::context::get_all_requested_dumps (vec
<recording::requested_dump
> *out
)
1901 m_parent_ctxt
->get_all_requested_dumps (out
);
1903 out
->reserve (m_requested_dumps
.length ());
1904 out
->splice (m_requested_dumps
);
1907 /* This is a pre-compilation check for the context (and any parents).
1909 Detect errors within the context, adding errors if any are found. */
1912 recording::context::validate ()
1914 JIT_LOG_SCOPE (get_logger ());
1917 m_parent_ctxt
->validate ();
1921 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1925 /* The implementation of class gcc::jit::recording::memento. */
1927 /* Get a (const char *) debug description of the given memento, by
1928 calling the pure-virtual make_debug_string hook, caching the
1931 It is intended that this should only be called in debugging and
1932 error-handling paths, so this doesn't need to be particularly
1936 recording::memento::get_debug_string ()
1938 if (!m_debug_string
)
1939 m_debug_string
= make_debug_string ();
1940 return m_debug_string
->c_str ();
1943 /* Default implementation of recording::memento::write_to_dump, writing
1944 an indented form of the memento's debug string to the dump. */
1947 recording::memento::write_to_dump (dump
&d
)
1949 d
.write(" %s\n", get_debug_string ());
1952 /* The implementation of class gcc::jit::recording::string. */
1954 /* Constructor for gcc::jit::recording::string::string, allocating a
1955 copy of the given text using new char[]. */
1957 recording::string::string (context
*ctxt
, const char *text
)
1960 m_len
= strlen (text
);
1961 m_buffer
= new char[m_len
+ 1];
1962 strcpy (m_buffer
, text
);
1965 /* Destructor for gcc::jit::recording::string::string. */
1967 recording::string::~string ()
1972 /* Function for making gcc::jit::recording::string instances on a
1973 context via printf-style formatting.
1975 It is intended that this should only be called in debugging and
1976 error-handling paths, so this doesn't need to be particularly
1977 optimized, hence the double-copy of the string is acceptable. */
1980 recording::string::from_printf (context
*ctxt
, const char *fmt
, ...)
1985 recording::string
*result
;
1988 len
= vasprintf (&buf
, fmt
, ap
);
1991 if (buf
== NULL
|| len
< 0)
1993 ctxt
->add_error (NULL
, "malloc failure");
1997 result
= ctxt
->new_string (buf
);
2002 /* Implementation of recording::memento::make_debug_string for strings,
2003 wrapping the given string in quotes and escaping as necessary. */
2006 recording::string::make_debug_string ()
2008 /* Hack to avoid infinite recursion into strings when logging all
2009 mementos: don't re-escape strings: */
2010 if (m_buffer
[0] == '"')
2013 /* Wrap in quotes and do escaping etc */
2015 size_t sz
= (1 /* opening quote */
2016 + (m_len
* 2) /* each char might get escaped */
2017 + 1 /* closing quote */
2018 + 1); /* nil termintator */
2019 char *tmp
= new char[sz
];
2022 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
2023 APPEND('"'); /* opening quote */
2024 for (size_t i
= 0; i
< m_len
; i
++)
2026 char ch
= m_buffer
[i
];
2027 if (ch
== '\t' || ch
== '\n' || ch
== '\\' || ch
== '"')
2031 APPEND('"'); /* closing quote */
2033 tmp
[len
] = '\0'; /* nil termintator */
2035 string
*result
= m_ctxt
->new_string (tmp
);
2041 /* Implementation of recording::memento::write_reproducer for strings. */
2044 recording::string::write_reproducer (reproducer
&)
2049 /* The implementation of class gcc::jit::recording::location. */
2051 /* Implementation of recording::memento::replay_into for locations.
2053 Create a new playback::location and store it into the
2054 recording::location's m_playback_obj field. */
2057 recording::location::replay_into (replayer
*r
)
2059 m_playback_obj
= r
->new_location (this,
2060 m_filename
->c_str (),
2065 /* Implementation of recording::memento::make_debug_string for locations,
2066 turning them into the usual form:
2067 FILENAME:LINE:COLUMN
2068 like we do when emitting diagnostics. */
2071 recording::location::make_debug_string ()
2073 return string::from_printf (m_ctxt
,
2075 m_filename
->c_str (), m_line
, m_column
);
2078 /* Implementation of recording::memento::write_reproducer for locations. */
2081 recording::location::write_reproducer (reproducer
&r
)
2083 const char *id
= r
.make_identifier (this, "loc");
2084 r
.write (" gcc_jit_location *%s =\n"
2085 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
2086 " %s, /* const char *filename */\n"
2087 " %i, /* int line */\n"
2088 " %i);/* int column */\n",
2090 r
.get_identifier (get_context ()),
2091 m_filename
->get_debug_string (),
2095 /* The implementation of class gcc::jit::recording::type. */
2097 /* Given a type T, get the type T*.
2099 If this doesn't already exist, generate a new memento_of_get_pointer
2100 instance and add it to this type's context's list of mementos.
2102 Otherwise, use the cached type.
2104 Implements the post-error-checking part of
2105 gcc_jit_type_get_pointer. */
2108 recording::type::get_pointer ()
2110 if (!m_pointer_to_this_type
)
2112 m_pointer_to_this_type
= new memento_of_get_pointer (this);
2113 m_ctxt
->record (m_pointer_to_this_type
);
2115 return m_pointer_to_this_type
;
2118 /* Given a type T, get the type const T.
2120 Implements the post-error-checking part of
2121 gcc_jit_type_get_const. */
2124 recording::type::get_const ()
2126 recording::type
*result
= new memento_of_get_const (this);
2127 m_ctxt
->record (result
);
2131 /* Given a type T, get the type volatile T.
2133 Implements the post-error-checking part of
2134 gcc_jit_type_get_volatile. */
2137 recording::type::get_volatile ()
2139 recording::type
*result
= new memento_of_get_volatile (this);
2140 m_ctxt
->record (result
);
2144 /* Given a type, get an aligned version of the type.
2146 Implements the post-error-checking part of
2147 gcc_jit_type_get_aligned. */
2150 recording::type::get_aligned (size_t alignment_in_bytes
)
2152 recording::type
*result
2153 = new memento_of_get_aligned (this, alignment_in_bytes
);
2154 m_ctxt
->record (result
);
2158 /* Given a type, get a vector version of the type.
2160 Implements the post-error-checking part of
2161 gcc_jit_type_get_vector. */
2164 recording::type::get_vector (size_t num_units
)
2166 recording::type
*result
2167 = new vector_type (this, num_units
);
2168 m_ctxt
->record (result
);
2173 recording::type::access_as_type (reproducer
&r
)
2175 return r
.get_identifier (this);
2178 /* Override of default implementation of
2179 recording::type::get_size.
2181 Return the size in bytes. This is in use for global
2185 recording::memento_of_get_type::get_size ()
2190 case GCC_JIT_TYPE_VOID
:
2192 case GCC_JIT_TYPE_BOOL
:
2193 case GCC_JIT_TYPE_CHAR
:
2194 case GCC_JIT_TYPE_SIGNED_CHAR
:
2195 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2197 case GCC_JIT_TYPE_SHORT
:
2198 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2199 size
= SHORT_TYPE_SIZE
;
2201 case GCC_JIT_TYPE_INT
:
2202 case GCC_JIT_TYPE_UNSIGNED_INT
:
2203 size
= INT_TYPE_SIZE
;
2205 case GCC_JIT_TYPE_LONG
:
2206 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2207 size
= LONG_TYPE_SIZE
;
2209 case GCC_JIT_TYPE_LONG_LONG
:
2210 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2211 size
= LONG_LONG_TYPE_SIZE
;
2213 case GCC_JIT_TYPE_FLOAT
:
2214 size
= FLOAT_TYPE_SIZE
;
2216 case GCC_JIT_TYPE_DOUBLE
:
2217 size
= DOUBLE_TYPE_SIZE
;
2219 case GCC_JIT_TYPE_LONG_DOUBLE
:
2220 size
= LONG_DOUBLE_TYPE_SIZE
;
2223 /* As this function is called by
2224 'gcc_jit_global_set_initializer' and
2225 'recording::global::write_reproducer' possible types are only
2226 integrals and are covered by the previous cases. */
2230 return size
/ BITS_PER_UNIT
;
2233 /* Implementation of pure virtual hook recording::type::dereference for
2234 recording::memento_of_get_type. */
2237 recording::memento_of_get_type::dereference ()
2241 default: gcc_unreachable ();
2243 case GCC_JIT_TYPE_VOID
:
2246 case GCC_JIT_TYPE_VOID_PTR
:
2247 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
2249 case GCC_JIT_TYPE_BOOL
:
2250 case GCC_JIT_TYPE_CHAR
:
2251 case GCC_JIT_TYPE_SIGNED_CHAR
:
2252 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2253 case GCC_JIT_TYPE_SHORT
:
2254 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2255 case GCC_JIT_TYPE_INT
:
2256 case GCC_JIT_TYPE_UNSIGNED_INT
:
2257 case GCC_JIT_TYPE_LONG
:
2258 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2259 case GCC_JIT_TYPE_LONG_LONG
:
2260 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2261 case GCC_JIT_TYPE_FLOAT
:
2262 case GCC_JIT_TYPE_DOUBLE
:
2263 case GCC_JIT_TYPE_LONG_DOUBLE
:
2264 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2265 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2266 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2267 /* Not a pointer: */
2270 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2271 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
2273 case GCC_JIT_TYPE_SIZE_T
:
2274 /* Not a pointer: */
2277 case GCC_JIT_TYPE_FILE_PTR
:
2278 /* Give the client code back an opaque "struct FILE". */
2279 return m_ctxt
->get_opaque_FILE_type ();
2283 /* Implementation of pure virtual hook recording::type::is_int for
2284 recording::memento_of_get_type. */
2287 recording::memento_of_get_type::is_int () const
2291 default: gcc_unreachable ();
2293 case GCC_JIT_TYPE_VOID
:
2296 case GCC_JIT_TYPE_VOID_PTR
:
2299 case GCC_JIT_TYPE_BOOL
:
2302 case GCC_JIT_TYPE_CHAR
:
2303 case GCC_JIT_TYPE_SIGNED_CHAR
:
2304 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2305 case GCC_JIT_TYPE_SHORT
:
2306 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2307 case GCC_JIT_TYPE_INT
:
2308 case GCC_JIT_TYPE_UNSIGNED_INT
:
2309 case GCC_JIT_TYPE_LONG
:
2310 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2311 case GCC_JIT_TYPE_LONG_LONG
:
2312 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2315 case GCC_JIT_TYPE_FLOAT
:
2316 case GCC_JIT_TYPE_DOUBLE
:
2317 case GCC_JIT_TYPE_LONG_DOUBLE
:
2320 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2323 case GCC_JIT_TYPE_SIZE_T
:
2326 case GCC_JIT_TYPE_FILE_PTR
:
2329 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2330 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2331 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2336 /* Implementation of pure virtual hook recording::type::is_float for
2337 recording::memento_of_get_type. */
2340 recording::memento_of_get_type::is_float () const
2344 default: gcc_unreachable ();
2346 case GCC_JIT_TYPE_VOID
:
2349 case GCC_JIT_TYPE_VOID_PTR
:
2352 case GCC_JIT_TYPE_BOOL
:
2355 case GCC_JIT_TYPE_CHAR
:
2356 case GCC_JIT_TYPE_SIGNED_CHAR
:
2357 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2358 case GCC_JIT_TYPE_SHORT
:
2359 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2360 case GCC_JIT_TYPE_INT
:
2361 case GCC_JIT_TYPE_UNSIGNED_INT
:
2362 case GCC_JIT_TYPE_LONG
:
2363 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2364 case GCC_JIT_TYPE_LONG_LONG
:
2365 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2368 case GCC_JIT_TYPE_FLOAT
:
2369 case GCC_JIT_TYPE_DOUBLE
:
2370 case GCC_JIT_TYPE_LONG_DOUBLE
:
2373 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2376 case GCC_JIT_TYPE_SIZE_T
:
2379 case GCC_JIT_TYPE_FILE_PTR
:
2382 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2383 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2384 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2389 /* Implementation of pure virtual hook recording::type::is_bool for
2390 recording::memento_of_get_type. */
2393 recording::memento_of_get_type::is_bool () const
2397 default: gcc_unreachable ();
2399 case GCC_JIT_TYPE_VOID
:
2402 case GCC_JIT_TYPE_VOID_PTR
:
2405 case GCC_JIT_TYPE_BOOL
:
2408 case GCC_JIT_TYPE_CHAR
:
2409 case GCC_JIT_TYPE_SIGNED_CHAR
:
2410 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2411 case GCC_JIT_TYPE_SHORT
:
2412 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2413 case GCC_JIT_TYPE_INT
:
2414 case GCC_JIT_TYPE_UNSIGNED_INT
:
2415 case GCC_JIT_TYPE_LONG
:
2416 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2417 case GCC_JIT_TYPE_LONG_LONG
:
2418 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2421 case GCC_JIT_TYPE_FLOAT
:
2422 case GCC_JIT_TYPE_DOUBLE
:
2423 case GCC_JIT_TYPE_LONG_DOUBLE
:
2426 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2429 case GCC_JIT_TYPE_SIZE_T
:
2432 case GCC_JIT_TYPE_FILE_PTR
:
2435 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2436 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2437 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2442 /* Implementation of pure virtual hook recording::memento::replay_into
2443 for recording::memento_of_get_type. */
2446 recording::memento_of_get_type::replay_into (replayer
*r
)
2448 set_playback_obj (r
->get_type (m_kind
));
2451 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2453 /* Descriptive strings for each of enum gcc_jit_types. */
2455 static const char * const get_type_strings
[] = {
2456 "void", /* GCC_JIT_TYPE_VOID */
2457 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2459 "bool", /* GCC_JIT_TYPE_BOOL */
2461 "char", /* GCC_JIT_TYPE_CHAR */
2462 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2463 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2465 "short", /* GCC_JIT_TYPE_SHORT */
2466 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2468 "int", /* GCC_JIT_TYPE_INT */
2469 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2471 "long", /* GCC_JIT_TYPE_LONG */
2472 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2474 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2475 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2477 "float", /* GCC_JIT_TYPE_FLOAT */
2478 "double", /* GCC_JIT_TYPE_DOUBLE */
2479 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2481 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2483 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2485 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2487 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2488 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2489 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2493 /* Implementation of recording::memento::make_debug_string for
2494 results of get_type, using a simple table of type names. */
2497 recording::memento_of_get_type::make_debug_string ()
2499 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
2502 static const char * const get_type_enum_strings
[] = {
2503 "GCC_JIT_TYPE_VOID",
2504 "GCC_JIT_TYPE_VOID_PTR",
2505 "GCC_JIT_TYPE_BOOL",
2506 "GCC_JIT_TYPE_CHAR",
2507 "GCC_JIT_TYPE_SIGNED_CHAR",
2508 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2509 "GCC_JIT_TYPE_SHORT",
2510 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2512 "GCC_JIT_TYPE_UNSIGNED_INT",
2513 "GCC_JIT_TYPE_LONG",
2514 "GCC_JIT_TYPE_UNSIGNED_LONG",
2515 "GCC_JIT_TYPE_LONG_LONG",
2516 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2517 "GCC_JIT_TYPE_FLOAT",
2518 "GCC_JIT_TYPE_DOUBLE",
2519 "GCC_JIT_TYPE_LONG_DOUBLE",
2520 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2521 "GCC_JIT_TYPE_SIZE_T",
2522 "GCC_JIT_TYPE_FILE_PTR",
2523 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2524 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2525 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2529 recording::memento_of_get_type::write_reproducer (reproducer
&r
)
2531 const char *id
= r
.make_identifier (this, "type");
2532 r
.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2534 r
.get_identifier (get_context ()),
2535 get_type_enum_strings
[m_kind
]);
2538 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2540 /* Override of default implementation of
2541 recording::type::get_size for get_pointer. */
2544 recording::memento_of_get_pointer::get_size ()
2546 return POINTER_SIZE
/ BITS_PER_UNIT
;
2549 /* Override of default implementation of
2550 recording::type::accepts_writes_from for get_pointer.
2552 Require a pointer type, and allowing writes to
2553 (const T *) from a (T*), but not the other way around. */
2556 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
2558 /* Must be a pointer type: */
2559 type
*rtype_points_to
= rtype
->is_pointer ();
2560 if (!rtype_points_to
)
2563 /* It's OK to assign to a (const T *) from a (T *). */
2564 return m_other_type
->unqualified ()
2565 ->accepts_writes_from (rtype_points_to
);
2568 /* Implementation of pure virtual hook recording::memento::replay_into
2569 for recording::memento_of_get_pointer. */
2572 recording::memento_of_get_pointer::replay_into (replayer
*)
2574 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
2577 /* Implementation of recording::memento::make_debug_string for
2578 results of get_pointer, adding " *" to the underlying type,
2579 with special-casing to handle function pointer types. */
2582 recording::memento_of_get_pointer::make_debug_string ()
2584 /* Special-case function pointer types, to put the "*" in parens between
2585 the return type and the params (for one level of dereferencing, at
2587 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2588 return fn_type
->make_debug_string_with_ptr ();
2590 return string::from_printf (m_ctxt
,
2591 "%s *", m_other_type
->get_debug_string ());
2594 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2597 recording::memento_of_get_pointer::write_reproducer (reproducer
&r
)
2599 /* We need to special-case function pointer types; see the notes in
2600 recording::function_type::write_deferred_reproducer. */
2601 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2603 fn_type
->write_deferred_reproducer (r
, this);
2607 const char *id
= r
.make_identifier (this, "type");
2608 r
.write (" gcc_jit_type *%s =\n"
2609 " gcc_jit_type_get_pointer (%s);\n",
2611 r
.get_identifier_as_type (m_other_type
));
2614 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2616 /* Implementation of pure virtual hook recording::memento::replay_into
2617 for recording::memento_of_get_const. */
2620 recording::memento_of_get_const::replay_into (replayer
*)
2622 set_playback_obj (m_other_type
->playback_type ()->get_const ());
2625 /* Implementation of recording::memento::make_debug_string for
2626 results of get_const, prepending "const ". */
2629 recording::memento_of_get_const::make_debug_string ()
2631 return string::from_printf (m_ctxt
,
2632 "const %s", m_other_type
->get_debug_string ());
2635 /* Implementation of recording::memento::write_reproducer for const types. */
2638 recording::memento_of_get_const::write_reproducer (reproducer
&r
)
2640 const char *id
= r
.make_identifier (this, "type");
2641 r
.write (" gcc_jit_type *%s =\n"
2642 " gcc_jit_type_get_const (%s);\n",
2644 r
.get_identifier_as_type (m_other_type
));
2647 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2649 /* Implementation of pure virtual hook recording::memento::replay_into
2650 for recording::memento_of_get_volatile. */
2653 recording::memento_of_get_volatile::replay_into (replayer
*)
2655 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
2658 /* Implementation of recording::memento::make_debug_string for
2659 results of get_volatile, prepending "volatile ". */
2662 recording::memento_of_get_volatile::make_debug_string ()
2664 return string::from_printf (m_ctxt
,
2665 "volatile %s", m_other_type
->get_debug_string ());
2668 /* Implementation of recording::memento::write_reproducer for volatile
2672 recording::memento_of_get_volatile::write_reproducer (reproducer
&r
)
2674 const char *id
= r
.make_identifier (this, "type");
2675 r
.write (" gcc_jit_type *%s =\n"
2676 " gcc_jit_type_get_volatile (%s);\n",
2678 r
.get_identifier_as_type (m_other_type
));
2681 /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
2683 /* Implementation of pure virtual hook recording::memento::replay_into
2684 for recording::memento_of_get_aligned. */
2687 recording::memento_of_get_aligned::replay_into (replayer
*)
2690 (m_other_type
->playback_type ()->get_aligned (m_alignment_in_bytes
));
2693 /* Implementation of recording::memento::make_debug_string for
2694 results of get_aligned. */
2697 recording::memento_of_get_aligned::make_debug_string ()
2699 return string::from_printf (m_ctxt
,
2700 "%s __attribute__((aligned(%zi)))",
2701 m_other_type
->get_debug_string (),
2702 m_alignment_in_bytes
);
2705 /* Implementation of recording::memento::write_reproducer for aligned
2709 recording::memento_of_get_aligned::write_reproducer (reproducer
&r
)
2711 const char *id
= r
.make_identifier (this, "type");
2712 r
.write (" gcc_jit_type *%s =\n"
2713 " gcc_jit_type_get_aligned (%s, %zi);\n",
2715 r
.get_identifier_as_type (m_other_type
),
2716 m_alignment_in_bytes
);
2719 /* The implementation of class gcc::jit::recording::vector_type. */
2721 /* Implementation of pure virtual hook recording::memento::replay_into
2722 for recording::vector_type. */
2725 recording::vector_type::replay_into (replayer
*)
2728 (m_other_type
->playback_type ()->get_vector (m_num_units
));
2731 /* Implementation of recording::memento::make_debug_string for
2732 results of get_vector. */
2735 recording::vector_type::make_debug_string ()
2737 return string::from_printf
2739 "%s __attribute__((vector_size(sizeof (%s) * %zi)))",
2740 m_other_type
->get_debug_string (),
2741 m_other_type
->get_debug_string (),
2745 /* Implementation of recording::memento::write_reproducer for vector types. */
2748 recording::vector_type::write_reproducer (reproducer
&r
)
2750 const char *id
= r
.make_identifier (this, "type");
2751 r
.write (" gcc_jit_type *%s =\n"
2752 " gcc_jit_type_get_vector (%s, %zi);\n",
2754 r
.get_identifier_as_type (m_other_type
),
2758 /* The implementation of class gcc::jit::recording::array_type */
2760 /* Implementation of pure virtual hook recording::type::dereference for
2761 recording::array_type. */
2764 recording::array_type::dereference ()
2766 return m_element_type
;
2769 /* Implementation of pure virtual hook recording::memento::replay_into
2770 for recording::array_type. */
2773 recording::array_type::replay_into (replayer
*r
)
2775 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
2776 m_element_type
->playback_type (),
2780 /* Implementation of recording::memento::make_debug_string for
2781 results of new_array_type. */
2784 recording::array_type::make_debug_string ()
2786 return string::from_printf (m_ctxt
,
2788 m_element_type
->get_debug_string (),
2792 /* Implementation of recording::memento::write_reproducer for array
2796 recording::array_type::write_reproducer (reproducer
&r
)
2798 const char *id
= r
.make_identifier (this, "array_type");
2799 r
.write (" gcc_jit_type *%s =\n"
2800 " gcc_jit_context_new_array_type (%s,\n"
2801 " %s, /* gcc_jit_location *loc */\n"
2802 " %s, /* gcc_jit_type *element_type */\n"
2803 " %i); /* int num_elements */\n",
2805 r
.get_identifier (get_context ()),
2806 r
.get_identifier (m_loc
),
2807 r
.get_identifier_as_type (m_element_type
),
2811 /* The implementation of class gcc::jit::recording::function_type */
2813 /* Constructor for gcc::jit::recording::function_type. */
2815 recording::function_type::function_type (context
*ctxt
,
2821 m_return_type (return_type
),
2823 m_is_variadic (is_variadic
)
2825 for (int i
= 0; i
< num_params
; i
++)
2826 m_param_types
.safe_push (param_types
[i
]);
2829 /* Implementation of pure virtual hook recording::type::dereference for
2830 recording::function_type. */
2833 recording::function_type::dereference ()
2838 /* Implementation of virtual hook recording::type::is_same_type_as for
2839 recording::function_type.
2841 We override this to avoid requiring identity of function pointer types,
2842 so that if client code has obtained the same signature in
2843 different ways (e.g. via gcc_jit_context_new_function_ptr_type
2844 vs gcc_jit_function_get_address), the different function_type
2845 instances are treated as compatible.
2847 We can't use type::accepts_writes_from for this as we need a stronger
2848 notion of "sameness": if we have a fn_ptr type that has args that are
2849 themselves fn_ptr types, then those args still need to match exactly.
2851 Alternatively, we could consolidate attempts to create identical
2852 function_type instances so that pointer equality works, but that runs
2853 into issues about the lifetimes of the cache (w.r.t. nested contexts). */
2856 recording::function_type::is_same_type_as (type
*other
)
2860 function_type
*other_fn_type
= other
->dyn_cast_function_type ();
2864 /* Everything must match. */
2866 if (!m_return_type
->is_same_type_as (other_fn_type
->m_return_type
))
2869 if (m_param_types
.length () != other_fn_type
->m_param_types
.length ())
2874 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
2875 if (!param_type
->is_same_type_as (other_fn_type
->m_param_types
[i
]))
2878 if (m_is_variadic
!= other_fn_type
->m_is_variadic
)
2881 /* Passed all tests. */
2885 /* Implementation of pure virtual hook recording::memento::replay_into
2886 for recording::function_type. */
2889 recording::function_type::replay_into (replayer
*r
)
2891 /* Convert m_param_types to a vec of playback type. */
2892 auto_vec
<playback::type
*> param_types
;
2894 recording::type
*type
;
2895 param_types
.create (m_param_types
.length ());
2896 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
2897 param_types
.safe_push (type
->playback_type ());
2899 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
2904 /* Special-casing for make_debug_string for get_pointer results for
2905 handling (one level) of pointers to functions. */
2908 recording::function_type::make_debug_string_with_ptr ()
2910 return make_debug_string_with ("(*) ");
2913 /* Implementation of recording::memento::make_debug_string for
2914 results of new_function_type. */
2917 recording::function_type::make_debug_string ()
2919 return make_debug_string_with ("");
2922 /* Build a debug string representation of the form:
2924 RESULT_TYPE INSERT (PARAM_TYPES)
2926 for use when handling 0 and 1 level of indirection to this
2930 recording::function_type::make_debug_string_with (const char *insert
)
2932 /* First, build a buffer for the arguments. */
2933 /* Calculate length of said buffer. */
2934 size_t sz
= 1; /* nil terminator */
2935 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2937 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
2938 sz
+= 2; /* ", " separator */
2941 sz
+= 5; /* ", ..." separator and ellipsis */
2943 /* Now allocate and populate the buffer. */
2944 char *argbuf
= new char[sz
];
2947 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2949 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
2950 len
+= strlen (m_param_types
[i
]->get_debug_string ());
2951 if (i
+ 1 < m_param_types
.length ())
2953 strcpy (argbuf
+ len
, ", ");
2959 if (m_param_types
.length ())
2961 strcpy (argbuf
+ len
, ", ");
2964 strcpy (argbuf
+ len
, "...");
2969 /* ...and use it to get the string for the call as a whole. */
2970 string
*result
= string::from_printf (m_ctxt
,
2972 m_return_type
->get_debug_string (),
2981 /* Implementation of recording::memento::write_reproducer for function
2985 recording::function_type::write_reproducer (reproducer
&)
2987 /* see notes below. */
2990 /* There's a get_pointer within context::new_function_ptr_type:
2991 the type received by client code isn't the memento for the
2992 function_type, but instead the result of get_pointer on it.
2994 Hence we can't directly write a reproducer that gives function_type.
2995 Instead we special-case things within get_pointer, detecting this
2996 case, calling the following function. */
2999 recording::function_type::write_deferred_reproducer (reproducer
&r
,
3002 gcc_assert (ptr_type
);
3003 r
.make_identifier (this, "function_type");
3004 const char *ptr_id
= r
.make_identifier (ptr_type
, "ptr_to");
3005 const char *param_types_id
= r
.make_tmp_identifier ("params_for", this);
3006 r
.write (" gcc_jit_type *%s[%i] = {\n",
3008 m_param_types
.length ());
3011 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
3012 r
.write (" %s,\n", r
.get_identifier_as_type (param_type
));
3014 r
.write (" gcc_jit_type *%s =\n"
3015 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
3016 " %s, /* gcc_jit_location *loc */\n"
3017 " %s, /* gcc_jit_type *return_type */\n"
3018 " %i, /* int num_params */\n"
3019 " %s, /* gcc_jit_type **param_types */\n"
3020 " %i); /* int is_variadic */\n",
3022 r
.get_identifier (get_context ()),
3023 "NULL", /* location is not stored */
3024 r
.get_identifier_as_type (m_return_type
),
3025 m_param_types
.length (),
3030 /* The implementation of class gcc::jit::recording::field. */
3032 /* Implementation of pure virtual hook recording::memento::replay_into
3033 for recording::field. */
3036 recording::field::replay_into (replayer
*r
)
3038 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
3039 m_type
->playback_type (),
3040 playback_string (m_name
)));
3043 /* Override the default implementation of
3044 recording::memento::write_to_dump. Dump each field
3045 by dumping a line of the form:
3047 so that we can build up a struct/union field by field. */
3050 recording::field::write_to_dump (dump
&d
)
3052 d
.write (" %s %s;\n",
3053 m_type
->get_debug_string (),
3057 /* Implementation of recording::memento::make_debug_string for
3058 results of new_field. */
3061 recording::field::make_debug_string ()
3066 /* Implementation of recording::memento::write_reproducer for fields. */
3069 recording::field::write_reproducer (reproducer
&r
)
3071 const char *id
= r
.make_identifier (this, "field");
3072 r
.write(" gcc_jit_field *%s =\n"
3073 " gcc_jit_context_new_field (%s,\n"
3074 " %s, /* gcc_jit_location *loc */\n"
3075 " %s, /* gcc_jit_type *type, */\n"
3076 " %s); /* const char *name */\n",
3078 r
.get_identifier (get_context ()),
3079 r
.get_identifier (m_loc
),
3080 r
.get_identifier_as_type (m_type
),
3081 m_name
->get_debug_string ());
3084 /* The implementation of class gcc::jit::recording::bitfield. */
3086 /* Implementation of pure virtual hook recording::memento::replay_into
3087 for recording::bitfield. */
3090 recording::bitfield::replay_into (replayer
*r
)
3092 set_playback_obj (r
->new_bitfield (playback_location (r
, m_loc
),
3093 m_type
->playback_type (),
3095 playback_string (m_name
)));
3098 /* Override the default implementation of
3099 recording::memento::write_to_dump. Dump each bit field
3100 by dumping a line of the form:
3102 so that we can build up a struct/union field by field. */
3105 recording::bitfield::write_to_dump (dump
&d
)
3107 d
.write (" %s %s:%d;\n",
3108 m_type
->get_debug_string (),
3113 /* Implementation of recording::memento::make_debug_string for
3114 results of new_bitfield. */
3117 recording::bitfield::make_debug_string ()
3119 return string::from_printf (m_ctxt
,
3121 m_name
->c_str (), m_width
);
3124 /* Implementation of recording::memento::write_reproducer for bitfields. */
3127 recording::bitfield::write_reproducer (reproducer
&r
)
3129 const char *id
= r
.make_identifier (this, "bitfield");
3130 r
.write (" gcc_jit_field *%s =\n"
3131 " gcc_jit_context_new_bitfield (%s,\n"
3132 " %s, /* gcc_jit_location *loc */\n"
3133 " %s, /* gcc_jit_type *type, */\n"
3134 " %d, /* int width, */\n"
3135 " %s); /* const char *name */\n",
3137 r
.get_identifier (get_context ()),
3138 r
.get_identifier (m_loc
),
3139 r
.get_identifier_as_type (m_type
),
3141 m_name
->get_debug_string ());
3144 /* The implementation of class gcc::jit::recording::compound_type */
3146 /* The constructor for gcc::jit::recording::compound_type. */
3148 recording::compound_type::compound_type (context
*ctxt
,
3158 /* Set the fields of a compound type.
3160 Implements the post-error-checking part of
3161 gcc_jit_struct_set_fields, and is also used by
3162 gcc_jit_context_new_union_type. */
3165 recording::compound_type::set_fields (location
*loc
,
3167 field
**field_array
)
3170 gcc_assert (m_fields
== NULL
);
3172 m_fields
= new fields (this, num_fields
, field_array
);
3173 m_ctxt
->record (m_fields
);
3176 /* Implementation of pure virtual hook recording::type::dereference for
3177 recording::compound_type. */
3180 recording::compound_type::dereference ()
3182 return NULL
; /* not a pointer */
3185 /* The implementation of class gcc::jit::recording::struct_. */
3187 /* The constructor for gcc::jit::recording::struct_. */
3189 recording::struct_::struct_ (context
*ctxt
,
3192 : compound_type (ctxt
, loc
, name
)
3196 /* Implementation of pure virtual hook recording::memento::replay_into
3197 for recording::struct_. */
3200 recording::struct_::replay_into (replayer
*r
)
3203 r
->new_compound_type (playback_location (r
, get_loc ()),
3204 get_name ()->c_str (),
3205 true /* is_struct */));
3209 recording::struct_::access_as_type (reproducer
&r
)
3211 return r
.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
3212 r
.get_identifier (this));
3215 /* Implementation of recording::memento::make_debug_string for
3219 recording::struct_::make_debug_string ()
3221 return string::from_printf (m_ctxt
,
3222 "struct %s", get_name ()->c_str ());
3226 recording::struct_::write_reproducer (reproducer
&r
)
3228 const char *id
= r
.make_identifier (this, "struct");
3229 r
.write (" gcc_jit_struct *%s =\n"
3230 " gcc_jit_context_new_opaque_struct (%s,\n"
3231 " %s, /* gcc_jit_location *loc */\n"
3232 " %s); /* const char *name */\n",
3234 r
.get_identifier (get_context ()),
3235 r
.get_identifier (get_loc ()),
3236 get_name ()->get_debug_string ());
3239 /* The implementation of class gcc::jit::recording::union_. */
3241 /* The constructor for gcc::jit::recording::union_. */
3243 recording::union_::union_ (context
*ctxt
,
3246 : compound_type (ctxt
, loc
, name
)
3250 /* Implementation of pure virtual hook recording::memento::replay_into
3251 for recording::union_. */
3254 recording::union_::replay_into (replayer
*r
)
3257 r
->new_compound_type (playback_location (r
, get_loc ()),
3258 get_name ()->c_str (),
3259 false /* is_struct */));
3262 /* Implementation of recording::memento::make_debug_string for
3266 recording::union_::make_debug_string ()
3268 return string::from_printf (m_ctxt
,
3269 "union %s", get_name ()->c_str ());
3272 /* Implementation of recording::memento::write_reproducer for unions. */
3275 recording::union_::write_reproducer (reproducer
&r
)
3277 const char *id
= r
.make_identifier (this, "union");
3279 const char *fields_id
= r
.make_tmp_identifier ("fields_for", this);
3280 r
.write (" gcc_jit_field *%s[%i] = {\n",
3282 get_fields ()->length ());
3283 for (int i
= 0; i
< get_fields ()->length (); i
++)
3284 r
.write (" %s,\n", r
.get_identifier (get_fields ()->get_field (i
)));
3287 r
.write (" gcc_jit_type *%s =\n"
3288 " gcc_jit_context_new_union_type (%s,\n"
3289 " %s, /* gcc_jit_location *loc */\n"
3290 " %s, /* const char *name */\n"
3291 " %i, /* int num_fields */\n"
3292 " %s); /* gcc_jit_field **fields */\n",
3294 r
.get_identifier (get_context ()),
3295 r
.get_identifier (get_loc ()),
3296 get_name ()->get_debug_string (),
3297 get_fields ()->length (),
3301 /* The implementation of class gcc::jit::recording::fields. */
3303 /* The constructor for gcc::jit::recording::fields. */
3305 recording::fields::fields (compound_type
*struct_or_union
,
3308 : memento (struct_or_union
->m_ctxt
),
3309 m_struct_or_union (struct_or_union
),
3312 for (int i
= 0; i
< num_fields
; i
++)
3314 gcc_assert (fields
[i
]->get_container () == NULL
);
3315 fields
[i
]->set_container (m_struct_or_union
);
3316 m_fields
.safe_push (fields
[i
]);
3320 /* Implementation of pure virtual hook recording::memento::replay_into
3321 for recording::fields. */
3324 recording::fields::replay_into (replayer
*)
3326 auto_vec
<playback::field
*> playback_fields
;
3327 playback_fields
.create (m_fields
.length ());
3328 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
3329 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
3330 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
3333 /* Override the default implementation of
3334 recording::memento::write_to_dump by writing a union/struct
3335 declaration of this form:
3347 recording::fields::write_to_dump (dump
&d
)
3352 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
3353 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
3354 f
->write_to_dump (d
);
3358 /* Implementation of recording::memento::write_reproducer for the fields
3362 recording::fields::write_reproducer (reproducer
&r
)
3364 if (m_struct_or_union
)
3365 if (m_struct_or_union
->dyn_cast_struct () == NULL
)
3366 /* We have a union; the fields have already been written by
3367 union::write_reproducer. */
3370 const char *fields_id
= r
.make_identifier (this, "fields");
3371 r
.write (" gcc_jit_field *%s[%i] = {\n",
3373 m_fields
.length ());
3376 FOR_EACH_VEC_ELT (m_fields
, i
, field
)
3377 r
.write (" %s,\n", r
.get_identifier (field
));
3380 r
.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
3381 " %s, /* gcc_jit_location *loc */\n"
3382 " %i, /* int num_fields */\n"
3383 " %s); /* gcc_jit_field **fields */\n",
3384 r
.get_identifier (m_struct_or_union
),
3385 r
.get_identifier ((memento
*)NULL
),
3390 /* Implementation of recording::memento::make_debug_string for
3394 recording::fields::make_debug_string ()
3396 return string::from_printf (m_ctxt
,
3400 /* The implementation of class gcc::jit::recording::rvalue. */
3402 /* Create a recording::access_field_rvalue instance and add it to
3403 the rvalue's context's list of mementos.
3405 Implements the post-error-checking part of
3406 gcc_jit_rvalue_access_field. */
3409 recording::rvalue::access_field (recording::location
*loc
,
3412 recording::rvalue
*result
=
3413 new access_field_rvalue (m_ctxt
, loc
, this, field
);
3414 m_ctxt
->record (result
);
3418 /* Create a recording::dereference_field_rvalue instance and add it to
3419 the rvalue's context's list of mementos.
3421 Implements the post-error-checking part of
3422 gcc_jit_rvalue_dereference_field. */
3425 recording::rvalue::dereference_field (recording::location
*loc
,
3428 recording::lvalue
*result
=
3429 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
3430 m_ctxt
->record (result
);
3434 /* Create a recording::dereference_rvalue instance and add it to the
3435 rvalue's context's list of mementos.
3437 Implements the post-error-checking part of
3438 gcc_jit_rvalue_dereference. */
3441 recording::rvalue::dereference (recording::location
*loc
)
3443 recording::lvalue
*result
=
3444 new dereference_rvalue (m_ctxt
, loc
, this);
3445 m_ctxt
->record (result
);
3449 /* An rvalue visitor, for validating that every rvalue within an expression
3450 trees within "STMT" has the correct scope (e.g. no access to locals
3451 of a different function). */
3453 class rvalue_usage_validator
: public recording::rvalue_visitor
3456 rvalue_usage_validator (const char *api_funcname
,
3457 recording::context
*ctxt
,
3458 recording::statement
*stmt
);
3461 visit (recording::rvalue
*rvalue
) FINAL OVERRIDE
;
3464 const char *m_api_funcname
;
3465 recording::context
*m_ctxt
;
3466 recording::statement
*m_stmt
;
3469 /* The trivial constructor for rvalue_usage_validator. */
3471 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname
,
3472 recording::context
*ctxt
,
3473 recording::statement
*stmt
)
3474 : m_api_funcname (api_funcname
),
3480 /* Verify that the given rvalue is in the correct scope. */
3483 rvalue_usage_validator::visit (recording::rvalue
*rvalue
)
3485 gcc_assert (m_stmt
->get_block ());
3486 recording::function
*stmt_scope
= m_stmt
->get_block ()->get_function ();
3488 /* Most rvalues don't have a scope (only locals and params). */
3489 if (rvalue
->get_scope ())
3491 if (rvalue
->get_scope () != stmt_scope
)
3493 (rvalue
->get_loc (),
3495 " rvalue %s (type: %s)"
3496 " has scope limited to function %s"
3497 " but was used within function %s"
3498 " (in statement: %s)",
3500 rvalue
->get_debug_string (),
3501 rvalue
->get_type ()->get_debug_string (),
3502 rvalue
->get_scope ()->get_debug_string (),
3503 stmt_scope
->get_debug_string (),
3504 m_stmt
->get_debug_string ());
3508 if (rvalue
->dyn_cast_param ())
3510 (rvalue
->get_loc (),
3512 " param %s (type: %s)"
3513 " was used within function %s"
3514 " (in statement: %s)"
3515 " but is not associated with any function",
3517 rvalue
->get_debug_string (),
3518 rvalue
->get_type ()->get_debug_string (),
3519 stmt_scope
->get_debug_string (),
3520 m_stmt
->get_debug_string ());
3524 /* Verify that it's valid to use this rvalue (and all expressions
3525 in the tree below it) within the given statement.
3527 For example, we must reject attempts to use a local from one
3528 function within a different function here, or we'll get
3529 an ICE deep inside toplev::main. */
3532 recording::rvalue::verify_valid_within_stmt (const char *api_funcname
, statement
*s
)
3534 rvalue_usage_validator
v (api_funcname
,
3538 /* Verify that it's OK to use this rvalue within s. */
3541 /* Traverse the expression tree below "this", verifying all rvalues
3543 visit_children (&v
);
3546 /* Set the scope of this rvalue to be the given function. This can only
3547 be done once on a given rvalue. */
3550 recording::rvalue::set_scope (function
*scope
)
3553 gcc_assert (m_scope
== NULL
);
3558 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3560 Instances of rvalue don't need an upcast call. */
3563 recording::rvalue::access_as_rvalue (reproducer
&r
)
3565 return r
.get_identifier (this);
3568 /* Return a debug string for the given rvalue, wrapping it in parentheses
3569 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3570 stronger precedence that this rvalue's precedence.
3584 since MULT has strong precedence than PLUS and MINUS, whereas for:
3596 since PLUS has weaker precedence than MULT and DIVIDE. */
3599 recording::rvalue::get_debug_string_parens (enum precedence outer_prec
)
3601 enum precedence this_prec
= get_precedence ();
3603 /* If this_prec has stronger precedence than outer_prec, we don't
3604 need to wrap this in parens within the outer debug string.
3605 Stronger precedences occur earlier than weaker within the enum,
3606 so this is a less than test. Equal precedences don't need
3608 if (this_prec
<= outer_prec
)
3609 return get_debug_string();
3611 /* Otherwise, we need parentheses. */
3613 /* Lazily-build and cache m_parenthesized_string. */
3614 if (!m_parenthesized_string
)
3616 const char *debug_string
= get_debug_string ();
3617 m_parenthesized_string
= string::from_printf (get_context (),
3621 gcc_assert (m_parenthesized_string
);
3622 return m_parenthesized_string
->c_str ();
3626 /* The implementation of class gcc::jit::recording::lvalue. */
3628 /* Create a recording::new_access_field_of_lvalue instance and add it to
3629 the lvalue's context's list of mementos.
3631 Implements the post-error-checking part of
3632 gcc_jit_lvalue_access_field. */
3635 recording::lvalue::access_field (recording::location
*loc
,
3638 recording::lvalue
*result
=
3639 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
3640 m_ctxt
->record (result
);
3644 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3645 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3649 recording::lvalue::access_as_rvalue (reproducer
&r
)
3651 return r
.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3652 r
.get_identifier (this));
3655 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3656 Instances of lvalue don't need to be upcast. */
3659 recording::lvalue::access_as_lvalue (reproducer
&r
)
3661 return r
.get_identifier (this);
3664 /* Create a recording::get_address_of_lvalue instance and add it to
3665 the lvalue's context's list of mementos.
3667 Implements the post-error-checking part of
3668 gcc_jit_lvalue_get_address. */
3671 recording::lvalue::get_address (recording::location
*loc
)
3673 recording::rvalue
*result
=
3674 new get_address_of_lvalue (m_ctxt
, loc
, this);
3675 m_ctxt
->record (result
);
3679 /* The implementation of class gcc::jit::recording::param. */
3681 /* Implementation of pure virtual hook recording::memento::replay_into
3682 for recording::param. */
3685 recording::param::replay_into (replayer
*r
)
3687 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
3688 m_type
->playback_type (),
3692 /* Implementation of recording::rvalue::access_as_rvalue for params.
3693 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3697 recording::param::access_as_rvalue (reproducer
&r
)
3699 return r
.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3700 r
.get_identifier (this));
3703 /* Implementation of recording::lvalue::access_as_lvalue for params.
3704 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3708 recording::param::access_as_lvalue (reproducer
&r
)
3710 return r
.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3711 r
.get_identifier (this));
3714 /* Implementation of recording::memento::write_reproducer for params. */
3717 recording::param::write_reproducer (reproducer
&r
)
3719 const char *id
= r
.make_identifier (this, "param");
3720 r
.write (" gcc_jit_param *%s =\n"
3721 " gcc_jit_context_new_param (%s,\n"
3722 " %s, /* gcc_jit_location *loc */\n"
3723 " %s, /*gcc_jit_type *type */\n"
3724 " %s); /* const char *name */\n",
3726 r
.get_identifier (get_context ()),
3727 r
.get_identifier (m_loc
),
3728 r
.get_identifier_as_type (m_type
),
3729 m_name
->get_debug_string ());
3732 /* The implementation of class gcc::jit::recording::function. */
3734 /* gcc::jit::recording::function's constructor. */
3736 recording::function::function (context
*ctxt
,
3737 recording::location
*loc
,
3738 enum gcc_jit_function_kind kind
,
3740 recording::string
*name
,
3742 recording::param
**params
,
3744 enum built_in_function builtin_id
)
3748 m_return_type (return_type
),
3751 m_is_variadic (is_variadic
),
3752 m_builtin_id (builtin_id
),
3755 m_fn_ptr_type (NULL
)
3757 for (int i
= 0; i
< num_params
; i
++)
3759 param
*param
= params
[i
];
3762 /* Associate each param with this function.
3764 Verify that the param doesn't already have a function. */
3765 if (param
->get_scope ())
3767 /* We've already rejected attempts to reuse a param between
3768 different functions (within gcc_jit_context_new_function), so
3769 if the param *does* already have a function, it must be being
3770 reused within the params array for this function. We must
3771 produce an error for this reuse (blocking the compile), since
3772 otherwise we'd have an ICE later on. */
3773 gcc_assert (this == param
->get_scope ());
3776 "gcc_jit_context_new_function:"
3777 " parameter %s (type: %s)"
3778 " is used more than once when creating function %s",
3779 param
->get_debug_string (),
3780 param
->get_type ()->get_debug_string (),
3785 /* The normal, non-error case: associate this function with the
3787 param
->set_scope (this);
3790 m_params
.safe_push (param
);
3794 /* Implementation of pure virtual hook recording::memento::replay_into
3795 for recording::function. */
3798 recording::function::replay_into (replayer
*r
)
3800 /* Convert m_params to a vec of playback param. */
3801 auto_vec
<playback::param
*> params
;
3803 recording::param
*param
;
3804 params
.create (m_params
.length ());
3805 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3806 params
.safe_push (param
->playback_param ());
3808 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
3810 m_return_type
->playback_type (),
3817 /* Create a recording::local instance and add it to
3818 the functions's context's list of mementos, and to the function's
3821 Implements the post-error-checking part of
3822 gcc_jit_function_new_local. */
3825 recording::function::new_local (recording::location
*loc
,
3829 local
*result
= new local (this, loc
, type
, new_string (name
));
3830 m_ctxt
->record (result
);
3831 m_locals
.safe_push (result
);
3835 /* Create a recording::block instance and add it to
3836 the functions's context's list of mementos, and to the function's
3839 Implements the post-error-checking part of
3840 gcc_jit_function_new_block. */
3843 recording::function::new_block (const char *name
)
3845 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
3847 recording::block
*result
=
3848 new recording::block (this, m_blocks
.length (), new_string (name
));
3849 m_ctxt
->record (result
);
3850 m_blocks
.safe_push (result
);
3854 /* Override the default implementation of
3855 recording::memento::write_to_dump by dumping a C-like
3856 representation of the function; either like a prototype
3857 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3858 all other kinds of function. */
3861 recording::function::write_to_dump (dump
&d
)
3865 default: gcc_unreachable ();
3866 case GCC_JIT_FUNCTION_EXPORTED
:
3867 case GCC_JIT_FUNCTION_IMPORTED
:
3868 d
.write ("extern ");
3870 case GCC_JIT_FUNCTION_INTERNAL
:
3871 d
.write ("static ");
3873 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
3874 d
.write ("static inline ");
3877 d
.write ("%s\n", m_return_type
->get_debug_string ());
3879 if (d
.update_locations ())
3880 m_loc
= d
.make_location ();
3882 d
.write ("%s (", get_debug_string ());
3885 recording::param
*param
;
3886 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3891 param
->get_type ()->get_debug_string (),
3892 param
->get_debug_string ());
3895 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
3897 d
.write ("; /* (imported) */\n\n");
3907 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
3908 var
->write_to_dump (d
);
3909 if (m_locals
.length ())
3912 /* Write each block: */
3913 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3917 b
->write_to_dump (d
);
3924 /* Pre-compilation validation of a function, for those things we can't
3925 check until the context is (supposedly) fully-populated. */
3928 recording::function::validate ()
3930 /* Complain about empty functions with non-void return type. */
3931 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
3932 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
3933 if (m_blocks
.length () == 0)
3934 m_ctxt
->add_error (m_loc
,
3935 "function %s returns non-void (type: %s)"
3936 " but has no blocks",
3937 get_debug_string (),
3938 m_return_type
->get_debug_string ());
3940 /* Check that all blocks are terminated. */
3941 int num_invalid_blocks
= 0;
3946 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3947 if (!b
->validate ())
3948 num_invalid_blocks
++;
3951 /* Check that all blocks are reachable. */
3952 if (!m_ctxt
->get_inner_bool_option
3953 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS
)
3954 && m_blocks
.length () > 0 && num_invalid_blocks
== 0)
3956 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3957 flag, starting at the initial block. */
3958 auto_vec
<block
*> worklist (m_blocks
.length ());
3959 worklist
.safe_push (m_blocks
[0]);
3960 while (worklist
.length () > 0)
3962 block
*b
= worklist
.pop ();
3963 b
->m_is_reachable
= true;
3965 /* Add successor blocks that aren't yet marked to the worklist. */
3966 /* We checked that each block has a terminating statement above . */
3967 vec
<block
*> successors
= b
->get_successor_blocks ();
3970 FOR_EACH_VEC_ELT (successors
, i
, succ
)
3971 if (!succ
->m_is_reachable
)
3972 worklist
.safe_push (succ
);
3973 successors
.release ();
3976 /* Now complain about any blocks that haven't been marked. */
3980 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3981 if (!b
->m_is_reachable
)
3982 m_ctxt
->add_error (b
->get_loc (),
3983 "unreachable block: %s",
3984 b
->get_debug_string ());
3989 /* Implements the post-error-checking part of
3990 gcc_jit_function_dump_to_dot. */
3993 recording::function::dump_to_dot (const char *path
)
3995 FILE *fp
= fopen (path
, "w");
3999 pretty_printer the_pp
;
4000 the_pp
.buffer
->stream
= fp
;
4002 pretty_printer
*pp
= &the_pp
;
4005 "digraph %s {\n", get_debug_string ());
4011 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
4012 b
->dump_to_dot (pp
);
4019 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
4020 b
->dump_edges_to_dot (pp
);
4023 pp_printf (pp
, "}\n");
4028 /* Implements the post-error-checking part of
4029 gcc_jit_function_get_address. */
4032 recording::function::get_address (recording::location
*loc
)
4034 /* Lazily create and cache the function pointer type. */
4037 /* Make a recording::function_type for this function. */
4038 auto_vec
<recording::type
*> param_types (m_params
.length ());
4040 recording::param
*param
;
4041 FOR_EACH_VEC_ELT (m_params
, i
, param
)
4042 param_types
.safe_push (param
->get_type ());
4043 recording::function_type
*fn_type
4044 = m_ctxt
->new_function_type (m_return_type
,
4046 param_types
.address (),
4048 m_fn_ptr_type
= fn_type
->get_pointer ();
4050 gcc_assert (m_fn_ptr_type
);
4052 rvalue
*result
= new function_pointer (get_context (), loc
, this, m_fn_ptr_type
);
4053 m_ctxt
->record (result
);
4057 /* Implementation of recording::memento::make_debug_string for
4061 recording::function::make_debug_string ()
4066 /* A table of enum gcc_jit_function_kind values expressed in string
4069 static const char * const names_of_function_kinds
[] = {
4070 "GCC_JIT_FUNCTION_EXPORTED",
4071 "GCC_JIT_FUNCTION_INTERNAL",
4072 "GCC_JIT_FUNCTION_IMPORTED",
4073 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
4076 /* Implementation of recording::memento::write_reproducer for functions. */
4079 recording::function::write_reproducer (reproducer
&r
)
4081 const char *id
= r
.make_identifier (this, "func");
4085 r
.write (" gcc_jit_function *%s =\n"
4086 " gcc_jit_context_get_builtin_function (%s,\n"
4089 r
.get_identifier (get_context ()),
4090 m_name
->get_debug_string ());
4093 const char *params_id
= r
.make_tmp_identifier ("params_for", this);
4094 r
.write (" gcc_jit_param *%s[%i] = {\n",
4096 m_params
.length ());
4099 FOR_EACH_VEC_ELT (m_params
, i
, param
)
4100 r
.write (" %s,\n", r
.get_identifier (param
));
4102 r
.write (" gcc_jit_function *%s =\n"
4103 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
4104 " %s, /* gcc_jit_location *loc */\n"
4105 " %s, /* enum gcc_jit_function_kind kind */\n"
4106 " %s, /* gcc_jit_type *return_type */\n"
4107 " %s, /* const char *name */\n"
4108 " %i, /* int num_params */\n"
4109 " %s, /* gcc_jit_param **params */\n"
4110 " %i); /* int is_variadic */\n",
4112 r
.get_identifier (get_context ()),
4113 r
.get_identifier (m_loc
),
4114 names_of_function_kinds
[m_kind
],
4115 r
.get_identifier_as_type (m_return_type
),
4116 m_name
->get_debug_string (),
4123 /* The implementation of class gcc::jit::recording::block. */
4125 /* Create a recording::eval instance and add it to
4126 the block's context's list of mementos, and to the block's
4129 Implements the heart of gcc_jit_block_add_eval. */
4131 recording::statement
*
4132 recording::block::add_eval (recording::location
*loc
,
4133 recording::rvalue
*rvalue
)
4135 statement
*result
= new eval (this, loc
, rvalue
);
4136 m_ctxt
->record (result
);
4137 m_statements
.safe_push (result
);
4141 /* Create a recording::assignment instance and add it to
4142 the block's context's list of mementos, and to the block's
4145 Implements the heart of gcc_jit_block_add_assignment. */
4147 recording::statement
*
4148 recording::block::add_assignment (recording::location
*loc
,
4149 recording::lvalue
*lvalue
,
4150 recording::rvalue
*rvalue
)
4152 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
4153 m_ctxt
->record (result
);
4154 m_statements
.safe_push (result
);
4158 /* Create a recording::assignment_op instance and add it to
4159 the block's context's list of mementos, and to the block's
4162 Implements the heart of gcc_jit_block_add_assignment_op. */
4164 recording::statement
*
4165 recording::block::add_assignment_op (recording::location
*loc
,
4166 recording::lvalue
*lvalue
,
4167 enum gcc_jit_binary_op op
,
4168 recording::rvalue
*rvalue
)
4170 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
4171 m_ctxt
->record (result
);
4172 m_statements
.safe_push (result
);
4176 /* Create a recording::comment instance and add it to
4177 the block's context's list of mementos, and to the block's
4180 Implements the heart of gcc_jit_block_add_comment. */
4182 recording::statement
*
4183 recording::block::add_comment (recording::location
*loc
,
4186 statement
*result
= new comment (this, loc
, new_string (text
));
4187 m_ctxt
->record (result
);
4188 m_statements
.safe_push (result
);
4192 /* Create a recording::end_with_conditional instance and add it to
4193 the block's context's list of mementos, and to the block's
4196 Implements the heart of gcc_jit_block_end_with_conditional. */
4198 recording::statement
*
4199 recording::block::end_with_conditional (recording::location
*loc
,
4200 recording::rvalue
*boolval
,
4201 recording::block
*on_true
,
4202 recording::block
*on_false
)
4204 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
4205 m_ctxt
->record (result
);
4206 m_statements
.safe_push (result
);
4207 m_has_been_terminated
= true;
4211 /* Create a recording::end_with_jump instance and add it to
4212 the block's context's list of mementos, and to the block's
4215 Implements the heart of gcc_jit_block_end_with_jump. */
4217 recording::statement
*
4218 recording::block::end_with_jump (recording::location
*loc
,
4219 recording::block
*target
)
4221 statement
*result
= new jump (this, loc
, target
);
4222 m_ctxt
->record (result
);
4223 m_statements
.safe_push (result
);
4224 m_has_been_terminated
= true;
4228 /* Create a recording::end_with_return instance and add it to
4229 the block's context's list of mementos, and to the block's
4232 Implements the post-error-checking parts of
4233 gcc_jit_block_end_with_return and
4234 gcc_jit_block_end_with_void_return. */
4236 recording::statement
*
4237 recording::block::end_with_return (recording::location
*loc
,
4238 recording::rvalue
*rvalue
)
4240 /* This is used by both gcc_jit_function_add_return and
4241 gcc_jit_function_add_void_return; rvalue will be non-NULL for
4242 the former and NULL for the latter. */
4243 statement
*result
= new return_ (this, loc
, rvalue
);
4244 m_ctxt
->record (result
);
4245 m_statements
.safe_push (result
);
4246 m_has_been_terminated
= true;
4250 /* Create a recording::switch_ instance and add it to
4251 the block's context's list of mementos, and to the block's
4254 Implements the heart of gcc_jit_block_end_with_switch. */
4256 recording::statement
*
4257 recording::block::end_with_switch (recording::location
*loc
,
4258 recording::rvalue
*expr
,
4259 recording::block
*default_block
,
4261 recording::case_
**cases
)
4263 statement
*result
= new switch_ (this, loc
,
4268 m_ctxt
->record (result
);
4269 m_statements
.safe_push (result
);
4270 m_has_been_terminated
= true;
4274 /* Override the default implementation of
4275 recording::memento::write_to_dump for blocks by writing
4276 an unindented block name as a label, followed by the indented
4286 recording::block::write_to_dump (dump
&d
)
4288 d
.write ("%s:\n", get_debug_string ());
4292 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
4293 s
->write_to_dump (d
);
4296 /* Validate a block by ensuring that it has been terminated. */
4299 recording::block::validate ()
4301 /* Check for termination. */
4302 if (!has_been_terminated ())
4304 statement
*stmt
= get_last_statement ();
4305 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
4306 m_func
->get_context ()->add_error (loc
,
4307 "unterminated block in %s: %s",
4308 m_func
->get_debug_string (),
4309 get_debug_string ());
4316 /* Get the source-location of a block by using that of the first
4317 statement within it, if any. */
4319 recording::location
*
4320 recording::block::get_loc () const
4322 recording::statement
*stmt
= get_first_statement ();
4324 return stmt
->get_loc ();
4329 /* Get the first statement within a block, if any. */
4331 recording::statement
*
4332 recording::block::get_first_statement () const
4334 if (m_statements
.length ())
4335 return m_statements
[0];
4340 /* Get the last statement within a block, if any. */
4342 recording::statement
*
4343 recording::block::get_last_statement () const
4345 if (m_statements
.length ())
4346 return m_statements
[m_statements
.length () - 1];
4351 /* Assuming that this block has been terminated, get the successor blocks
4352 as a vector. Ownership of the vector transfers to the caller, which
4353 must call its release () method.
4355 Used when validating functions, and when dumping dot representations
4358 vec
<recording::block
*>
4359 recording::block::get_successor_blocks () const
4361 gcc_assert (m_has_been_terminated
);
4362 statement
*last_statement
= get_last_statement ();
4363 gcc_assert (last_statement
);
4364 return last_statement
->get_successor_blocks ();
4367 /* Implementation of pure virtual hook recording::memento::replay_into
4368 for recording::block. */
4371 recording::block::replay_into (replayer
*)
4373 set_playback_obj (m_func
->playback_function ()
4374 ->new_block (playback_string (m_name
)));
4377 /* Implementation of recording::memento::make_debug_string for
4381 recording::block::make_debug_string ()
4386 return string::from_printf (m_ctxt
,
4387 "<UNNAMED BLOCK %p>",
4391 /* Implementation of recording::memento::write_reproducer for blocks. */
4394 recording::block::write_reproducer (reproducer
&r
)
4396 const char *id
= r
.make_identifier (this, "block");
4397 r
.write (" gcc_jit_block *%s =\n"
4398 " gcc_jit_function_new_block (%s, %s);\n",
4400 r
.get_identifier (m_func
),
4401 m_name
? m_name
->get_debug_string () : "NULL");
4404 /* Dump a block in graphviz form into PP, capturing the block name (if
4405 any) and the statements. */
4408 recording::block::dump_to_dot (pretty_printer
*pp
)
4412 "[shape=record,style=filled,fillcolor=white,label=\"{"),
4414 pp_write_text_to_stream (pp
);
4417 pp_string (pp
, m_name
->c_str ());
4418 pp_string (pp
, ":");
4420 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
4425 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
4427 pp_string (pp
, s
->get_debug_string ());
4429 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
4437 /* Dump the out-edges of the block in graphviz form into PP. */
4440 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
4442 vec
<block
*> successors
= get_successor_blocks ();
4445 FOR_EACH_VEC_ELT (successors
, i
, succ
)
4447 "\tblock_%d:s -> block_%d:n;\n",
4448 m_index
, succ
->m_index
);
4449 successors
.release ();
4452 /* The implementation of class gcc::jit::recording::global. */
4454 /* Implementation of pure virtual hook recording::memento::replay_into
4455 for recording::global. */
4458 recording::global::replay_into (replayer
*r
)
4462 ? r
->new_global_initialized (playback_location (r
, m_loc
),
4464 m_type
->playback_type (),
4465 m_type
->dereference ()->get_size (),
4466 m_initializer_num_bytes
4467 / m_type
->dereference ()->get_size (),
4469 playback_string (m_name
))
4470 : r
->new_global (playback_location (r
, m_loc
),
4472 m_type
->playback_type (),
4473 playback_string (m_name
)));
4476 /* Override the default implementation of
4477 recording::memento::write_to_dump for globals.
4478 This will be of the form:
4480 GCC_JIT_GLOBAL_EXPORTED:
4484 GCC_JIT_GLOBAL_INTERNAL:
4486 e.g. "static int foo;"
4488 GCC_JIT_GLOBAL_IMPORTED:
4490 e.g. "extern int foo;"
4492 These are written to the top of the dump by
4493 recording::context::dump_to_file. */
4496 recording::global::write_to_dump (dump
&d
)
4498 if (d
.update_locations ())
4499 m_loc
= d
.make_location ();
4506 case GCC_JIT_GLOBAL_EXPORTED
:
4509 case GCC_JIT_GLOBAL_INTERNAL
:
4510 d
.write ("static ");
4513 case GCC_JIT_GLOBAL_IMPORTED
:
4514 d
.write ("extern ");
4519 m_type
->get_debug_string (),
4520 get_debug_string ());
4529 const unsigned char *p
= (const unsigned char *)m_initializer
;
4530 for (size_t i
= 0; i
< m_initializer_num_bytes
; i
++)
4532 d
.write ("0x%x, ", p
[i
]);
4539 /* A table of enum gcc_jit_global_kind values expressed in string
4542 static const char * const global_kind_reproducer_strings
[] = {
4543 "GCC_JIT_GLOBAL_EXPORTED",
4544 "GCC_JIT_GLOBAL_INTERNAL",
4545 "GCC_JIT_GLOBAL_IMPORTED"
4548 template <typename T
>
4550 recording::global::write_initializer_reproducer (const char *id
, reproducer
&r
)
4552 const char *init_id
= r
.make_tmp_identifier ("init_for", this);
4553 r
.write (" %s %s[] =\n {",
4554 m_type
->dereference ()->get_debug_string (),
4557 const T
*p
= (const T
*)m_initializer
;
4558 for (size_t i
= 0; i
< m_initializer_num_bytes
/ sizeof (T
); i
++)
4560 r
.write ("%" PRIu64
", ", (uint64_t)p
[i
]);
4565 r
.write (" gcc_jit_global_set_initializer (%s, %s, sizeof (%s));\n",
4566 id
, init_id
, init_id
);
4569 /* Implementation of recording::memento::write_reproducer for globals. */
4572 recording::global::write_reproducer (reproducer
&r
)
4574 const char *id
= r
.make_identifier (this, "block");
4575 r
.write (" gcc_jit_lvalue *%s =\n"
4576 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4577 " %s, /* gcc_jit_location *loc */\n"
4578 " %s, /* enum gcc_jit_global_kind kind */\n"
4579 " %s, /* gcc_jit_type *type */\n"
4580 " %s); /* const char *name */\n",
4582 r
.get_identifier (get_context ()),
4583 r
.get_identifier (m_loc
),
4584 global_kind_reproducer_strings
[m_kind
],
4585 r
.get_identifier_as_type (get_type ()),
4586 m_name
->get_debug_string ());
4589 switch (m_type
->dereference ()->get_size ())
4592 write_initializer_reproducer
<uint8_t> (id
, r
);
4595 write_initializer_reproducer
<uint16_t> (id
, r
);
4598 write_initializer_reproducer
<uint32_t> (id
, r
);
4601 write_initializer_reproducer
<uint64_t> (id
, r
);
4604 /* This function is serving on sizes returned by 'get_size',
4605 these are all covered by the previous cases. */
4610 /* The implementation of the various const-handling classes:
4611 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4613 /* Explicit specialization of the various mementos we're interested in. */
4614 template class recording::memento_of_new_rvalue_from_const
<int>;
4615 template class recording::memento_of_new_rvalue_from_const
<long>;
4616 template class recording::memento_of_new_rvalue_from_const
<double>;
4617 template class recording::memento_of_new_rvalue_from_const
<void *>;
4619 /* Implementation of the pure virtual hook recording::memento::replay_into
4620 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4622 template <typename HOST_TYPE
>
4625 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
4628 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
4632 /* The make_debug_string and write_reproducer methods vary between the
4634 memento_of_new_rvalue_from_const <HOST_TYPE>
4635 classes, so we explicitly write specializations of them.
4637 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4638 namespaces are written out explicitly, which is why most of this file
4639 doesn't abbreviate things by entering the "recording" namespace.
4641 However, these specializations are required to be in the same namespace
4642 as the template, hence we now have to enter the gcc::jit::recording
4648 /* The make_debug_string specialization for <int>, which renders it as
4649 (TARGET_TYPE)LITERAL
4655 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
4657 return string::from_printf (m_ctxt
,
4659 m_type
->get_debug_string (),
4663 /* The get_wide_int specialization for <int>. */
4667 memento_of_new_rvalue_from_const
<int>::get_wide_int (wide_int
*out
) const
4669 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
4673 /* The write_reproducer specialization for <int>. */
4677 memento_of_new_rvalue_from_const
<int>::write_reproducer (reproducer
&r
)
4679 const char *id
= r
.make_identifier (this, "rvalue");
4680 r
.write (" gcc_jit_rvalue *%s =\n"
4681 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4682 " %s, /* gcc_jit_type *numeric_type */\n"
4683 " %i); /* int value */\n",
4685 r
.get_identifier (get_context ()),
4686 r
.get_identifier_as_type (m_type
),
4690 /* The make_debug_string specialization for <long>, rendering it as
4691 (TARGET_TYPE)LITERAL
4697 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
4699 return string::from_printf (m_ctxt
,
4701 m_type
->get_debug_string (),
4705 /* The get_wide_int specialization for <long>. */
4709 memento_of_new_rvalue_from_const
<long>::get_wide_int (wide_int
*out
) const
4711 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
4715 /* The write_reproducer specialization for <long>. */
4719 recording::memento_of_new_rvalue_from_const
<long>::write_reproducer (reproducer
&r
)
4721 const char *id
= r
.make_identifier (this, "rvalue");
4723 /* We have to special-case LONG_MIN, since e.g.
4724 -9223372036854775808L
4726 -(9223372036854775808L)
4728 error: integer constant is so large that it is unsigned [-Werror]
4729 Workaround this by writing (LONG_MIN + 1) - 1. */
4730 if (m_value
== LONG_MIN
)
4732 r
.write (" gcc_jit_rvalue *%s =\n"
4733 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4734 " %s, /* gcc_jit_type *numeric_type */\n"
4735 " %ldL - 1); /* long value */\n",
4737 r
.get_identifier (get_context ()),
4738 r
.get_identifier_as_type (m_type
),
4743 r
.write (" gcc_jit_rvalue *%s =\n"
4744 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4745 " %s, /* gcc_jit_type *numeric_type */\n"
4746 " %ldL); /* long value */\n",
4748 r
.get_identifier (get_context ()),
4749 r
.get_identifier_as_type (m_type
),
4753 /* The make_debug_string specialization for <double>, rendering it as
4754 (TARGET_TYPE)LITERAL
4760 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
4762 return string::from_printf (m_ctxt
,
4764 m_type
->get_debug_string (),
4768 /* The get_wide_int specialization for <double>. */
4772 memento_of_new_rvalue_from_const
<double>::get_wide_int (wide_int
*) const
4777 /* The write_reproducer specialization for <double>. */
4781 recording::memento_of_new_rvalue_from_const
<double>::write_reproducer (reproducer
&r
)
4783 const char *id
= r
.make_identifier (this, "rvalue");
4784 r
.write (" gcc_jit_rvalue *%s =\n"
4785 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4786 " %s, /* gcc_jit_type *numeric_type */\n"
4787 " %f); /* double value */\n",
4789 r
.get_identifier (get_context ()),
4790 r
.get_identifier_as_type (m_type
),
4794 /* The make_debug_string specialization for <void *>, rendering it as
4799 Zero is rendered as NULL e.g.
4804 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
4806 if (m_value
!= NULL
)
4807 return string::from_printf (m_ctxt
,
4809 m_type
->get_debug_string (), m_value
);
4811 return string::from_printf (m_ctxt
,
4813 m_type
->get_debug_string ());
4816 /* The get_wide_int specialization for <void *>. */
4820 memento_of_new_rvalue_from_const
<void *>::get_wide_int (wide_int
*) const
4825 /* Implementation of recording::memento::write_reproducer for <void *>
4830 memento_of_new_rvalue_from_const
<void *>::write_reproducer (reproducer
&r
)
4832 const char *id
= r
.make_identifier (this, "rvalue");
4834 r
.write (" gcc_jit_rvalue *%s =\n"
4835 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4836 " %s, /* gcc_jit_type *pointer_type */\n"
4837 " (void *)%p); /* void *value */\n",
4839 r
.get_identifier (get_context ()),
4840 r
.get_identifier_as_type (m_type
),
4843 r
.write (" gcc_jit_rvalue *%s =\n"
4844 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4845 " %s); /* gcc_jit_type *pointer_type */\n",
4847 r
.get_identifier (get_context ()),
4848 r
.get_identifier_as_type (m_type
));
4851 /* We're done specializing make_debug_string and write_reproducer, so we
4852 can exit the gcc::jit::recording namespace. */
4854 } // namespace recording
4856 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4858 /* Implementation of pure virtual hook recording::memento::replay_into
4859 for recording::memento_of_new_string_literal. */
4862 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
4864 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
4867 /* Implementation of recording::memento::make_debug_string for
4871 recording::memento_of_new_string_literal::make_debug_string ()
4873 return string::from_printf (m_ctxt
,
4875 m_value
->get_debug_string ());
4878 /* Implementation of recording::memento::write_reproducer for string literal
4882 recording::memento_of_new_string_literal::write_reproducer (reproducer
&r
)
4884 const char *id
= r
.make_identifier (this, "rvalue");
4885 r
.write (" gcc_jit_rvalue *%s =\n"
4886 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4887 " %s); /* const char *value */\n",
4889 r
.get_identifier (get_context ()),
4890 m_value
->get_debug_string ());
4893 /* The implementation of class
4894 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
4896 /* The constructor for
4897 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
4899 recording::memento_of_new_rvalue_from_vector::
4900 memento_of_new_rvalue_from_vector (context
*ctxt
,
4904 : rvalue (ctxt
, loc
, type
),
4905 m_vector_type (type
),
4908 for (unsigned i
= 0; i
< type
->get_num_units (); i
++)
4909 m_elements
.safe_push (elements
[i
]);
4912 /* Implementation of pure virtual hook recording::memento::replay_into
4913 for recording::memento_of_new_rvalue_from_vector. */
4916 recording::memento_of_new_rvalue_from_vector::replay_into (replayer
*r
)
4918 auto_vec
<playback::rvalue
*> playback_elements
;
4919 playback_elements
.create (m_elements
.length ());
4920 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
4921 playback_elements
.safe_push (m_elements
[i
]->playback_rvalue ());
4923 set_playback_obj (r
->new_rvalue_from_vector (playback_location (r
, m_loc
),
4924 m_type
->playback_type (),
4925 playback_elements
));
4928 /* Implementation of pure virtual hook recording::rvalue::visit_children
4929 for recording::memento_of_new_rvalue_from_vector. */
4932 recording::memento_of_new_rvalue_from_vector::visit_children (rvalue_visitor
*v
)
4934 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
4935 v
->visit (m_elements
[i
]);
4938 /* Implementation of recording::memento::make_debug_string for
4942 recording::memento_of_new_rvalue_from_vector::make_debug_string ()
4944 comma_separated_string
elements (m_elements
, get_precedence ());
4946 /* Now build a string. */
4947 string
*result
= string::from_printf (m_ctxt
,
4949 elements
.as_char_ptr ());
4955 /* Implementation of recording::memento::write_reproducer for
4959 recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer
&r
)
4961 const char *id
= r
.make_identifier (this, "vector");
4962 const char *elements_id
= r
.make_tmp_identifier ("elements_for_", this);
4963 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4965 m_elements
.length ());
4966 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
4967 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_elements
[i
]));
4969 r
.write (" gcc_jit_rvalue *%s =\n"
4970 " gcc_jit_context_new_rvalue_from_vector (%s, /* gcc_jit_context *ctxt */\n"
4971 " %s, /* gcc_jit_location *loc */\n"
4972 " %s, /* gcc_jit_type *vec_type */\n"
4973 " %i, /* size_t num_elements */ \n"
4974 " %s); /* gcc_jit_rvalue **elements*/\n",
4976 r
.get_identifier (get_context ()),
4977 r
.get_identifier (m_loc
),
4978 r
.get_identifier (m_vector_type
),
4979 m_elements
.length (),
4983 /* The implementation of class gcc::jit::recording::unary_op. */
4985 /* Implementation of pure virtual hook recording::memento::replay_into
4986 for recording::unary_op. */
4989 recording::unary_op::replay_into (replayer
*r
)
4991 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
4993 get_type ()->playback_type (),
4994 m_a
->playback_rvalue ()));
4997 /* Implementation of pure virtual hook recording::rvalue::visit_children
4998 for recording::unary_op. */
5000 recording::unary_op::visit_children (rvalue_visitor
*v
)
5005 /* Implementation of recording::memento::make_debug_string for
5008 static const char * const unary_op_strings
[] = {
5009 "-", /* GCC_JIT_UNARY_OP_MINUS */
5010 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
5011 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
5012 "abs ", /* GCC_JIT_UNARY_OP_ABS */
5016 recording::unary_op::make_debug_string ()
5018 return string::from_printf (m_ctxt
,
5020 unary_op_strings
[m_op
],
5021 m_a
->get_debug_string ());
5024 const char * const unary_op_reproducer_strings
[] = {
5025 "GCC_JIT_UNARY_OP_MINUS",
5026 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
5027 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
5028 "GCC_JIT_UNARY_OP_ABS"
5031 /* Implementation of recording::memento::write_reproducer for unary ops. */
5034 recording::unary_op::write_reproducer (reproducer
&r
)
5036 const char *id
= r
.make_identifier (this, "rvalue");
5037 r
.write (" gcc_jit_rvalue *%s =\n"
5038 " gcc_jit_context_new_unary_op (%s,\n"
5039 " %s, /* gcc_jit_location *loc */\n"
5040 " %s, /* enum gcc_jit_unary_op op */\n"
5041 " %s, /* gcc_jit_type *result_type */\n"
5042 " %s); /* gcc_jit_rvalue *a */\n",
5044 r
.get_identifier (get_context ()),
5045 r
.get_identifier (m_loc
),
5046 unary_op_reproducer_strings
[m_op
],
5047 r
.get_identifier_as_type (get_type ()),
5048 r
.get_identifier_as_rvalue (m_a
));
5051 /* The implementation of class gcc::jit::recording::binary_op. */
5053 /* Implementation of pure virtual hook recording::memento::replay_into
5054 for recording::binary_op. */
5057 recording::binary_op::replay_into (replayer
*r
)
5059 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
5061 get_type ()->playback_type (),
5062 m_a
->playback_rvalue (),
5063 m_b
->playback_rvalue ()));
5066 /* Implementation of pure virtual hook recording::rvalue::visit_children
5067 for recording::binary_op. */
5069 recording::binary_op::visit_children (rvalue_visitor
*v
)
5075 /* Implementation of recording::memento::make_debug_string for
5078 static const char * const binary_op_strings
[] = {
5079 "+", /* GCC_JIT_BINARY_OP_PLUS */
5080 "-", /* GCC_JIT_BINARY_OP_MINUS */
5081 "*", /* GCC_JIT_BINARY_OP_MULT */
5082 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
5083 "%", /* GCC_JIT_BINARY_OP_MODULO */
5084 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
5085 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
5086 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
5087 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
5088 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
5089 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
5090 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
5094 recording::binary_op::make_debug_string ()
5096 enum precedence prec
= get_precedence ();
5097 return string::from_printf (m_ctxt
,
5099 m_a
->get_debug_string_parens (prec
),
5100 binary_op_strings
[m_op
],
5101 m_b
->get_debug_string_parens (prec
));
5104 const char * const binary_op_reproducer_strings
[] = {
5105 "GCC_JIT_BINARY_OP_PLUS",
5106 "GCC_JIT_BINARY_OP_MINUS",
5107 "GCC_JIT_BINARY_OP_MULT",
5108 "GCC_JIT_BINARY_OP_DIVIDE",
5109 "GCC_JIT_BINARY_OP_MODULO",
5110 "GCC_JIT_BINARY_OP_BITWISE_AND",
5111 "GCC_JIT_BINARY_OP_BITWISE_XOR",
5112 "GCC_JIT_BINARY_OP_BITWISE_OR",
5113 "GCC_JIT_BINARY_OP_LOGICAL_AND",
5114 "GCC_JIT_BINARY_OP_LOGICAL_OR",
5115 "GCC_JIT_BINARY_OP_LSHIFT",
5116 "GCC_JIT_BINARY_OP_RSHIFT"
5119 /* Implementation of recording::memento::write_reproducer for binary ops. */
5122 recording::binary_op::write_reproducer (reproducer
&r
)
5124 const char *id
= r
.make_identifier (this, "rvalue");
5125 r
.write (" gcc_jit_rvalue *%s =\n"
5126 " gcc_jit_context_new_binary_op (%s,\n"
5127 " %s, /* gcc_jit_location *loc */\n"
5128 " %s, /* enum gcc_jit_binary_op op */\n"
5129 " %s, /* gcc_jit_type *result_type */\n"
5130 " %s, /* gcc_jit_rvalue *a */\n"
5131 " %s); /* gcc_jit_rvalue *b */\n",
5133 r
.get_identifier (get_context ()),
5134 r
.get_identifier (m_loc
),
5135 binary_op_reproducer_strings
[m_op
],
5136 r
.get_identifier_as_type (get_type ()),
5137 r
.get_identifier_as_rvalue (m_a
),
5138 r
.get_identifier_as_rvalue (m_b
));
5141 namespace recording
{
5142 static const enum precedence binary_op_precedence
[] = {
5143 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_PLUS */
5144 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_MINUS */
5146 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MULT */
5147 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_DIVIDE */
5148 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MODULO */
5150 PRECEDENCE_BITWISE_AND
, /* GCC_JIT_BINARY_OP_BITWISE_AND */
5151 PRECEDENCE_BITWISE_XOR
, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
5152 PRECEDENCE_BITWISE_IOR
, /* GCC_JIT_BINARY_OP_BITWISE_OR */
5153 PRECEDENCE_LOGICAL_AND
, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
5154 PRECEDENCE_LOGICAL_OR
, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
5155 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_LSHIFT */
5156 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_RSHIFT */
5158 } /* namespace recording */
5160 enum recording::precedence
5161 recording::binary_op::get_precedence () const
5163 return binary_op_precedence
[m_op
];
5166 /* The implementation of class gcc::jit::recording::comparison. */
5168 /* Implementation of recording::memento::make_debug_string for
5171 static const char * const comparison_strings
[] =
5173 "==", /* GCC_JIT_COMPARISON_EQ */
5174 "!=", /* GCC_JIT_COMPARISON_NE */
5175 "<", /* GCC_JIT_COMPARISON_LT */
5176 "<=", /* GCC_JIT_COMPARISON_LE */
5177 ">", /* GCC_JIT_COMPARISON_GT */
5178 ">=", /* GCC_JIT_COMPARISON_GE */
5182 recording::comparison::make_debug_string ()
5184 enum precedence prec
= get_precedence ();
5185 return string::from_printf (m_ctxt
,
5187 m_a
->get_debug_string_parens (prec
),
5188 comparison_strings
[m_op
],
5189 m_b
->get_debug_string_parens (prec
));
5192 /* A table of enum gcc_jit_comparison values expressed in string
5195 static const char * const comparison_reproducer_strings
[] =
5197 "GCC_JIT_COMPARISON_EQ",
5198 "GCC_JIT_COMPARISON_NE",
5199 "GCC_JIT_COMPARISON_LT",
5200 "GCC_JIT_COMPARISON_LE",
5201 "GCC_JIT_COMPARISON_GT",
5202 "GCC_JIT_COMPARISON_GE"
5205 /* Implementation of recording::memento::write_reproducer for comparisons. */
5208 recording::comparison::write_reproducer (reproducer
&r
)
5210 const char *id
= r
.make_identifier (this, "rvalue");
5211 r
.write (" gcc_jit_rvalue *%s =\n"
5212 " gcc_jit_context_new_comparison (%s,\n"
5213 " %s, /* gcc_jit_location *loc */\n"
5214 " %s, /* enum gcc_jit_comparison op */\n"
5215 " %s, /* gcc_jit_rvalue *a */\n"
5216 " %s); /* gcc_jit_rvalue *b */\n",
5218 r
.get_identifier (get_context ()),
5219 r
.get_identifier (m_loc
),
5220 comparison_reproducer_strings
[m_op
],
5221 r
.get_identifier_as_rvalue (m_a
),
5222 r
.get_identifier_as_rvalue (m_b
));
5225 /* Implementation of pure virtual hook recording::memento::replay_into
5226 for recording::comparison. */
5229 recording::comparison::replay_into (replayer
*r
)
5231 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
5233 m_a
->playback_rvalue (),
5234 m_b
->playback_rvalue ()));
5237 /* Implementation of pure virtual hook recording::rvalue::visit_children
5238 for recording::comparison. */
5241 recording::comparison::visit_children (rvalue_visitor
*v
)
5247 namespace recording
{
5248 static const enum precedence comparison_precedence
[] =
5250 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_EQ */
5251 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_NE */
5253 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LT */
5254 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LE */
5255 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GT */
5256 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GE */
5258 } /* namespace recording */
5260 enum recording::precedence
5261 recording::comparison::get_precedence () const
5263 return comparison_precedence
[m_op
];
5266 /* Implementation of pure virtual hook recording::memento::replay_into
5267 for recording::cast. */
5270 recording::cast::replay_into (replayer
*r
)
5272 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
5273 m_rvalue
->playback_rvalue (),
5274 get_type ()->playback_type ()));
5277 /* Implementation of pure virtual hook recording::rvalue::visit_children
5278 for recording::cast. */
5280 recording::cast::visit_children (rvalue_visitor
*v
)
5282 v
->visit (m_rvalue
);
5285 /* Implementation of recording::memento::make_debug_string for
5289 recording::cast::make_debug_string ()
5291 enum precedence prec
= get_precedence ();
5292 return string::from_printf (m_ctxt
,
5294 get_type ()->get_debug_string (),
5295 m_rvalue
->get_debug_string_parens (prec
));
5298 /* Implementation of recording::memento::write_reproducer for casts. */
5301 recording::cast::write_reproducer (reproducer
&r
)
5303 const char *id
= r
.make_identifier (this, "rvalue");
5304 r
.write (" gcc_jit_rvalue *%s =\n"
5305 " gcc_jit_context_new_cast (%s,\n"
5306 " %s, /* gcc_jit_location *loc */\n"
5307 " %s, /* gcc_jit_rvalue *rvalue */\n"
5308 " %s); /* gcc_jit_type *type */\n",
5310 r
.get_identifier (get_context ()),
5311 r
.get_identifier (m_loc
),
5312 r
.get_identifier_as_rvalue (m_rvalue
),
5313 r
.get_identifier_as_type (get_type ()));
5316 /* The implementation of class gcc::jit::recording::base_call. */
5318 /* The constructor for gcc::jit::recording::base_call. */
5320 recording::base_call::base_call (context
*ctxt
,
5325 : rvalue (ctxt
, loc
, type_
),
5327 m_require_tail_call (0)
5329 for (int i
= 0; i
< numargs
; i
++)
5330 m_args
.safe_push (args
[i
]);
5333 /* Subroutine for use by call and call_though_ptr's write_reproducer
5337 recording::base_call::write_reproducer_tail_call (reproducer
&r
,
5340 if (m_require_tail_call
)
5342 r
.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
5343 " %i); /* int require_tail_call*/\n",
5349 /* The implementation of class gcc::jit::recording::call. */
5351 /* The constructor for gcc::jit::recording::call. */
5353 recording::call::call (recording::context
*ctxt
,
5354 recording::location
*loc
,
5355 recording::function
*func
,
5358 : base_call (ctxt
, loc
, func
->get_return_type (), numargs
, args
),
5363 /* Implementation of pure virtual hook recording::memento::replay_into
5364 for recording::call. */
5367 recording::call::replay_into (replayer
*r
)
5369 auto_vec
<playback::rvalue
*> playback_args
;
5370 playback_args
.create (m_args
.length ());
5371 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5372 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
5374 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
5375 m_func
->playback_function (),
5377 m_require_tail_call
));
5380 /* Implementation of pure virtual hook recording::rvalue::visit_children
5381 for recording::call. */
5384 recording::call::visit_children (rvalue_visitor
*v
)
5386 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5387 v
->visit (m_args
[i
]);
5390 /* Implementation of recording::memento::make_debug_string for
5394 recording::call::make_debug_string ()
5396 /* First, build a buffer for the arguments. */
5397 comma_separated_string
args (m_args
, get_precedence ());
5399 /* ...and use it to get the string for the call as a whole. */
5400 string
*result
= string::from_printf (m_ctxt
,
5402 m_func
->get_debug_string (),
5403 args
.as_char_ptr ());
5409 recording::call::write_reproducer (reproducer
&r
)
5411 const char *id
= r
.make_identifier (this, "call");
5412 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
5413 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
5416 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5417 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
5419 r
.write (" gcc_jit_rvalue *%s =\n"
5420 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
5421 " %s, /* gcc_jit_location *loc */\n"
5422 " %s, /* gcc_jit_function *func */\n"
5423 " %i, /* int numargs */ \n"
5424 " %s); /* gcc_jit_rvalue **args*/\n",
5426 r
.get_identifier (get_context ()),
5427 r
.get_identifier (m_loc
),
5428 r
.get_identifier (m_func
),
5431 write_reproducer_tail_call (r
, id
);
5434 /* The implementation of class gcc::jit::recording::call_through_ptr. */
5436 /* The constructor for recording::call_through_ptr. */
5438 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
5439 recording::location
*loc
,
5440 recording::rvalue
*fn_ptr
,
5443 : base_call (ctxt
, loc
,
5444 fn_ptr
->get_type ()->dereference ()
5445 ->as_a_function_type ()->get_return_type (),
5451 /* Implementation of pure virtual hook recording::memento::replay_into
5452 for recording::call_through_ptr. */
5455 recording::call_through_ptr::replay_into (replayer
*r
)
5457 auto_vec
<playback::rvalue
*> playback_args
;
5458 playback_args
.create (m_args
.length ());
5459 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5460 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
5462 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
5463 m_fn_ptr
->playback_rvalue (),
5465 m_require_tail_call
));
5468 /* Implementation of pure virtual hook recording::rvalue::visit_children
5469 for recording::call_through_ptr. */
5472 recording::call_through_ptr::visit_children (rvalue_visitor
*v
)
5474 v
->visit (m_fn_ptr
);
5475 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5476 v
->visit (m_args
[i
]);
5479 /* Implementation of recording::memento::make_debug_string for
5480 calls through function ptrs. */
5483 recording::call_through_ptr::make_debug_string ()
5485 enum precedence prec
= get_precedence ();
5486 /* First, build a buffer for the arguments. */
5487 /* Calculate length of said buffer. */
5488 size_t sz
= 1; /* nil terminator */
5489 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5491 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
5492 sz
+= 2; /* ", " separator */
5495 /* Now allocate and populate the buffer. */
5496 char *argbuf
= new char[sz
];
5499 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5501 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
5502 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
5503 if (i
+ 1 < m_args
.length ())
5505 strcpy (argbuf
+ len
, ", ");
5511 /* ...and use it to get the string for the call as a whole. */
5512 string
*result
= string::from_printf (m_ctxt
,
5514 m_fn_ptr
->get_debug_string_parens (prec
),
5522 /* Implementation of recording::memento::write_reproducer for
5523 call_through_ptr. */
5526 recording::call_through_ptr::write_reproducer (reproducer
&r
)
5528 const char *id
= r
.make_identifier (this, "call");
5529 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
5530 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
5533 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5534 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
5536 r
.write (" gcc_jit_rvalue *%s =\n"
5537 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
5538 " %s, /* gcc_jit_location *loc */\n"
5539 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
5540 " %i, /* int numargs */ \n"
5541 " %s); /* gcc_jit_rvalue **args*/\n",
5543 r
.get_identifier (get_context ()),
5544 r
.get_identifier (m_loc
),
5545 r
.get_identifier_as_rvalue (m_fn_ptr
),
5548 write_reproducer_tail_call (r
, id
);
5551 /* The implementation of class gcc::jit::recording::array_access. */
5553 /* Implementation of pure virtual hook recording::memento::replay_into
5554 for recording::array_access. */
5557 recording::array_access::replay_into (replayer
*r
)
5560 r
->new_array_access (playback_location (r
, m_loc
),
5561 m_ptr
->playback_rvalue (),
5562 m_index
->playback_rvalue ()));
5565 /* Implementation of pure virtual hook recording::rvalue::visit_children
5566 for recording::array_access. */
5569 recording::array_access::visit_children (rvalue_visitor
*v
)
5575 /* Implementation of recording::memento::make_debug_string for
5579 recording::array_access::make_debug_string ()
5581 enum precedence prec
= get_precedence ();
5582 return string::from_printf (m_ctxt
,
5584 m_ptr
->get_debug_string_parens (prec
),
5585 m_index
->get_debug_string_parens (prec
));
5588 /* Implementation of recording::memento::write_reproducer for
5592 recording::array_access::write_reproducer (reproducer
&r
)
5594 const char *id
= r
.make_identifier (this, "lvalue");
5595 r
.write (" gcc_jit_lvalue *%s = \n"
5596 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
5597 " %s, /*gcc_jit_location *loc */\n"
5598 " %s, /* gcc_jit_rvalue *ptr */\n"
5599 " %s); /* gcc_jit_rvalue *index */\n",
5601 r
.get_identifier (get_context ()),
5602 r
.get_identifier (m_loc
),
5603 r
.get_identifier_as_rvalue (m_ptr
),
5604 r
.get_identifier_as_rvalue (m_index
));
5607 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
5609 /* Implementation of pure virtual hook recording::memento::replay_into
5610 for recording::access_field_of_lvalue. */
5613 recording::access_field_of_lvalue::replay_into (replayer
*r
)
5616 m_lvalue
->playback_lvalue ()
5617 ->access_field (playback_location (r
, m_loc
),
5618 m_field
->playback_field ()));
5622 /* Implementation of pure virtual hook recording::rvalue::visit_children
5623 for recording::access_field_of_lvalue. */
5626 recording::access_field_of_lvalue::visit_children (rvalue_visitor
*v
)
5628 v
->visit (m_lvalue
);
5631 /* Implementation of recording::memento::make_debug_string for
5632 accessing a field of an lvalue. */
5635 recording::access_field_of_lvalue::make_debug_string ()
5637 enum precedence prec
= get_precedence ();
5638 return string::from_printf (m_ctxt
,
5640 m_lvalue
->get_debug_string_parens (prec
),
5641 m_field
->get_debug_string ());
5644 /* Implementation of recording::memento::write_reproducer for
5645 access_field_of_lvalue. */
5648 recording::access_field_of_lvalue::write_reproducer (reproducer
&r
)
5650 const char *id
= r
.make_identifier (this, "lvalue");
5651 r
.write (" gcc_jit_lvalue *%s = \n"
5652 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5653 " %s, /*gcc_jit_location *loc */\n"
5656 r
.get_identifier_as_lvalue (m_lvalue
),
5657 r
.get_identifier (m_loc
),
5658 r
.get_identifier (m_field
));
5661 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
5663 /* Implementation of pure virtual hook recording::memento::replay_into
5664 for recording::access_field_rvalue. */
5667 recording::access_field_rvalue::replay_into (replayer
*r
)
5670 m_rvalue
->playback_rvalue ()
5671 ->access_field (playback_location (r
, m_loc
),
5672 m_field
->playback_field ()));
5675 /* Implementation of pure virtual hook recording::rvalue::visit_children
5676 for recording::access_field_rvalue. */
5679 recording::access_field_rvalue::visit_children (rvalue_visitor
*v
)
5681 v
->visit (m_rvalue
);
5684 /* Implementation of recording::memento::make_debug_string for
5685 accessing a field of an rvalue. */
5688 recording::access_field_rvalue::make_debug_string ()
5690 enum precedence prec
= get_precedence ();
5691 return string::from_printf (m_ctxt
,
5693 m_rvalue
->get_debug_string_parens (prec
),
5694 m_field
->get_debug_string ());
5697 /* Implementation of recording::memento::write_reproducer for
5698 access_field_rvalue. */
5701 recording::access_field_rvalue::write_reproducer (reproducer
&r
)
5703 const char *id
= r
.make_identifier (this, "rvalue");
5704 r
.write (" gcc_jit_rvalue *%s = \n"
5705 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5706 " %s, /*gcc_jit_location *loc */\n"
5709 r
.get_identifier_as_rvalue (m_rvalue
),
5710 r
.get_identifier (m_loc
),
5711 r
.get_identifier (m_field
));
5714 /* The implementation of class
5715 gcc::jit::recording::dereference_field_rvalue. */
5717 /* Implementation of pure virtual hook recording::memento::replay_into
5718 for recording::dereference_field_rvalue. */
5721 recording::dereference_field_rvalue::replay_into (replayer
*r
)
5724 m_rvalue
->playback_rvalue ()->
5725 dereference_field (playback_location (r
, m_loc
),
5726 m_field
->playback_field ()));
5729 /* Implementation of pure virtual hook recording::rvalue::visit_children
5730 for recording::dereference_field_rvalue. */
5733 recording::dereference_field_rvalue::visit_children (rvalue_visitor
*v
)
5735 v
->visit (m_rvalue
);
5738 /* Implementation of recording::memento::make_debug_string for
5739 dereferencing a field of an rvalue. */
5742 recording::dereference_field_rvalue::make_debug_string ()
5744 enum precedence prec
= get_precedence ();
5745 return string::from_printf (m_ctxt
,
5747 m_rvalue
->get_debug_string_parens (prec
),
5748 m_field
->get_debug_string ());
5751 /* Implementation of recording::memento::write_reproducer for
5752 dereference_field_rvalue. */
5755 recording::dereference_field_rvalue::write_reproducer (reproducer
&r
)
5757 const char *id
= r
.make_identifier (this, "lvalue");
5758 r
.write (" gcc_jit_lvalue *%s=\n"
5759 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5760 " %s, /* gcc_jit_location *loc */\n"
5761 " %s); /* gcc_jit_field *field */\n",
5763 r
.get_identifier_as_rvalue (m_rvalue
),
5764 r
.get_identifier (m_loc
),
5765 r
.get_identifier (m_field
));
5768 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5770 /* Implementation of pure virtual hook recording::memento::replay_into
5771 for recording::dereference_rvalue. */
5774 recording::dereference_rvalue::replay_into (replayer
*r
)
5777 m_rvalue
->playback_rvalue ()->
5778 dereference (playback_location (r
, m_loc
)));
5781 /* Implementation of pure virtual hook recording::rvalue::visit_children
5782 for recording::dereference_rvalue. */
5785 recording::dereference_rvalue::visit_children (rvalue_visitor
*v
)
5787 v
->visit (m_rvalue
);
5790 /* Implementation of recording::memento::make_debug_string for
5791 dereferencing an rvalue. */
5794 recording::dereference_rvalue::make_debug_string ()
5796 enum precedence prec
= get_precedence ();
5797 return string::from_printf (m_ctxt
,
5799 m_rvalue
->get_debug_string_parens (prec
));
5802 /* Implementation of recording::memento::write_reproducer for
5803 dereference_rvalue. */
5806 recording::dereference_rvalue::write_reproducer (reproducer
&r
)
5808 const char *id
= r
.make_identifier (this, "dereference");
5809 r
.write (" gcc_jit_lvalue *%s =\n"
5810 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5811 " %s); /* gcc_jit_location *loc */\n",
5813 r
.get_identifier_as_rvalue (m_rvalue
),
5814 r
.get_identifier (m_loc
));
5817 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5819 /* Implementation of pure virtual hook recording::memento::replay_into
5820 for recording::get_address_of_lvalue. */
5823 recording::get_address_of_lvalue::replay_into (replayer
*r
)
5826 m_lvalue
->playback_lvalue ()->
5827 get_address (playback_location (r
, m_loc
)));
5830 /* Implementation of pure virtual hook recording::rvalue::visit_children
5831 for recording::get_address_of_lvalue. */
5834 recording::get_address_of_lvalue::visit_children (rvalue_visitor
*v
)
5836 v
->visit (m_lvalue
);
5839 /* Implementation of recording::memento::make_debug_string for
5840 getting the address of an lvalue. */
5843 recording::get_address_of_lvalue::make_debug_string ()
5845 enum precedence prec
= get_precedence ();
5846 return string::from_printf (m_ctxt
,
5848 m_lvalue
->get_debug_string_parens (prec
));
5851 /* Implementation of recording::memento::write_reproducer for
5852 get_address_of_lvalue. */
5855 recording::get_address_of_lvalue::write_reproducer (reproducer
&r
)
5857 const char *id
= r
.make_identifier (this, "address_of");
5858 r
.write (" gcc_jit_rvalue *%s =\n"
5859 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5860 " %s); /* gcc_jit_location *loc */\n",
5862 r
.get_identifier_as_lvalue (m_lvalue
),
5863 r
.get_identifier (m_loc
));
5866 /* The implementation of class gcc::jit::recording::function_pointer. */
5868 /* Implementation of pure virtual hook recording::memento::replay_into
5869 for recording::function_pointer. */
5872 recording::function_pointer::replay_into (replayer
*r
)
5875 m_fn
->playback_function ()->
5876 get_address (playback_location (r
, m_loc
)));
5880 recording::function_pointer::visit_children (rvalue_visitor
*)
5885 /* Implementation of recording::memento::make_debug_string for
5886 getting the address of an lvalue. */
5889 recording::function_pointer::make_debug_string ()
5891 return string::from_printf (m_ctxt
,
5893 m_fn
->get_debug_string ());
5896 /* Implementation of recording::memento::write_reproducer for
5897 function_pointer. */
5900 recording::function_pointer::write_reproducer (reproducer
&r
)
5902 const char *id
= r
.make_identifier (this, "address_of");
5903 r
.write (" gcc_jit_rvalue *%s =\n"
5904 " gcc_jit_function_get_address (%s, /* gcc_jit_function *fn */\n"
5905 " %s); /* gcc_jit_location *loc */\n",
5907 r
.get_identifier (m_fn
),
5908 r
.get_identifier (m_loc
));
5911 /* The implementation of class gcc::jit::recording::local. */
5913 /* Implementation of pure virtual hook recording::memento::replay_into
5914 for recording::local. */
5917 recording::local::replay_into (replayer
*r
)
5920 m_func
->playback_function ()
5921 ->new_local (playback_location (r
, m_loc
),
5922 m_type
->playback_type (),
5923 playback_string (m_name
)));
5926 /* Override the default implementation of
5927 recording::memento::write_to_dump for locals by writing
5929 for use at the top of the function body as if it were a
5933 recording::local::write_to_dump (dump
&d
)
5935 if (d
.update_locations ())
5936 m_loc
= d
.make_location ();
5937 d
.write(" %s %s;\n",
5938 m_type
->get_debug_string (),
5939 get_debug_string ());
5943 recording::local::write_reproducer (reproducer
&r
)
5945 const char *id
= r
.make_identifier (this, "local");
5946 r
.write (" gcc_jit_lvalue *%s =\n"
5947 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5948 " %s, /* gcc_jit_location *loc */\n"
5949 " %s, /* gcc_jit_type *type */\n"
5950 " %s); /* const char *name */\n",
5952 r
.get_identifier (m_func
),
5953 r
.get_identifier (m_loc
),
5954 r
.get_identifier_as_type (m_type
),
5955 m_name
->get_debug_string ());
5958 /* The implementation of class gcc::jit::recording::statement. */
5960 /* We poison the default implementation of
5961 gcc::jit::recording::statement::get_successor_blocks
5962 since this vfunc must only ever be called on terminator
5965 vec
<recording::block
*>
5966 recording::statement::get_successor_blocks () const
5968 /* The base class implementation is for non-terminating statements,
5969 and thus should never be called. */
5971 vec
<block
*> result
;
5976 /* Extend the default implementation of
5977 recording::memento::write_to_dump for statements by (if requested)
5978 updating the location of the statement to the current location in
5982 recording::statement::write_to_dump (dump
&d
)
5984 memento::write_to_dump (d
);
5985 if (d
.update_locations ())
5986 m_loc
= d
.make_location ();
5989 /* The implementation of class gcc::jit::recording::eval. */
5991 /* Implementation of pure virtual hook recording::memento::replay_into
5992 for recording::eval. */
5995 recording::eval::replay_into (replayer
*r
)
5997 playback_block (get_block ())
5998 ->add_eval (playback_location (r
),
5999 m_rvalue
->playback_rvalue ());
6002 /* Implementation of recording::memento::make_debug_string for
6003 an eval statement. */
6006 recording::eval::make_debug_string ()
6008 return string::from_printf (m_ctxt
,
6010 m_rvalue
->get_debug_string ());
6013 /* Implementation of recording::memento::write_reproducer for
6017 recording::eval::write_reproducer (reproducer
&r
)
6019 r
.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
6020 " %s, /* gcc_jit_location *loc */\n"
6021 " %s); /* gcc_jit_rvalue *rvalue */\n",
6022 r
.get_identifier (get_block ()),
6023 r
.get_identifier (get_loc ()),
6024 r
.get_identifier_as_rvalue (m_rvalue
));
6027 /* The implementation of class gcc::jit::recording::assignment. */
6029 /* Implementation of pure virtual hook recording::memento::replay_into
6030 for recording::assignment. */
6033 recording::assignment::replay_into (replayer
*r
)
6035 playback_block (get_block ())
6036 ->add_assignment (playback_location (r
),
6037 m_lvalue
->playback_lvalue (),
6038 m_rvalue
->playback_rvalue ());
6041 /* Implementation of recording::memento::make_debug_string for
6042 an assignment statement. */
6045 recording::assignment::make_debug_string ()
6047 return string::from_printf (m_ctxt
,
6049 m_lvalue
->get_debug_string (),
6050 m_rvalue
->get_debug_string ());
6053 /* Implementation of recording::memento::write_reproducer for
6054 assignment statements. */
6057 recording::assignment::write_reproducer (reproducer
&r
)
6059 r
.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
6060 " %s, /* gcc_jit_location *loc */\n"
6061 " %s, /* gcc_jit_lvalue *lvalue */\n"
6062 " %s); /* gcc_jit_rvalue *rvalue */\n",
6063 r
.get_identifier (get_block ()),
6064 r
.get_identifier (get_loc ()),
6065 r
.get_identifier_as_lvalue (m_lvalue
),
6066 r
.get_identifier_as_rvalue (m_rvalue
));
6069 /* The implementation of class gcc::jit::recording::assignment_op. */
6071 /* Implementation of pure virtual hook recording::memento::replay_into
6072 for recording::assignment_op. */
6075 recording::assignment_op::replay_into (replayer
*r
)
6077 playback::type
*result_type
=
6078 m_lvalue
->playback_lvalue ()->get_type ();
6080 playback::rvalue
*binary_op
=
6081 r
->new_binary_op (playback_location (r
),
6084 m_lvalue
->playback_rvalue (),
6085 m_rvalue
->playback_rvalue ());
6087 playback_block (get_block ())
6088 ->add_assignment (playback_location (r
),
6089 m_lvalue
->playback_lvalue (),
6093 /* Implementation of recording::memento::make_debug_string for
6094 an assignment_op statement. */
6097 recording::assignment_op::make_debug_string ()
6099 return string::from_printf (m_ctxt
,
6101 m_lvalue
->get_debug_string (),
6102 binary_op_strings
[m_op
],
6103 m_rvalue
->get_debug_string ());
6106 /* Implementation of recording::memento::write_reproducer for
6107 assignment_op statements. */
6110 recording::assignment_op::write_reproducer (reproducer
&r
)
6112 r
.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
6113 " %s, /* gcc_jit_location *loc */\n"
6114 " %s, /* gcc_jit_lvalue *lvalue */\n"
6115 " %s, /* enum gcc_jit_binary_op op */\n"
6116 " %s); /* gcc_jit_rvalue *rvalue */\n",
6117 r
.get_identifier (get_block ()),
6118 r
.get_identifier (get_loc ()),
6119 r
.get_identifier_as_lvalue (m_lvalue
),
6120 binary_op_reproducer_strings
[m_op
],
6121 r
.get_identifier_as_rvalue (m_rvalue
));
6124 /* The implementation of class gcc::jit::recording::comment. */
6126 /* Implementation of pure virtual hook recording::memento::replay_into
6127 for recording::comment. */
6130 recording::comment::replay_into (replayer
*r
)
6132 playback_block (get_block ())
6133 ->add_comment (playback_location (r
),
6137 /* Implementation of recording::memento::make_debug_string for
6138 a comment "statement". */
6141 recording::comment::make_debug_string ()
6143 return string::from_printf (m_ctxt
,
6148 /* Implementation of recording::memento::write_reproducer for
6152 recording::comment::write_reproducer (reproducer
&r
)
6154 r
.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
6155 " %s, /* gcc_jit_location *loc */\n"
6156 " %s); /* const char *text */\n",
6157 r
.get_identifier (get_block ()),
6158 r
.get_identifier (get_loc ()),
6159 m_text
->get_debug_string ());
6162 /* The implementation of class gcc::jit::recording::conditional. */
6164 /* Implementation of pure virtual hook recording::memento::replay_into
6165 for recording::conditional. */
6168 recording::conditional::replay_into (replayer
*r
)
6170 playback_block (get_block ())
6171 ->add_conditional (playback_location (r
),
6172 m_boolval
->playback_rvalue (),
6173 playback_block (m_on_true
),
6174 playback_block (m_on_false
));
6177 /* Override the poisoned default implementation of
6178 gcc::jit::recording::statement::get_successor_blocks
6180 A conditional jump has 2 successor blocks. */
6182 vec
<recording::block
*>
6183 recording::conditional::get_successor_blocks () const
6185 vec
<block
*> result
;
6187 result
.quick_push (m_on_true
);
6188 result
.quick_push (m_on_false
);
6192 /* Implementation of recording::memento::make_debug_string for
6193 a conditional jump statement. */
6196 recording::conditional::make_debug_string ()
6199 return string::from_printf (m_ctxt
,
6200 "if (%s) goto %s; else goto %s;",
6201 m_boolval
->get_debug_string (),
6202 m_on_true
->get_debug_string (),
6203 m_on_false
->get_debug_string ());
6205 return string::from_printf (m_ctxt
,
6207 m_boolval
->get_debug_string (),
6208 m_on_true
->get_debug_string ());
6211 /* Implementation of recording::memento::write_reproducer for
6212 conditional statements. */
6215 recording::conditional::write_reproducer (reproducer
&r
)
6217 r
.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
6218 " %s, /* gcc_jit_location *loc */\n"
6219 " %s, /* gcc_jit_rvalue *boolval */\n"
6220 " %s, /* gcc_jit_block *on_true */\n"
6221 " %s); /* gcc_jit_block *on_false */\n",
6222 r
.get_identifier (get_block ()),
6223 r
.get_identifier (get_loc ()),
6224 r
.get_identifier_as_rvalue (m_boolval
),
6225 r
.get_identifier (m_on_true
),
6226 r
.get_identifier (m_on_false
));
6229 /* The implementation of class gcc::jit::recording::jump. */
6231 /* Implementation of pure virtual hook recording::memento::replay_into
6232 for recording::jump. */
6235 recording::jump::replay_into (replayer
*r
)
6237 playback_block (get_block ())
6238 ->add_jump (playback_location (r
),
6239 m_target
->playback_block ());
6242 /* Override the poisoned default implementation of
6243 gcc::jit::recording::statement::get_successor_blocks
6245 An unconditional jump has 1 successor block. */
6247 vec
<recording::block
*>
6248 recording::jump::get_successor_blocks () const
6250 vec
<block
*> result
;
6252 result
.quick_push (m_target
);
6256 /* Implementation of recording::memento::make_debug_string for
6257 a unconditional jump statement. */
6260 recording::jump::make_debug_string ()
6262 return string::from_printf (m_ctxt
,
6264 m_target
->get_debug_string ());
6267 /* Implementation of recording::memento::write_reproducer for
6271 recording::jump::write_reproducer (reproducer
&r
)
6273 r
.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
6274 " %s, /* gcc_jit_location *loc */\n"
6275 " %s); /* gcc_jit_block *target */\n",
6276 r
.get_identifier (get_block ()),
6277 r
.get_identifier (get_loc ()),
6278 r
.get_identifier (m_target
));
6281 /* The implementation of class gcc::jit::recording::return_. */
6283 /* Implementation of pure virtual hook recording::memento::replay_into
6284 for recording::return_. */
6287 recording::return_::replay_into (replayer
*r
)
6289 playback_block (get_block ())
6290 ->add_return (playback_location (r
),
6291 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
6294 /* Override the poisoned default implementation of
6295 gcc::jit::recording::statement::get_successor_blocks
6297 A return statement has no successor block. */
6299 vec
<recording::block
*>
6300 recording::return_::get_successor_blocks () const
6302 vec
<block
*> result
;
6307 /* Implementation of recording::memento::make_debug_string for
6308 a return statement (covers both those with and without rvalues). */
6311 recording::return_::make_debug_string ()
6314 return string::from_printf (m_ctxt
,
6316 m_rvalue
->get_debug_string ());
6318 return string::from_printf (m_ctxt
,
6322 /* Implementation of recording::memento::write_reproducer for
6323 return statements. */
6326 recording::return_::write_reproducer (reproducer
&r
)
6329 r
.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
6330 " %s, /* gcc_jit_location *loc */\n"
6331 " %s); /* gcc_jit_rvalue *rvalue */\n",
6332 r
.get_identifier (get_block ()),
6333 r
.get_identifier (get_loc ()),
6334 r
.get_identifier_as_rvalue (m_rvalue
));
6336 r
.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
6337 " %s); /* gcc_jit_location *loc */\n",
6338 r
.get_identifier (get_block ()),
6339 r
.get_identifier (get_loc ()));
6342 /* The implementation of class gcc::jit::recording::case_. */
6345 recording::case_::write_reproducer (reproducer
&r
)
6347 const char *id
= r
.make_identifier (this, "case");
6349 " gcc_jit_case *%s = \n"
6350 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
6351 " %s, /* gcc_jit_rvalue *min_value */\n"
6352 " %s, /* gcc_jit_rvalue *max_value */\n"
6353 " %s); /* gcc_jit_block *dest_block */\n";
6356 r
.get_identifier (get_context ()),
6357 r
.get_identifier_as_rvalue (m_min_value
),
6358 r
.get_identifier_as_rvalue (m_max_value
),
6359 r
.get_identifier (m_dest_block
));
6363 recording::case_::make_debug_string ()
6365 return string::from_printf (get_context (),
6366 "case %s ... %s: goto %s;",
6367 m_min_value
->get_debug_string (),
6368 m_max_value
->get_debug_string (),
6369 m_dest_block
->get_debug_string ());
6372 /* The implementation of class gcc::jit::recording::switch_. */
6374 /* gcc::jit::recording::switch_'s constructor. */
6376 recording::switch_::switch_ (block
*b
,
6379 block
*default_block
,
6382 : statement (b
, loc
),
6384 m_default_block (default_block
)
6386 m_cases
.reserve_exact (num_cases
);
6387 for (int i
= 0; i
< num_cases
; i
++)
6388 m_cases
.quick_push (cases
[i
]);
6391 /* Implementation of pure virtual hook recording::memento::replay_into
6392 for recording::switch_. */
6395 recording::switch_::replay_into (replayer
*r
)
6397 auto_vec
<playback::case_
> pcases
;
6399 recording::case_
*rcase
;
6400 pcases
.reserve_exact (m_cases
.length ());
6401 FOR_EACH_VEC_ELT (m_cases
, i
, rcase
)
6403 playback::case_
pcase (rcase
->get_min_value ()->playback_rvalue (),
6404 rcase
->get_max_value ()->playback_rvalue (),
6405 rcase
->get_dest_block ()->playback_block ());
6406 pcases
.safe_push (pcase
);
6408 playback_block (get_block ())
6409 ->add_switch (playback_location (r
),
6410 m_expr
->playback_rvalue (),
6411 m_default_block
->playback_block (),
6415 /* Override the poisoned default implementation of
6416 gcc::jit::recording::statement::get_successor_blocks
6418 A switch statement has (NUM_CASES + 1) successor blocks. */
6420 vec
<recording::block
*>
6421 recording::switch_::get_successor_blocks () const
6423 vec
<block
*> result
;
6424 result
.create (m_cases
.length () + 1);
6425 result
.quick_push (m_default_block
);
6428 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
6429 result
.quick_push (c
->get_dest_block ());
6433 /* Implementation of recording::memento::make_debug_string for
6434 a switch statement. */
6437 recording::switch_::make_debug_string ()
6439 auto_vec
<char> cases_str
;
6442 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
6444 size_t len
= strlen (c
->get_debug_string ());
6445 unsigned idx
= cases_str
.length ();
6446 cases_str
.safe_grow (idx
+ 1 + len
, true);
6447 cases_str
[idx
] = ' ';
6448 memcpy (&(cases_str
[idx
+ 1]),
6449 c
->get_debug_string (),
6452 cases_str
.safe_push ('\0');
6454 return string::from_printf (m_ctxt
,
6455 "switch (%s) {default: goto %s;%s}",
6456 m_expr
->get_debug_string (),
6457 m_default_block
->get_debug_string (),
6461 /* Implementation of recording::memento::write_reproducer for
6462 switch statements. */
6465 recording::switch_::write_reproducer (reproducer
&r
)
6467 r
.make_identifier (this, "switch");
6470 const char *cases_id
=
6471 r
.make_tmp_identifier ("cases_for", this);
6472 r
.write (" gcc_jit_case *%s[%i] = {\n",
6475 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
6476 r
.write (" %s,\n", r
.get_identifier (c
));
6479 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
6480 " %s, /* gcc_jit_location *loc */\n"
6481 " %s, /* gcc_jit_rvalue *expr */\n"
6482 " %s, /* gcc_jit_block *default_block */\n"
6483 " %i, /* int num_cases */\n"
6484 " %s); /* gcc_jit_case **cases */\n";
6486 r
.get_identifier (get_block ()),
6487 r
.get_identifier (get_loc ()),
6488 r
.get_identifier_as_rvalue (m_expr
),
6489 r
.get_identifier (m_default_block
),
6494 } // namespace gcc::jit