1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2015 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"
27 #include "pretty-print.h"
31 #include "jit-common.h"
32 #include "jit-builtins.h"
33 #include "jit-logging.h"
34 #include "jit-recording.h"
35 #include "jit-playback.h"
42 dump::dump (recording::context
&ctxt
,
44 bool update_locations
)
46 m_filename (filename
),
47 m_update_locations (update_locations
),
51 m_file
= fopen (filename
, "w");
54 "error opening dump file %s for writing: %s",
63 int err
= fclose (m_file
);
65 m_ctxt
.add_error (NULL
,
66 "error closing dump file %s: %s",
72 /* Write the given message to the dump, using printf-formatting
73 conventions, updating the line/column within the dump.
75 Emit an error on the context if a failure occurs. */
78 dump::write (const char *fmt
, ...)
83 /* If there was an error opening the file, we've already reported it.
84 Don't attempt further work. */
89 vasprintf (&buf
, fmt
, ap
);
94 m_ctxt
.add_error (NULL
, "malloc failure writing to dumpfile %s",
99 if (fwrite (buf
, strlen (buf
), 1, m_file
) != 1)
100 m_ctxt
.add_error (NULL
, "error writing to dump file %s",
103 /* Update line/column: */
104 for (const char *ptr
= buf
; *ptr
; ptr
++)
118 /* Construct a gcc::jit::recording::location instance for the current
119 location within the dump. */
121 recording::location
*
122 dump::make_location () const
124 return m_ctxt
.new_location (m_filename
, m_line
, m_column
);
127 /**********************************************************************
129 **********************************************************************/
131 /* Get the playback::location for the given recording::location,
132 handling a NULL input with a NULL output. */
135 recording::playback_location (replayer
*r
, recording::location
*loc
)
138 return loc
->playback_location (r
);
143 /* Get a const char * for the given recording::string
144 handling a NULL input with a NULL output. */
147 recording::playback_string (recording::string
*str
)
150 return str
->c_str ();
155 /* Get the playback::block for the given recording::block,
156 handling a NULL input with a NULL output. */
159 recording::playback_block (recording::block
*b
)
162 return b
->playback_block ();
167 /* Methods of cc::jit::recording::context. */
169 /* The constructor for gcc::jit::recording::context, used by
170 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
172 recording::context::context (context
*parent_ctxt
)
174 m_parent_ctxt (parent_ctxt
),
176 m_first_error_str (NULL
),
177 m_owns_first_error_str (false),
178 m_last_error_str (NULL
),
179 m_owns_last_error_str (false),
184 m_builtins_manager(NULL
)
188 /* Inherit options from parent. */
190 i
< sizeof (m_str_options
) / sizeof (m_str_options
[0]);
193 const char *parent_opt
= parent_ctxt
->m_str_options
[i
];
194 m_str_options
[i
] = parent_opt
? xstrdup (parent_opt
) : NULL
;
196 memcpy (m_int_options
,
197 parent_ctxt
->m_int_options
,
198 sizeof (m_int_options
));
199 memcpy (m_bool_options
,
200 parent_ctxt
->m_bool_options
,
201 sizeof (m_bool_options
));
202 set_logger (parent_ctxt
->get_logger ());
206 memset (m_str_options
, 0, sizeof (m_str_options
));
207 memset (m_int_options
, 0, sizeof (m_int_options
));
208 memset (m_bool_options
, 0, sizeof (m_bool_options
));
211 memset (m_basic_types
, 0, sizeof (m_basic_types
));
214 /* The destructor for gcc::jit::recording::context, implicitly used by
215 gcc_jit_context_release. */
217 recording::context::~context ()
219 JIT_LOG_SCOPE (get_logger ());
222 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
227 for (i
= 0; i
< GCC_JIT_NUM_STR_OPTIONS
; ++i
)
228 free (m_str_options
[i
]);
230 if (m_builtins_manager
)
231 delete m_builtins_manager
;
233 if (m_owns_first_error_str
)
234 free (m_first_error_str
);
236 if (m_owns_last_error_str
)
237 if (m_last_error_str
!= m_first_error_str
)
238 free (m_last_error_str
);
241 /* Add the given mememto to the list of those tracked by this
242 gcc::jit::recording::context, so that e.g. it can be deleted
243 when this context is released. */
246 recording::context::record (memento
*m
)
250 m_mementos
.safe_push (m
);
253 /* Replay this context (and any parents) into the given replayer. */
256 recording::context::replay_into (replayer
*r
)
258 JIT_LOG_SCOPE (get_logger ());
262 /* If we have a parent context, we must replay it. This will
263 recursively walk backwards up the historical tree, then replay things
264 forwards "in historical order", starting with the ultimate parent
265 context, until we reach the "this" context.
267 Note that we fully replay the parent, then fully replay the child,
268 which means that inter-context references can only exist from child
269 to parent, not the other way around.
271 All of this replaying is suboptimal - it would be better to do the
272 work for the parent context *once*, rather than replaying the parent
273 every time we replay each child. However, fixing this requires deep
274 surgery to lifetime-management: we'd need every context family tree
275 to have its own GC heap, and to initialize the GCC code to use that
276 heap (with a mutex on such a heap). */
278 m_parent_ctxt
->replay_into (r
);
280 if (r
->errors_occurred ())
283 /* Replay this context's saved operations into r. */
284 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
286 /* Disabled low-level debugging, here if we need it: print what
288 Note that the calls to get_debug_string might lead to more
289 mementos being created for the strings.
290 This can also be used to exercise the debug_string
293 printf ("context %p replaying (%p): %s\n",
294 (void *)this, (void *)m
, m
->get_debug_string ());
298 if (r
->errors_occurred ())
303 /* During a playback, we associate objects from the recording with
304 their counterparts during this playback.
306 For simplicity, we store this within the recording objects.
308 The following method cleans away these associations, to ensure that
309 we never have out-of-date associations lingering on subsequent
310 playbacks (the objects pointed to are GC-managed, but the
311 recording objects don't own refs to them). */
314 recording::context::disassociate_from_playback ()
316 JIT_LOG_SCOPE (get_logger ());
321 m_parent_ctxt
->disassociate_from_playback ();
323 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
325 m
->set_playback_obj (NULL
);
329 /* Create a recording::string instance and add it to this context's list
332 This creates a fresh copy of the given 0-terminated buffer. */
335 recording::context::new_string (const char *text
)
340 recording::string
*result
= new string (this, text
);
345 /* Create a recording::location instance and add it to this context's
348 Implements the post-error-checking part of
349 gcc_jit_context_new_location. */
351 recording::location
*
352 recording::context::new_location (const char *filename
,
356 recording::location
*result
=
357 new recording::location (this,
358 new_string (filename
),
364 /* If we haven't seen this enum value yet, create a recording::type
365 instance and add it to this context's list of mementos.
367 If we have seen it before, reuse our cached value, so that repeated
368 calls on the context give the same object.
370 If we have a parent context, the cache is within the ultimate
373 Implements the post-error-checking part of
374 gcc_jit_context_get_type. */
377 recording::context::get_type (enum gcc_jit_types kind
)
379 if (!m_basic_types
[kind
])
382 m_basic_types
[kind
] = m_parent_ctxt
->get_type (kind
);
385 recording::type
*result
= new memento_of_get_type (this, kind
);
387 m_basic_types
[kind
] = result
;
391 return m_basic_types
[kind
];
394 /* Get a recording::type instance for the given size and signedness.
395 This is implemented in terms of recording::context::get_type
398 Implements the post-error-checking part of
399 gcc_jit_context_get_int_type. */
402 recording::context::get_int_type (int num_bytes
, int is_signed
)
404 /* We can't use a switch here since some of the values are macros affected
405 by options; e.g. i386.h has
406 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
407 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
408 are in bits, rather than bytes.
410 const int num_bits
= num_bytes
* 8;
411 if (num_bits
== INT_TYPE_SIZE
)
412 return get_type (is_signed
414 : GCC_JIT_TYPE_UNSIGNED_INT
);
415 if (num_bits
== CHAR_TYPE_SIZE
)
416 return get_type (is_signed
417 ? GCC_JIT_TYPE_SIGNED_CHAR
418 : GCC_JIT_TYPE_UNSIGNED_CHAR
);
419 if (num_bits
== SHORT_TYPE_SIZE
)
420 return get_type (is_signed
422 : GCC_JIT_TYPE_UNSIGNED_SHORT
);
423 if (num_bits
== LONG_TYPE_SIZE
)
424 return get_type (is_signed
426 : GCC_JIT_TYPE_UNSIGNED_LONG
);
427 if (num_bits
== LONG_LONG_TYPE_SIZE
)
428 return get_type (is_signed
429 ? GCC_JIT_TYPE_LONG_LONG
430 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
432 /* Some other size, not corresponding to the C int types. */
433 /* To be written: support arbitrary other sizes, sharing by
434 memoizing at the recording::context level? */
438 /* Create a recording::type instance and add it to this context's list
441 Implements the post-error-checking part of
442 gcc_jit_context_new_array_type. */
445 recording::context::new_array_type (recording::location
*loc
,
446 recording::type
*element_type
,
449 if (struct_
*s
= element_type
->dyn_cast_struct ())
450 if (!s
->get_fields ())
453 "cannot create an array of type %s"
454 " until the fields have been set",
455 s
->get_name ()->c_str ());
458 recording::type
*result
=
459 new recording::array_type (this, loc
, element_type
, num_elements
);
464 /* Create a recording::field instance and add it to this context's list
467 Implements the post-error-checking part of
468 gcc_jit_context_new_field. */
471 recording::context::new_field (recording::location
*loc
,
472 recording::type
*type
,
475 recording::field
*result
=
476 new recording::field (this, loc
, type
, new_string (name
));
481 /* Create a recording::struct_ instance and add it to this context's
482 list of mementos and list of compound types.
484 Implements the post-error-checking part of
485 gcc_jit_context_new_struct_type. */
488 recording::context::new_struct_type (recording::location
*loc
,
491 recording::struct_
*result
= new struct_ (this, loc
, new_string (name
));
493 m_compound_types
.safe_push (result
);
497 /* Create a recording::union_ instance and add it to this context's
498 list of mementos and list of compound types.
500 Implements the first post-error-checking part of
501 gcc_jit_context_new_union_type. */
504 recording::context::new_union_type (recording::location
*loc
,
507 recording::union_
*result
= new union_ (this, loc
, new_string (name
));
509 m_compound_types
.safe_push (result
);
513 /* Create a recording::function_type instance and add it to this context's
516 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
518 recording::function_type
*
519 recording::context::new_function_type (recording::type
*return_type
,
521 recording::type
**param_types
,
524 recording::function_type
*fn_type
525 = new function_type (this,
534 /* Create a recording::type instance and add it to this context's list
537 Implements the post-error-checking part of
538 gcc_jit_context_new_function_ptr_type. */
541 recording::context::new_function_ptr_type (recording::location
*, /* unused loc */
542 recording::type
*return_type
,
544 recording::type
**param_types
,
547 recording::function_type
*fn_type
548 = new_function_type (return_type
,
553 /* Return a pointer-type to the the function type. */
554 return fn_type
->get_pointer ();
557 /* Create a recording::param instance and add it to this context's list
560 Implements the post-error-checking part of
561 gcc_jit_context_new_param. */
564 recording::context::new_param (recording::location
*loc
,
565 recording::type
*type
,
568 recording::param
*result
= new recording::param (this, loc
, type
, new_string (name
));
573 /* Create a recording::function instance and add it to this context's list
574 of mementos and list of functions.
576 Implements the post-error-checking part of
577 gcc_jit_context_new_function. */
579 recording::function
*
580 recording::context::new_function (recording::location
*loc
,
581 enum gcc_jit_function_kind kind
,
582 recording::type
*return_type
,
585 recording::param
**params
,
587 enum built_in_function builtin_id
)
589 recording::function
*result
=
590 new recording::function (this,
591 loc
, kind
, return_type
,
593 num_params
, params
, is_variadic
,
596 m_functions
.safe_push (result
);
601 /* Locate the builtins_manager (if any) for this family of contexts,
602 creating it if it doesn't exist already.
604 All of the recording contexts in a family share one builtins_manager:
605 if we have a child context, follow the parent links to get the
606 ultimate ancestor context, and look for it/store it there. */
609 recording::context::get_builtins_manager ()
612 return m_parent_ctxt
->get_builtins_manager ();
614 if (!m_builtins_manager
)
615 m_builtins_manager
= new builtins_manager (this);
617 return m_builtins_manager
;
620 /* Get a recording::function instance, which is lazily-created and added
621 to the context's lists of mementos.
623 Implements the post-error-checking part of
624 gcc_jit_context_get_builtin_function. */
626 recording::function
*
627 recording::context::get_builtin_function (const char *name
)
629 builtins_manager
*bm
= get_builtins_manager ();
630 return bm
->get_builtin_function (name
);
633 /* Create a recording::global instance and add it to this context's list
636 Implements the post-error-checking part of
637 gcc_jit_context_new_global. */
640 recording::context::new_global (recording::location
*loc
,
641 recording::type
*type
,
644 recording::lvalue
*result
=
645 new recording::global (this, loc
, type
, new_string (name
));
650 /* Create a recording::memento_of_new_string_literal instance and add it
651 to this context's list of mementos.
653 Implements the post-error-checking part of
654 gcc_jit_context_new_string_literal. */
657 recording::context::new_string_literal (const char *value
)
659 recording::rvalue
*result
=
660 new memento_of_new_string_literal (this, NULL
, new_string (value
));
665 /* Create a recording::unary_op instance and add it to this context's
668 Implements the post-error-checking part of
669 gcc_jit_context_new_unary_op. */
672 recording::context::new_unary_op (recording::location
*loc
,
673 enum gcc_jit_unary_op op
,
674 recording::type
*result_type
,
675 recording::rvalue
*a
)
677 recording::rvalue
*result
=
678 new unary_op (this, loc
, op
, result_type
, a
);
683 /* Create a recording::binary_op instance and add it to this context's
686 Implements the post-error-checking part of
687 gcc_jit_context_new_binary_op. */
690 recording::context::new_binary_op (recording::location
*loc
,
691 enum gcc_jit_binary_op op
,
692 recording::type
*result_type
,
693 recording::rvalue
*a
,
694 recording::rvalue
*b
)
696 recording::rvalue
*result
=
697 new binary_op (this, loc
, op
, result_type
, a
, b
);
702 /* Create a recording::comparison instance and add it to this context's
705 Implements the post-error-checking part of
706 gcc_jit_context_new_comparison. */
709 recording::context::new_comparison (recording::location
*loc
,
710 enum gcc_jit_comparison op
,
711 recording::rvalue
*a
,
712 recording::rvalue
*b
)
714 recording::rvalue
*result
= new comparison (this, loc
, op
, a
, b
);
719 /* Create a recording::cast instance and add it to this context's list
722 Implements the post-error-checking part of
723 gcc_jit_context_new_cast. */
726 recording::context::new_cast (recording::location
*loc
,
727 recording::rvalue
*expr
,
728 recording::type
*type_
)
730 recording::rvalue
*result
= new cast (this, loc
, expr
, type_
);
735 /* Create a recording::call instance and add it to this context's list
738 Implements the post-error-checking part of
739 gcc_jit_context_new_call. */
742 recording::context::new_call (recording::location
*loc
,
744 int numargs
, recording::rvalue
**args
)
746 recording::rvalue
*result
= new call (this, loc
, func
, numargs
, args
);
751 /* Create a recording::call_through_ptr instance and add it to this
752 context's list of mementos.
754 Implements the post-error-checking part of
755 gcc_jit_context_new_call_through_ptr. */
758 recording::context::new_call_through_ptr (recording::location
*loc
,
759 recording::rvalue
*fn_ptr
,
761 recording::rvalue
**args
)
763 recording::rvalue
*result
= new call_through_ptr (this, loc
, fn_ptr
, numargs
, args
);
768 /* Create a recording::array_access instance and add it to this context's list
771 Implements the post-error-checking part of
772 gcc_jit_context_new_array_access. */
775 recording::context::new_array_access (recording::location
*loc
,
776 recording::rvalue
*ptr
,
777 recording::rvalue
*index
)
779 recording::lvalue
*result
= new array_access (this, loc
, ptr
, index
);
784 /* Set the given string option for this context, or add an error if
787 Implements the post-error-checking part of
788 gcc_jit_context_set_str_option. */
791 recording::context::set_str_option (enum gcc_jit_str_option opt
,
794 if (opt
< 0 || opt
>= GCC_JIT_NUM_STR_OPTIONS
)
797 "unrecognized (enum gcc_jit_str_option) value: %i", opt
);
800 free (m_str_options
[opt
]);
801 m_str_options
[opt
] = value
? xstrdup (value
) : NULL
;
804 /* Set the given integer option for this context, or add an error if
807 Implements the post-error-checking part of
808 gcc_jit_context_set_int_option. */
811 recording::context::set_int_option (enum gcc_jit_int_option opt
,
814 if (opt
< 0 || opt
>= GCC_JIT_NUM_INT_OPTIONS
)
817 "unrecognized (enum gcc_jit_int_option) value: %i", opt
);
820 m_int_options
[opt
] = value
;
823 /* Set the given boolean option for this context, or add an error if
826 Implements the post-error-checking part of
827 gcc_jit_context_set_bool_option. */
830 recording::context::set_bool_option (enum gcc_jit_bool_option opt
,
833 if (opt
< 0 || opt
>= GCC_JIT_NUM_BOOL_OPTIONS
)
836 "unrecognized (enum gcc_jit_bool_option) value: %i", opt
);
839 m_bool_options
[opt
] = value
? true : false;
842 /* Add the given dumpname/out_ptr pair to this context's list of requested
845 Implements the post-error-checking part of
846 gcc_jit_context_enable_dump. */
849 recording::context::enable_dump (const char *dumpname
,
853 gcc_assert (dumpname
);
854 gcc_assert (out_ptr
);
856 d
.m_dumpname
= dumpname
;
857 d
.m_out_ptr
= out_ptr
;
859 m_requested_dumps
.safe_push (d
);
862 /* Validate this context, and if it passes, compile it within a
865 Implements the post-error-checking part of
866 gcc_jit_context_compile. */
869 recording::context::compile ()
871 JIT_LOG_SCOPE (get_logger ());
875 if (errors_occurred ())
878 /* Set up a playback context. */
879 ::gcc::jit::playback::context
replayer (this);
882 result
*result_obj
= replayer
.compile ();
887 /* Format the given error using printf's conventions, print
888 it to stderr, and add it to the context. */
891 recording::context::add_error (location
*loc
, const char *fmt
, ...)
895 add_error_va (loc
, fmt
, ap
);
899 /* Format the given error using printf's conventions, print
900 it to stderr, and add it to the context. */
903 recording::context::add_error_va (location
*loc
, const char *fmt
, va_list ap
)
909 JIT_LOG_SCOPE (get_logger ());
911 vasprintf (&malloced_msg
, fmt
, ap
);
914 errmsg
= malloced_msg
;
915 has_ownership
= true;
919 errmsg
= "out of memory generating error message";
920 has_ownership
= false;
923 get_logger ()->log ("error %i: %s", m_error_count
, errmsg
);
925 const char *ctxt_progname
=
926 get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
928 ctxt_progname
= "libgccjit.so";
931 fprintf (stderr
, "%s: %s: error: %s\n",
933 loc
->get_debug_string (),
936 fprintf (stderr
, "%s: error: %s\n",
942 m_first_error_str
= const_cast <char *> (errmsg
);
943 m_owns_first_error_str
= has_ownership
;
946 if (m_owns_last_error_str
)
947 if (m_last_error_str
!= m_first_error_str
)
948 free (m_last_error_str
);
949 m_last_error_str
= const_cast <char *> (errmsg
);
950 m_owns_last_error_str
= has_ownership
;
955 /* Get the message for the first error that occurred on this context, or
956 NULL if no errors have occurred on it.
958 Implements the post-error-checking part of
959 gcc_jit_context_get_first_error. */
962 recording::context::get_first_error () const
964 return m_first_error_str
;
967 /* Get the message for the last error that occurred on this context, or
968 NULL if no errors have occurred on it.
970 Implements the post-error-checking part of
971 gcc_jit_context_get_last_error. */
974 recording::context::get_last_error () const
976 return m_last_error_str
;
979 /* Lazily generate and record a recording::type representing an opaque
982 For use if client code tries to dereference the result of
983 get_type (GCC_JIT_TYPE_FILE_PTR). */
986 recording::context::get_opaque_FILE_type ()
989 m_FILE_type
= new_struct_type (NULL
, "FILE");
993 /* Dump a C-like representation of the given context to the given path.
994 If UPDATE_LOCATIONS is true, update the locations within the
995 context's mementos to point to the dumpfile.
997 Implements the post-error-checking part of
998 gcc_jit_context_dump_to_file. */
1001 recording::context::dump_to_file (const char *path
, bool update_locations
)
1004 dump
d (*this, path
, update_locations
);
1006 /* Forward declaration of structs and unions. */
1008 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1010 d
.write ("%s;\n\n", st
->get_debug_string ());
1013 /* Content of structs, where set. */
1014 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1015 if (st
->get_fields ())
1017 st
->get_fields ()->write_to_dump (d
);
1022 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1024 fn
->write_to_dump (d
);
1028 /* Copy the requested dumps within this context and all ancestors into
1032 recording::context::get_all_requested_dumps (vec
<recording::requested_dump
> *out
)
1035 m_parent_ctxt
->get_all_requested_dumps (out
);
1037 out
->reserve (m_requested_dumps
.length ());
1038 out
->splice (m_requested_dumps
);
1041 /* This is a pre-compilation check for the context (and any parents).
1043 Detect errors within the context, adding errors if any are found. */
1046 recording::context::validate ()
1048 JIT_LOG_SCOPE (get_logger ());
1051 m_parent_ctxt
->validate ();
1055 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1059 /* The implementation of class gcc::jit::recording::memento. */
1061 /* Get a (const char *) debug description of the given memento, by
1062 calling the pure-virtual make_debug_string hook, caching the
1065 It is intended that this should only be called in debugging and
1066 error-handling paths, so this doesn't need to be particularly
1070 recording::memento::get_debug_string ()
1072 if (!m_debug_string
)
1073 m_debug_string
= make_debug_string ();
1074 return m_debug_string
->c_str ();
1077 /* Default implementation of recording::memento::write_to_dump, writing
1078 an indented form of the memento's debug string to the dump. */
1081 recording::memento::write_to_dump (dump
&d
)
1083 d
.write(" %s\n", get_debug_string ());
1086 /* The implementation of class gcc::jit::recording::string. */
1088 /* Constructor for gcc::jit::recording::string::string, allocating a
1089 copy of the given text using new char[]. */
1091 recording::string::string (context
*ctxt
, const char *text
)
1094 m_len
= strlen (text
);
1095 m_buffer
= new char[m_len
+ 1];
1096 strcpy (m_buffer
, text
);
1099 /* Destructor for gcc::jit::recording::string::string. */
1101 recording::string::~string ()
1106 /* Function for making gcc::jit::recording::string instances on a
1107 context via printf-style formatting.
1109 It is intended that this should only be called in debugging and
1110 error-handling paths, so this doesn't need to be particularly
1111 optimized, hence the double-copy of the string is acceptable. */
1114 recording::string::from_printf (context
*ctxt
, const char *fmt
, ...)
1118 recording::string
*result
;
1121 vasprintf (&buf
, fmt
, ap
);
1126 ctxt
->add_error (NULL
, "malloc failure");
1130 result
= ctxt
->new_string (buf
);
1135 /* Implementation of recording::memento::make_debug_string for strings,
1136 wrapping the given string in quotes and escaping as necessary. */
1139 recording::string::make_debug_string ()
1141 /* Hack to avoid infinite recursion into strings when logging all
1142 mementos: don't re-escape strings: */
1143 if (m_buffer
[0] == '"')
1146 /* Wrap in quotes and do escaping etc */
1148 size_t sz
= (1 /* opening quote */
1149 + (m_len
* 2) /* each char might get escaped */
1150 + 1 /* closing quote */
1151 + 1); /* nil termintator */
1152 char *tmp
= new char[sz
];
1155 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1156 APPEND('"'); /* opening quote */
1157 for (size_t i
= 0; i
< m_len
; i
++)
1159 char ch
= m_buffer
[i
];
1160 if (ch
== '\t' || ch
== '\n' || ch
== '\\' || ch
== '"')
1164 APPEND('"'); /* closing quote */
1166 tmp
[len
] = '\0'; /* nil termintator */
1168 string
*result
= m_ctxt
->new_string (tmp
);
1174 /* The implementation of class gcc::jit::recording::location. */
1176 /* Implementation of recording::memento::replay_into for locations.
1178 Create a new playback::location and store it into the
1179 recording::location's m_playback_obj field. */
1182 recording::location::replay_into (replayer
*r
)
1184 m_playback_obj
= r
->new_location (this,
1185 m_filename
->c_str (),
1190 /* Implementation of recording::memento::make_debug_string for locations,
1191 turning them into the usual form:
1192 FILENAME:LINE:COLUMN
1193 like we do when emitting diagnostics. */
1196 recording::location::make_debug_string ()
1198 return string::from_printf (m_ctxt
,
1200 m_filename
->c_str (), m_line
, m_column
);
1203 /* The implementation of class gcc::jit::recording::type. */
1205 /* Given a type T, get the type T*.
1207 If this doesn't already exist, generate a new memento_of_get_pointer
1208 instance and add it to this type's context's list of mementos.
1210 Otherwise, use the cached type.
1212 Implements the post-error-checking part of
1213 gcc_jit_type_get_pointer. */
1216 recording::type::get_pointer ()
1218 if (!m_pointer_to_this_type
)
1220 m_pointer_to_this_type
= new memento_of_get_pointer (this);
1221 m_ctxt
->record (m_pointer_to_this_type
);
1223 return m_pointer_to_this_type
;
1226 /* Given a type T, get the type const T.
1228 Implements the post-error-checking part of
1229 gcc_jit_type_get_const. */
1232 recording::type::get_const ()
1234 recording::type
*result
= new memento_of_get_const (this);
1235 m_ctxt
->record (result
);
1239 /* Given a type T, get the type volatile T.
1241 Implements the post-error-checking part of
1242 gcc_jit_type_get_volatile. */
1245 recording::type::get_volatile ()
1247 recording::type
*result
= new memento_of_get_volatile (this);
1248 m_ctxt
->record (result
);
1252 /* Implementation of pure virtual hook recording::type::dereference for
1253 recording::memento_of_get_type. */
1256 recording::memento_of_get_type::dereference ()
1260 default: gcc_unreachable ();
1262 case GCC_JIT_TYPE_VOID
:
1265 case GCC_JIT_TYPE_VOID_PTR
:
1266 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
1268 case GCC_JIT_TYPE_BOOL
:
1269 case GCC_JIT_TYPE_CHAR
:
1270 case GCC_JIT_TYPE_SIGNED_CHAR
:
1271 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1272 case GCC_JIT_TYPE_SHORT
:
1273 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1274 case GCC_JIT_TYPE_INT
:
1275 case GCC_JIT_TYPE_UNSIGNED_INT
:
1276 case GCC_JIT_TYPE_LONG
:
1277 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1278 case GCC_JIT_TYPE_LONG_LONG
:
1279 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1280 case GCC_JIT_TYPE_FLOAT
:
1281 case GCC_JIT_TYPE_DOUBLE
:
1282 case GCC_JIT_TYPE_LONG_DOUBLE
:
1283 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1284 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1285 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1286 /* Not a pointer: */
1289 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1290 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
1292 case GCC_JIT_TYPE_SIZE_T
:
1293 /* Not a pointer: */
1296 case GCC_JIT_TYPE_FILE_PTR
:
1297 /* Give the client code back an opaque "struct FILE". */
1298 return m_ctxt
->get_opaque_FILE_type ();
1302 /* Implementation of pure virtual hook recording::type::is_int for
1303 recording::memento_of_get_type. */
1306 recording::memento_of_get_type::is_int () const
1310 default: gcc_unreachable ();
1312 case GCC_JIT_TYPE_VOID
:
1315 case GCC_JIT_TYPE_VOID_PTR
:
1318 case GCC_JIT_TYPE_BOOL
:
1321 case GCC_JIT_TYPE_CHAR
:
1322 case GCC_JIT_TYPE_SIGNED_CHAR
:
1323 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1324 case GCC_JIT_TYPE_SHORT
:
1325 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1326 case GCC_JIT_TYPE_INT
:
1327 case GCC_JIT_TYPE_UNSIGNED_INT
:
1328 case GCC_JIT_TYPE_LONG
:
1329 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1330 case GCC_JIT_TYPE_LONG_LONG
:
1331 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1334 case GCC_JIT_TYPE_FLOAT
:
1335 case GCC_JIT_TYPE_DOUBLE
:
1336 case GCC_JIT_TYPE_LONG_DOUBLE
:
1339 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1342 case GCC_JIT_TYPE_SIZE_T
:
1345 case GCC_JIT_TYPE_FILE_PTR
:
1348 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1349 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1350 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1355 /* Implementation of pure virtual hook recording::type::is_float for
1356 recording::memento_of_get_type. */
1359 recording::memento_of_get_type::is_float () const
1363 default: gcc_unreachable ();
1365 case GCC_JIT_TYPE_VOID
:
1368 case GCC_JIT_TYPE_VOID_PTR
:
1371 case GCC_JIT_TYPE_BOOL
:
1374 case GCC_JIT_TYPE_CHAR
:
1375 case GCC_JIT_TYPE_SIGNED_CHAR
:
1376 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1377 case GCC_JIT_TYPE_SHORT
:
1378 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1379 case GCC_JIT_TYPE_INT
:
1380 case GCC_JIT_TYPE_UNSIGNED_INT
:
1381 case GCC_JIT_TYPE_LONG
:
1382 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1383 case GCC_JIT_TYPE_LONG_LONG
:
1384 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1387 case GCC_JIT_TYPE_FLOAT
:
1388 case GCC_JIT_TYPE_DOUBLE
:
1389 case GCC_JIT_TYPE_LONG_DOUBLE
:
1392 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1395 case GCC_JIT_TYPE_SIZE_T
:
1398 case GCC_JIT_TYPE_FILE_PTR
:
1401 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1402 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1403 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1408 /* Implementation of pure virtual hook recording::type::is_bool for
1409 recording::memento_of_get_type. */
1412 recording::memento_of_get_type::is_bool () const
1416 default: gcc_unreachable ();
1418 case GCC_JIT_TYPE_VOID
:
1421 case GCC_JIT_TYPE_VOID_PTR
:
1424 case GCC_JIT_TYPE_BOOL
:
1427 case GCC_JIT_TYPE_CHAR
:
1428 case GCC_JIT_TYPE_SIGNED_CHAR
:
1429 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1430 case GCC_JIT_TYPE_SHORT
:
1431 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1432 case GCC_JIT_TYPE_INT
:
1433 case GCC_JIT_TYPE_UNSIGNED_INT
:
1434 case GCC_JIT_TYPE_LONG
:
1435 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1436 case GCC_JIT_TYPE_LONG_LONG
:
1437 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1440 case GCC_JIT_TYPE_FLOAT
:
1441 case GCC_JIT_TYPE_DOUBLE
:
1442 case GCC_JIT_TYPE_LONG_DOUBLE
:
1445 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1448 case GCC_JIT_TYPE_SIZE_T
:
1451 case GCC_JIT_TYPE_FILE_PTR
:
1454 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1455 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1456 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1461 /* Implementation of pure virtual hook recording::memento::replay_into
1462 for recording::memento_of_get_type. */
1465 recording::memento_of_get_type::replay_into (replayer
*r
)
1467 set_playback_obj (r
->get_type (m_kind
));
1470 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
1472 /* Descriptive strings for each of enum gcc_jit_types. */
1474 static const char * const get_type_strings
[] = {
1475 "void", /* GCC_JIT_TYPE_VOID */
1476 "void *", /* GCC_JIT_TYPE_VOID_PTR */
1478 "bool", /* GCC_JIT_TYPE_BOOL */
1480 "char", /* GCC_JIT_TYPE_CHAR */
1481 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
1482 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
1484 "short", /* GCC_JIT_TYPE_SHORT */
1485 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
1487 "int", /* GCC_JIT_TYPE_INT */
1488 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
1490 "long", /* GCC_JIT_TYPE_LONG */
1491 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
1493 "long long", /* GCC_JIT_TYPE_LONG_LONG */
1494 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
1496 "float", /* GCC_JIT_TYPE_FLOAT */
1497 "double", /* GCC_JIT_TYPE_DOUBLE */
1498 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
1500 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
1502 "size_t", /* GCC_JIT_TYPE_SIZE_T */
1504 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
1506 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
1507 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
1508 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
1512 /* Implementation of recording::memento::make_debug_string for
1513 results of get_type, using a simple table of type names. */
1516 recording::memento_of_get_type::make_debug_string ()
1518 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
1521 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
1523 /* Override of default implementation of
1524 recording::type::accepts_writes_from for get_pointer.
1526 Require a pointer type, and allowing writes to
1527 (const T *) from a (T*), but not the other way around. */
1530 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
1532 /* Must be a pointer type: */
1533 type
*rtype_points_to
= rtype
->is_pointer ();
1534 if (!rtype_points_to
)
1537 /* It's OK to assign to a (const T *) from a (T *). */
1538 return m_other_type
->unqualified ()
1539 ->accepts_writes_from (rtype_points_to
);
1542 /* Implementation of pure virtual hook recording::memento::replay_into
1543 for recording::memento_of_get_pointer. */
1546 recording::memento_of_get_pointer::replay_into (replayer
*)
1548 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
1551 /* Implementation of recording::memento::make_debug_string for
1552 results of get_pointer, adding " *" to the underlying type,
1553 with special-casing to handle function pointer types. */
1556 recording::memento_of_get_pointer::make_debug_string ()
1558 /* Special-case function pointer types, to put the "*" in parens between
1559 the return type and the params (for one level of dereferencing, at
1561 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
1562 return fn_type
->make_debug_string_with_ptr ();
1564 return string::from_printf (m_ctxt
,
1565 "%s *", m_other_type
->get_debug_string ());
1568 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
1570 /* Implementation of pure virtual hook recording::memento::replay_into
1571 for recording::memento_of_get_const. */
1574 recording::memento_of_get_const::replay_into (replayer
*)
1576 set_playback_obj (m_other_type
->playback_type ()->get_const ());
1579 /* Implementation of recording::memento::make_debug_string for
1580 results of get_const, prepending "const ". */
1583 recording::memento_of_get_const::make_debug_string ()
1585 return string::from_printf (m_ctxt
,
1586 "const %s", m_other_type
->get_debug_string ());
1589 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
1591 /* Implementation of pure virtual hook recording::memento::replay_into
1592 for recording::memento_of_get_volatile. */
1595 recording::memento_of_get_volatile::replay_into (replayer
*)
1597 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
1600 /* Implementation of recording::memento::make_debug_string for
1601 results of get_volatile, prepending "volatile ". */
1604 recording::memento_of_get_volatile::make_debug_string ()
1606 return string::from_printf (m_ctxt
,
1607 "volatile %s", m_other_type
->get_debug_string ());
1610 /* The implementation of class gcc::jit::recording::array_type */
1612 /* Implementation of pure virtual hook recording::type::dereference for
1613 recording::array_type. */
1616 recording::array_type::dereference ()
1618 return m_element_type
;
1621 /* Implementation of pure virtual hook recording::memento::replay_into
1622 for recording::array_type. */
1625 recording::array_type::replay_into (replayer
*r
)
1627 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
1628 m_element_type
->playback_type (),
1632 /* Implementation of recording::memento::make_debug_string for
1633 results of new_array_type. */
1636 recording::array_type::make_debug_string ()
1638 return string::from_printf (m_ctxt
,
1640 m_element_type
->get_debug_string (),
1644 /* The implementation of class gcc::jit::recording::function_type */
1646 /* Constructor for gcc::jit::recording::function_type. */
1648 recording::function_type::function_type (context
*ctxt
,
1654 m_return_type (return_type
),
1656 m_is_variadic (is_variadic
)
1658 for (int i
= 0; i
< num_params
; i
++)
1659 m_param_types
.safe_push (param_types
[i
]);
1662 /* Implementation of pure virtual hook recording::type::dereference for
1663 recording::function_type. */
1666 recording::function_type::dereference ()
1671 /* Implementation of pure virtual hook recording::memento::replay_into
1672 for recording::function_type. */
1675 recording::function_type::replay_into (replayer
*r
)
1677 /* Convert m_param_types to a vec of playback type. */
1678 auto_vec
<playback::type
*> param_types
;
1680 recording::type
*type
;
1681 param_types
.create (m_param_types
.length ());
1682 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
1683 param_types
.safe_push (type
->playback_type ());
1685 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
1690 /* Special-casing for make_debug_string for get_pointer results for
1691 handling (one level) of pointers to functions. */
1694 recording::function_type::make_debug_string_with_ptr ()
1696 return make_debug_string_with ("(*) ");
1699 /* Implementation of recording::memento::make_debug_string for
1700 results of new_function_type. */
1703 recording::function_type::make_debug_string ()
1705 return make_debug_string_with ("");
1708 /* Build a debug string representation of the form:
1710 RESULT_TYPE INSERT (PARAM_TYPES)
1712 for use when handling 0 and 1 level of indirection to this
1716 recording::function_type::make_debug_string_with (const char *insert
)
1718 /* First, build a buffer for the arguments. */
1719 /* Calculate length of said buffer. */
1720 size_t sz
= 1; /* nil terminator */
1721 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
1723 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
1724 sz
+= 2; /* ", " separator */
1727 sz
+= 5; /* ", ..." separator and ellipsis */
1729 /* Now allocate and populate the buffer. */
1730 char *argbuf
= new char[sz
];
1733 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
1735 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
1736 len
+= strlen (m_param_types
[i
]->get_debug_string ());
1737 if (i
+ 1 < m_param_types
.length ())
1739 strcpy (argbuf
+ len
, ", ");
1745 if (m_param_types
.length ())
1747 strcpy (argbuf
+ len
, ", ");
1750 strcpy (argbuf
+ len
, "...");
1755 /* ...and use it to get the string for the call as a whole. */
1756 string
*result
= string::from_printf (m_ctxt
,
1758 m_return_type
->get_debug_string (),
1767 /* The implementation of class gcc::jit::recording::field. */
1769 /* Implementation of pure virtual hook recording::memento::replay_into
1770 for recording::field. */
1773 recording::field::replay_into (replayer
*r
)
1775 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
1776 m_type
->playback_type (),
1777 playback_string (m_name
)));
1780 /* Override the default implementation of
1781 recording::memento::write_to_dump. Dump each field
1782 by dumping a line of the form:
1784 so that we can build up a struct/union field-byfield. */
1787 recording::field::write_to_dump (dump
&d
)
1789 d
.write (" %s %s;\n",
1790 m_type
->get_debug_string (),
1794 /* Implementation of recording::memento::make_debug_string for
1795 results of new_field. */
1798 recording::field::make_debug_string ()
1803 /* The implementation of class gcc::jit::recording::compound_type */
1805 /* The constructor for gcc::jit::recording::compound_type. */
1807 recording::compound_type::compound_type (context
*ctxt
,
1817 /* Set the fields of a compound type.
1819 Implements the post-error-checking part of
1820 gcc_jit_struct_set_fields, and is also used by
1821 gcc_jit_context_new_union_type. */
1824 recording::compound_type::set_fields (location
*loc
,
1826 field
**field_array
)
1829 gcc_assert (NULL
== m_fields
);
1831 m_fields
= new fields (this, num_fields
, field_array
);
1832 m_ctxt
->record (m_fields
);
1835 /* Implementation of pure virtual hook recording::type::dereference for
1836 recording::compound_type. */
1839 recording::compound_type::dereference ()
1841 return NULL
; /* not a pointer */
1844 /* The implementation of class gcc::jit::recording::struct_. */
1846 /* The constructor for gcc::jit::recording::struct_. */
1848 recording::struct_::struct_ (context
*ctxt
,
1851 : compound_type (ctxt
, loc
, name
)
1855 /* Implementation of pure virtual hook recording::memento::replay_into
1856 for recording::struct_. */
1859 recording::struct_::replay_into (replayer
*r
)
1862 r
->new_compound_type (playback_location (r
, get_loc ()),
1863 get_name ()->c_str (),
1864 true /* is_struct */));
1867 /* Implementation of recording::memento::make_debug_string for
1871 recording::struct_::make_debug_string ()
1873 return string::from_printf (m_ctxt
,
1874 "struct %s", get_name ()->c_str ());
1877 /* The implementation of class gcc::jit::recording::union_. */
1879 /* The constructor for gcc::jit::recording::union_. */
1881 recording::union_::union_ (context
*ctxt
,
1884 : compound_type (ctxt
, loc
, name
)
1888 /* Implementation of pure virtual hook recording::memento::replay_into
1889 for recording::union_. */
1892 recording::union_::replay_into (replayer
*r
)
1895 r
->new_compound_type (playback_location (r
, get_loc ()),
1896 get_name ()->c_str (),
1897 false /* is_struct */));
1900 /* Implementation of recording::memento::make_debug_string for
1904 recording::union_::make_debug_string ()
1906 return string::from_printf (m_ctxt
,
1907 "union %s", get_name ()->c_str ());
1910 /* The implementation of class gcc::jit::recording::fields. */
1912 /* The constructor for gcc::jit::recording::fields. */
1914 recording::fields::fields (compound_type
*struct_or_union
,
1917 : memento (struct_or_union
->m_ctxt
),
1918 m_struct_or_union (struct_or_union
),
1921 for (int i
= 0; i
< num_fields
; i
++)
1923 gcc_assert (fields
[i
]->get_container () == NULL
);
1924 fields
[i
]->set_container (m_struct_or_union
);
1925 m_fields
.safe_push (fields
[i
]);
1929 /* Implementation of pure virtual hook recording::memento::replay_into
1930 for recording::fields. */
1933 recording::fields::replay_into (replayer
*)
1935 auto_vec
<playback::field
*> playback_fields
;
1936 playback_fields
.create (m_fields
.length ());
1937 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
1938 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
1939 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
1942 /* Override the default implementation of
1943 recording::memento::write_to_dump by writing a union/struct
1944 declaration of this form:
1956 recording::fields::write_to_dump (dump
&d
)
1961 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
1962 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
1963 f
->write_to_dump (d
);
1967 /* Implementation of recording::memento::make_debug_string for
1971 recording::fields::make_debug_string ()
1973 return string::from_printf (m_ctxt
,
1977 /* The implementation of class gcc::jit::recording::rvalue. */
1979 /* Create a recording::access_field_rvalue instance and add it to
1980 the rvalue's context's list of mementos.
1982 Implements the post-error-checking part of
1983 gcc_jit_rvalue_access_field. */
1986 recording::rvalue::access_field (recording::location
*loc
,
1989 recording::rvalue
*result
=
1990 new access_field_rvalue (m_ctxt
, loc
, this, field
);
1991 m_ctxt
->record (result
);
1995 /* Create a recording::dereference_field_rvalue instance and add it to
1996 the rvalue's context's list of mementos.
1998 Implements the post-error-checking part of
1999 gcc_jit_rvalue_dereference_field. */
2002 recording::rvalue::dereference_field (recording::location
*loc
,
2005 recording::lvalue
*result
=
2006 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
2007 m_ctxt
->record (result
);
2011 /* Create a recording::dereference_rvalue instance and add it to the
2012 rvalue's context's list of mementos.
2014 Implements the post-error-checking part of
2015 gcc_jit_rvalue_dereference. */
2018 recording::rvalue::dereference (recording::location
*loc
)
2020 recording::lvalue
*result
=
2021 new dereference_rvalue (m_ctxt
, loc
, this);
2022 m_ctxt
->record (result
);
2026 /* The implementation of class gcc::jit::recording::lvalue. */
2028 /* Create a recording::new_access_field_of_lvalue instance and add it to
2029 the lvalue's context's list of mementos.
2031 Implements the post-error-checking part of
2032 gcc_jit_lvalue_access_field. */
2035 recording::lvalue::access_field (recording::location
*loc
,
2038 recording::lvalue
*result
=
2039 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
2040 m_ctxt
->record (result
);
2044 /* Create a recording::get_address_of_lvalue instance and add it to
2045 the lvalue's context's list of mementos.
2047 Implements the post-error-checking part of
2048 gcc_jit_lvalue_get_address. */
2051 recording::lvalue::get_address (recording::location
*loc
)
2053 recording::rvalue
*result
=
2054 new get_address_of_lvalue (m_ctxt
, loc
, this);
2055 m_ctxt
->record (result
);
2059 /* The implementation of class gcc::jit::recording::param. */
2061 /* Implementation of pure virtual hook recording::memento::replay_into
2062 for recording::param. */
2065 recording::param::replay_into (replayer
*r
)
2067 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
2068 m_type
->playback_type (),
2073 /* The implementation of class gcc::jit::recording::function. */
2075 /* gcc::jit::recording::function's constructor. */
2077 recording::function::function (context
*ctxt
,
2078 recording::location
*loc
,
2079 enum gcc_jit_function_kind kind
,
2081 recording::string
*name
,
2083 recording::param
**params
,
2085 enum built_in_function builtin_id
)
2089 m_return_type (return_type
),
2092 m_is_variadic (is_variadic
),
2093 m_builtin_id (builtin_id
),
2097 for (int i
= 0; i
< num_params
; i
++)
2098 m_params
.safe_push (params
[i
]);
2101 /* Implementation of pure virtual hook recording::memento::replay_into
2102 for recording::function. */
2105 recording::function::replay_into (replayer
*r
)
2107 /* Convert m_params to a vec of playback param. */
2108 auto_vec
<playback::param
*> params
;
2110 recording::param
*param
;
2111 params
.create (m_params
.length ());
2112 FOR_EACH_VEC_ELT (m_params
, i
, param
)
2113 params
.safe_push (param
->playback_param ());
2115 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
2117 m_return_type
->playback_type (),
2124 /* Create a recording::local instance and add it to
2125 the functions's context's list of mementos, and to the function's
2128 Implements the post-error-checking part of
2129 gcc_jit_function_new_local. */
2132 recording::function::new_local (recording::location
*loc
,
2136 local
*result
= new local (this, loc
, type
, new_string (name
));
2137 m_ctxt
->record (result
);
2138 m_locals
.safe_push (result
);
2142 /* Create a recording::block instance and add it to
2143 the functions's context's list of mementos, and to the function's
2146 Implements the post-error-checking part of
2147 gcc_jit_function_new_block. */
2150 recording::function::new_block (const char *name
)
2152 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
2154 recording::block
*result
=
2155 new recording::block (this, m_blocks
.length (), new_string (name
));
2156 m_ctxt
->record (result
);
2157 m_blocks
.safe_push (result
);
2161 /* Override the default implementation of
2162 recording::memento::write_to_dump by dumping a C-like
2163 representation of the function; either like a prototype
2164 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
2165 all other kinds of function. */
2168 recording::function::write_to_dump (dump
&d
)
2172 default: gcc_unreachable ();
2173 case GCC_JIT_FUNCTION_EXPORTED
:
2174 case GCC_JIT_FUNCTION_IMPORTED
:
2175 d
.write ("extern ");
2177 case GCC_JIT_FUNCTION_INTERNAL
:
2178 d
.write ("static ");
2180 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
2181 d
.write ("static inline ");
2184 d
.write ("%s\n", m_return_type
->get_debug_string ());
2186 if (d
.update_locations ())
2187 m_loc
= d
.make_location ();
2189 d
.write ("%s (", get_debug_string ());
2192 recording::param
*param
;
2193 FOR_EACH_VEC_ELT (m_params
, i
, param
)
2198 param
->get_type ()->get_debug_string (),
2199 param
->get_debug_string ());
2202 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
2204 d
.write ("; /* (imported) */\n\n");
2214 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
2215 var
->write_to_dump (d
);
2216 if (m_locals
.length ())
2219 /* Write each block: */
2220 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2224 b
->write_to_dump (d
);
2231 /* Pre-compilation validation of a function, for those things we can't
2232 check until the context is (supposedly) fully-populated. */
2235 recording::function::validate ()
2237 /* Complain about empty functions with non-void return type. */
2238 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
2239 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
2240 if (0 == m_blocks
.length ())
2241 m_ctxt
->add_error (m_loc
,
2242 "function %s returns non-void (type: %s)"
2243 " but has no blocks",
2244 get_debug_string (),
2245 m_return_type
->get_debug_string ());
2247 /* Check that all blocks are terminated. */
2248 int num_invalid_blocks
= 0;
2253 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2254 if (!b
->validate ())
2255 num_invalid_blocks
++;
2258 /* Check that all blocks are reachable. */
2259 if (m_blocks
.length () > 0 && 0 == num_invalid_blocks
)
2261 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
2262 flag, starting at the initial block. */
2263 auto_vec
<block
*> worklist (m_blocks
.length ());
2264 worklist
.safe_push (m_blocks
[0]);
2265 while (worklist
.length () > 0)
2267 block
*b
= worklist
.pop ();
2268 b
->m_is_reachable
= true;
2270 /* Add successor blocks that aren't yet marked to the worklist. */
2271 /* We checked that each block has a terminating statement above . */
2272 block
*next1
, *next2
;
2273 int n
= b
->get_successor_blocks (&next1
, &next2
);
2279 if (!next2
->m_is_reachable
)
2280 worklist
.safe_push (next2
);
2283 if (!next1
->m_is_reachable
)
2284 worklist
.safe_push (next1
);
2291 /* Now complain about any blocks that haven't been marked. */
2295 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2296 if (!b
->m_is_reachable
)
2297 m_ctxt
->add_error (b
->get_loc (),
2298 "unreachable block: %s",
2299 b
->get_debug_string ());
2304 /* Implements the post-error-checking part of
2305 gcc_jit_function_dump_to_dot. */
2308 recording::function::dump_to_dot (const char *path
)
2310 FILE *fp
= fopen (path
, "w");
2314 pretty_printer the_pp
;
2315 the_pp
.buffer
->stream
= fp
;
2317 pretty_printer
*pp
= &the_pp
;
2320 "digraph %s {\n", get_debug_string ());
2326 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2327 b
->dump_to_dot (pp
);
2334 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2335 b
->dump_edges_to_dot (pp
);
2338 pp_printf (pp
, "}\n");
2343 /* Implementation of recording::memento::make_debug_string for
2347 recording::function::make_debug_string ()
2352 /* The implementation of class gcc::jit::recording::block. */
2354 /* Create a recording::eval instance and add it to
2355 the block's context's list of mementos, and to the block's
2358 Implements the post-error-checking part of
2359 gcc_jit_block_add_eval. */
2362 recording::block::add_eval (recording::location
*loc
,
2363 recording::rvalue
*rvalue
)
2365 statement
*result
= new eval (this, loc
, rvalue
);
2366 m_ctxt
->record (result
);
2367 m_statements
.safe_push (result
);
2370 /* Create a recording::assignment instance and add it to
2371 the block's context's list of mementos, and to the block's
2374 Implements the post-error-checking part of
2375 gcc_jit_block_add_assignment. */
2378 recording::block::add_assignment (recording::location
*loc
,
2379 recording::lvalue
*lvalue
,
2380 recording::rvalue
*rvalue
)
2382 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
2383 m_ctxt
->record (result
);
2384 m_statements
.safe_push (result
);
2387 /* Create a recording::assignment_op instance and add it to
2388 the block's context's list of mementos, and to the block's
2391 Implements the post-error-checking part of
2392 gcc_jit_block_add_assignment_op. */
2395 recording::block::add_assignment_op (recording::location
*loc
,
2396 recording::lvalue
*lvalue
,
2397 enum gcc_jit_binary_op op
,
2398 recording::rvalue
*rvalue
)
2400 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
2401 m_ctxt
->record (result
);
2402 m_statements
.safe_push (result
);
2405 /* Create a recording::comment instance and add it to
2406 the block's context's list of mementos, and to the block's
2409 Implements the post-error-checking part of
2410 gcc_jit_block_add_comment. */
2413 recording::block::add_comment (recording::location
*loc
,
2416 statement
*result
= new comment (this, loc
, new_string (text
));
2417 m_ctxt
->record (result
);
2418 m_statements
.safe_push (result
);
2421 /* Create a recording::end_with_conditional instance and add it to
2422 the block's context's list of mementos, and to the block's
2425 Implements the post-error-checking part of
2426 gcc_jit_block_end_with_conditional. */
2429 recording::block::end_with_conditional (recording::location
*loc
,
2430 recording::rvalue
*boolval
,
2431 recording::block
*on_true
,
2432 recording::block
*on_false
)
2434 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
2435 m_ctxt
->record (result
);
2436 m_statements
.safe_push (result
);
2437 m_has_been_terminated
= true;
2440 /* Create a recording::end_with_jump instance and add it to
2441 the block's context's list of mementos, and to the block's
2444 Implements the post-error-checking part of
2445 gcc_jit_block_end_with_jump. */
2448 recording::block::end_with_jump (recording::location
*loc
,
2449 recording::block
*target
)
2451 statement
*result
= new jump (this, loc
, target
);
2452 m_ctxt
->record (result
);
2453 m_statements
.safe_push (result
);
2454 m_has_been_terminated
= true;
2457 /* Create a recording::end_with_return instance and add it to
2458 the block's context's list of mementos, and to the block's
2461 Implements the post-error-checking parts of
2462 gcc_jit_block_end_with_return and
2463 gcc_jit_block_end_with_void_return. */
2466 recording::block::end_with_return (recording::location
*loc
,
2467 recording::rvalue
*rvalue
)
2469 /* This is used by both gcc_jit_function_add_return and
2470 gcc_jit_function_add_void_return; rvalue will be non-NULL for
2471 the former and NULL for the latter. */
2472 statement
*result
= new return_ (this, loc
, rvalue
);
2473 m_ctxt
->record (result
);
2474 m_statements
.safe_push (result
);
2475 m_has_been_terminated
= true;
2478 /* Override the default implementation of
2479 recording::memento::write_to_dump for blocks by writing
2480 an unindented block name as a label, followed by the indented
2490 recording::block::write_to_dump (dump
&d
)
2492 d
.write ("%s:\n", get_debug_string ());
2496 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
2497 s
->write_to_dump (d
);
2500 /* Validate a block by ensuring that it has been terminated. */
2503 recording::block::validate ()
2505 if (!has_been_terminated ())
2507 statement
*stmt
= get_last_statement ();
2508 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
2509 m_func
->get_context ()->add_error (loc
,
2510 "unterminated block in %s: %s",
2511 m_func
->get_debug_string (),
2512 get_debug_string ());
2519 /* Get the source-location of a block by using that of the first
2520 statement within it, if any. */
2522 recording::location
*
2523 recording::block::get_loc () const
2525 recording::statement
*stmt
= get_first_statement ();
2527 return stmt
->get_loc ();
2532 /* Get the first statement within a block, if any. */
2534 recording::statement
*
2535 recording::block::get_first_statement () const
2537 if (m_statements
.length ())
2538 return m_statements
[0];
2543 /* Get the last statement within a block, if any. */
2545 recording::statement
*
2546 recording::block::get_last_statement () const
2548 if (m_statements
.length ())
2549 return m_statements
[m_statements
.length () - 1];
2554 /* Assuming that this block has been terminated, get the number of
2555 successor blocks, which will be 0, 1 or 2, for return, unconditional
2556 jump, and conditional jump respectively.
2557 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
2558 is written to NEXT1, and the second (if any) to NEXT2.
2560 Used when validating functions, and when dumping dot representations
2564 recording::block::get_successor_blocks (block
**next1
, block
**next2
) const
2566 gcc_assert (m_has_been_terminated
);
2569 statement
*last_statement
= get_last_statement ();
2570 gcc_assert (last_statement
);
2571 return last_statement
->get_successor_blocks (next1
, next2
);
2574 /* Implementation of pure virtual hook recording::memento::replay_into
2575 for recording::block. */
2578 recording::block::replay_into (replayer
*)
2580 set_playback_obj (m_func
->playback_function ()
2581 ->new_block (playback_string (m_name
)));
2584 /* Implementation of recording::memento::make_debug_string for
2588 recording::block::make_debug_string ()
2593 return string::from_printf (m_ctxt
,
2594 "<UNNAMED BLOCK %p>",
2598 /* Dump a block in graphviz form into PP, capturing the block name (if
2599 any) and the statements. */
2602 recording::block::dump_to_dot (pretty_printer
*pp
)
2606 "[shape=record,style=filled,fillcolor=white,label=\"{"),
2608 pp_write_text_to_stream (pp
);
2611 pp_string (pp
, m_name
->c_str ());
2612 pp_string (pp
, ":");
2614 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
2619 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
2621 pp_string (pp
, s
->get_debug_string ());
2623 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
2631 /* Dump the out-edges of the block in graphviz form into PP. */
2634 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
2637 int num_succs
= get_successor_blocks (&next
[0], &next
[1]);
2638 for (int i
= 0; i
< num_succs
; i
++)
2640 "\tblock_%d:s -> block_%d:n;\n",
2641 m_index
, next
[i
]->m_index
);
2644 /* The implementation of class gcc::jit::recording::global. */
2646 /* Implementation of pure virtual hook recording::memento::replay_into
2647 for recording::global. */
2650 recording::global::replay_into (replayer
*r
)
2652 set_playback_obj (r
->new_global (playback_location (r
, m_loc
),
2653 m_type
->playback_type (),
2654 playback_string (m_name
)));
2657 /* The implementation of the various const-handling classes:
2658 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
2660 /* Explicit specialization of the various mementos we're interested in. */
2661 template class recording::memento_of_new_rvalue_from_const
<int>;
2662 template class recording::memento_of_new_rvalue_from_const
<long>;
2663 template class recording::memento_of_new_rvalue_from_const
<double>;
2664 template class recording::memento_of_new_rvalue_from_const
<void *>;
2666 /* Implementation of the pure virtual hook recording::memento::replay_into
2667 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
2669 template <typename HOST_TYPE
>
2672 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
2675 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
2679 /* The make_debug_string method varies between the various
2680 memento_of_new_rvalue_from_const <HOST_TYPE> classes, so we explicitly
2681 write specializations of it.
2683 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
2684 namespaces are written out explicitly, which is why most of this file
2685 doesn't abbreviate things by entering the "recording" namespace.
2687 However, these specializations are required to be in the same namespace
2688 as the template, hence we now have to enter the gcc::jit::recording
2694 /* The make_debug_string specialization for <int>, which renders it as
2695 (TARGET_TYPE)LITERAL
2701 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
2703 return string::from_printf (m_ctxt
,
2705 m_type
->get_debug_string (),
2709 /* The make_debug_string specialization for <long>, rendering it as
2710 (TARGET_TYPE)LITERAL
2716 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
2718 return string::from_printf (m_ctxt
,
2720 m_type
->get_debug_string (),
2724 /* The make_debug_string specialization for <double>, rendering it as
2725 (TARGET_TYPE)LITERAL
2731 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
2733 return string::from_printf (m_ctxt
,
2735 m_type
->get_debug_string (),
2739 /* The make_debug_string specialization for <void *>, rendering it as
2744 Zero is rendered as NULL e.g.
2749 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
2751 if (m_value
!= NULL
)
2752 return string::from_printf (m_ctxt
,
2754 m_type
->get_debug_string (), m_value
);
2756 return string::from_printf (m_ctxt
,
2758 m_type
->get_debug_string ());
2761 /* We're done specializing make_debug_string, so we can exit the
2762 gcc::jit::recording namespace. */
2764 } // namespace recording
2766 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
2768 /* Implementation of pure virtual hook recording::memento::replay_into
2769 for recording::memento_of_new_string_literal. */
2772 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
2774 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
2777 /* Implementation of recording::memento::make_debug_string for
2781 recording::memento_of_new_string_literal::make_debug_string ()
2783 return string::from_printf (m_ctxt
,
2784 m_value
->get_debug_string ());
2787 /* The implementation of class gcc::jit::recording::unary_op. */
2789 /* Implementation of pure virtual hook recording::memento::replay_into
2790 for recording::unary_op. */
2793 recording::unary_op::replay_into (replayer
*r
)
2795 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
2797 get_type ()->playback_type (),
2798 m_a
->playback_rvalue ()));
2801 /* Implementation of recording::memento::make_debug_string for
2804 static const char * const unary_op_strings
[] = {
2805 "-", /* GCC_JIT_UNARY_OP_MINUS */
2806 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
2807 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
2808 "abs ", /* GCC_JIT_UNARY_OP_ABS */
2812 recording::unary_op::make_debug_string ()
2814 return string::from_printf (m_ctxt
,
2816 unary_op_strings
[m_op
],
2817 m_a
->get_debug_string ());
2820 /* The implementation of class gcc::jit::recording::binary_op. */
2822 /* Implementation of pure virtual hook recording::memento::replay_into
2823 for recording::binary_op. */
2826 recording::binary_op::replay_into (replayer
*r
)
2828 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
2830 get_type ()->playback_type (),
2831 m_a
->playback_rvalue (),
2832 m_b
->playback_rvalue ()));
2835 /* Implementation of recording::memento::make_debug_string for
2838 static const char * const binary_op_strings
[] = {
2839 "+", /* GCC_JIT_BINARY_OP_PLUS */
2840 "-", /* GCC_JIT_BINARY_OP_MINUS */
2841 "*", /* GCC_JIT_BINARY_OP_MULT */
2842 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
2843 "%", /* GCC_JIT_BINARY_OP_MODULO */
2844 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
2845 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
2846 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
2847 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
2848 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
2849 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
2850 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
2854 recording::binary_op::make_debug_string ()
2856 return string::from_printf (m_ctxt
,
2858 m_a
->get_debug_string (),
2859 binary_op_strings
[m_op
],
2860 m_b
->get_debug_string ());
2863 /* The implementation of class gcc::jit::recording::comparison. */
2865 /* Implementation of recording::memento::make_debug_string for
2868 static const char * const comparison_strings
[] =
2870 "==", /* GCC_JIT_COMPARISON_EQ */
2871 "!=", /* GCC_JIT_COMPARISON_NE */
2872 "<", /* GCC_JIT_COMPARISON_LT */
2873 "<=", /* GCC_JIT_COMPARISON_LE */
2874 ">", /* GCC_JIT_COMPARISON_GT */
2875 ">=", /* GCC_JIT_COMPARISON_GE */
2879 recording::comparison::make_debug_string ()
2881 return string::from_printf (m_ctxt
,
2883 m_a
->get_debug_string (),
2884 comparison_strings
[m_op
],
2885 m_b
->get_debug_string ());
2888 /* Implementation of pure virtual hook recording::memento::replay_into
2889 for recording::comparison. */
2892 recording::comparison::replay_into (replayer
*r
)
2894 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
2896 m_a
->playback_rvalue (),
2897 m_b
->playback_rvalue ()));
2900 /* Implementation of pure virtual hook recording::memento::replay_into
2901 for recording::cast. */
2904 recording::cast::replay_into (replayer
*r
)
2906 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
2907 m_rvalue
->playback_rvalue (),
2908 get_type ()->playback_type ()));
2911 /* Implementation of recording::memento::make_debug_string for
2915 recording::cast::make_debug_string ()
2917 return string::from_printf (m_ctxt
,
2919 get_type ()->get_debug_string (),
2920 m_rvalue
->get_debug_string ());
2923 /* The implementation of class gcc::jit::recording::call. */
2925 /* The constructor for gcc::jit::recording::call. */
2927 recording::call::call (recording::context
*ctxt
,
2928 recording::location
*loc
,
2929 recording::function
*func
,
2932 : rvalue (ctxt
, loc
, func
->get_return_type ()),
2936 for (int i
= 0; i
< numargs
; i
++)
2937 m_args
.safe_push (args
[i
]);
2940 /* Implementation of pure virtual hook recording::memento::replay_into
2941 for recording::call. */
2944 recording::call::replay_into (replayer
*r
)
2946 auto_vec
<playback::rvalue
*> playback_args
;
2947 playback_args
.create (m_args
.length ());
2948 for (unsigned i
= 0; i
< m_args
.length (); i
++)
2949 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
2951 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
2952 m_func
->playback_function (),
2956 /* Implementation of recording::memento::make_debug_string for
2960 recording::call::make_debug_string ()
2962 /* First, build a buffer for the arguments. */
2963 /* Calculate length of said buffer. */
2964 size_t sz
= 1; /* nil terminator */
2965 for (unsigned i
= 0; i
< m_args
.length (); i
++)
2967 sz
+= strlen (m_args
[i
]->get_debug_string ());
2968 sz
+= 2; /* ", " separator */
2971 /* Now allocate and populate the buffer. */
2972 char *argbuf
= new char[sz
];
2975 for (unsigned i
= 0; i
< m_args
.length (); i
++)
2977 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string ());
2978 len
+= strlen (m_args
[i
]->get_debug_string ());
2979 if (i
+ 1 < m_args
.length ())
2981 strcpy (argbuf
+ len
, ", ");
2987 /* ...and use it to get the string for the call as a whole. */
2988 string
*result
= string::from_printf (m_ctxt
,
2990 m_func
->get_debug_string (),
2998 /* The implementation of class gcc::jit::recording::call_through_ptr. */
3000 /* The constructor for recording::call_through_ptr. */
3002 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
3003 recording::location
*loc
,
3004 recording::rvalue
*fn_ptr
,
3007 : rvalue (ctxt
, loc
,
3008 fn_ptr
->get_type ()->dereference ()
3009 ->as_a_function_type ()->get_return_type ()),
3013 for (int i
= 0; i
< numargs
; i
++)
3014 m_args
.safe_push (args
[i
]);
3017 /* Implementation of pure virtual hook recording::memento::replay_into
3018 for recording::call_through_ptr. */
3021 recording::call_through_ptr::replay_into (replayer
*r
)
3023 auto_vec
<playback::rvalue
*> playback_args
;
3024 playback_args
.create (m_args
.length ());
3025 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3026 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
3028 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
3029 m_fn_ptr
->playback_rvalue (),
3033 /* Implementation of recording::memento::make_debug_string for
3034 calls through function ptrs. */
3037 recording::call_through_ptr::make_debug_string ()
3039 /* First, build a buffer for the arguments. */
3040 /* Calculate length of said buffer. */
3041 size_t sz
= 1; /* nil terminator */
3042 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3044 sz
+= strlen (m_args
[i
]->get_debug_string ());
3045 sz
+= 2; /* ", " separator */
3048 /* Now allocate and populate the buffer. */
3049 char *argbuf
= new char[sz
];
3052 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3054 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string ());
3055 len
+= strlen (m_args
[i
]->get_debug_string ());
3056 if (i
+ 1 < m_args
.length ())
3058 strcpy (argbuf
+ len
, ", ");
3064 /* ...and use it to get the string for the call as a whole. */
3065 string
*result
= string::from_printf (m_ctxt
,
3067 m_fn_ptr
->get_debug_string (),
3075 /* The implementation of class gcc::jit::recording::array_access. */
3077 /* Implementation of pure virtual hook recording::memento::replay_into
3078 for recording::array_access. */
3081 recording::array_access::replay_into (replayer
*r
)
3084 r
->new_array_access (playback_location (r
, m_loc
),
3085 m_ptr
->playback_rvalue (),
3086 m_index
->playback_rvalue ()));
3089 /* Implementation of recording::memento::make_debug_string for
3093 recording::array_access::make_debug_string ()
3095 return string::from_printf (m_ctxt
,
3097 m_ptr
->get_debug_string (),
3098 m_index
->get_debug_string ());
3101 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
3103 /* Implementation of pure virtual hook recording::memento::replay_into
3104 for recording::access_field_of_lvalue. */
3107 recording::access_field_of_lvalue::replay_into (replayer
*r
)
3110 m_lvalue
->playback_lvalue ()
3111 ->access_field (playback_location (r
, m_loc
),
3112 m_field
->playback_field ()));
3116 /* Implementation of recording::memento::make_debug_string for
3117 accessing a field of an lvalue. */
3120 recording::access_field_of_lvalue::make_debug_string ()
3122 return string::from_printf (m_ctxt
,
3124 m_lvalue
->get_debug_string (),
3125 m_field
->get_debug_string ());
3128 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
3130 /* Implementation of pure virtual hook recording::memento::replay_into
3131 for recording::access_field_rvalue. */
3134 recording::access_field_rvalue::replay_into (replayer
*r
)
3137 m_rvalue
->playback_rvalue ()
3138 ->access_field (playback_location (r
, m_loc
),
3139 m_field
->playback_field ()));
3142 /* Implementation of recording::memento::make_debug_string for
3143 accessing a field of an rvalue. */
3146 recording::access_field_rvalue::make_debug_string ()
3148 return string::from_printf (m_ctxt
,
3150 m_rvalue
->get_debug_string (),
3151 m_field
->get_debug_string ());
3154 /* The implementation of class
3155 gcc::jit::recording::dereference_field_rvalue. */
3157 /* Implementation of pure virtual hook recording::memento::replay_into
3158 for recording::dereference_field_rvalue. */
3161 recording::dereference_field_rvalue::replay_into (replayer
*r
)
3164 m_rvalue
->playback_rvalue ()->
3165 dereference_field (playback_location (r
, m_loc
),
3166 m_field
->playback_field ()));
3169 /* Implementation of recording::memento::make_debug_string for
3170 dereferencing a field of an rvalue. */
3173 recording::dereference_field_rvalue::make_debug_string ()
3175 return string::from_printf (m_ctxt
,
3177 m_rvalue
->get_debug_string (),
3178 m_field
->get_debug_string ());
3181 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
3183 /* Implementation of pure virtual hook recording::memento::replay_into
3184 for recording::dereference_rvalue. */
3187 recording::dereference_rvalue::replay_into (replayer
*r
)
3190 m_rvalue
->playback_rvalue ()->
3191 dereference (playback_location (r
, m_loc
)));
3194 /* Implementation of recording::memento::make_debug_string for
3195 dereferencing an rvalue. */
3198 recording::dereference_rvalue::make_debug_string ()
3200 return string::from_printf (m_ctxt
,
3202 m_rvalue
->get_debug_string ());
3205 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
3207 /* Implementation of pure virtual hook recording::memento::replay_into
3208 for recording::get_address_of_lvalue. */
3211 recording::get_address_of_lvalue::replay_into (replayer
*r
)
3214 m_lvalue
->playback_lvalue ()->
3215 get_address (playback_location (r
, m_loc
)));
3218 /* Implementation of recording::memento::make_debug_string for
3219 getting the address of an lvalue. */
3222 recording::get_address_of_lvalue::make_debug_string ()
3224 return string::from_printf (m_ctxt
,
3226 m_lvalue
->get_debug_string ());
3229 /* The implementation of class gcc::jit::recording::local. */
3231 /* Implementation of pure virtual hook recording::memento::replay_into
3232 for recording::local. */
3235 recording::local::replay_into (replayer
*r
)
3238 m_func
->playback_function ()
3239 ->new_local (playback_location (r
, m_loc
),
3240 m_type
->playback_type (),
3241 playback_string (m_name
)));
3244 /* Override the default implementation of
3245 recording::memento::write_to_dump for locals by writing
3247 for use at the top of the function body as if it were a
3251 recording::local::write_to_dump (dump
&d
)
3253 if (d
.update_locations ())
3254 m_loc
= d
.make_location ();
3255 d
.write(" %s %s;\n",
3256 m_type
->get_debug_string (),
3257 get_debug_string ());
3260 /* The implementation of class gcc::jit::recording::statement. */
3262 /* We poison the default implementation of
3263 gcc::jit::recording::statement::get_successor_blocks
3264 since this vfunc must only ever be called on terminator
3268 recording::statement::get_successor_blocks (block
**/
*out_next1*/
,
3269 block
**/
*out_next2*/
) const
3271 /* The base class implementation is for non-terminating statements,
3272 and thus should never be called. */
3277 /* Extend the default implementation of
3278 recording::memento::write_to_dump for statements by (if requested)
3279 updating the location of the statement to the current location in
3283 recording::statement::write_to_dump (dump
&d
)
3285 memento::write_to_dump (d
);
3286 if (d
.update_locations ())
3287 m_loc
= d
.make_location ();
3290 /* The implementation of class gcc::jit::recording::eval. */
3292 /* Implementation of pure virtual hook recording::memento::replay_into
3293 for recording::eval. */
3296 recording::eval::replay_into (replayer
*r
)
3298 playback_block (get_block ())
3299 ->add_eval (playback_location (r
),
3300 m_rvalue
->playback_rvalue ());
3303 /* Implementation of recording::memento::make_debug_string for
3304 an eval statement. */
3307 recording::eval::make_debug_string ()
3309 return string::from_printf (m_ctxt
,
3311 m_rvalue
->get_debug_string ());
3314 /* The implementation of class gcc::jit::recording::assignment. */
3316 /* Implementation of pure virtual hook recording::memento::replay_into
3317 for recording::assignment. */
3320 recording::assignment::replay_into (replayer
*r
)
3322 playback_block (get_block ())
3323 ->add_assignment (playback_location (r
),
3324 m_lvalue
->playback_lvalue (),
3325 m_rvalue
->playback_rvalue ());
3328 /* Implementation of recording::memento::make_debug_string for
3329 an assignment statement. */
3332 recording::assignment::make_debug_string ()
3334 return string::from_printf (m_ctxt
,
3336 m_lvalue
->get_debug_string (),
3337 m_rvalue
->get_debug_string ());
3340 /* The implementation of class gcc::jit::recording::assignment_op. */
3342 /* Implementation of pure virtual hook recording::memento::replay_into
3343 for recording::assignment_op. */
3346 recording::assignment_op::replay_into (replayer
*r
)
3348 playback::type
*result_type
=
3349 m_lvalue
->playback_lvalue ()->get_type ();
3351 playback::rvalue
*binary_op
=
3352 r
->new_binary_op (playback_location (r
),
3355 m_lvalue
->playback_rvalue (),
3356 m_rvalue
->playback_rvalue ());
3358 playback_block (get_block ())
3359 ->add_assignment (playback_location (r
),
3360 m_lvalue
->playback_lvalue (),
3364 /* Implementation of recording::memento::make_debug_string for
3365 an assignment_op statement. */
3368 recording::assignment_op::make_debug_string ()
3370 return string::from_printf (m_ctxt
,
3372 m_lvalue
->get_debug_string (),
3373 binary_op_strings
[m_op
],
3374 m_rvalue
->get_debug_string ());
3377 /* The implementation of class gcc::jit::recording::comment. */
3379 /* Implementation of pure virtual hook recording::memento::replay_into
3380 for recording::comment. */
3383 recording::comment::replay_into (replayer
*r
)
3385 playback_block (get_block ())
3386 ->add_comment (playback_location (r
),
3390 /* Implementation of recording::memento::make_debug_string for
3391 a comment "statement". */
3394 recording::comment::make_debug_string ()
3396 return string::from_printf (m_ctxt
,
3401 /* The implementation of class gcc::jit::recording::conditional. */
3403 /* Implementation of pure virtual hook recording::memento::replay_into
3404 for recording::conditional. */
3407 recording::conditional::replay_into (replayer
*r
)
3409 playback_block (get_block ())
3410 ->add_conditional (playback_location (r
),
3411 m_boolval
->playback_rvalue (),
3412 playback_block (m_on_true
),
3413 playback_block (m_on_false
));
3416 /* Override the poisoned default implementation of
3417 gcc::jit::recording::statement::get_successor_blocks
3419 A conditional jump has 2 successor blocks. */
3422 recording::conditional::get_successor_blocks (block
**out_next1
,
3423 block
**out_next2
) const
3425 *out_next1
= m_on_true
;
3426 *out_next2
= m_on_false
;
3430 /* Implementation of recording::memento::make_debug_string for
3431 a conditional jump statement. */
3434 recording::conditional::make_debug_string ()
3437 return string::from_printf (m_ctxt
,
3438 "if (%s) goto %s; else goto %s;",
3439 m_boolval
->get_debug_string (),
3440 m_on_true
->get_debug_string (),
3441 m_on_false
->get_debug_string ());
3443 return string::from_printf (m_ctxt
,
3445 m_boolval
->get_debug_string (),
3446 m_on_true
->get_debug_string ());
3449 /* The implementation of class gcc::jit::recording::jump. */
3451 /* Implementation of pure virtual hook recording::memento::replay_into
3452 for recording::jump. */
3455 recording::jump::replay_into (replayer
*r
)
3457 playback_block (get_block ())
3458 ->add_jump (playback_location (r
),
3459 m_target
->playback_block ());
3462 /* Override the poisoned default implementation of
3463 gcc::jit::recording::statement::get_successor_blocks
3465 An unconditional jump has 1 successor block. */
3468 recording::jump::get_successor_blocks (block
**out_next1
,
3469 block
**/
*out_next2*/
) const
3471 *out_next1
= m_target
;
3475 /* Implementation of recording::memento::make_debug_string for
3476 a unconditional jump statement. */
3479 recording::jump::make_debug_string ()
3481 return string::from_printf (m_ctxt
,
3483 m_target
->get_debug_string ());
3486 /* The implementation of class gcc::jit::recording::return_. */
3488 /* Implementation of pure virtual hook recording::memento::replay_into
3489 for recording::return_. */
3492 recording::return_::replay_into (replayer
*r
)
3494 playback_block (get_block ())
3495 ->add_return (playback_location (r
),
3496 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
3499 /* Override the poisoned default implementation of
3500 gcc::jit::recording::statement::get_successor_blocks
3502 A return statement has no successor block. */
3505 recording::return_::get_successor_blocks (block
**/
*out_next1*/
,
3506 block
**/
*out_next2*/
) const
3511 /* Implementation of recording::memento::make_debug_string for
3512 a return statement (covers both those with and without rvalues). */
3515 recording::return_::make_debug_string ()
3518 return string::from_printf (m_ctxt
,
3520 m_rvalue
->get_debug_string ());
3522 return string::from_printf (m_ctxt
,
3526 } // namespace gcc::jit