1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2019 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 /* Implementation of pure virtual hook recording::type::dereference for
2179 recording::memento_of_get_type. */
2182 recording::memento_of_get_type::dereference ()
2186 default: gcc_unreachable ();
2188 case GCC_JIT_TYPE_VOID
:
2191 case GCC_JIT_TYPE_VOID_PTR
:
2192 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
2194 case GCC_JIT_TYPE_BOOL
:
2195 case GCC_JIT_TYPE_CHAR
:
2196 case GCC_JIT_TYPE_SIGNED_CHAR
:
2197 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2198 case GCC_JIT_TYPE_SHORT
:
2199 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2200 case GCC_JIT_TYPE_INT
:
2201 case GCC_JIT_TYPE_UNSIGNED_INT
:
2202 case GCC_JIT_TYPE_LONG
:
2203 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2204 case GCC_JIT_TYPE_LONG_LONG
:
2205 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2206 case GCC_JIT_TYPE_FLOAT
:
2207 case GCC_JIT_TYPE_DOUBLE
:
2208 case GCC_JIT_TYPE_LONG_DOUBLE
:
2209 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2210 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2211 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2212 /* Not a pointer: */
2215 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2216 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
2218 case GCC_JIT_TYPE_SIZE_T
:
2219 /* Not a pointer: */
2222 case GCC_JIT_TYPE_FILE_PTR
:
2223 /* Give the client code back an opaque "struct FILE". */
2224 return m_ctxt
->get_opaque_FILE_type ();
2228 /* Implementation of pure virtual hook recording::type::is_int for
2229 recording::memento_of_get_type. */
2232 recording::memento_of_get_type::is_int () const
2236 default: gcc_unreachable ();
2238 case GCC_JIT_TYPE_VOID
:
2241 case GCC_JIT_TYPE_VOID_PTR
:
2244 case GCC_JIT_TYPE_BOOL
:
2247 case GCC_JIT_TYPE_CHAR
:
2248 case GCC_JIT_TYPE_SIGNED_CHAR
:
2249 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2250 case GCC_JIT_TYPE_SHORT
:
2251 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2252 case GCC_JIT_TYPE_INT
:
2253 case GCC_JIT_TYPE_UNSIGNED_INT
:
2254 case GCC_JIT_TYPE_LONG
:
2255 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2256 case GCC_JIT_TYPE_LONG_LONG
:
2257 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2260 case GCC_JIT_TYPE_FLOAT
:
2261 case GCC_JIT_TYPE_DOUBLE
:
2262 case GCC_JIT_TYPE_LONG_DOUBLE
:
2265 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2268 case GCC_JIT_TYPE_SIZE_T
:
2271 case GCC_JIT_TYPE_FILE_PTR
:
2274 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2275 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2276 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2281 /* Implementation of pure virtual hook recording::type::is_float for
2282 recording::memento_of_get_type. */
2285 recording::memento_of_get_type::is_float () const
2289 default: gcc_unreachable ();
2291 case GCC_JIT_TYPE_VOID
:
2294 case GCC_JIT_TYPE_VOID_PTR
:
2297 case GCC_JIT_TYPE_BOOL
:
2300 case GCC_JIT_TYPE_CHAR
:
2301 case GCC_JIT_TYPE_SIGNED_CHAR
:
2302 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2303 case GCC_JIT_TYPE_SHORT
:
2304 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2305 case GCC_JIT_TYPE_INT
:
2306 case GCC_JIT_TYPE_UNSIGNED_INT
:
2307 case GCC_JIT_TYPE_LONG
:
2308 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2309 case GCC_JIT_TYPE_LONG_LONG
:
2310 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2313 case GCC_JIT_TYPE_FLOAT
:
2314 case GCC_JIT_TYPE_DOUBLE
:
2315 case GCC_JIT_TYPE_LONG_DOUBLE
:
2318 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2321 case GCC_JIT_TYPE_SIZE_T
:
2324 case GCC_JIT_TYPE_FILE_PTR
:
2327 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2328 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2329 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2334 /* Implementation of pure virtual hook recording::type::is_bool for
2335 recording::memento_of_get_type. */
2338 recording::memento_of_get_type::is_bool () const
2342 default: gcc_unreachable ();
2344 case GCC_JIT_TYPE_VOID
:
2347 case GCC_JIT_TYPE_VOID_PTR
:
2350 case GCC_JIT_TYPE_BOOL
:
2353 case GCC_JIT_TYPE_CHAR
:
2354 case GCC_JIT_TYPE_SIGNED_CHAR
:
2355 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
2356 case GCC_JIT_TYPE_SHORT
:
2357 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
2358 case GCC_JIT_TYPE_INT
:
2359 case GCC_JIT_TYPE_UNSIGNED_INT
:
2360 case GCC_JIT_TYPE_LONG
:
2361 case GCC_JIT_TYPE_UNSIGNED_LONG
:
2362 case GCC_JIT_TYPE_LONG_LONG
:
2363 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
2366 case GCC_JIT_TYPE_FLOAT
:
2367 case GCC_JIT_TYPE_DOUBLE
:
2368 case GCC_JIT_TYPE_LONG_DOUBLE
:
2371 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
2374 case GCC_JIT_TYPE_SIZE_T
:
2377 case GCC_JIT_TYPE_FILE_PTR
:
2380 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
2381 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
2382 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
2387 /* Implementation of pure virtual hook recording::memento::replay_into
2388 for recording::memento_of_get_type. */
2391 recording::memento_of_get_type::replay_into (replayer
*r
)
2393 set_playback_obj (r
->get_type (m_kind
));
2396 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
2398 /* Descriptive strings for each of enum gcc_jit_types. */
2400 static const char * const get_type_strings
[] = {
2401 "void", /* GCC_JIT_TYPE_VOID */
2402 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2404 "bool", /* GCC_JIT_TYPE_BOOL */
2406 "char", /* GCC_JIT_TYPE_CHAR */
2407 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2408 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2410 "short", /* GCC_JIT_TYPE_SHORT */
2411 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2413 "int", /* GCC_JIT_TYPE_INT */
2414 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2416 "long", /* GCC_JIT_TYPE_LONG */
2417 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2419 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2420 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2422 "float", /* GCC_JIT_TYPE_FLOAT */
2423 "double", /* GCC_JIT_TYPE_DOUBLE */
2424 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2426 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2428 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2430 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2432 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2433 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2434 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
2438 /* Implementation of recording::memento::make_debug_string for
2439 results of get_type, using a simple table of type names. */
2442 recording::memento_of_get_type::make_debug_string ()
2444 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
2447 static const char * const get_type_enum_strings
[] = {
2448 "GCC_JIT_TYPE_VOID",
2449 "GCC_JIT_TYPE_VOID_PTR",
2450 "GCC_JIT_TYPE_BOOL",
2451 "GCC_JIT_TYPE_CHAR",
2452 "GCC_JIT_TYPE_SIGNED_CHAR",
2453 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2454 "GCC_JIT_TYPE_SHORT",
2455 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2457 "GCC_JIT_TYPE_UNSIGNED_INT",
2458 "GCC_JIT_TYPE_LONG",
2459 "GCC_JIT_TYPE_UNSIGNED_LONG",
2460 "GCC_JIT_TYPE_LONG_LONG",
2461 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2462 "GCC_JIT_TYPE_FLOAT",
2463 "GCC_JIT_TYPE_DOUBLE",
2464 "GCC_JIT_TYPE_LONG_DOUBLE",
2465 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2466 "GCC_JIT_TYPE_SIZE_T",
2467 "GCC_JIT_TYPE_FILE_PTR",
2468 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2469 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2470 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2474 recording::memento_of_get_type::write_reproducer (reproducer
&r
)
2476 const char *id
= r
.make_identifier (this, "type");
2477 r
.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2479 r
.get_identifier (get_context ()),
2480 get_type_enum_strings
[m_kind
]);
2483 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2485 /* Override of default implementation of
2486 recording::type::accepts_writes_from for get_pointer.
2488 Require a pointer type, and allowing writes to
2489 (const T *) from a (T*), but not the other way around. */
2492 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
2494 /* Must be a pointer type: */
2495 type
*rtype_points_to
= rtype
->is_pointer ();
2496 if (!rtype_points_to
)
2499 /* It's OK to assign to a (const T *) from a (T *). */
2500 return m_other_type
->unqualified ()
2501 ->accepts_writes_from (rtype_points_to
);
2504 /* Implementation of pure virtual hook recording::memento::replay_into
2505 for recording::memento_of_get_pointer. */
2508 recording::memento_of_get_pointer::replay_into (replayer
*)
2510 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
2513 /* Implementation of recording::memento::make_debug_string for
2514 results of get_pointer, adding " *" to the underlying type,
2515 with special-casing to handle function pointer types. */
2518 recording::memento_of_get_pointer::make_debug_string ()
2520 /* Special-case function pointer types, to put the "*" in parens between
2521 the return type and the params (for one level of dereferencing, at
2523 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2524 return fn_type
->make_debug_string_with_ptr ();
2526 return string::from_printf (m_ctxt
,
2527 "%s *", m_other_type
->get_debug_string ());
2530 /* Implementation of recording::memento::write_reproducer for get_pointer. */
2533 recording::memento_of_get_pointer::write_reproducer (reproducer
&r
)
2535 /* We need to special-case function pointer types; see the notes in
2536 recording::function_type::write_deferred_reproducer. */
2537 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
2539 fn_type
->write_deferred_reproducer (r
, this);
2543 const char *id
= r
.make_identifier (this, "type");
2544 r
.write (" gcc_jit_type *%s =\n"
2545 " gcc_jit_type_get_pointer (%s);\n",
2547 r
.get_identifier_as_type (m_other_type
));
2550 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
2552 /* Implementation of pure virtual hook recording::memento::replay_into
2553 for recording::memento_of_get_const. */
2556 recording::memento_of_get_const::replay_into (replayer
*)
2558 set_playback_obj (m_other_type
->playback_type ()->get_const ());
2561 /* Implementation of recording::memento::make_debug_string for
2562 results of get_const, prepending "const ". */
2565 recording::memento_of_get_const::make_debug_string ()
2567 return string::from_printf (m_ctxt
,
2568 "const %s", m_other_type
->get_debug_string ());
2571 /* Implementation of recording::memento::write_reproducer for const types. */
2574 recording::memento_of_get_const::write_reproducer (reproducer
&r
)
2576 const char *id
= r
.make_identifier (this, "type");
2577 r
.write (" gcc_jit_type *%s =\n"
2578 " gcc_jit_type_get_const (%s);\n",
2580 r
.get_identifier_as_type (m_other_type
));
2583 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2585 /* Implementation of pure virtual hook recording::memento::replay_into
2586 for recording::memento_of_get_volatile. */
2589 recording::memento_of_get_volatile::replay_into (replayer
*)
2591 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
2594 /* Implementation of recording::memento::make_debug_string for
2595 results of get_volatile, prepending "volatile ". */
2598 recording::memento_of_get_volatile::make_debug_string ()
2600 return string::from_printf (m_ctxt
,
2601 "volatile %s", m_other_type
->get_debug_string ());
2604 /* Implementation of recording::memento::write_reproducer for volatile
2608 recording::memento_of_get_volatile::write_reproducer (reproducer
&r
)
2610 const char *id
= r
.make_identifier (this, "type");
2611 r
.write (" gcc_jit_type *%s =\n"
2612 " gcc_jit_type_get_volatile (%s);\n",
2614 r
.get_identifier_as_type (m_other_type
));
2617 /* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
2619 /* Implementation of pure virtual hook recording::memento::replay_into
2620 for recording::memento_of_get_aligned. */
2623 recording::memento_of_get_aligned::replay_into (replayer
*)
2626 (m_other_type
->playback_type ()->get_aligned (m_alignment_in_bytes
));
2629 /* Implementation of recording::memento::make_debug_string for
2630 results of get_aligned. */
2633 recording::memento_of_get_aligned::make_debug_string ()
2635 return string::from_printf (m_ctxt
,
2636 "%s __attribute__((aligned(%zi)))",
2637 m_other_type
->get_debug_string (),
2638 m_alignment_in_bytes
);
2641 /* Implementation of recording::memento::write_reproducer for aligned
2645 recording::memento_of_get_aligned::write_reproducer (reproducer
&r
)
2647 const char *id
= r
.make_identifier (this, "type");
2648 r
.write (" gcc_jit_type *%s =\n"
2649 " gcc_jit_type_get_aligned (%s, %zi);\n",
2651 r
.get_identifier_as_type (m_other_type
),
2652 m_alignment_in_bytes
);
2655 /* The implementation of class gcc::jit::recording::vector_type. */
2657 /* Implementation of pure virtual hook recording::memento::replay_into
2658 for recording::vector_type. */
2661 recording::vector_type::replay_into (replayer
*)
2664 (m_other_type
->playback_type ()->get_vector (m_num_units
));
2667 /* Implementation of recording::memento::make_debug_string for
2668 results of get_vector. */
2671 recording::vector_type::make_debug_string ()
2673 return string::from_printf
2675 "%s __attribute__((vector_size(sizeof (%s) * %zi)))",
2676 m_other_type
->get_debug_string (),
2677 m_other_type
->get_debug_string (),
2681 /* Implementation of recording::memento::write_reproducer for vector types. */
2684 recording::vector_type::write_reproducer (reproducer
&r
)
2686 const char *id
= r
.make_identifier (this, "type");
2687 r
.write (" gcc_jit_type *%s =\n"
2688 " gcc_jit_type_get_vector (%s, %zi);\n",
2690 r
.get_identifier_as_type (m_other_type
),
2694 /* The implementation of class gcc::jit::recording::array_type */
2696 /* Implementation of pure virtual hook recording::type::dereference for
2697 recording::array_type. */
2700 recording::array_type::dereference ()
2702 return m_element_type
;
2705 /* Implementation of pure virtual hook recording::memento::replay_into
2706 for recording::array_type. */
2709 recording::array_type::replay_into (replayer
*r
)
2711 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
2712 m_element_type
->playback_type (),
2716 /* Implementation of recording::memento::make_debug_string for
2717 results of new_array_type. */
2720 recording::array_type::make_debug_string ()
2722 return string::from_printf (m_ctxt
,
2724 m_element_type
->get_debug_string (),
2728 /* Implementation of recording::memento::write_reproducer for array
2732 recording::array_type::write_reproducer (reproducer
&r
)
2734 const char *id
= r
.make_identifier (this, "array_type");
2735 r
.write (" gcc_jit_type *%s =\n"
2736 " gcc_jit_context_new_array_type (%s,\n"
2737 " %s, /* gcc_jit_location *loc */\n"
2738 " %s, /* gcc_jit_type *element_type */\n"
2739 " %i); /* int num_elements */\n",
2741 r
.get_identifier (get_context ()),
2742 r
.get_identifier (m_loc
),
2743 r
.get_identifier_as_type (m_element_type
),
2747 /* The implementation of class gcc::jit::recording::function_type */
2749 /* Constructor for gcc::jit::recording::function_type. */
2751 recording::function_type::function_type (context
*ctxt
,
2757 m_return_type (return_type
),
2759 m_is_variadic (is_variadic
)
2761 for (int i
= 0; i
< num_params
; i
++)
2762 m_param_types
.safe_push (param_types
[i
]);
2765 /* Implementation of pure virtual hook recording::type::dereference for
2766 recording::function_type. */
2769 recording::function_type::dereference ()
2774 /* Implementation of virtual hook recording::type::is_same_type_as for
2775 recording::function_type.
2777 We override this to avoid requiring identity of function pointer types,
2778 so that if client code has obtained the same signature in
2779 different ways (e.g. via gcc_jit_context_new_function_ptr_type
2780 vs gcc_jit_function_get_address), the different function_type
2781 instances are treated as compatible.
2783 We can't use type::accepts_writes_from for this as we need a stronger
2784 notion of "sameness": if we have a fn_ptr type that has args that are
2785 themselves fn_ptr types, then those args still need to match exactly.
2787 Alternatively, we could consolidate attempts to create identical
2788 function_type instances so that pointer equality works, but that runs
2789 into issues about the lifetimes of the cache (w.r.t. nested contexts). */
2792 recording::function_type::is_same_type_as (type
*other
)
2796 function_type
*other_fn_type
= other
->dyn_cast_function_type ();
2800 /* Everything must match. */
2802 if (!m_return_type
->is_same_type_as (other_fn_type
->m_return_type
))
2805 if (m_param_types
.length () != other_fn_type
->m_param_types
.length ())
2810 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
2811 if (!param_type
->is_same_type_as (other_fn_type
->m_param_types
[i
]))
2814 if (m_is_variadic
!= other_fn_type
->m_is_variadic
)
2817 /* Passed all tests. */
2821 /* Implementation of pure virtual hook recording::memento::replay_into
2822 for recording::function_type. */
2825 recording::function_type::replay_into (replayer
*r
)
2827 /* Convert m_param_types to a vec of playback type. */
2828 auto_vec
<playback::type
*> param_types
;
2830 recording::type
*type
;
2831 param_types
.create (m_param_types
.length ());
2832 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
2833 param_types
.safe_push (type
->playback_type ());
2835 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
2840 /* Special-casing for make_debug_string for get_pointer results for
2841 handling (one level) of pointers to functions. */
2844 recording::function_type::make_debug_string_with_ptr ()
2846 return make_debug_string_with ("(*) ");
2849 /* Implementation of recording::memento::make_debug_string for
2850 results of new_function_type. */
2853 recording::function_type::make_debug_string ()
2855 return make_debug_string_with ("");
2858 /* Build a debug string representation of the form:
2860 RESULT_TYPE INSERT (PARAM_TYPES)
2862 for use when handling 0 and 1 level of indirection to this
2866 recording::function_type::make_debug_string_with (const char *insert
)
2868 /* First, build a buffer for the arguments. */
2869 /* Calculate length of said buffer. */
2870 size_t sz
= 1; /* nil terminator */
2871 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2873 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
2874 sz
+= 2; /* ", " separator */
2877 sz
+= 5; /* ", ..." separator and ellipsis */
2879 /* Now allocate and populate the buffer. */
2880 char *argbuf
= new char[sz
];
2883 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
2885 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
2886 len
+= strlen (m_param_types
[i
]->get_debug_string ());
2887 if (i
+ 1 < m_param_types
.length ())
2889 strcpy (argbuf
+ len
, ", ");
2895 if (m_param_types
.length ())
2897 strcpy (argbuf
+ len
, ", ");
2900 strcpy (argbuf
+ len
, "...");
2905 /* ...and use it to get the string for the call as a whole. */
2906 string
*result
= string::from_printf (m_ctxt
,
2908 m_return_type
->get_debug_string (),
2917 /* Implementation of recording::memento::write_reproducer for function
2921 recording::function_type::write_reproducer (reproducer
&)
2923 /* see notes below. */
2926 /* There's a get_pointer within context::new_function_ptr_type:
2927 the type received by client code isn't the memento for the
2928 function_type, but instead the result of get_pointer on it.
2930 Hence we can't directly write a reproducer that gives function_type.
2931 Instead we special-case things within get_pointer, detecting this
2932 case, calling the following function. */
2935 recording::function_type::write_deferred_reproducer (reproducer
&r
,
2938 gcc_assert (ptr_type
);
2939 r
.make_identifier (this, "function_type");
2940 const char *ptr_id
= r
.make_identifier (ptr_type
, "ptr_to");
2941 const char *param_types_id
= r
.make_tmp_identifier ("params_for", this);
2942 r
.write (" gcc_jit_type *%s[%i] = {\n",
2944 m_param_types
.length ());
2947 FOR_EACH_VEC_ELT (m_param_types
, i
, param_type
)
2948 r
.write (" %s,\n", r
.get_identifier_as_type (param_type
));
2950 r
.write (" gcc_jit_type *%s =\n"
2951 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2952 " %s, /* gcc_jit_location *loc */\n"
2953 " %s, /* gcc_jit_type *return_type */\n"
2954 " %i, /* int num_params */\n"
2955 " %s, /* gcc_jit_type **param_types */\n"
2956 " %i); /* int is_variadic */\n",
2958 r
.get_identifier (get_context ()),
2959 "NULL", /* location is not stored */
2960 r
.get_identifier_as_type (m_return_type
),
2961 m_param_types
.length (),
2966 /* The implementation of class gcc::jit::recording::field. */
2968 /* Implementation of pure virtual hook recording::memento::replay_into
2969 for recording::field. */
2972 recording::field::replay_into (replayer
*r
)
2974 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
2975 m_type
->playback_type (),
2976 playback_string (m_name
)));
2979 /* Override the default implementation of
2980 recording::memento::write_to_dump. Dump each field
2981 by dumping a line of the form:
2983 so that we can build up a struct/union field by field. */
2986 recording::field::write_to_dump (dump
&d
)
2988 d
.write (" %s %s;\n",
2989 m_type
->get_debug_string (),
2993 /* Implementation of recording::memento::make_debug_string for
2994 results of new_field. */
2997 recording::field::make_debug_string ()
3002 /* Implementation of recording::memento::write_reproducer for fields. */
3005 recording::field::write_reproducer (reproducer
&r
)
3007 const char *id
= r
.make_identifier (this, "field");
3008 r
.write(" gcc_jit_field *%s =\n"
3009 " gcc_jit_context_new_field (%s,\n"
3010 " %s, /* gcc_jit_location *loc */\n"
3011 " %s, /* gcc_jit_type *type, */\n"
3012 " %s); /* const char *name */\n",
3014 r
.get_identifier (get_context ()),
3015 r
.get_identifier (m_loc
),
3016 r
.get_identifier_as_type (m_type
),
3017 m_name
->get_debug_string ());
3020 /* The implementation of class gcc::jit::recording::bitfield. */
3022 /* Implementation of pure virtual hook recording::memento::replay_into
3023 for recording::bitfield. */
3026 recording::bitfield::replay_into (replayer
*r
)
3028 set_playback_obj (r
->new_bitfield (playback_location (r
, m_loc
),
3029 m_type
->playback_type (),
3031 playback_string (m_name
)));
3034 /* Override the default implementation of
3035 recording::memento::write_to_dump. Dump each bit field
3036 by dumping a line of the form:
3038 so that we can build up a struct/union field by field. */
3041 recording::bitfield::write_to_dump (dump
&d
)
3043 d
.write (" %s %s:%d;\n",
3044 m_type
->get_debug_string (),
3049 /* Implementation of recording::memento::make_debug_string for
3050 results of new_bitfield. */
3053 recording::bitfield::make_debug_string ()
3055 return string::from_printf (m_ctxt
,
3057 m_name
->c_str (), m_width
);
3060 /* Implementation of recording::memento::write_reproducer for bitfields. */
3063 recording::bitfield::write_reproducer (reproducer
&r
)
3065 const char *id
= r
.make_identifier (this, "bitfield");
3066 r
.write (" gcc_jit_field *%s =\n"
3067 " gcc_jit_context_new_bitfield (%s,\n"
3068 " %s, /* gcc_jit_location *loc */\n"
3069 " %s, /* gcc_jit_type *type, */\n"
3070 " %d, /* int width, */\n"
3071 " %s); /* const char *name */\n",
3073 r
.get_identifier (get_context ()),
3074 r
.get_identifier (m_loc
),
3075 r
.get_identifier_as_type (m_type
),
3077 m_name
->get_debug_string ());
3080 /* The implementation of class gcc::jit::recording::compound_type */
3082 /* The constructor for gcc::jit::recording::compound_type. */
3084 recording::compound_type::compound_type (context
*ctxt
,
3094 /* Set the fields of a compound type.
3096 Implements the post-error-checking part of
3097 gcc_jit_struct_set_fields, and is also used by
3098 gcc_jit_context_new_union_type. */
3101 recording::compound_type::set_fields (location
*loc
,
3103 field
**field_array
)
3106 gcc_assert (m_fields
== NULL
);
3108 m_fields
= new fields (this, num_fields
, field_array
);
3109 m_ctxt
->record (m_fields
);
3112 /* Implementation of pure virtual hook recording::type::dereference for
3113 recording::compound_type. */
3116 recording::compound_type::dereference ()
3118 return NULL
; /* not a pointer */
3121 /* The implementation of class gcc::jit::recording::struct_. */
3123 /* The constructor for gcc::jit::recording::struct_. */
3125 recording::struct_::struct_ (context
*ctxt
,
3128 : compound_type (ctxt
, loc
, name
)
3132 /* Implementation of pure virtual hook recording::memento::replay_into
3133 for recording::struct_. */
3136 recording::struct_::replay_into (replayer
*r
)
3139 r
->new_compound_type (playback_location (r
, get_loc ()),
3140 get_name ()->c_str (),
3141 true /* is_struct */));
3145 recording::struct_::access_as_type (reproducer
&r
)
3147 return r
.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
3148 r
.get_identifier (this));
3151 /* Implementation of recording::memento::make_debug_string for
3155 recording::struct_::make_debug_string ()
3157 return string::from_printf (m_ctxt
,
3158 "struct %s", get_name ()->c_str ());
3162 recording::struct_::write_reproducer (reproducer
&r
)
3164 const char *id
= r
.make_identifier (this, "struct");
3165 r
.write (" gcc_jit_struct *%s =\n"
3166 " gcc_jit_context_new_opaque_struct (%s,\n"
3167 " %s, /* gcc_jit_location *loc */\n"
3168 " %s); /* const char *name */\n",
3170 r
.get_identifier (get_context ()),
3171 r
.get_identifier (get_loc ()),
3172 get_name ()->get_debug_string ());
3175 /* The implementation of class gcc::jit::recording::union_. */
3177 /* The constructor for gcc::jit::recording::union_. */
3179 recording::union_::union_ (context
*ctxt
,
3182 : compound_type (ctxt
, loc
, name
)
3186 /* Implementation of pure virtual hook recording::memento::replay_into
3187 for recording::union_. */
3190 recording::union_::replay_into (replayer
*r
)
3193 r
->new_compound_type (playback_location (r
, get_loc ()),
3194 get_name ()->c_str (),
3195 false /* is_struct */));
3198 /* Implementation of recording::memento::make_debug_string for
3202 recording::union_::make_debug_string ()
3204 return string::from_printf (m_ctxt
,
3205 "union %s", get_name ()->c_str ());
3208 /* Implementation of recording::memento::write_reproducer for unions. */
3211 recording::union_::write_reproducer (reproducer
&r
)
3213 const char *id
= r
.make_identifier (this, "union");
3215 const char *fields_id
= r
.make_tmp_identifier ("fields_for", this);
3216 r
.write (" gcc_jit_field *%s[%i] = {\n",
3218 get_fields ()->length ());
3219 for (int i
= 0; i
< get_fields ()->length (); i
++)
3220 r
.write (" %s,\n", r
.get_identifier (get_fields ()->get_field (i
)));
3223 r
.write (" gcc_jit_type *%s =\n"
3224 " gcc_jit_context_new_union_type (%s,\n"
3225 " %s, /* gcc_jit_location *loc */\n"
3226 " %s, /* const char *name */\n"
3227 " %i, /* int num_fields */\n"
3228 " %s); /* gcc_jit_field **fields */\n",
3230 r
.get_identifier (get_context ()),
3231 r
.get_identifier (get_loc ()),
3232 get_name ()->get_debug_string (),
3233 get_fields ()->length (),
3237 /* The implementation of class gcc::jit::recording::fields. */
3239 /* The constructor for gcc::jit::recording::fields. */
3241 recording::fields::fields (compound_type
*struct_or_union
,
3244 : memento (struct_or_union
->m_ctxt
),
3245 m_struct_or_union (struct_or_union
),
3248 for (int i
= 0; i
< num_fields
; i
++)
3250 gcc_assert (fields
[i
]->get_container () == NULL
);
3251 fields
[i
]->set_container (m_struct_or_union
);
3252 m_fields
.safe_push (fields
[i
]);
3256 /* Implementation of pure virtual hook recording::memento::replay_into
3257 for recording::fields. */
3260 recording::fields::replay_into (replayer
*)
3262 auto_vec
<playback::field
*> playback_fields
;
3263 playback_fields
.create (m_fields
.length ());
3264 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
3265 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
3266 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
3269 /* Override the default implementation of
3270 recording::memento::write_to_dump by writing a union/struct
3271 declaration of this form:
3283 recording::fields::write_to_dump (dump
&d
)
3288 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
3289 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
3290 f
->write_to_dump (d
);
3294 /* Implementation of recording::memento::write_reproducer for the fields
3298 recording::fields::write_reproducer (reproducer
&r
)
3300 if (m_struct_or_union
)
3301 if (m_struct_or_union
->dyn_cast_struct () == NULL
)
3302 /* We have a union; the fields have already been written by
3303 union::write_reproducer. */
3306 const char *fields_id
= r
.make_identifier (this, "fields");
3307 r
.write (" gcc_jit_field *%s[%i] = {\n",
3309 m_fields
.length ());
3312 FOR_EACH_VEC_ELT (m_fields
, i
, field
)
3313 r
.write (" %s,\n", r
.get_identifier (field
));
3316 r
.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
3317 " %s, /* gcc_jit_location *loc */\n"
3318 " %i, /* int num_fields */\n"
3319 " %s); /* gcc_jit_field **fields */\n",
3320 r
.get_identifier (m_struct_or_union
),
3321 r
.get_identifier ((memento
*)NULL
),
3326 /* Implementation of recording::memento::make_debug_string for
3330 recording::fields::make_debug_string ()
3332 return string::from_printf (m_ctxt
,
3336 /* The implementation of class gcc::jit::recording::rvalue. */
3338 /* Create a recording::access_field_rvalue instance and add it to
3339 the rvalue's context's list of mementos.
3341 Implements the post-error-checking part of
3342 gcc_jit_rvalue_access_field. */
3345 recording::rvalue::access_field (recording::location
*loc
,
3348 recording::rvalue
*result
=
3349 new access_field_rvalue (m_ctxt
, loc
, this, field
);
3350 m_ctxt
->record (result
);
3354 /* Create a recording::dereference_field_rvalue instance and add it to
3355 the rvalue's context's list of mementos.
3357 Implements the post-error-checking part of
3358 gcc_jit_rvalue_dereference_field. */
3361 recording::rvalue::dereference_field (recording::location
*loc
,
3364 recording::lvalue
*result
=
3365 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
3366 m_ctxt
->record (result
);
3370 /* Create a recording::dereference_rvalue instance and add it to the
3371 rvalue's context's list of mementos.
3373 Implements the post-error-checking part of
3374 gcc_jit_rvalue_dereference. */
3377 recording::rvalue::dereference (recording::location
*loc
)
3379 recording::lvalue
*result
=
3380 new dereference_rvalue (m_ctxt
, loc
, this);
3381 m_ctxt
->record (result
);
3385 /* An rvalue visitor, for validating that every rvalue within an expression
3386 trees within "STMT" has the correct scope (e.g. no access to locals
3387 of a different function). */
3389 class rvalue_usage_validator
: public recording::rvalue_visitor
3392 rvalue_usage_validator (const char *api_funcname
,
3393 recording::context
*ctxt
,
3394 recording::statement
*stmt
);
3397 visit (recording::rvalue
*rvalue
) FINAL OVERRIDE
;
3400 const char *m_api_funcname
;
3401 recording::context
*m_ctxt
;
3402 recording::statement
*m_stmt
;
3405 /* The trivial constructor for rvalue_usage_validator. */
3407 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname
,
3408 recording::context
*ctxt
,
3409 recording::statement
*stmt
)
3410 : m_api_funcname (api_funcname
),
3416 /* Verify that the given rvalue is in the correct scope. */
3419 rvalue_usage_validator::visit (recording::rvalue
*rvalue
)
3421 gcc_assert (m_stmt
->get_block ());
3422 recording::function
*stmt_scope
= m_stmt
->get_block ()->get_function ();
3424 /* Most rvalues don't have a scope (only locals and params). */
3425 if (rvalue
->get_scope ())
3427 if (rvalue
->get_scope () != stmt_scope
)
3429 (rvalue
->get_loc (),
3431 " rvalue %s (type: %s)"
3432 " has scope limited to function %s"
3433 " but was used within function %s"
3434 " (in statement: %s)",
3436 rvalue
->get_debug_string (),
3437 rvalue
->get_type ()->get_debug_string (),
3438 rvalue
->get_scope ()->get_debug_string (),
3439 stmt_scope
->get_debug_string (),
3440 m_stmt
->get_debug_string ());
3444 if (rvalue
->dyn_cast_param ())
3446 (rvalue
->get_loc (),
3448 " param %s (type: %s)"
3449 " was used within function %s"
3450 " (in statement: %s)"
3451 " but is not associated with any function",
3453 rvalue
->get_debug_string (),
3454 rvalue
->get_type ()->get_debug_string (),
3455 stmt_scope
->get_debug_string (),
3456 m_stmt
->get_debug_string ());
3460 /* Verify that it's valid to use this rvalue (and all expressions
3461 in the tree below it) within the given statement.
3463 For example, we must reject attempts to use a local from one
3464 function within a different function here, or we'll get
3465 an ICE deep inside toplev::main. */
3468 recording::rvalue::verify_valid_within_stmt (const char *api_funcname
, statement
*s
)
3470 rvalue_usage_validator
v (api_funcname
,
3474 /* Verify that it's OK to use this rvalue within s. */
3477 /* Traverse the expression tree below "this", verifying all rvalues
3479 visit_children (&v
);
3482 /* Set the scope of this rvalue to be the given function. This can only
3483 be done once on a given rvalue. */
3486 recording::rvalue::set_scope (function
*scope
)
3489 gcc_assert (m_scope
== NULL
);
3494 /* Implementation of recording::rvalue::access_as_rvalue for rvalues
3496 Instances of rvalue don't need an upcast call. */
3499 recording::rvalue::access_as_rvalue (reproducer
&r
)
3501 return r
.get_identifier (this);
3504 /* Return a debug string for the given rvalue, wrapping it in parentheses
3505 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3506 stronger precedence that this rvalue's precedence.
3520 since MULT has strong precedence than PLUS and MINUS, whereas for:
3532 since PLUS has weaker precedence than MULT and DIVIDE. */
3535 recording::rvalue::get_debug_string_parens (enum precedence outer_prec
)
3537 enum precedence this_prec
= get_precedence ();
3539 /* If this_prec has stronger precedence than outer_prec, we don't
3540 need to wrap this in parens within the outer debug string.
3541 Stronger precedences occur earlier than weaker within the enum,
3542 so this is a less than test. Equal precedences don't need
3544 if (this_prec
<= outer_prec
)
3545 return get_debug_string();
3547 /* Otherwise, we need parentheses. */
3549 /* Lazily-build and cache m_parenthesized_string. */
3550 if (!m_parenthesized_string
)
3552 const char *debug_string
= get_debug_string ();
3553 m_parenthesized_string
= string::from_printf (get_context (),
3557 gcc_assert (m_parenthesized_string
);
3558 return m_parenthesized_string
->c_str ();
3562 /* The implementation of class gcc::jit::recording::lvalue. */
3564 /* Create a recording::new_access_field_of_lvalue instance and add it to
3565 the lvalue's context's list of mementos.
3567 Implements the post-error-checking part of
3568 gcc_jit_lvalue_access_field. */
3571 recording::lvalue::access_field (recording::location
*loc
,
3574 recording::lvalue
*result
=
3575 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
3576 m_ctxt
->record (result
);
3580 /* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3581 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3585 recording::lvalue::access_as_rvalue (reproducer
&r
)
3587 return r
.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3588 r
.get_identifier (this));
3591 /* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3592 Instances of lvalue don't need to be upcast. */
3595 recording::lvalue::access_as_lvalue (reproducer
&r
)
3597 return r
.get_identifier (this);
3600 /* Create a recording::get_address_of_lvalue instance and add it to
3601 the lvalue's context's list of mementos.
3603 Implements the post-error-checking part of
3604 gcc_jit_lvalue_get_address. */
3607 recording::lvalue::get_address (recording::location
*loc
)
3609 recording::rvalue
*result
=
3610 new get_address_of_lvalue (m_ctxt
, loc
, this);
3611 m_ctxt
->record (result
);
3615 /* The implementation of class gcc::jit::recording::param. */
3617 /* Implementation of pure virtual hook recording::memento::replay_into
3618 for recording::param. */
3621 recording::param::replay_into (replayer
*r
)
3623 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
3624 m_type
->playback_type (),
3628 /* Implementation of recording::rvalue::access_as_rvalue for params.
3629 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3633 recording::param::access_as_rvalue (reproducer
&r
)
3635 return r
.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3636 r
.get_identifier (this));
3639 /* Implementation of recording::lvalue::access_as_lvalue for params.
3640 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3644 recording::param::access_as_lvalue (reproducer
&r
)
3646 return r
.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3647 r
.get_identifier (this));
3650 /* Implementation of recording::memento::write_reproducer for params. */
3653 recording::param::write_reproducer (reproducer
&r
)
3655 const char *id
= r
.make_identifier (this, "param");
3656 r
.write (" gcc_jit_param *%s =\n"
3657 " gcc_jit_context_new_param (%s,\n"
3658 " %s, /* gcc_jit_location *loc */\n"
3659 " %s, /*gcc_jit_type *type */\n"
3660 " %s); /* const char *name */\n",
3662 r
.get_identifier (get_context ()),
3663 r
.get_identifier (m_loc
),
3664 r
.get_identifier_as_type (m_type
),
3665 m_name
->get_debug_string ());
3668 /* The implementation of class gcc::jit::recording::function. */
3670 /* gcc::jit::recording::function's constructor. */
3672 recording::function::function (context
*ctxt
,
3673 recording::location
*loc
,
3674 enum gcc_jit_function_kind kind
,
3676 recording::string
*name
,
3678 recording::param
**params
,
3680 enum built_in_function builtin_id
)
3684 m_return_type (return_type
),
3687 m_is_variadic (is_variadic
),
3688 m_builtin_id (builtin_id
),
3691 m_fn_ptr_type (NULL
)
3693 for (int i
= 0; i
< num_params
; i
++)
3695 param
*param
= params
[i
];
3698 /* Associate each param with this function.
3700 Verify that the param doesn't already have a function. */
3701 if (param
->get_scope ())
3703 /* We've already rejected attempts to reuse a param between
3704 different functions (within gcc_jit_context_new_function), so
3705 if the param *does* already have a function, it must be being
3706 reused within the params array for this function. We must
3707 produce an error for this reuse (blocking the compile), since
3708 otherwise we'd have an ICE later on. */
3709 gcc_assert (this == param
->get_scope ());
3712 "gcc_jit_context_new_function:"
3713 " parameter %s (type: %s)"
3714 " is used more than once when creating function %s",
3715 param
->get_debug_string (),
3716 param
->get_type ()->get_debug_string (),
3721 /* The normal, non-error case: associate this function with the
3723 param
->set_scope (this);
3726 m_params
.safe_push (param
);
3730 /* Implementation of pure virtual hook recording::memento::replay_into
3731 for recording::function. */
3734 recording::function::replay_into (replayer
*r
)
3736 /* Convert m_params to a vec of playback param. */
3737 auto_vec
<playback::param
*> params
;
3739 recording::param
*param
;
3740 params
.create (m_params
.length ());
3741 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3742 params
.safe_push (param
->playback_param ());
3744 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
3746 m_return_type
->playback_type (),
3753 /* Create a recording::local instance and add it to
3754 the functions's context's list of mementos, and to the function's
3757 Implements the post-error-checking part of
3758 gcc_jit_function_new_local. */
3761 recording::function::new_local (recording::location
*loc
,
3765 local
*result
= new local (this, loc
, type
, new_string (name
));
3766 m_ctxt
->record (result
);
3767 m_locals
.safe_push (result
);
3771 /* Create a recording::block instance and add it to
3772 the functions's context's list of mementos, and to the function's
3775 Implements the post-error-checking part of
3776 gcc_jit_function_new_block. */
3779 recording::function::new_block (const char *name
)
3781 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
3783 recording::block
*result
=
3784 new recording::block (this, m_blocks
.length (), new_string (name
));
3785 m_ctxt
->record (result
);
3786 m_blocks
.safe_push (result
);
3790 /* Override the default implementation of
3791 recording::memento::write_to_dump by dumping a C-like
3792 representation of the function; either like a prototype
3793 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3794 all other kinds of function. */
3797 recording::function::write_to_dump (dump
&d
)
3801 default: gcc_unreachable ();
3802 case GCC_JIT_FUNCTION_EXPORTED
:
3803 case GCC_JIT_FUNCTION_IMPORTED
:
3804 d
.write ("extern ");
3806 case GCC_JIT_FUNCTION_INTERNAL
:
3807 d
.write ("static ");
3809 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
3810 d
.write ("static inline ");
3813 d
.write ("%s\n", m_return_type
->get_debug_string ());
3815 if (d
.update_locations ())
3816 m_loc
= d
.make_location ();
3818 d
.write ("%s (", get_debug_string ());
3821 recording::param
*param
;
3822 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3827 param
->get_type ()->get_debug_string (),
3828 param
->get_debug_string ());
3831 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
3833 d
.write ("; /* (imported) */\n\n");
3843 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
3844 var
->write_to_dump (d
);
3845 if (m_locals
.length ())
3848 /* Write each block: */
3849 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3853 b
->write_to_dump (d
);
3860 /* Pre-compilation validation of a function, for those things we can't
3861 check until the context is (supposedly) fully-populated. */
3864 recording::function::validate ()
3866 /* Complain about empty functions with non-void return type. */
3867 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
3868 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
3869 if (m_blocks
.length () == 0)
3870 m_ctxt
->add_error (m_loc
,
3871 "function %s returns non-void (type: %s)"
3872 " but has no blocks",
3873 get_debug_string (),
3874 m_return_type
->get_debug_string ());
3876 /* Check that all blocks are terminated. */
3877 int num_invalid_blocks
= 0;
3882 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3883 if (!b
->validate ())
3884 num_invalid_blocks
++;
3887 /* Check that all blocks are reachable. */
3888 if (!m_ctxt
->get_inner_bool_option
3889 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS
)
3890 && m_blocks
.length () > 0 && num_invalid_blocks
== 0)
3892 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3893 flag, starting at the initial block. */
3894 auto_vec
<block
*> worklist (m_blocks
.length ());
3895 worklist
.safe_push (m_blocks
[0]);
3896 while (worklist
.length () > 0)
3898 block
*b
= worklist
.pop ();
3899 b
->m_is_reachable
= true;
3901 /* Add successor blocks that aren't yet marked to the worklist. */
3902 /* We checked that each block has a terminating statement above . */
3903 vec
<block
*> successors
= b
->get_successor_blocks ();
3906 FOR_EACH_VEC_ELT (successors
, i
, succ
)
3907 if (!succ
->m_is_reachable
)
3908 worklist
.safe_push (succ
);
3909 successors
.release ();
3912 /* Now complain about any blocks that haven't been marked. */
3916 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3917 if (!b
->m_is_reachable
)
3918 m_ctxt
->add_error (b
->get_loc (),
3919 "unreachable block: %s",
3920 b
->get_debug_string ());
3925 /* Implements the post-error-checking part of
3926 gcc_jit_function_dump_to_dot. */
3929 recording::function::dump_to_dot (const char *path
)
3931 FILE *fp
= fopen (path
, "w");
3935 pretty_printer the_pp
;
3936 the_pp
.buffer
->stream
= fp
;
3938 pretty_printer
*pp
= &the_pp
;
3941 "digraph %s {\n", get_debug_string ());
3947 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3948 b
->dump_to_dot (pp
);
3955 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
3956 b
->dump_edges_to_dot (pp
);
3959 pp_printf (pp
, "}\n");
3964 /* Implements the post-error-checking part of
3965 gcc_jit_function_get_address. */
3968 recording::function::get_address (recording::location
*loc
)
3970 /* Lazily create and cache the function pointer type. */
3973 /* Make a recording::function_type for this function. */
3974 auto_vec
<recording::type
*> param_types (m_params
.length ());
3976 recording::param
*param
;
3977 FOR_EACH_VEC_ELT (m_params
, i
, param
)
3978 param_types
.safe_push (param
->get_type ());
3979 recording::function_type
*fn_type
3980 = m_ctxt
->new_function_type (m_return_type
,
3982 param_types
.address (),
3984 m_fn_ptr_type
= fn_type
->get_pointer ();
3986 gcc_assert (m_fn_ptr_type
);
3988 rvalue
*result
= new function_pointer (get_context (), loc
, this, m_fn_ptr_type
);
3989 m_ctxt
->record (result
);
3993 /* Implementation of recording::memento::make_debug_string for
3997 recording::function::make_debug_string ()
4002 /* A table of enum gcc_jit_function_kind values expressed in string
4005 static const char * const names_of_function_kinds
[] = {
4006 "GCC_JIT_FUNCTION_EXPORTED",
4007 "GCC_JIT_FUNCTION_INTERNAL",
4008 "GCC_JIT_FUNCTION_IMPORTED",
4009 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
4012 /* Implementation of recording::memento::write_reproducer for functions. */
4015 recording::function::write_reproducer (reproducer
&r
)
4017 const char *id
= r
.make_identifier (this, "func");
4021 r
.write (" gcc_jit_function *%s =\n"
4022 " gcc_jit_context_get_builtin_function (%s,\n"
4025 r
.get_identifier (get_context ()),
4026 m_name
->get_debug_string ());
4029 const char *params_id
= r
.make_tmp_identifier ("params_for", this);
4030 r
.write (" gcc_jit_param *%s[%i] = {\n",
4032 m_params
.length ());
4035 FOR_EACH_VEC_ELT (m_params
, i
, param
)
4036 r
.write (" %s,\n", r
.get_identifier (param
));
4038 r
.write (" gcc_jit_function *%s =\n"
4039 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
4040 " %s, /* gcc_jit_location *loc */\n"
4041 " %s, /* enum gcc_jit_function_kind kind */\n"
4042 " %s, /* gcc_jit_type *return_type */\n"
4043 " %s, /* const char *name */\n"
4044 " %i, /* int num_params */\n"
4045 " %s, /* gcc_jit_param **params */\n"
4046 " %i); /* int is_variadic */\n",
4048 r
.get_identifier (get_context ()),
4049 r
.get_identifier (m_loc
),
4050 names_of_function_kinds
[m_kind
],
4051 r
.get_identifier_as_type (m_return_type
),
4052 m_name
->get_debug_string (),
4059 /* The implementation of class gcc::jit::recording::block. */
4061 /* Create a recording::eval instance and add it to
4062 the block's context's list of mementos, and to the block's
4065 Implements the heart of gcc_jit_block_add_eval. */
4067 recording::statement
*
4068 recording::block::add_eval (recording::location
*loc
,
4069 recording::rvalue
*rvalue
)
4071 statement
*result
= new eval (this, loc
, rvalue
);
4072 m_ctxt
->record (result
);
4073 m_statements
.safe_push (result
);
4077 /* Create a recording::assignment instance and add it to
4078 the block's context's list of mementos, and to the block's
4081 Implements the heart of gcc_jit_block_add_assignment. */
4083 recording::statement
*
4084 recording::block::add_assignment (recording::location
*loc
,
4085 recording::lvalue
*lvalue
,
4086 recording::rvalue
*rvalue
)
4088 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
4089 m_ctxt
->record (result
);
4090 m_statements
.safe_push (result
);
4094 /* Create a recording::assignment_op instance and add it to
4095 the block's context's list of mementos, and to the block's
4098 Implements the heart of gcc_jit_block_add_assignment_op. */
4100 recording::statement
*
4101 recording::block::add_assignment_op (recording::location
*loc
,
4102 recording::lvalue
*lvalue
,
4103 enum gcc_jit_binary_op op
,
4104 recording::rvalue
*rvalue
)
4106 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
4107 m_ctxt
->record (result
);
4108 m_statements
.safe_push (result
);
4112 /* Create a recording::comment instance and add it to
4113 the block's context's list of mementos, and to the block's
4116 Implements the heart of gcc_jit_block_add_comment. */
4118 recording::statement
*
4119 recording::block::add_comment (recording::location
*loc
,
4122 statement
*result
= new comment (this, loc
, new_string (text
));
4123 m_ctxt
->record (result
);
4124 m_statements
.safe_push (result
);
4128 /* Create a recording::end_with_conditional instance and add it to
4129 the block's context's list of mementos, and to the block's
4132 Implements the heart of gcc_jit_block_end_with_conditional. */
4134 recording::statement
*
4135 recording::block::end_with_conditional (recording::location
*loc
,
4136 recording::rvalue
*boolval
,
4137 recording::block
*on_true
,
4138 recording::block
*on_false
)
4140 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
4141 m_ctxt
->record (result
);
4142 m_statements
.safe_push (result
);
4143 m_has_been_terminated
= true;
4147 /* Create a recording::end_with_jump instance and add it to
4148 the block's context's list of mementos, and to the block's
4151 Implements the heart of gcc_jit_block_end_with_jump. */
4153 recording::statement
*
4154 recording::block::end_with_jump (recording::location
*loc
,
4155 recording::block
*target
)
4157 statement
*result
= new jump (this, loc
, target
);
4158 m_ctxt
->record (result
);
4159 m_statements
.safe_push (result
);
4160 m_has_been_terminated
= true;
4164 /* Create a recording::end_with_return instance and add it to
4165 the block's context's list of mementos, and to the block's
4168 Implements the post-error-checking parts of
4169 gcc_jit_block_end_with_return and
4170 gcc_jit_block_end_with_void_return. */
4172 recording::statement
*
4173 recording::block::end_with_return (recording::location
*loc
,
4174 recording::rvalue
*rvalue
)
4176 /* This is used by both gcc_jit_function_add_return and
4177 gcc_jit_function_add_void_return; rvalue will be non-NULL for
4178 the former and NULL for the latter. */
4179 statement
*result
= new return_ (this, loc
, rvalue
);
4180 m_ctxt
->record (result
);
4181 m_statements
.safe_push (result
);
4182 m_has_been_terminated
= true;
4186 /* Create a recording::switch_ instance and add it to
4187 the block's context's list of mementos, and to the block's
4190 Implements the heart of gcc_jit_block_end_with_switch. */
4192 recording::statement
*
4193 recording::block::end_with_switch (recording::location
*loc
,
4194 recording::rvalue
*expr
,
4195 recording::block
*default_block
,
4197 recording::case_
**cases
)
4199 statement
*result
= new switch_ (this, loc
,
4204 m_ctxt
->record (result
);
4205 m_statements
.safe_push (result
);
4206 m_has_been_terminated
= true;
4210 /* Override the default implementation of
4211 recording::memento::write_to_dump for blocks by writing
4212 an unindented block name as a label, followed by the indented
4222 recording::block::write_to_dump (dump
&d
)
4224 d
.write ("%s:\n", get_debug_string ());
4228 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
4229 s
->write_to_dump (d
);
4232 /* Validate a block by ensuring that it has been terminated. */
4235 recording::block::validate ()
4237 /* Check for termination. */
4238 if (!has_been_terminated ())
4240 statement
*stmt
= get_last_statement ();
4241 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
4242 m_func
->get_context ()->add_error (loc
,
4243 "unterminated block in %s: %s",
4244 m_func
->get_debug_string (),
4245 get_debug_string ());
4252 /* Get the source-location of a block by using that of the first
4253 statement within it, if any. */
4255 recording::location
*
4256 recording::block::get_loc () const
4258 recording::statement
*stmt
= get_first_statement ();
4260 return stmt
->get_loc ();
4265 /* Get the first statement within a block, if any. */
4267 recording::statement
*
4268 recording::block::get_first_statement () const
4270 if (m_statements
.length ())
4271 return m_statements
[0];
4276 /* Get the last statement within a block, if any. */
4278 recording::statement
*
4279 recording::block::get_last_statement () const
4281 if (m_statements
.length ())
4282 return m_statements
[m_statements
.length () - 1];
4287 /* Assuming that this block has been terminated, get the successor blocks
4288 as a vector. Ownership of the vector transfers to the caller, which
4289 must call its release () method.
4291 Used when validating functions, and when dumping dot representations
4294 vec
<recording::block
*>
4295 recording::block::get_successor_blocks () const
4297 gcc_assert (m_has_been_terminated
);
4298 statement
*last_statement
= get_last_statement ();
4299 gcc_assert (last_statement
);
4300 return last_statement
->get_successor_blocks ();
4303 /* Implementation of pure virtual hook recording::memento::replay_into
4304 for recording::block. */
4307 recording::block::replay_into (replayer
*)
4309 set_playback_obj (m_func
->playback_function ()
4310 ->new_block (playback_string (m_name
)));
4313 /* Implementation of recording::memento::make_debug_string for
4317 recording::block::make_debug_string ()
4322 return string::from_printf (m_ctxt
,
4323 "<UNNAMED BLOCK %p>",
4327 /* Implementation of recording::memento::write_reproducer for blocks. */
4330 recording::block::write_reproducer (reproducer
&r
)
4332 const char *id
= r
.make_identifier (this, "block");
4333 r
.write (" gcc_jit_block *%s =\n"
4334 " gcc_jit_function_new_block (%s, %s);\n",
4336 r
.get_identifier (m_func
),
4337 m_name
? m_name
->get_debug_string () : "NULL");
4340 /* Dump a block in graphviz form into PP, capturing the block name (if
4341 any) and the statements. */
4344 recording::block::dump_to_dot (pretty_printer
*pp
)
4348 "[shape=record,style=filled,fillcolor=white,label=\"{"),
4350 pp_write_text_to_stream (pp
);
4353 pp_string (pp
, m_name
->c_str ());
4354 pp_string (pp
, ":");
4356 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
4361 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
4363 pp_string (pp
, s
->get_debug_string ());
4365 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
4373 /* Dump the out-edges of the block in graphviz form into PP. */
4376 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
4378 vec
<block
*> successors
= get_successor_blocks ();
4381 FOR_EACH_VEC_ELT (successors
, i
, succ
)
4383 "\tblock_%d:s -> block_%d:n;\n",
4384 m_index
, succ
->m_index
);
4385 successors
.release ();
4388 /* The implementation of class gcc::jit::recording::global. */
4390 /* Implementation of pure virtual hook recording::memento::replay_into
4391 for recording::global. */
4394 recording::global::replay_into (replayer
*r
)
4396 set_playback_obj (r
->new_global (playback_location (r
, m_loc
),
4398 m_type
->playback_type (),
4399 playback_string (m_name
)));
4402 /* Override the default implementation of
4403 recording::memento::write_to_dump for globals.
4404 This will be of the form:
4406 GCC_JIT_GLOBAL_EXPORTED:
4410 GCC_JIT_GLOBAL_INTERNAL:
4412 e.g. "static int foo;"
4414 GCC_JIT_GLOBAL_IMPORTED:
4416 e.g. "extern int foo;"
4418 These are written to the top of the dump by
4419 recording::context::dump_to_file. */
4422 recording::global::write_to_dump (dump
&d
)
4424 if (d
.update_locations ())
4425 m_loc
= d
.make_location ();
4432 case GCC_JIT_GLOBAL_EXPORTED
:
4435 case GCC_JIT_GLOBAL_INTERNAL
:
4436 d
.write ("static ");
4439 case GCC_JIT_GLOBAL_IMPORTED
:
4440 d
.write ("extern ");
4443 d
.write ("%s %s;\n",
4444 m_type
->get_debug_string (),
4445 get_debug_string ());
4448 /* A table of enum gcc_jit_global_kind values expressed in string
4451 static const char * const global_kind_reproducer_strings
[] = {
4452 "GCC_JIT_GLOBAL_EXPORTED",
4453 "GCC_JIT_GLOBAL_INTERNAL",
4454 "GCC_JIT_GLOBAL_IMPORTED"
4457 /* Implementation of recording::memento::write_reproducer for globals. */
4460 recording::global::write_reproducer (reproducer
&r
)
4462 const char *id
= r
.make_identifier (this, "block");
4463 r
.write (" gcc_jit_lvalue *%s =\n"
4464 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4465 " %s, /* gcc_jit_location *loc */\n"
4466 " %s, /* enum gcc_jit_global_kind kind */\n"
4467 " %s, /* gcc_jit_type *type */\n"
4468 " %s); /* const char *name */\n",
4470 r
.get_identifier (get_context ()),
4471 r
.get_identifier (m_loc
),
4472 global_kind_reproducer_strings
[m_kind
],
4473 r
.get_identifier_as_type (get_type ()),
4474 m_name
->get_debug_string ());
4477 /* The implementation of the various const-handling classes:
4478 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4480 /* Explicit specialization of the various mementos we're interested in. */
4481 template class recording::memento_of_new_rvalue_from_const
<int>;
4482 template class recording::memento_of_new_rvalue_from_const
<long>;
4483 template class recording::memento_of_new_rvalue_from_const
<double>;
4484 template class recording::memento_of_new_rvalue_from_const
<void *>;
4486 /* Implementation of the pure virtual hook recording::memento::replay_into
4487 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
4489 template <typename HOST_TYPE
>
4492 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
4495 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
4499 /* The make_debug_string and write_reproducer methods vary between the
4501 memento_of_new_rvalue_from_const <HOST_TYPE>
4502 classes, so we explicitly write specializations of them.
4504 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4505 namespaces are written out explicitly, which is why most of this file
4506 doesn't abbreviate things by entering the "recording" namespace.
4508 However, these specializations are required to be in the same namespace
4509 as the template, hence we now have to enter the gcc::jit::recording
4515 /* The make_debug_string specialization for <int>, which renders it as
4516 (TARGET_TYPE)LITERAL
4522 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
4524 return string::from_printf (m_ctxt
,
4526 m_type
->get_debug_string (),
4530 /* The get_wide_int specialization for <int>. */
4534 memento_of_new_rvalue_from_const
<int>::get_wide_int (wide_int
*out
) const
4536 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
4540 /* The write_reproducer specialization for <int>. */
4544 memento_of_new_rvalue_from_const
<int>::write_reproducer (reproducer
&r
)
4546 const char *id
= r
.make_identifier (this, "rvalue");
4547 r
.write (" gcc_jit_rvalue *%s =\n"
4548 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4549 " %s, /* gcc_jit_type *numeric_type */\n"
4550 " %i); /* int value */\n",
4552 r
.get_identifier (get_context ()),
4553 r
.get_identifier_as_type (m_type
),
4557 /* The make_debug_string specialization for <long>, rendering it as
4558 (TARGET_TYPE)LITERAL
4564 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
4566 return string::from_printf (m_ctxt
,
4568 m_type
->get_debug_string (),
4572 /* The get_wide_int specialization for <long>. */
4576 memento_of_new_rvalue_from_const
<long>::get_wide_int (wide_int
*out
) const
4578 *out
= wi::shwi (m_value
, sizeof (m_value
) * 8);
4582 /* The write_reproducer specialization for <long>. */
4586 recording::memento_of_new_rvalue_from_const
<long>::write_reproducer (reproducer
&r
)
4588 const char *id
= r
.make_identifier (this, "rvalue");
4590 /* We have to special-case LONG_MIN, since e.g.
4591 -9223372036854775808L
4593 -(9223372036854775808L)
4595 error: integer constant is so large that it is unsigned [-Werror]
4596 Workaround this by writing (LONG_MIN + 1) - 1. */
4597 if (m_value
== LONG_MIN
)
4599 r
.write (" gcc_jit_rvalue *%s =\n"
4600 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4601 " %s, /* gcc_jit_type *numeric_type */\n"
4602 " %ldL - 1); /* long value */\n",
4604 r
.get_identifier (get_context ()),
4605 r
.get_identifier_as_type (m_type
),
4610 r
.write (" gcc_jit_rvalue *%s =\n"
4611 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4612 " %s, /* gcc_jit_type *numeric_type */\n"
4613 " %ldL); /* long value */\n",
4615 r
.get_identifier (get_context ()),
4616 r
.get_identifier_as_type (m_type
),
4620 /* The make_debug_string specialization for <double>, rendering it as
4621 (TARGET_TYPE)LITERAL
4627 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
4629 return string::from_printf (m_ctxt
,
4631 m_type
->get_debug_string (),
4635 /* The get_wide_int specialization for <double>. */
4639 memento_of_new_rvalue_from_const
<double>::get_wide_int (wide_int
*) const
4644 /* The write_reproducer specialization for <double>. */
4648 recording::memento_of_new_rvalue_from_const
<double>::write_reproducer (reproducer
&r
)
4650 const char *id
= r
.make_identifier (this, "rvalue");
4651 r
.write (" gcc_jit_rvalue *%s =\n"
4652 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4653 " %s, /* gcc_jit_type *numeric_type */\n"
4654 " %f); /* double value */\n",
4656 r
.get_identifier (get_context ()),
4657 r
.get_identifier_as_type (m_type
),
4661 /* The make_debug_string specialization for <void *>, rendering it as
4666 Zero is rendered as NULL e.g.
4671 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
4673 if (m_value
!= NULL
)
4674 return string::from_printf (m_ctxt
,
4676 m_type
->get_debug_string (), m_value
);
4678 return string::from_printf (m_ctxt
,
4680 m_type
->get_debug_string ());
4683 /* The get_wide_int specialization for <void *>. */
4687 memento_of_new_rvalue_from_const
<void *>::get_wide_int (wide_int
*) const
4692 /* Implementation of recording::memento::write_reproducer for <void *>
4697 memento_of_new_rvalue_from_const
<void *>::write_reproducer (reproducer
&r
)
4699 const char *id
= r
.make_identifier (this, "rvalue");
4701 r
.write (" gcc_jit_rvalue *%s =\n"
4702 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4703 " %s, /* gcc_jit_type *pointer_type */\n"
4704 " (void *)%p); /* void *value */\n",
4706 r
.get_identifier (get_context ()),
4707 r
.get_identifier_as_type (m_type
),
4710 r
.write (" gcc_jit_rvalue *%s =\n"
4711 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4712 " %s); /* gcc_jit_type *pointer_type */\n",
4714 r
.get_identifier (get_context ()),
4715 r
.get_identifier_as_type (m_type
));
4718 /* We're done specializing make_debug_string and write_reproducer, so we
4719 can exit the gcc::jit::recording namespace. */
4721 } // namespace recording
4723 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4725 /* Implementation of pure virtual hook recording::memento::replay_into
4726 for recording::memento_of_new_string_literal. */
4729 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
4731 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
4734 /* Implementation of recording::memento::make_debug_string for
4738 recording::memento_of_new_string_literal::make_debug_string ()
4740 return string::from_printf (m_ctxt
,
4742 m_value
->get_debug_string ());
4745 /* Implementation of recording::memento::write_reproducer for string literal
4749 recording::memento_of_new_string_literal::write_reproducer (reproducer
&r
)
4751 const char *id
= r
.make_identifier (this, "rvalue");
4752 r
.write (" gcc_jit_rvalue *%s =\n"
4753 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4754 " %s); /* const char *value */\n",
4756 r
.get_identifier (get_context ()),
4757 m_value
->get_debug_string ());
4760 /* The implementation of class
4761 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
4763 /* The constructor for
4764 gcc::jit::recording::memento_of_new_rvalue_from_vector. */
4766 recording::memento_of_new_rvalue_from_vector::
4767 memento_of_new_rvalue_from_vector (context
*ctxt
,
4771 : rvalue (ctxt
, loc
, type
),
4772 m_vector_type (type
),
4775 for (unsigned i
= 0; i
< type
->get_num_units (); i
++)
4776 m_elements
.safe_push (elements
[i
]);
4779 /* Implementation of pure virtual hook recording::memento::replay_into
4780 for recording::memento_of_new_rvalue_from_vector. */
4783 recording::memento_of_new_rvalue_from_vector::replay_into (replayer
*r
)
4785 auto_vec
<playback::rvalue
*> playback_elements
;
4786 playback_elements
.create (m_elements
.length ());
4787 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
4788 playback_elements
.safe_push (m_elements
[i
]->playback_rvalue ());
4790 set_playback_obj (r
->new_rvalue_from_vector (playback_location (r
, m_loc
),
4791 m_type
->playback_type (),
4792 playback_elements
));
4795 /* Implementation of pure virtual hook recording::rvalue::visit_children
4796 for recording::memento_of_new_rvalue_from_vector. */
4799 recording::memento_of_new_rvalue_from_vector::visit_children (rvalue_visitor
*v
)
4801 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
4802 v
->visit (m_elements
[i
]);
4805 /* Implementation of recording::memento::make_debug_string for
4809 recording::memento_of_new_rvalue_from_vector::make_debug_string ()
4811 comma_separated_string
elements (m_elements
, get_precedence ());
4813 /* Now build a string. */
4814 string
*result
= string::from_printf (m_ctxt
,
4816 elements
.as_char_ptr ());
4822 /* Implementation of recording::memento::write_reproducer for
4826 recording::memento_of_new_rvalue_from_vector::write_reproducer (reproducer
&r
)
4828 const char *id
= r
.make_identifier (this, "vector");
4829 const char *elements_id
= r
.make_tmp_identifier ("elements_for_", this);
4830 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
4832 m_elements
.length ());
4833 for (unsigned i
= 0; i
< m_elements
.length (); i
++)
4834 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_elements
[i
]));
4836 r
.write (" gcc_jit_rvalue *%s =\n"
4837 " gcc_jit_context_new_rvalue_from_vector (%s, /* gcc_jit_context *ctxt */\n"
4838 " %s, /* gcc_jit_location *loc */\n"
4839 " %s, /* gcc_jit_type *vec_type */\n"
4840 " %i, /* size_t num_elements */ \n"
4841 " %s); /* gcc_jit_rvalue **elements*/\n",
4843 r
.get_identifier (get_context ()),
4844 r
.get_identifier (m_loc
),
4845 r
.get_identifier (m_vector_type
),
4846 m_elements
.length (),
4850 /* The implementation of class gcc::jit::recording::unary_op. */
4852 /* Implementation of pure virtual hook recording::memento::replay_into
4853 for recording::unary_op. */
4856 recording::unary_op::replay_into (replayer
*r
)
4858 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
4860 get_type ()->playback_type (),
4861 m_a
->playback_rvalue ()));
4864 /* Implementation of pure virtual hook recording::rvalue::visit_children
4865 for recording::unary_op. */
4867 recording::unary_op::visit_children (rvalue_visitor
*v
)
4872 /* Implementation of recording::memento::make_debug_string for
4875 static const char * const unary_op_strings
[] = {
4876 "-", /* GCC_JIT_UNARY_OP_MINUS */
4877 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4878 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
4879 "abs ", /* GCC_JIT_UNARY_OP_ABS */
4883 recording::unary_op::make_debug_string ()
4885 return string::from_printf (m_ctxt
,
4887 unary_op_strings
[m_op
],
4888 m_a
->get_debug_string ());
4891 const char * const unary_op_reproducer_strings
[] = {
4892 "GCC_JIT_UNARY_OP_MINUS",
4893 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4894 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4895 "GCC_JIT_UNARY_OP_ABS"
4898 /* Implementation of recording::memento::write_reproducer for unary ops. */
4901 recording::unary_op::write_reproducer (reproducer
&r
)
4903 const char *id
= r
.make_identifier (this, "rvalue");
4904 r
.write (" gcc_jit_rvalue *%s =\n"
4905 " gcc_jit_context_new_unary_op (%s,\n"
4906 " %s, /* gcc_jit_location *loc */\n"
4907 " %s, /* enum gcc_jit_unary_op op */\n"
4908 " %s, /* gcc_jit_type *result_type */\n"
4909 " %s); /* gcc_jit_rvalue *a */\n",
4911 r
.get_identifier (get_context ()),
4912 r
.get_identifier (m_loc
),
4913 unary_op_reproducer_strings
[m_op
],
4914 r
.get_identifier_as_type (get_type ()),
4915 r
.get_identifier_as_rvalue (m_a
));
4918 /* The implementation of class gcc::jit::recording::binary_op. */
4920 /* Implementation of pure virtual hook recording::memento::replay_into
4921 for recording::binary_op. */
4924 recording::binary_op::replay_into (replayer
*r
)
4926 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
4928 get_type ()->playback_type (),
4929 m_a
->playback_rvalue (),
4930 m_b
->playback_rvalue ()));
4933 /* Implementation of pure virtual hook recording::rvalue::visit_children
4934 for recording::binary_op. */
4936 recording::binary_op::visit_children (rvalue_visitor
*v
)
4942 /* Implementation of recording::memento::make_debug_string for
4945 static const char * const binary_op_strings
[] = {
4946 "+", /* GCC_JIT_BINARY_OP_PLUS */
4947 "-", /* GCC_JIT_BINARY_OP_MINUS */
4948 "*", /* GCC_JIT_BINARY_OP_MULT */
4949 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4950 "%", /* GCC_JIT_BINARY_OP_MODULO */
4951 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4952 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4953 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4954 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4955 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4956 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4957 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4961 recording::binary_op::make_debug_string ()
4963 enum precedence prec
= get_precedence ();
4964 return string::from_printf (m_ctxt
,
4966 m_a
->get_debug_string_parens (prec
),
4967 binary_op_strings
[m_op
],
4968 m_b
->get_debug_string_parens (prec
));
4971 const char * const binary_op_reproducer_strings
[] = {
4972 "GCC_JIT_BINARY_OP_PLUS",
4973 "GCC_JIT_BINARY_OP_MINUS",
4974 "GCC_JIT_BINARY_OP_MULT",
4975 "GCC_JIT_BINARY_OP_DIVIDE",
4976 "GCC_JIT_BINARY_OP_MODULO",
4977 "GCC_JIT_BINARY_OP_BITWISE_AND",
4978 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4979 "GCC_JIT_BINARY_OP_BITWISE_OR",
4980 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4981 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4982 "GCC_JIT_BINARY_OP_LSHIFT",
4983 "GCC_JIT_BINARY_OP_RSHIFT"
4986 /* Implementation of recording::memento::write_reproducer for binary ops. */
4989 recording::binary_op::write_reproducer (reproducer
&r
)
4991 const char *id
= r
.make_identifier (this, "rvalue");
4992 r
.write (" gcc_jit_rvalue *%s =\n"
4993 " gcc_jit_context_new_binary_op (%s,\n"
4994 " %s, /* gcc_jit_location *loc */\n"
4995 " %s, /* enum gcc_jit_binary_op op */\n"
4996 " %s, /* gcc_jit_type *result_type */\n"
4997 " %s, /* gcc_jit_rvalue *a */\n"
4998 " %s); /* gcc_jit_rvalue *b */\n",
5000 r
.get_identifier (get_context ()),
5001 r
.get_identifier (m_loc
),
5002 binary_op_reproducer_strings
[m_op
],
5003 r
.get_identifier_as_type (get_type ()),
5004 r
.get_identifier_as_rvalue (m_a
),
5005 r
.get_identifier_as_rvalue (m_b
));
5008 namespace recording
{
5009 static const enum precedence binary_op_precedence
[] = {
5010 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_PLUS */
5011 PRECEDENCE_ADDITIVE
, /* GCC_JIT_BINARY_OP_MINUS */
5013 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MULT */
5014 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_DIVIDE */
5015 PRECEDENCE_MULTIPLICATIVE
, /* GCC_JIT_BINARY_OP_MODULO */
5017 PRECEDENCE_BITWISE_AND
, /* GCC_JIT_BINARY_OP_BITWISE_AND */
5018 PRECEDENCE_BITWISE_XOR
, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
5019 PRECEDENCE_BITWISE_IOR
, /* GCC_JIT_BINARY_OP_BITWISE_OR */
5020 PRECEDENCE_LOGICAL_AND
, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
5021 PRECEDENCE_LOGICAL_OR
, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
5022 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_LSHIFT */
5023 PRECEDENCE_SHIFT
, /* GCC_JIT_BINARY_OP_RSHIFT */
5025 } /* namespace recording */
5027 enum recording::precedence
5028 recording::binary_op::get_precedence () const
5030 return binary_op_precedence
[m_op
];
5033 /* The implementation of class gcc::jit::recording::comparison. */
5035 /* Implementation of recording::memento::make_debug_string for
5038 static const char * const comparison_strings
[] =
5040 "==", /* GCC_JIT_COMPARISON_EQ */
5041 "!=", /* GCC_JIT_COMPARISON_NE */
5042 "<", /* GCC_JIT_COMPARISON_LT */
5043 "<=", /* GCC_JIT_COMPARISON_LE */
5044 ">", /* GCC_JIT_COMPARISON_GT */
5045 ">=", /* GCC_JIT_COMPARISON_GE */
5049 recording::comparison::make_debug_string ()
5051 enum precedence prec
= get_precedence ();
5052 return string::from_printf (m_ctxt
,
5054 m_a
->get_debug_string_parens (prec
),
5055 comparison_strings
[m_op
],
5056 m_b
->get_debug_string_parens (prec
));
5059 /* A table of enum gcc_jit_comparison values expressed in string
5062 static const char * const comparison_reproducer_strings
[] =
5064 "GCC_JIT_COMPARISON_EQ",
5065 "GCC_JIT_COMPARISON_NE",
5066 "GCC_JIT_COMPARISON_LT",
5067 "GCC_JIT_COMPARISON_LE",
5068 "GCC_JIT_COMPARISON_GT",
5069 "GCC_JIT_COMPARISON_GE"
5072 /* Implementation of recording::memento::write_reproducer for comparisons. */
5075 recording::comparison::write_reproducer (reproducer
&r
)
5077 const char *id
= r
.make_identifier (this, "rvalue");
5078 r
.write (" gcc_jit_rvalue *%s =\n"
5079 " gcc_jit_context_new_comparison (%s,\n"
5080 " %s, /* gcc_jit_location *loc */\n"
5081 " %s, /* enum gcc_jit_comparison op */\n"
5082 " %s, /* gcc_jit_rvalue *a */\n"
5083 " %s); /* gcc_jit_rvalue *b */\n",
5085 r
.get_identifier (get_context ()),
5086 r
.get_identifier (m_loc
),
5087 comparison_reproducer_strings
[m_op
],
5088 r
.get_identifier_as_rvalue (m_a
),
5089 r
.get_identifier_as_rvalue (m_b
));
5092 /* Implementation of pure virtual hook recording::memento::replay_into
5093 for recording::comparison. */
5096 recording::comparison::replay_into (replayer
*r
)
5098 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
5100 m_a
->playback_rvalue (),
5101 m_b
->playback_rvalue ()));
5104 /* Implementation of pure virtual hook recording::rvalue::visit_children
5105 for recording::comparison. */
5108 recording::comparison::visit_children (rvalue_visitor
*v
)
5114 namespace recording
{
5115 static const enum precedence comparison_precedence
[] =
5117 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_EQ */
5118 PRECEDENCE_EQUALITY
, /* GCC_JIT_COMPARISON_NE */
5120 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LT */
5121 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_LE */
5122 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GT */
5123 PRECEDENCE_RELATIONAL
, /* GCC_JIT_COMPARISON_GE */
5125 } /* namespace recording */
5127 enum recording::precedence
5128 recording::comparison::get_precedence () const
5130 return comparison_precedence
[m_op
];
5133 /* Implementation of pure virtual hook recording::memento::replay_into
5134 for recording::cast. */
5137 recording::cast::replay_into (replayer
*r
)
5139 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
5140 m_rvalue
->playback_rvalue (),
5141 get_type ()->playback_type ()));
5144 /* Implementation of pure virtual hook recording::rvalue::visit_children
5145 for recording::cast. */
5147 recording::cast::visit_children (rvalue_visitor
*v
)
5149 v
->visit (m_rvalue
);
5152 /* Implementation of recording::memento::make_debug_string for
5156 recording::cast::make_debug_string ()
5158 enum precedence prec
= get_precedence ();
5159 return string::from_printf (m_ctxt
,
5161 get_type ()->get_debug_string (),
5162 m_rvalue
->get_debug_string_parens (prec
));
5165 /* Implementation of recording::memento::write_reproducer for casts. */
5168 recording::cast::write_reproducer (reproducer
&r
)
5170 const char *id
= r
.make_identifier (this, "rvalue");
5171 r
.write (" gcc_jit_rvalue *%s =\n"
5172 " gcc_jit_context_new_cast (%s,\n"
5173 " %s, /* gcc_jit_location *loc */\n"
5174 " %s, /* gcc_jit_rvalue *rvalue */\n"
5175 " %s); /* gcc_jit_type *type */\n",
5177 r
.get_identifier (get_context ()),
5178 r
.get_identifier (m_loc
),
5179 r
.get_identifier_as_rvalue (m_rvalue
),
5180 r
.get_identifier_as_type (get_type ()));
5183 /* The implementation of class gcc::jit::recording::base_call. */
5185 /* The constructor for gcc::jit::recording::base_call. */
5187 recording::base_call::base_call (context
*ctxt
,
5192 : rvalue (ctxt
, loc
, type_
),
5194 m_require_tail_call (0)
5196 for (int i
= 0; i
< numargs
; i
++)
5197 m_args
.safe_push (args
[i
]);
5200 /* Subroutine for use by call and call_though_ptr's write_reproducer
5204 recording::base_call::write_reproducer_tail_call (reproducer
&r
,
5207 if (m_require_tail_call
)
5209 r
.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
5210 " %i); /* int require_tail_call*/\n",
5216 /* The implementation of class gcc::jit::recording::call. */
5218 /* The constructor for gcc::jit::recording::call. */
5220 recording::call::call (recording::context
*ctxt
,
5221 recording::location
*loc
,
5222 recording::function
*func
,
5225 : base_call (ctxt
, loc
, func
->get_return_type (), numargs
, args
),
5230 /* Implementation of pure virtual hook recording::memento::replay_into
5231 for recording::call. */
5234 recording::call::replay_into (replayer
*r
)
5236 auto_vec
<playback::rvalue
*> playback_args
;
5237 playback_args
.create (m_args
.length ());
5238 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5239 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
5241 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
5242 m_func
->playback_function (),
5244 m_require_tail_call
));
5247 /* Implementation of pure virtual hook recording::rvalue::visit_children
5248 for recording::call. */
5251 recording::call::visit_children (rvalue_visitor
*v
)
5253 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5254 v
->visit (m_args
[i
]);
5257 /* Implementation of recording::memento::make_debug_string for
5261 recording::call::make_debug_string ()
5263 /* First, build a buffer for the arguments. */
5264 comma_separated_string
args (m_args
, get_precedence ());
5266 /* ...and use it to get the string for the call as a whole. */
5267 string
*result
= string::from_printf (m_ctxt
,
5269 m_func
->get_debug_string (),
5270 args
.as_char_ptr ());
5276 recording::call::write_reproducer (reproducer
&r
)
5278 const char *id
= r
.make_identifier (this, "call");
5279 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
5280 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
5283 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5284 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
5286 r
.write (" gcc_jit_rvalue *%s =\n"
5287 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
5288 " %s, /* gcc_jit_location *loc */\n"
5289 " %s, /* gcc_jit_function *func */\n"
5290 " %i, /* int numargs */ \n"
5291 " %s); /* gcc_jit_rvalue **args*/\n",
5293 r
.get_identifier (get_context ()),
5294 r
.get_identifier (m_loc
),
5295 r
.get_identifier (m_func
),
5298 write_reproducer_tail_call (r
, id
);
5301 /* The implementation of class gcc::jit::recording::call_through_ptr. */
5303 /* The constructor for recording::call_through_ptr. */
5305 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
5306 recording::location
*loc
,
5307 recording::rvalue
*fn_ptr
,
5310 : base_call (ctxt
, loc
,
5311 fn_ptr
->get_type ()->dereference ()
5312 ->as_a_function_type ()->get_return_type (),
5318 /* Implementation of pure virtual hook recording::memento::replay_into
5319 for recording::call_through_ptr. */
5322 recording::call_through_ptr::replay_into (replayer
*r
)
5324 auto_vec
<playback::rvalue
*> playback_args
;
5325 playback_args
.create (m_args
.length ());
5326 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5327 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
5329 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
5330 m_fn_ptr
->playback_rvalue (),
5332 m_require_tail_call
));
5335 /* Implementation of pure virtual hook recording::rvalue::visit_children
5336 for recording::call_through_ptr. */
5339 recording::call_through_ptr::visit_children (rvalue_visitor
*v
)
5341 v
->visit (m_fn_ptr
);
5342 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5343 v
->visit (m_args
[i
]);
5346 /* Implementation of recording::memento::make_debug_string for
5347 calls through function ptrs. */
5350 recording::call_through_ptr::make_debug_string ()
5352 enum precedence prec
= get_precedence ();
5353 /* First, build a buffer for the arguments. */
5354 /* Calculate length of said buffer. */
5355 size_t sz
= 1; /* nil terminator */
5356 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5358 sz
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
5359 sz
+= 2; /* ", " separator */
5362 /* Now allocate and populate the buffer. */
5363 char *argbuf
= new char[sz
];
5366 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5368 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string_parens (prec
));
5369 len
+= strlen (m_args
[i
]->get_debug_string_parens (prec
));
5370 if (i
+ 1 < m_args
.length ())
5372 strcpy (argbuf
+ len
, ", ");
5378 /* ...and use it to get the string for the call as a whole. */
5379 string
*result
= string::from_printf (m_ctxt
,
5381 m_fn_ptr
->get_debug_string_parens (prec
),
5389 /* Implementation of recording::memento::write_reproducer for
5390 call_through_ptr. */
5393 recording::call_through_ptr::write_reproducer (reproducer
&r
)
5395 const char *id
= r
.make_identifier (this, "call");
5396 const char *args_id
= r
.make_tmp_identifier ("args_for_", this);
5397 r
.write (" gcc_jit_rvalue *%s[%i] = {\n",
5400 for (unsigned i
= 0; i
< m_args
.length (); i
++)
5401 r
.write (" %s,\n", r
.get_identifier_as_rvalue (m_args
[i
]));
5403 r
.write (" gcc_jit_rvalue *%s =\n"
5404 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
5405 " %s, /* gcc_jit_location *loc */\n"
5406 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
5407 " %i, /* int numargs */ \n"
5408 " %s); /* gcc_jit_rvalue **args*/\n",
5410 r
.get_identifier (get_context ()),
5411 r
.get_identifier (m_loc
),
5412 r
.get_identifier_as_rvalue (m_fn_ptr
),
5415 write_reproducer_tail_call (r
, id
);
5418 /* The implementation of class gcc::jit::recording::array_access. */
5420 /* Implementation of pure virtual hook recording::memento::replay_into
5421 for recording::array_access. */
5424 recording::array_access::replay_into (replayer
*r
)
5427 r
->new_array_access (playback_location (r
, m_loc
),
5428 m_ptr
->playback_rvalue (),
5429 m_index
->playback_rvalue ()));
5432 /* Implementation of pure virtual hook recording::rvalue::visit_children
5433 for recording::array_access. */
5436 recording::array_access::visit_children (rvalue_visitor
*v
)
5442 /* Implementation of recording::memento::make_debug_string for
5446 recording::array_access::make_debug_string ()
5448 enum precedence prec
= get_precedence ();
5449 return string::from_printf (m_ctxt
,
5451 m_ptr
->get_debug_string_parens (prec
),
5452 m_index
->get_debug_string_parens (prec
));
5455 /* Implementation of recording::memento::write_reproducer for
5459 recording::array_access::write_reproducer (reproducer
&r
)
5461 const char *id
= r
.make_identifier (this, "lvalue");
5462 r
.write (" gcc_jit_lvalue *%s = \n"
5463 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
5464 " %s, /*gcc_jit_location *loc */\n"
5465 " %s, /* gcc_jit_rvalue *ptr */\n"
5466 " %s); /* gcc_jit_rvalue *index */\n",
5468 r
.get_identifier (get_context ()),
5469 r
.get_identifier (m_loc
),
5470 r
.get_identifier_as_rvalue (m_ptr
),
5471 r
.get_identifier_as_rvalue (m_index
));
5474 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
5476 /* Implementation of pure virtual hook recording::memento::replay_into
5477 for recording::access_field_of_lvalue. */
5480 recording::access_field_of_lvalue::replay_into (replayer
*r
)
5483 m_lvalue
->playback_lvalue ()
5484 ->access_field (playback_location (r
, m_loc
),
5485 m_field
->playback_field ()));
5489 /* Implementation of pure virtual hook recording::rvalue::visit_children
5490 for recording::access_field_of_lvalue. */
5493 recording::access_field_of_lvalue::visit_children (rvalue_visitor
*v
)
5495 v
->visit (m_lvalue
);
5498 /* Implementation of recording::memento::make_debug_string for
5499 accessing a field of an lvalue. */
5502 recording::access_field_of_lvalue::make_debug_string ()
5504 enum precedence prec
= get_precedence ();
5505 return string::from_printf (m_ctxt
,
5507 m_lvalue
->get_debug_string_parens (prec
),
5508 m_field
->get_debug_string ());
5511 /* Implementation of recording::memento::write_reproducer for
5512 access_field_of_lvalue. */
5515 recording::access_field_of_lvalue::write_reproducer (reproducer
&r
)
5517 const char *id
= r
.make_identifier (this, "lvalue");
5518 r
.write (" gcc_jit_lvalue *%s = \n"
5519 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5520 " %s, /*gcc_jit_location *loc */\n"
5523 r
.get_identifier_as_lvalue (m_lvalue
),
5524 r
.get_identifier (m_loc
),
5525 r
.get_identifier (m_field
));
5528 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
5530 /* Implementation of pure virtual hook recording::memento::replay_into
5531 for recording::access_field_rvalue. */
5534 recording::access_field_rvalue::replay_into (replayer
*r
)
5537 m_rvalue
->playback_rvalue ()
5538 ->access_field (playback_location (r
, m_loc
),
5539 m_field
->playback_field ()));
5542 /* Implementation of pure virtual hook recording::rvalue::visit_children
5543 for recording::access_field_rvalue. */
5546 recording::access_field_rvalue::visit_children (rvalue_visitor
*v
)
5548 v
->visit (m_rvalue
);
5551 /* Implementation of recording::memento::make_debug_string for
5552 accessing a field of an rvalue. */
5555 recording::access_field_rvalue::make_debug_string ()
5557 enum precedence prec
= get_precedence ();
5558 return string::from_printf (m_ctxt
,
5560 m_rvalue
->get_debug_string_parens (prec
),
5561 m_field
->get_debug_string ());
5564 /* Implementation of recording::memento::write_reproducer for
5565 access_field_rvalue. */
5568 recording::access_field_rvalue::write_reproducer (reproducer
&r
)
5570 const char *id
= r
.make_identifier (this, "rvalue");
5571 r
.write (" gcc_jit_rvalue *%s = \n"
5572 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5573 " %s, /*gcc_jit_location *loc */\n"
5576 r
.get_identifier_as_rvalue (m_rvalue
),
5577 r
.get_identifier (m_loc
),
5578 r
.get_identifier (m_field
));
5581 /* The implementation of class
5582 gcc::jit::recording::dereference_field_rvalue. */
5584 /* Implementation of pure virtual hook recording::memento::replay_into
5585 for recording::dereference_field_rvalue. */
5588 recording::dereference_field_rvalue::replay_into (replayer
*r
)
5591 m_rvalue
->playback_rvalue ()->
5592 dereference_field (playback_location (r
, m_loc
),
5593 m_field
->playback_field ()));
5596 /* Implementation of pure virtual hook recording::rvalue::visit_children
5597 for recording::dereference_field_rvalue. */
5600 recording::dereference_field_rvalue::visit_children (rvalue_visitor
*v
)
5602 v
->visit (m_rvalue
);
5605 /* Implementation of recording::memento::make_debug_string for
5606 dereferencing a field of an rvalue. */
5609 recording::dereference_field_rvalue::make_debug_string ()
5611 enum precedence prec
= get_precedence ();
5612 return string::from_printf (m_ctxt
,
5614 m_rvalue
->get_debug_string_parens (prec
),
5615 m_field
->get_debug_string ());
5618 /* Implementation of recording::memento::write_reproducer for
5619 dereference_field_rvalue. */
5622 recording::dereference_field_rvalue::write_reproducer (reproducer
&r
)
5624 const char *id
= r
.make_identifier (this, "lvalue");
5625 r
.write (" gcc_jit_lvalue *%s=\n"
5626 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5627 " %s, /* gcc_jit_location *loc */\n"
5628 " %s); /* gcc_jit_field *field */\n",
5630 r
.get_identifier_as_rvalue (m_rvalue
),
5631 r
.get_identifier (m_loc
),
5632 r
.get_identifier (m_field
));
5635 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
5637 /* Implementation of pure virtual hook recording::memento::replay_into
5638 for recording::dereference_rvalue. */
5641 recording::dereference_rvalue::replay_into (replayer
*r
)
5644 m_rvalue
->playback_rvalue ()->
5645 dereference (playback_location (r
, m_loc
)));
5648 /* Implementation of pure virtual hook recording::rvalue::visit_children
5649 for recording::dereference_rvalue. */
5652 recording::dereference_rvalue::visit_children (rvalue_visitor
*v
)
5654 v
->visit (m_rvalue
);
5657 /* Implementation of recording::memento::make_debug_string for
5658 dereferencing an rvalue. */
5661 recording::dereference_rvalue::make_debug_string ()
5663 enum precedence prec
= get_precedence ();
5664 return string::from_printf (m_ctxt
,
5666 m_rvalue
->get_debug_string_parens (prec
));
5669 /* Implementation of recording::memento::write_reproducer for
5670 dereference_rvalue. */
5673 recording::dereference_rvalue::write_reproducer (reproducer
&r
)
5675 const char *id
= r
.make_identifier (this, "dereference");
5676 r
.write (" gcc_jit_lvalue *%s =\n"
5677 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5678 " %s); /* gcc_jit_location *loc */\n",
5680 r
.get_identifier_as_rvalue (m_rvalue
),
5681 r
.get_identifier (m_loc
));
5684 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5686 /* Implementation of pure virtual hook recording::memento::replay_into
5687 for recording::get_address_of_lvalue. */
5690 recording::get_address_of_lvalue::replay_into (replayer
*r
)
5693 m_lvalue
->playback_lvalue ()->
5694 get_address (playback_location (r
, m_loc
)));
5697 /* Implementation of pure virtual hook recording::rvalue::visit_children
5698 for recording::get_address_of_lvalue. */
5701 recording::get_address_of_lvalue::visit_children (rvalue_visitor
*v
)
5703 v
->visit (m_lvalue
);
5706 /* Implementation of recording::memento::make_debug_string for
5707 getting the address of an lvalue. */
5710 recording::get_address_of_lvalue::make_debug_string ()
5712 enum precedence prec
= get_precedence ();
5713 return string::from_printf (m_ctxt
,
5715 m_lvalue
->get_debug_string_parens (prec
));
5718 /* Implementation of recording::memento::write_reproducer for
5719 get_address_of_lvalue. */
5722 recording::get_address_of_lvalue::write_reproducer (reproducer
&r
)
5724 const char *id
= r
.make_identifier (this, "address_of");
5725 r
.write (" gcc_jit_rvalue *%s =\n"
5726 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5727 " %s); /* gcc_jit_location *loc */\n",
5729 r
.get_identifier_as_lvalue (m_lvalue
),
5730 r
.get_identifier (m_loc
));
5733 /* The implementation of class gcc::jit::recording::function_pointer. */
5735 /* Implementation of pure virtual hook recording::memento::replay_into
5736 for recording::function_pointer. */
5739 recording::function_pointer::replay_into (replayer
*r
)
5742 m_fn
->playback_function ()->
5743 get_address (playback_location (r
, m_loc
)));
5747 recording::function_pointer::visit_children (rvalue_visitor
*)
5752 /* Implementation of recording::memento::make_debug_string for
5753 getting the address of an lvalue. */
5756 recording::function_pointer::make_debug_string ()
5758 return string::from_printf (m_ctxt
,
5760 m_fn
->get_debug_string ());
5763 /* Implementation of recording::memento::write_reproducer for
5764 function_pointer. */
5767 recording::function_pointer::write_reproducer (reproducer
&r
)
5769 const char *id
= r
.make_identifier (this, "address_of");
5770 r
.write (" gcc_jit_rvalue *%s =\n"
5771 " gcc_jit_function_get_address (%s, /* gcc_jit_function *fn */\n"
5772 " %s); /* gcc_jit_location *loc */\n",
5774 r
.get_identifier (m_fn
),
5775 r
.get_identifier (m_loc
));
5778 /* The implementation of class gcc::jit::recording::local. */
5780 /* Implementation of pure virtual hook recording::memento::replay_into
5781 for recording::local. */
5784 recording::local::replay_into (replayer
*r
)
5787 m_func
->playback_function ()
5788 ->new_local (playback_location (r
, m_loc
),
5789 m_type
->playback_type (),
5790 playback_string (m_name
)));
5793 /* Override the default implementation of
5794 recording::memento::write_to_dump for locals by writing
5796 for use at the top of the function body as if it were a
5800 recording::local::write_to_dump (dump
&d
)
5802 if (d
.update_locations ())
5803 m_loc
= d
.make_location ();
5804 d
.write(" %s %s;\n",
5805 m_type
->get_debug_string (),
5806 get_debug_string ());
5810 recording::local::write_reproducer (reproducer
&r
)
5812 const char *id
= r
.make_identifier (this, "local");
5813 r
.write (" gcc_jit_lvalue *%s =\n"
5814 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5815 " %s, /* gcc_jit_location *loc */\n"
5816 " %s, /* gcc_jit_type *type */\n"
5817 " %s); /* const char *name */\n",
5819 r
.get_identifier (m_func
),
5820 r
.get_identifier (m_loc
),
5821 r
.get_identifier_as_type (m_type
),
5822 m_name
->get_debug_string ());
5825 /* The implementation of class gcc::jit::recording::statement. */
5827 /* We poison the default implementation of
5828 gcc::jit::recording::statement::get_successor_blocks
5829 since this vfunc must only ever be called on terminator
5832 vec
<recording::block
*>
5833 recording::statement::get_successor_blocks () const
5835 /* The base class implementation is for non-terminating statements,
5836 and thus should never be called. */
5838 vec
<block
*> result
;
5843 /* Extend the default implementation of
5844 recording::memento::write_to_dump for statements by (if requested)
5845 updating the location of the statement to the current location in
5849 recording::statement::write_to_dump (dump
&d
)
5851 memento::write_to_dump (d
);
5852 if (d
.update_locations ())
5853 m_loc
= d
.make_location ();
5856 /* The implementation of class gcc::jit::recording::eval. */
5858 /* Implementation of pure virtual hook recording::memento::replay_into
5859 for recording::eval. */
5862 recording::eval::replay_into (replayer
*r
)
5864 playback_block (get_block ())
5865 ->add_eval (playback_location (r
),
5866 m_rvalue
->playback_rvalue ());
5869 /* Implementation of recording::memento::make_debug_string for
5870 an eval statement. */
5873 recording::eval::make_debug_string ()
5875 return string::from_printf (m_ctxt
,
5877 m_rvalue
->get_debug_string ());
5880 /* Implementation of recording::memento::write_reproducer for
5884 recording::eval::write_reproducer (reproducer
&r
)
5886 r
.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5887 " %s, /* gcc_jit_location *loc */\n"
5888 " %s); /* gcc_jit_rvalue *rvalue */\n",
5889 r
.get_identifier (get_block ()),
5890 r
.get_identifier (get_loc ()),
5891 r
.get_identifier_as_rvalue (m_rvalue
));
5894 /* The implementation of class gcc::jit::recording::assignment. */
5896 /* Implementation of pure virtual hook recording::memento::replay_into
5897 for recording::assignment. */
5900 recording::assignment::replay_into (replayer
*r
)
5902 playback_block (get_block ())
5903 ->add_assignment (playback_location (r
),
5904 m_lvalue
->playback_lvalue (),
5905 m_rvalue
->playback_rvalue ());
5908 /* Implementation of recording::memento::make_debug_string for
5909 an assignment statement. */
5912 recording::assignment::make_debug_string ()
5914 return string::from_printf (m_ctxt
,
5916 m_lvalue
->get_debug_string (),
5917 m_rvalue
->get_debug_string ());
5920 /* Implementation of recording::memento::write_reproducer for
5921 assignment statements. */
5924 recording::assignment::write_reproducer (reproducer
&r
)
5926 r
.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5927 " %s, /* gcc_jit_location *loc */\n"
5928 " %s, /* gcc_jit_lvalue *lvalue */\n"
5929 " %s); /* gcc_jit_rvalue *rvalue */\n",
5930 r
.get_identifier (get_block ()),
5931 r
.get_identifier (get_loc ()),
5932 r
.get_identifier_as_lvalue (m_lvalue
),
5933 r
.get_identifier_as_rvalue (m_rvalue
));
5936 /* The implementation of class gcc::jit::recording::assignment_op. */
5938 /* Implementation of pure virtual hook recording::memento::replay_into
5939 for recording::assignment_op. */
5942 recording::assignment_op::replay_into (replayer
*r
)
5944 playback::type
*result_type
=
5945 m_lvalue
->playback_lvalue ()->get_type ();
5947 playback::rvalue
*binary_op
=
5948 r
->new_binary_op (playback_location (r
),
5951 m_lvalue
->playback_rvalue (),
5952 m_rvalue
->playback_rvalue ());
5954 playback_block (get_block ())
5955 ->add_assignment (playback_location (r
),
5956 m_lvalue
->playback_lvalue (),
5960 /* Implementation of recording::memento::make_debug_string for
5961 an assignment_op statement. */
5964 recording::assignment_op::make_debug_string ()
5966 return string::from_printf (m_ctxt
,
5968 m_lvalue
->get_debug_string (),
5969 binary_op_strings
[m_op
],
5970 m_rvalue
->get_debug_string ());
5973 /* Implementation of recording::memento::write_reproducer for
5974 assignment_op statements. */
5977 recording::assignment_op::write_reproducer (reproducer
&r
)
5979 r
.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5980 " %s, /* gcc_jit_location *loc */\n"
5981 " %s, /* gcc_jit_lvalue *lvalue */\n"
5982 " %s, /* enum gcc_jit_binary_op op */\n"
5983 " %s); /* gcc_jit_rvalue *rvalue */\n",
5984 r
.get_identifier (get_block ()),
5985 r
.get_identifier (get_loc ()),
5986 r
.get_identifier_as_lvalue (m_lvalue
),
5987 binary_op_reproducer_strings
[m_op
],
5988 r
.get_identifier_as_rvalue (m_rvalue
));
5991 /* The implementation of class gcc::jit::recording::comment. */
5993 /* Implementation of pure virtual hook recording::memento::replay_into
5994 for recording::comment. */
5997 recording::comment::replay_into (replayer
*r
)
5999 playback_block (get_block ())
6000 ->add_comment (playback_location (r
),
6004 /* Implementation of recording::memento::make_debug_string for
6005 a comment "statement". */
6008 recording::comment::make_debug_string ()
6010 return string::from_printf (m_ctxt
,
6015 /* Implementation of recording::memento::write_reproducer for
6019 recording::comment::write_reproducer (reproducer
&r
)
6021 r
.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
6022 " %s, /* gcc_jit_location *loc */\n"
6023 " %s); /* const char *text */\n",
6024 r
.get_identifier (get_block ()),
6025 r
.get_identifier (get_loc ()),
6026 m_text
->get_debug_string ());
6029 /* The implementation of class gcc::jit::recording::conditional. */
6031 /* Implementation of pure virtual hook recording::memento::replay_into
6032 for recording::conditional. */
6035 recording::conditional::replay_into (replayer
*r
)
6037 playback_block (get_block ())
6038 ->add_conditional (playback_location (r
),
6039 m_boolval
->playback_rvalue (),
6040 playback_block (m_on_true
),
6041 playback_block (m_on_false
));
6044 /* Override the poisoned default implementation of
6045 gcc::jit::recording::statement::get_successor_blocks
6047 A conditional jump has 2 successor blocks. */
6049 vec
<recording::block
*>
6050 recording::conditional::get_successor_blocks () const
6052 vec
<block
*> result
;
6054 result
.quick_push (m_on_true
);
6055 result
.quick_push (m_on_false
);
6059 /* Implementation of recording::memento::make_debug_string for
6060 a conditional jump statement. */
6063 recording::conditional::make_debug_string ()
6066 return string::from_printf (m_ctxt
,
6067 "if (%s) goto %s; else goto %s;",
6068 m_boolval
->get_debug_string (),
6069 m_on_true
->get_debug_string (),
6070 m_on_false
->get_debug_string ());
6072 return string::from_printf (m_ctxt
,
6074 m_boolval
->get_debug_string (),
6075 m_on_true
->get_debug_string ());
6078 /* Implementation of recording::memento::write_reproducer for
6079 conditional statements. */
6082 recording::conditional::write_reproducer (reproducer
&r
)
6084 r
.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
6085 " %s, /* gcc_jit_location *loc */\n"
6086 " %s, /* gcc_jit_rvalue *boolval */\n"
6087 " %s, /* gcc_jit_block *on_true */\n"
6088 " %s); /* gcc_jit_block *on_false */\n",
6089 r
.get_identifier (get_block ()),
6090 r
.get_identifier (get_loc ()),
6091 r
.get_identifier_as_rvalue (m_boolval
),
6092 r
.get_identifier (m_on_true
),
6093 r
.get_identifier (m_on_false
));
6096 /* The implementation of class gcc::jit::recording::jump. */
6098 /* Implementation of pure virtual hook recording::memento::replay_into
6099 for recording::jump. */
6102 recording::jump::replay_into (replayer
*r
)
6104 playback_block (get_block ())
6105 ->add_jump (playback_location (r
),
6106 m_target
->playback_block ());
6109 /* Override the poisoned default implementation of
6110 gcc::jit::recording::statement::get_successor_blocks
6112 An unconditional jump has 1 successor block. */
6114 vec
<recording::block
*>
6115 recording::jump::get_successor_blocks () const
6117 vec
<block
*> result
;
6119 result
.quick_push (m_target
);
6123 /* Implementation of recording::memento::make_debug_string for
6124 a unconditional jump statement. */
6127 recording::jump::make_debug_string ()
6129 return string::from_printf (m_ctxt
,
6131 m_target
->get_debug_string ());
6134 /* Implementation of recording::memento::write_reproducer for
6138 recording::jump::write_reproducer (reproducer
&r
)
6140 r
.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
6141 " %s, /* gcc_jit_location *loc */\n"
6142 " %s); /* gcc_jit_block *target */\n",
6143 r
.get_identifier (get_block ()),
6144 r
.get_identifier (get_loc ()),
6145 r
.get_identifier (m_target
));
6148 /* The implementation of class gcc::jit::recording::return_. */
6150 /* Implementation of pure virtual hook recording::memento::replay_into
6151 for recording::return_. */
6154 recording::return_::replay_into (replayer
*r
)
6156 playback_block (get_block ())
6157 ->add_return (playback_location (r
),
6158 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
6161 /* Override the poisoned default implementation of
6162 gcc::jit::recording::statement::get_successor_blocks
6164 A return statement has no successor block. */
6166 vec
<recording::block
*>
6167 recording::return_::get_successor_blocks () const
6169 vec
<block
*> result
;
6174 /* Implementation of recording::memento::make_debug_string for
6175 a return statement (covers both those with and without rvalues). */
6178 recording::return_::make_debug_string ()
6181 return string::from_printf (m_ctxt
,
6183 m_rvalue
->get_debug_string ());
6185 return string::from_printf (m_ctxt
,
6189 /* Implementation of recording::memento::write_reproducer for
6190 return statements. */
6193 recording::return_::write_reproducer (reproducer
&r
)
6196 r
.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
6197 " %s, /* gcc_jit_location *loc */\n"
6198 " %s); /* gcc_jit_rvalue *rvalue */\n",
6199 r
.get_identifier (get_block ()),
6200 r
.get_identifier (get_loc ()),
6201 r
.get_identifier_as_rvalue (m_rvalue
));
6203 r
.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
6204 " %s); /* gcc_jit_location *loc */\n",
6205 r
.get_identifier (get_block ()),
6206 r
.get_identifier (get_loc ()));
6209 /* The implementation of class gcc::jit::recording::case_. */
6212 recording::case_::write_reproducer (reproducer
&r
)
6214 const char *id
= r
.make_identifier (this, "case");
6216 " gcc_jit_case *%s = \n"
6217 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
6218 " %s, /* gcc_jit_rvalue *min_value */\n"
6219 " %s, /* gcc_jit_rvalue *max_value */\n"
6220 " %s); /* gcc_jit_block *dest_block */\n";
6223 r
.get_identifier (get_context ()),
6224 r
.get_identifier_as_rvalue (m_min_value
),
6225 r
.get_identifier_as_rvalue (m_max_value
),
6226 r
.get_identifier (m_dest_block
));
6230 recording::case_::make_debug_string ()
6232 return string::from_printf (get_context (),
6233 "case %s ... %s: goto %s;",
6234 m_min_value
->get_debug_string (),
6235 m_max_value
->get_debug_string (),
6236 m_dest_block
->get_debug_string ());
6239 /* The implementation of class gcc::jit::recording::switch_. */
6241 /* gcc::jit::recording::switch_'s constructor. */
6243 recording::switch_::switch_ (block
*b
,
6246 block
*default_block
,
6249 : statement (b
, loc
),
6251 m_default_block (default_block
)
6253 m_cases
.reserve_exact (num_cases
);
6254 for (int i
= 0; i
< num_cases
; i
++)
6255 m_cases
.quick_push (cases
[i
]);
6258 /* Implementation of pure virtual hook recording::memento::replay_into
6259 for recording::switch_. */
6262 recording::switch_::replay_into (replayer
*r
)
6264 auto_vec
<playback::case_
> pcases
;
6266 recording::case_
*rcase
;
6267 pcases
.reserve_exact (m_cases
.length ());
6268 FOR_EACH_VEC_ELT (m_cases
, i
, rcase
)
6270 playback::case_
pcase (rcase
->get_min_value ()->playback_rvalue (),
6271 rcase
->get_max_value ()->playback_rvalue (),
6272 rcase
->get_dest_block ()->playback_block ());
6273 pcases
.safe_push (pcase
);
6275 playback_block (get_block ())
6276 ->add_switch (playback_location (r
),
6277 m_expr
->playback_rvalue (),
6278 m_default_block
->playback_block (),
6282 /* Override the poisoned default implementation of
6283 gcc::jit::recording::statement::get_successor_blocks
6285 A switch statement has (NUM_CASES + 1) successor blocks. */
6287 vec
<recording::block
*>
6288 recording::switch_::get_successor_blocks () const
6290 vec
<block
*> result
;
6291 result
.create (m_cases
.length () + 1);
6292 result
.quick_push (m_default_block
);
6295 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
6296 result
.quick_push (c
->get_dest_block ());
6300 /* Implementation of recording::memento::make_debug_string for
6301 a switch statement. */
6304 recording::switch_::make_debug_string ()
6306 auto_vec
<char> cases_str
;
6309 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
6311 size_t len
= strlen (c
->get_debug_string ());
6312 unsigned idx
= cases_str
.length ();
6313 cases_str
.safe_grow (idx
+ 1 + len
);
6314 cases_str
[idx
] = ' ';
6315 memcpy (&(cases_str
[idx
+ 1]),
6316 c
->get_debug_string (),
6319 cases_str
.safe_push ('\0');
6321 return string::from_printf (m_ctxt
,
6322 "switch (%s) {default: goto %s;%s}",
6323 m_expr
->get_debug_string (),
6324 m_default_block
->get_debug_string (),
6328 /* Implementation of recording::memento::write_reproducer for
6329 switch statements. */
6332 recording::switch_::write_reproducer (reproducer
&r
)
6334 r
.make_identifier (this, "switch");
6337 const char *cases_id
=
6338 r
.make_tmp_identifier ("cases_for", this);
6339 r
.write (" gcc_jit_case *%s[%i] = {\n",
6342 FOR_EACH_VEC_ELT (m_cases
, i
, c
)
6343 r
.write (" %s,\n", r
.get_identifier (c
));
6346 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
6347 " %s, /* gcc_jit_location *loc */\n"
6348 " %s, /* gcc_jit_rvalue *expr */\n"
6349 " %s, /* gcc_jit_block *default_block */\n"
6350 " %i, /* int num_cases */\n"
6351 " %s); /* gcc_jit_case **cases */\n";
6353 r
.get_identifier (get_block ()),
6354 r
.get_identifier (get_loc ()),
6355 r
.get_identifier_as_rvalue (m_expr
),
6356 r
.get_identifier (m_default_block
),
6361 } // namespace gcc::jit