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"
25 #include "pretty-print.h"
29 #include "jit-common.h"
30 #include "jit-builtins.h"
31 #include "jit-logging.h"
32 #include "jit-recording.h"
33 #include "jit-playback.h"
40 dump::dump (recording::context
&ctxt
,
42 bool update_locations
)
44 m_filename (filename
),
45 m_update_locations (update_locations
),
49 m_file
= fopen (filename
, "w");
52 "error opening dump file %s for writing: %s",
61 int err
= fclose (m_file
);
63 m_ctxt
.add_error (NULL
,
64 "error closing dump file %s: %s",
70 /* Write the given message to the dump, using printf-formatting
71 conventions, updating the line/column within the dump.
73 Emit an error on the context if a failure occurs. */
76 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 vasprintf (&buf
, fmt
, ap
);
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 /* Update line/column: */
102 for (const char *ptr
= buf
; *ptr
; ptr
++)
116 /* Construct a gcc::jit::recording::location instance for the current
117 location within the dump. */
119 recording::location
*
120 dump::make_location () const
122 return m_ctxt
.new_location (m_filename
, m_line
, m_column
);
125 /**********************************************************************
127 **********************************************************************/
129 /* Get the playback::location for the given recording::location,
130 handling a NULL input with a NULL output. */
133 recording::playback_location (replayer
*r
, recording::location
*loc
)
136 return loc
->playback_location (r
);
141 /* Get a const char * for the given recording::string
142 handling a NULL input with a NULL output. */
145 recording::playback_string (recording::string
*str
)
148 return str
->c_str ();
153 /* Get the playback::block for the given recording::block,
154 handling a NULL input with a NULL output. */
157 recording::playback_block (recording::block
*b
)
160 return b
->playback_block ();
165 /* Methods of cc::jit::recording::context. */
167 /* The constructor for gcc::jit::recording::context, used by
168 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
170 recording::context::context (context
*parent_ctxt
)
172 m_parent_ctxt (parent_ctxt
),
174 m_first_error_str (NULL
),
175 m_owns_first_error_str (false),
176 m_last_error_str (NULL
),
177 m_owns_last_error_str (false),
183 m_builtins_manager(NULL
)
187 /* Inherit options from parent. */
189 i
< sizeof (m_str_options
) / sizeof (m_str_options
[0]);
192 const char *parent_opt
= parent_ctxt
->m_str_options
[i
];
193 m_str_options
[i
] = parent_opt
? xstrdup (parent_opt
) : NULL
;
195 memcpy (m_int_options
,
196 parent_ctxt
->m_int_options
,
197 sizeof (m_int_options
));
198 memcpy (m_bool_options
,
199 parent_ctxt
->m_bool_options
,
200 sizeof (m_bool_options
));
201 set_logger (parent_ctxt
->get_logger ());
205 memset (m_str_options
, 0, sizeof (m_str_options
));
206 memset (m_int_options
, 0, sizeof (m_int_options
));
207 memset (m_bool_options
, 0, sizeof (m_bool_options
));
210 memset (m_basic_types
, 0, sizeof (m_basic_types
));
213 /* The destructor for gcc::jit::recording::context, implicitly used by
214 gcc_jit_context_release. */
216 recording::context::~context ()
218 JIT_LOG_SCOPE (get_logger ());
221 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
226 for (i
= 0; i
< GCC_JIT_NUM_STR_OPTIONS
; ++i
)
227 free (m_str_options
[i
]);
229 if (m_builtins_manager
)
230 delete m_builtins_manager
;
232 if (m_owns_first_error_str
)
233 free (m_first_error_str
);
235 if (m_owns_last_error_str
)
236 if (m_last_error_str
!= m_first_error_str
)
237 free (m_last_error_str
);
240 /* Add the given mememto to the list of those tracked by this
241 gcc::jit::recording::context, so that e.g. it can be deleted
242 when this context is released. */
245 recording::context::record (memento
*m
)
249 m_mementos
.safe_push (m
);
252 /* Replay this context (and any parents) into the given replayer. */
255 recording::context::replay_into (replayer
*r
)
257 JIT_LOG_SCOPE (get_logger ());
261 /* If we have a parent context, we must replay it. This will
262 recursively walk backwards up the historical tree, then replay things
263 forwards "in historical order", starting with the ultimate parent
264 context, until we reach the "this" context.
266 Note that we fully replay the parent, then fully replay the child,
267 which means that inter-context references can only exist from child
268 to parent, not the other way around.
270 All of this replaying is suboptimal - it would be better to do the
271 work for the parent context *once*, rather than replaying the parent
272 every time we replay each child. However, fixing this requires deep
273 surgery to lifetime-management: we'd need every context family tree
274 to have its own GC heap, and to initialize the GCC code to use that
275 heap (with a mutex on such a heap). */
277 m_parent_ctxt
->replay_into (r
);
279 if (r
->errors_occurred ())
282 /* Replay this context's saved operations into r. */
283 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
285 /* Disabled low-level debugging, here if we need it: print what
287 Note that the calls to get_debug_string might lead to more
288 mementos being created for the strings.
289 This can also be used to exercise the debug_string
292 printf ("context %p replaying (%p): %s\n",
293 (void *)this, (void *)m
, m
->get_debug_string ());
297 if (r
->errors_occurred ())
302 /* During a playback, we associate objects from the recording with
303 their counterparts during this playback.
305 For simplicity, we store this within the recording objects.
307 The following method cleans away these associations, to ensure that
308 we never have out-of-date associations lingering on subsequent
309 playbacks (the objects pointed to are GC-managed, but the
310 recording objects don't own refs to them). */
313 recording::context::disassociate_from_playback ()
315 JIT_LOG_SCOPE (get_logger ());
320 m_parent_ctxt
->disassociate_from_playback ();
322 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
324 m
->set_playback_obj (NULL
);
328 /* Create a recording::string instance and add it to this context's list
331 This creates a fresh copy of the given 0-terminated buffer. */
334 recording::context::new_string (const char *text
)
339 recording::string
*result
= new string (this, text
);
344 /* Create a recording::location instance and add it to this context's
347 Implements the post-error-checking part of
348 gcc_jit_context_new_location. */
350 recording::location
*
351 recording::context::new_location (const char *filename
,
355 recording::location
*result
=
356 new recording::location (this,
357 new_string (filename
),
363 /* If we haven't seen this enum value yet, create a recording::type
364 instance and add it to this context's list of mementos.
366 If we have seen it before, reuse our cached value, so that repeated
367 calls on the context give the same object.
369 If we have a parent context, the cache is within the ultimate
372 Implements the post-error-checking part of
373 gcc_jit_context_get_type. */
376 recording::context::get_type (enum gcc_jit_types kind
)
378 if (!m_basic_types
[kind
])
381 m_basic_types
[kind
] = m_parent_ctxt
->get_type (kind
);
384 recording::type
*result
= new memento_of_get_type (this, kind
);
386 m_basic_types
[kind
] = result
;
390 return m_basic_types
[kind
];
393 /* Get a recording::type instance for the given size and signedness.
394 This is implemented in terms of recording::context::get_type
397 Implements the post-error-checking part of
398 gcc_jit_context_get_int_type. */
401 recording::context::get_int_type (int num_bytes
, int is_signed
)
403 /* We can't use a switch here since some of the values are macros affected
404 by options; e.g. i386.h has
405 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
406 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
407 are in bits, rather than bytes.
409 const int num_bits
= num_bytes
* 8;
410 if (num_bits
== INT_TYPE_SIZE
)
411 return get_type (is_signed
413 : GCC_JIT_TYPE_UNSIGNED_INT
);
414 if (num_bits
== CHAR_TYPE_SIZE
)
415 return get_type (is_signed
416 ? GCC_JIT_TYPE_SIGNED_CHAR
417 : GCC_JIT_TYPE_UNSIGNED_CHAR
);
418 if (num_bits
== SHORT_TYPE_SIZE
)
419 return get_type (is_signed
421 : GCC_JIT_TYPE_UNSIGNED_SHORT
);
422 if (num_bits
== LONG_TYPE_SIZE
)
423 return get_type (is_signed
425 : GCC_JIT_TYPE_UNSIGNED_LONG
);
426 if (num_bits
== LONG_LONG_TYPE_SIZE
)
427 return get_type (is_signed
428 ? GCC_JIT_TYPE_LONG_LONG
429 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
431 /* Some other size, not corresponding to the C int types. */
432 /* To be written: support arbitrary other sizes, sharing by
433 memoizing at the recording::context level? */
437 /* Create a recording::type instance and add it to this context's list
440 Implements the post-error-checking part of
441 gcc_jit_context_new_array_type. */
444 recording::context::new_array_type (recording::location
*loc
,
445 recording::type
*element_type
,
448 if (struct_
*s
= element_type
->dyn_cast_struct ())
449 if (!s
->get_fields ())
452 "cannot create an array of type %s"
453 " until the fields have been set",
454 s
->get_name ()->c_str ());
457 recording::type
*result
=
458 new recording::array_type (this, loc
, element_type
, num_elements
);
463 /* Create a recording::field instance and add it to this context's list
466 Implements the post-error-checking part of
467 gcc_jit_context_new_field. */
470 recording::context::new_field (recording::location
*loc
,
471 recording::type
*type
,
474 recording::field
*result
=
475 new recording::field (this, loc
, type
, new_string (name
));
480 /* Create a recording::struct_ instance and add it to this context's
481 list of mementos and list of compound types.
483 Implements the post-error-checking part of
484 gcc_jit_context_new_struct_type. */
487 recording::context::new_struct_type (recording::location
*loc
,
490 recording::struct_
*result
= new struct_ (this, loc
, new_string (name
));
492 m_compound_types
.safe_push (result
);
496 /* Create a recording::union_ instance and add it to this context's
497 list of mementos and list of compound types.
499 Implements the first post-error-checking part of
500 gcc_jit_context_new_union_type. */
503 recording::context::new_union_type (recording::location
*loc
,
506 recording::union_
*result
= new union_ (this, loc
, new_string (name
));
508 m_compound_types
.safe_push (result
);
512 /* Create a recording::function_type instance and add it to this context's
515 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
517 recording::function_type
*
518 recording::context::new_function_type (recording::type
*return_type
,
520 recording::type
**param_types
,
523 recording::function_type
*fn_type
524 = new function_type (this,
533 /* Create a recording::type instance and add it to this context's list
536 Implements the post-error-checking part of
537 gcc_jit_context_new_function_ptr_type. */
540 recording::context::new_function_ptr_type (recording::location
*, /* unused loc */
541 recording::type
*return_type
,
543 recording::type
**param_types
,
546 recording::function_type
*fn_type
547 = new_function_type (return_type
,
552 /* Return a pointer-type to the the function type. */
553 return fn_type
->get_pointer ();
556 /* Create a recording::param instance and add it to this context's list
559 Implements the post-error-checking part of
560 gcc_jit_context_new_param. */
563 recording::context::new_param (recording::location
*loc
,
564 recording::type
*type
,
567 recording::param
*result
= new recording::param (this, loc
, type
, new_string (name
));
572 /* Create a recording::function instance and add it to this context's list
573 of mementos and list of functions.
575 Implements the post-error-checking part of
576 gcc_jit_context_new_function. */
578 recording::function
*
579 recording::context::new_function (recording::location
*loc
,
580 enum gcc_jit_function_kind kind
,
581 recording::type
*return_type
,
584 recording::param
**params
,
586 enum built_in_function builtin_id
)
588 recording::function
*result
=
589 new recording::function (this,
590 loc
, kind
, return_type
,
592 num_params
, params
, is_variadic
,
595 m_functions
.safe_push (result
);
600 /* Locate the builtins_manager (if any) for this family of contexts,
601 creating it if it doesn't exist already.
603 All of the recording contexts in a family share one builtins_manager:
604 if we have a child context, follow the parent links to get the
605 ultimate ancestor context, and look for it/store it there. */
608 recording::context::get_builtins_manager ()
611 return m_parent_ctxt
->get_builtins_manager ();
613 if (!m_builtins_manager
)
614 m_builtins_manager
= new builtins_manager (this);
616 return m_builtins_manager
;
619 /* Get a recording::function instance, which is lazily-created and added
620 to the context's lists of mementos.
622 Implements the post-error-checking part of
623 gcc_jit_context_get_builtin_function. */
625 recording::function
*
626 recording::context::get_builtin_function (const char *name
)
628 builtins_manager
*bm
= get_builtins_manager ();
629 return bm
->get_builtin_function (name
);
632 /* Create a recording::global instance and add it to this context's list
635 Implements the post-error-checking part of
636 gcc_jit_context_new_global. */
639 recording::context::new_global (recording::location
*loc
,
640 enum gcc_jit_global_kind kind
,
641 recording::type
*type
,
644 recording::global
*result
=
645 new recording::global (this, loc
, kind
, type
, new_string (name
));
647 m_globals
.safe_push (result
);
652 /* Create a recording::memento_of_new_string_literal instance and add it
653 to this context's list of mementos.
655 Implements the post-error-checking part of
656 gcc_jit_context_new_string_literal. */
659 recording::context::new_string_literal (const char *value
)
661 recording::rvalue
*result
=
662 new memento_of_new_string_literal (this, NULL
, new_string (value
));
667 /* Create a recording::unary_op instance and add it to this context's
670 Implements the post-error-checking part of
671 gcc_jit_context_new_unary_op. */
674 recording::context::new_unary_op (recording::location
*loc
,
675 enum gcc_jit_unary_op op
,
676 recording::type
*result_type
,
677 recording::rvalue
*a
)
679 recording::rvalue
*result
=
680 new unary_op (this, loc
, op
, result_type
, a
);
685 /* Create a recording::binary_op instance and add it to this context's
688 Implements the post-error-checking part of
689 gcc_jit_context_new_binary_op. */
692 recording::context::new_binary_op (recording::location
*loc
,
693 enum gcc_jit_binary_op op
,
694 recording::type
*result_type
,
695 recording::rvalue
*a
,
696 recording::rvalue
*b
)
698 recording::rvalue
*result
=
699 new binary_op (this, loc
, op
, result_type
, a
, b
);
704 /* Create a recording::comparison instance and add it to this context's
707 Implements the post-error-checking part of
708 gcc_jit_context_new_comparison. */
711 recording::context::new_comparison (recording::location
*loc
,
712 enum gcc_jit_comparison op
,
713 recording::rvalue
*a
,
714 recording::rvalue
*b
)
716 recording::rvalue
*result
= new comparison (this, loc
, op
, a
, b
);
721 /* Create a recording::cast instance and add it to this context's list
724 Implements the post-error-checking part of
725 gcc_jit_context_new_cast. */
728 recording::context::new_cast (recording::location
*loc
,
729 recording::rvalue
*expr
,
730 recording::type
*type_
)
732 recording::rvalue
*result
= new cast (this, loc
, expr
, type_
);
737 /* Create a recording::call instance and add it to this context's list
740 Implements the post-error-checking part of
741 gcc_jit_context_new_call. */
744 recording::context::new_call (recording::location
*loc
,
746 int numargs
, recording::rvalue
**args
)
748 recording::rvalue
*result
= new call (this, loc
, func
, numargs
, args
);
753 /* Create a recording::call_through_ptr instance and add it to this
754 context's list of mementos.
756 Implements the post-error-checking part of
757 gcc_jit_context_new_call_through_ptr. */
760 recording::context::new_call_through_ptr (recording::location
*loc
,
761 recording::rvalue
*fn_ptr
,
763 recording::rvalue
**args
)
765 recording::rvalue
*result
= new call_through_ptr (this, loc
, fn_ptr
, numargs
, args
);
770 /* Create a recording::array_access instance and add it to this context's list
773 Implements the post-error-checking part of
774 gcc_jit_context_new_array_access. */
777 recording::context::new_array_access (recording::location
*loc
,
778 recording::rvalue
*ptr
,
779 recording::rvalue
*index
)
781 recording::lvalue
*result
= new array_access (this, loc
, ptr
, index
);
786 /* Set the given string option for this context, or add an error if
789 Implements the post-error-checking part of
790 gcc_jit_context_set_str_option. */
793 recording::context::set_str_option (enum gcc_jit_str_option opt
,
796 if (opt
< 0 || opt
>= GCC_JIT_NUM_STR_OPTIONS
)
799 "unrecognized (enum gcc_jit_str_option) value: %i", opt
);
802 free (m_str_options
[opt
]);
803 m_str_options
[opt
] = value
? xstrdup (value
) : NULL
;
806 /* Set the given integer option for this context, or add an error if
809 Implements the post-error-checking part of
810 gcc_jit_context_set_int_option. */
813 recording::context::set_int_option (enum gcc_jit_int_option opt
,
816 if (opt
< 0 || opt
>= GCC_JIT_NUM_INT_OPTIONS
)
819 "unrecognized (enum gcc_jit_int_option) value: %i", opt
);
822 m_int_options
[opt
] = value
;
825 /* Set the given boolean option for this context, or add an error if
828 Implements the post-error-checking part of
829 gcc_jit_context_set_bool_option. */
832 recording::context::set_bool_option (enum gcc_jit_bool_option opt
,
835 if (opt
< 0 || opt
>= GCC_JIT_NUM_BOOL_OPTIONS
)
838 "unrecognized (enum gcc_jit_bool_option) value: %i", opt
);
841 m_bool_options
[opt
] = value
? true : false;
844 /* Add the given dumpname/out_ptr pair to this context's list of requested
847 Implements the post-error-checking part of
848 gcc_jit_context_enable_dump. */
851 recording::context::enable_dump (const char *dumpname
,
855 gcc_assert (dumpname
);
856 gcc_assert (out_ptr
);
858 d
.m_dumpname
= dumpname
;
859 d
.m_out_ptr
= out_ptr
;
861 m_requested_dumps
.safe_push (d
);
864 /* Validate this context, and if it passes, compile it within a
867 Implements the post-error-checking part of
868 gcc_jit_context_compile. */
871 recording::context::compile ()
873 JIT_LOG_SCOPE (get_logger ());
877 if (errors_occurred ())
880 /* Set up a playback context. */
881 ::gcc::jit::playback::context
replayer (this);
884 result
*result_obj
= replayer
.compile ();
889 /* Format the given error using printf's conventions, print
890 it to stderr, and add it to the context. */
893 recording::context::add_error (location
*loc
, const char *fmt
, ...)
897 add_error_va (loc
, fmt
, ap
);
901 /* Format the given error using printf's conventions, print
902 it to stderr, and add it to the context. */
905 recording::context::add_error_va (location
*loc
, const char *fmt
, va_list ap
)
911 JIT_LOG_SCOPE (get_logger ());
913 vasprintf (&malloced_msg
, fmt
, ap
);
916 errmsg
= malloced_msg
;
917 has_ownership
= true;
921 errmsg
= "out of memory generating error message";
922 has_ownership
= false;
925 get_logger ()->log ("error %i: %s", m_error_count
, errmsg
);
927 const char *ctxt_progname
=
928 get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
930 ctxt_progname
= "libgccjit.so";
933 fprintf (stderr
, "%s: %s: error: %s\n",
935 loc
->get_debug_string (),
938 fprintf (stderr
, "%s: error: %s\n",
944 m_first_error_str
= const_cast <char *> (errmsg
);
945 m_owns_first_error_str
= has_ownership
;
948 if (m_owns_last_error_str
)
949 if (m_last_error_str
!= m_first_error_str
)
950 free (m_last_error_str
);
951 m_last_error_str
= const_cast <char *> (errmsg
);
952 m_owns_last_error_str
= has_ownership
;
957 /* Get the message for the first error that occurred on this context, or
958 NULL if no errors have occurred on it.
960 Implements the post-error-checking part of
961 gcc_jit_context_get_first_error. */
964 recording::context::get_first_error () const
966 return m_first_error_str
;
969 /* Get the message for the last error that occurred on this context, or
970 NULL if no errors have occurred on it.
972 Implements the post-error-checking part of
973 gcc_jit_context_get_last_error. */
976 recording::context::get_last_error () const
978 return m_last_error_str
;
981 /* Lazily generate and record a recording::type representing an opaque
984 For use if client code tries to dereference the result of
985 get_type (GCC_JIT_TYPE_FILE_PTR). */
988 recording::context::get_opaque_FILE_type ()
991 m_FILE_type
= new_struct_type (NULL
, "FILE");
995 /* Dump a C-like representation of the given context to the given path.
996 If UPDATE_LOCATIONS is true, update the locations within the
997 context's mementos to point to the dumpfile.
999 Implements the post-error-checking part of
1000 gcc_jit_context_dump_to_file. */
1003 recording::context::dump_to_file (const char *path
, bool update_locations
)
1006 dump
d (*this, path
, update_locations
);
1008 /* Forward declaration of structs and unions. */
1010 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1012 d
.write ("%s;\n\n", st
->get_debug_string ());
1015 /* Content of structs, where set. */
1016 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1017 if (st
->get_fields ())
1019 st
->get_fields ()->write_to_dump (d
);
1025 FOR_EACH_VEC_ELT (m_globals
, i
, g
)
1027 g
->write_to_dump (d
);
1029 if (!m_globals
.is_empty ())
1033 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1035 fn
->write_to_dump (d
);
1039 /* Copy the requested dumps within this context and all ancestors into
1043 recording::context::get_all_requested_dumps (vec
<recording::requested_dump
> *out
)
1046 m_parent_ctxt
->get_all_requested_dumps (out
);
1048 out
->reserve (m_requested_dumps
.length ());
1049 out
->splice (m_requested_dumps
);
1052 /* This is a pre-compilation check for the context (and any parents).
1054 Detect errors within the context, adding errors if any are found. */
1057 recording::context::validate ()
1059 JIT_LOG_SCOPE (get_logger ());
1062 m_parent_ctxt
->validate ();
1066 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1070 /* The implementation of class gcc::jit::recording::memento. */
1072 /* Get a (const char *) debug description of the given memento, by
1073 calling the pure-virtual make_debug_string hook, caching the
1076 It is intended that this should only be called in debugging and
1077 error-handling paths, so this doesn't need to be particularly
1081 recording::memento::get_debug_string ()
1083 if (!m_debug_string
)
1084 m_debug_string
= make_debug_string ();
1085 return m_debug_string
->c_str ();
1088 /* Default implementation of recording::memento::write_to_dump, writing
1089 an indented form of the memento's debug string to the dump. */
1092 recording::memento::write_to_dump (dump
&d
)
1094 d
.write(" %s\n", get_debug_string ());
1097 /* The implementation of class gcc::jit::recording::string. */
1099 /* Constructor for gcc::jit::recording::string::string, allocating a
1100 copy of the given text using new char[]. */
1102 recording::string::string (context
*ctxt
, const char *text
)
1105 m_len
= strlen (text
);
1106 m_buffer
= new char[m_len
+ 1];
1107 strcpy (m_buffer
, text
);
1110 /* Destructor for gcc::jit::recording::string::string. */
1112 recording::string::~string ()
1117 /* Function for making gcc::jit::recording::string instances on a
1118 context via printf-style formatting.
1120 It is intended that this should only be called in debugging and
1121 error-handling paths, so this doesn't need to be particularly
1122 optimized, hence the double-copy of the string is acceptable. */
1125 recording::string::from_printf (context
*ctxt
, const char *fmt
, ...)
1129 recording::string
*result
;
1132 vasprintf (&buf
, fmt
, ap
);
1137 ctxt
->add_error (NULL
, "malloc failure");
1141 result
= ctxt
->new_string (buf
);
1146 /* Implementation of recording::memento::make_debug_string for strings,
1147 wrapping the given string in quotes and escaping as necessary. */
1150 recording::string::make_debug_string ()
1152 /* Hack to avoid infinite recursion into strings when logging all
1153 mementos: don't re-escape strings: */
1154 if (m_buffer
[0] == '"')
1157 /* Wrap in quotes and do escaping etc */
1159 size_t sz
= (1 /* opening quote */
1160 + (m_len
* 2) /* each char might get escaped */
1161 + 1 /* closing quote */
1162 + 1); /* nil termintator */
1163 char *tmp
= new char[sz
];
1166 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1167 APPEND('"'); /* opening quote */
1168 for (size_t i
= 0; i
< m_len
; i
++)
1170 char ch
= m_buffer
[i
];
1171 if (ch
== '\t' || ch
== '\n' || ch
== '\\' || ch
== '"')
1175 APPEND('"'); /* closing quote */
1177 tmp
[len
] = '\0'; /* nil termintator */
1179 string
*result
= m_ctxt
->new_string (tmp
);
1185 /* The implementation of class gcc::jit::recording::location. */
1187 /* Implementation of recording::memento::replay_into for locations.
1189 Create a new playback::location and store it into the
1190 recording::location's m_playback_obj field. */
1193 recording::location::replay_into (replayer
*r
)
1195 m_playback_obj
= r
->new_location (this,
1196 m_filename
->c_str (),
1201 /* Implementation of recording::memento::make_debug_string for locations,
1202 turning them into the usual form:
1203 FILENAME:LINE:COLUMN
1204 like we do when emitting diagnostics. */
1207 recording::location::make_debug_string ()
1209 return string::from_printf (m_ctxt
,
1211 m_filename
->c_str (), m_line
, m_column
);
1214 /* The implementation of class gcc::jit::recording::type. */
1216 /* Given a type T, get the type T*.
1218 If this doesn't already exist, generate a new memento_of_get_pointer
1219 instance and add it to this type's context's list of mementos.
1221 Otherwise, use the cached type.
1223 Implements the post-error-checking part of
1224 gcc_jit_type_get_pointer. */
1227 recording::type::get_pointer ()
1229 if (!m_pointer_to_this_type
)
1231 m_pointer_to_this_type
= new memento_of_get_pointer (this);
1232 m_ctxt
->record (m_pointer_to_this_type
);
1234 return m_pointer_to_this_type
;
1237 /* Given a type T, get the type const T.
1239 Implements the post-error-checking part of
1240 gcc_jit_type_get_const. */
1243 recording::type::get_const ()
1245 recording::type
*result
= new memento_of_get_const (this);
1246 m_ctxt
->record (result
);
1250 /* Given a type T, get the type volatile T.
1252 Implements the post-error-checking part of
1253 gcc_jit_type_get_volatile. */
1256 recording::type::get_volatile ()
1258 recording::type
*result
= new memento_of_get_volatile (this);
1259 m_ctxt
->record (result
);
1263 /* Implementation of pure virtual hook recording::type::dereference for
1264 recording::memento_of_get_type. */
1267 recording::memento_of_get_type::dereference ()
1271 default: gcc_unreachable ();
1273 case GCC_JIT_TYPE_VOID
:
1276 case GCC_JIT_TYPE_VOID_PTR
:
1277 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
1279 case GCC_JIT_TYPE_BOOL
:
1280 case GCC_JIT_TYPE_CHAR
:
1281 case GCC_JIT_TYPE_SIGNED_CHAR
:
1282 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1283 case GCC_JIT_TYPE_SHORT
:
1284 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1285 case GCC_JIT_TYPE_INT
:
1286 case GCC_JIT_TYPE_UNSIGNED_INT
:
1287 case GCC_JIT_TYPE_LONG
:
1288 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1289 case GCC_JIT_TYPE_LONG_LONG
:
1290 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1291 case GCC_JIT_TYPE_FLOAT
:
1292 case GCC_JIT_TYPE_DOUBLE
:
1293 case GCC_JIT_TYPE_LONG_DOUBLE
:
1294 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1295 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1296 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1297 /* Not a pointer: */
1300 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1301 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
1303 case GCC_JIT_TYPE_SIZE_T
:
1304 /* Not a pointer: */
1307 case GCC_JIT_TYPE_FILE_PTR
:
1308 /* Give the client code back an opaque "struct FILE". */
1309 return m_ctxt
->get_opaque_FILE_type ();
1313 /* Implementation of pure virtual hook recording::type::is_int for
1314 recording::memento_of_get_type. */
1317 recording::memento_of_get_type::is_int () const
1321 default: gcc_unreachable ();
1323 case GCC_JIT_TYPE_VOID
:
1326 case GCC_JIT_TYPE_VOID_PTR
:
1329 case GCC_JIT_TYPE_BOOL
:
1332 case GCC_JIT_TYPE_CHAR
:
1333 case GCC_JIT_TYPE_SIGNED_CHAR
:
1334 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1335 case GCC_JIT_TYPE_SHORT
:
1336 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1337 case GCC_JIT_TYPE_INT
:
1338 case GCC_JIT_TYPE_UNSIGNED_INT
:
1339 case GCC_JIT_TYPE_LONG
:
1340 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1341 case GCC_JIT_TYPE_LONG_LONG
:
1342 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1345 case GCC_JIT_TYPE_FLOAT
:
1346 case GCC_JIT_TYPE_DOUBLE
:
1347 case GCC_JIT_TYPE_LONG_DOUBLE
:
1350 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1353 case GCC_JIT_TYPE_SIZE_T
:
1356 case GCC_JIT_TYPE_FILE_PTR
:
1359 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1360 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1361 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1366 /* Implementation of pure virtual hook recording::type::is_float for
1367 recording::memento_of_get_type. */
1370 recording::memento_of_get_type::is_float () const
1374 default: gcc_unreachable ();
1376 case GCC_JIT_TYPE_VOID
:
1379 case GCC_JIT_TYPE_VOID_PTR
:
1382 case GCC_JIT_TYPE_BOOL
:
1385 case GCC_JIT_TYPE_CHAR
:
1386 case GCC_JIT_TYPE_SIGNED_CHAR
:
1387 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1388 case GCC_JIT_TYPE_SHORT
:
1389 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1390 case GCC_JIT_TYPE_INT
:
1391 case GCC_JIT_TYPE_UNSIGNED_INT
:
1392 case GCC_JIT_TYPE_LONG
:
1393 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1394 case GCC_JIT_TYPE_LONG_LONG
:
1395 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1398 case GCC_JIT_TYPE_FLOAT
:
1399 case GCC_JIT_TYPE_DOUBLE
:
1400 case GCC_JIT_TYPE_LONG_DOUBLE
:
1403 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1406 case GCC_JIT_TYPE_SIZE_T
:
1409 case GCC_JIT_TYPE_FILE_PTR
:
1412 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1413 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1414 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1419 /* Implementation of pure virtual hook recording::type::is_bool for
1420 recording::memento_of_get_type. */
1423 recording::memento_of_get_type::is_bool () const
1427 default: gcc_unreachable ();
1429 case GCC_JIT_TYPE_VOID
:
1432 case GCC_JIT_TYPE_VOID_PTR
:
1435 case GCC_JIT_TYPE_BOOL
:
1438 case GCC_JIT_TYPE_CHAR
:
1439 case GCC_JIT_TYPE_SIGNED_CHAR
:
1440 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1441 case GCC_JIT_TYPE_SHORT
:
1442 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1443 case GCC_JIT_TYPE_INT
:
1444 case GCC_JIT_TYPE_UNSIGNED_INT
:
1445 case GCC_JIT_TYPE_LONG
:
1446 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1447 case GCC_JIT_TYPE_LONG_LONG
:
1448 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1451 case GCC_JIT_TYPE_FLOAT
:
1452 case GCC_JIT_TYPE_DOUBLE
:
1453 case GCC_JIT_TYPE_LONG_DOUBLE
:
1456 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1459 case GCC_JIT_TYPE_SIZE_T
:
1462 case GCC_JIT_TYPE_FILE_PTR
:
1465 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1466 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1467 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1472 /* Implementation of pure virtual hook recording::memento::replay_into
1473 for recording::memento_of_get_type. */
1476 recording::memento_of_get_type::replay_into (replayer
*r
)
1478 set_playback_obj (r
->get_type (m_kind
));
1481 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
1483 /* Descriptive strings for each of enum gcc_jit_types. */
1485 static const char * const get_type_strings
[] = {
1486 "void", /* GCC_JIT_TYPE_VOID */
1487 "void *", /* GCC_JIT_TYPE_VOID_PTR */
1489 "bool", /* GCC_JIT_TYPE_BOOL */
1491 "char", /* GCC_JIT_TYPE_CHAR */
1492 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
1493 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
1495 "short", /* GCC_JIT_TYPE_SHORT */
1496 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
1498 "int", /* GCC_JIT_TYPE_INT */
1499 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
1501 "long", /* GCC_JIT_TYPE_LONG */
1502 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
1504 "long long", /* GCC_JIT_TYPE_LONG_LONG */
1505 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
1507 "float", /* GCC_JIT_TYPE_FLOAT */
1508 "double", /* GCC_JIT_TYPE_DOUBLE */
1509 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
1511 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
1513 "size_t", /* GCC_JIT_TYPE_SIZE_T */
1515 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
1517 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
1518 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
1519 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
1523 /* Implementation of recording::memento::make_debug_string for
1524 results of get_type, using a simple table of type names. */
1527 recording::memento_of_get_type::make_debug_string ()
1529 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
1532 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
1534 /* Override of default implementation of
1535 recording::type::accepts_writes_from for get_pointer.
1537 Require a pointer type, and allowing writes to
1538 (const T *) from a (T*), but not the other way around. */
1541 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
1543 /* Must be a pointer type: */
1544 type
*rtype_points_to
= rtype
->is_pointer ();
1545 if (!rtype_points_to
)
1548 /* It's OK to assign to a (const T *) from a (T *). */
1549 return m_other_type
->unqualified ()
1550 ->accepts_writes_from (rtype_points_to
);
1553 /* Implementation of pure virtual hook recording::memento::replay_into
1554 for recording::memento_of_get_pointer. */
1557 recording::memento_of_get_pointer::replay_into (replayer
*)
1559 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
1562 /* Implementation of recording::memento::make_debug_string for
1563 results of get_pointer, adding " *" to the underlying type,
1564 with special-casing to handle function pointer types. */
1567 recording::memento_of_get_pointer::make_debug_string ()
1569 /* Special-case function pointer types, to put the "*" in parens between
1570 the return type and the params (for one level of dereferencing, at
1572 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
1573 return fn_type
->make_debug_string_with_ptr ();
1575 return string::from_printf (m_ctxt
,
1576 "%s *", m_other_type
->get_debug_string ());
1579 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
1581 /* Implementation of pure virtual hook recording::memento::replay_into
1582 for recording::memento_of_get_const. */
1585 recording::memento_of_get_const::replay_into (replayer
*)
1587 set_playback_obj (m_other_type
->playback_type ()->get_const ());
1590 /* Implementation of recording::memento::make_debug_string for
1591 results of get_const, prepending "const ". */
1594 recording::memento_of_get_const::make_debug_string ()
1596 return string::from_printf (m_ctxt
,
1597 "const %s", m_other_type
->get_debug_string ());
1600 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
1602 /* Implementation of pure virtual hook recording::memento::replay_into
1603 for recording::memento_of_get_volatile. */
1606 recording::memento_of_get_volatile::replay_into (replayer
*)
1608 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
1611 /* Implementation of recording::memento::make_debug_string for
1612 results of get_volatile, prepending "volatile ". */
1615 recording::memento_of_get_volatile::make_debug_string ()
1617 return string::from_printf (m_ctxt
,
1618 "volatile %s", m_other_type
->get_debug_string ());
1621 /* The implementation of class gcc::jit::recording::array_type */
1623 /* Implementation of pure virtual hook recording::type::dereference for
1624 recording::array_type. */
1627 recording::array_type::dereference ()
1629 return m_element_type
;
1632 /* Implementation of pure virtual hook recording::memento::replay_into
1633 for recording::array_type. */
1636 recording::array_type::replay_into (replayer
*r
)
1638 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
1639 m_element_type
->playback_type (),
1643 /* Implementation of recording::memento::make_debug_string for
1644 results of new_array_type. */
1647 recording::array_type::make_debug_string ()
1649 return string::from_printf (m_ctxt
,
1651 m_element_type
->get_debug_string (),
1655 /* The implementation of class gcc::jit::recording::function_type */
1657 /* Constructor for gcc::jit::recording::function_type. */
1659 recording::function_type::function_type (context
*ctxt
,
1665 m_return_type (return_type
),
1667 m_is_variadic (is_variadic
)
1669 for (int i
= 0; i
< num_params
; i
++)
1670 m_param_types
.safe_push (param_types
[i
]);
1673 /* Implementation of pure virtual hook recording::type::dereference for
1674 recording::function_type. */
1677 recording::function_type::dereference ()
1682 /* Implementation of pure virtual hook recording::memento::replay_into
1683 for recording::function_type. */
1686 recording::function_type::replay_into (replayer
*r
)
1688 /* Convert m_param_types to a vec of playback type. */
1689 auto_vec
<playback::type
*> param_types
;
1691 recording::type
*type
;
1692 param_types
.create (m_param_types
.length ());
1693 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
1694 param_types
.safe_push (type
->playback_type ());
1696 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
1701 /* Special-casing for make_debug_string for get_pointer results for
1702 handling (one level) of pointers to functions. */
1705 recording::function_type::make_debug_string_with_ptr ()
1707 return make_debug_string_with ("(*) ");
1710 /* Implementation of recording::memento::make_debug_string for
1711 results of new_function_type. */
1714 recording::function_type::make_debug_string ()
1716 return make_debug_string_with ("");
1719 /* Build a debug string representation of the form:
1721 RESULT_TYPE INSERT (PARAM_TYPES)
1723 for use when handling 0 and 1 level of indirection to this
1727 recording::function_type::make_debug_string_with (const char *insert
)
1729 /* First, build a buffer for the arguments. */
1730 /* Calculate length of said buffer. */
1731 size_t sz
= 1; /* nil terminator */
1732 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
1734 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
1735 sz
+= 2; /* ", " separator */
1738 sz
+= 5; /* ", ..." separator and ellipsis */
1740 /* Now allocate and populate the buffer. */
1741 char *argbuf
= new char[sz
];
1744 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
1746 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
1747 len
+= strlen (m_param_types
[i
]->get_debug_string ());
1748 if (i
+ 1 < m_param_types
.length ())
1750 strcpy (argbuf
+ len
, ", ");
1756 if (m_param_types
.length ())
1758 strcpy (argbuf
+ len
, ", ");
1761 strcpy (argbuf
+ len
, "...");
1766 /* ...and use it to get the string for the call as a whole. */
1767 string
*result
= string::from_printf (m_ctxt
,
1769 m_return_type
->get_debug_string (),
1778 /* The implementation of class gcc::jit::recording::field. */
1780 /* Implementation of pure virtual hook recording::memento::replay_into
1781 for recording::field. */
1784 recording::field::replay_into (replayer
*r
)
1786 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
1787 m_type
->playback_type (),
1788 playback_string (m_name
)));
1791 /* Override the default implementation of
1792 recording::memento::write_to_dump. Dump each field
1793 by dumping a line of the form:
1795 so that we can build up a struct/union field-byfield. */
1798 recording::field::write_to_dump (dump
&d
)
1800 d
.write (" %s %s;\n",
1801 m_type
->get_debug_string (),
1805 /* Implementation of recording::memento::make_debug_string for
1806 results of new_field. */
1809 recording::field::make_debug_string ()
1814 /* The implementation of class gcc::jit::recording::compound_type */
1816 /* The constructor for gcc::jit::recording::compound_type. */
1818 recording::compound_type::compound_type (context
*ctxt
,
1828 /* Set the fields of a compound type.
1830 Implements the post-error-checking part of
1831 gcc_jit_struct_set_fields, and is also used by
1832 gcc_jit_context_new_union_type. */
1835 recording::compound_type::set_fields (location
*loc
,
1837 field
**field_array
)
1840 gcc_assert (NULL
== m_fields
);
1842 m_fields
= new fields (this, num_fields
, field_array
);
1843 m_ctxt
->record (m_fields
);
1846 /* Implementation of pure virtual hook recording::type::dereference for
1847 recording::compound_type. */
1850 recording::compound_type::dereference ()
1852 return NULL
; /* not a pointer */
1855 /* The implementation of class gcc::jit::recording::struct_. */
1857 /* The constructor for gcc::jit::recording::struct_. */
1859 recording::struct_::struct_ (context
*ctxt
,
1862 : compound_type (ctxt
, loc
, name
)
1866 /* Implementation of pure virtual hook recording::memento::replay_into
1867 for recording::struct_. */
1870 recording::struct_::replay_into (replayer
*r
)
1873 r
->new_compound_type (playback_location (r
, get_loc ()),
1874 get_name ()->c_str (),
1875 true /* is_struct */));
1878 /* Implementation of recording::memento::make_debug_string for
1882 recording::struct_::make_debug_string ()
1884 return string::from_printf (m_ctxt
,
1885 "struct %s", get_name ()->c_str ());
1888 /* The implementation of class gcc::jit::recording::union_. */
1890 /* The constructor for gcc::jit::recording::union_. */
1892 recording::union_::union_ (context
*ctxt
,
1895 : compound_type (ctxt
, loc
, name
)
1899 /* Implementation of pure virtual hook recording::memento::replay_into
1900 for recording::union_. */
1903 recording::union_::replay_into (replayer
*r
)
1906 r
->new_compound_type (playback_location (r
, get_loc ()),
1907 get_name ()->c_str (),
1908 false /* is_struct */));
1911 /* Implementation of recording::memento::make_debug_string for
1915 recording::union_::make_debug_string ()
1917 return string::from_printf (m_ctxt
,
1918 "union %s", get_name ()->c_str ());
1921 /* The implementation of class gcc::jit::recording::fields. */
1923 /* The constructor for gcc::jit::recording::fields. */
1925 recording::fields::fields (compound_type
*struct_or_union
,
1928 : memento (struct_or_union
->m_ctxt
),
1929 m_struct_or_union (struct_or_union
),
1932 for (int i
= 0; i
< num_fields
; i
++)
1934 gcc_assert (fields
[i
]->get_container () == NULL
);
1935 fields
[i
]->set_container (m_struct_or_union
);
1936 m_fields
.safe_push (fields
[i
]);
1940 /* Implementation of pure virtual hook recording::memento::replay_into
1941 for recording::fields. */
1944 recording::fields::replay_into (replayer
*)
1946 auto_vec
<playback::field
*> playback_fields
;
1947 playback_fields
.create (m_fields
.length ());
1948 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
1949 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
1950 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
1953 /* Override the default implementation of
1954 recording::memento::write_to_dump by writing a union/struct
1955 declaration of this form:
1967 recording::fields::write_to_dump (dump
&d
)
1972 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
1973 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
1974 f
->write_to_dump (d
);
1978 /* Implementation of recording::memento::make_debug_string for
1982 recording::fields::make_debug_string ()
1984 return string::from_printf (m_ctxt
,
1988 /* The implementation of class gcc::jit::recording::rvalue. */
1990 /* Create a recording::access_field_rvalue instance and add it to
1991 the rvalue's context's list of mementos.
1993 Implements the post-error-checking part of
1994 gcc_jit_rvalue_access_field. */
1997 recording::rvalue::access_field (recording::location
*loc
,
2000 recording::rvalue
*result
=
2001 new access_field_rvalue (m_ctxt
, loc
, this, field
);
2002 m_ctxt
->record (result
);
2006 /* Create a recording::dereference_field_rvalue instance and add it to
2007 the rvalue's context's list of mementos.
2009 Implements the post-error-checking part of
2010 gcc_jit_rvalue_dereference_field. */
2013 recording::rvalue::dereference_field (recording::location
*loc
,
2016 recording::lvalue
*result
=
2017 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
2018 m_ctxt
->record (result
);
2022 /* Create a recording::dereference_rvalue instance and add it to the
2023 rvalue's context's list of mementos.
2025 Implements the post-error-checking part of
2026 gcc_jit_rvalue_dereference. */
2029 recording::rvalue::dereference (recording::location
*loc
)
2031 recording::lvalue
*result
=
2032 new dereference_rvalue (m_ctxt
, loc
, this);
2033 m_ctxt
->record (result
);
2037 /* The implementation of class gcc::jit::recording::lvalue. */
2039 /* Create a recording::new_access_field_of_lvalue instance and add it to
2040 the lvalue's context's list of mementos.
2042 Implements the post-error-checking part of
2043 gcc_jit_lvalue_access_field. */
2046 recording::lvalue::access_field (recording::location
*loc
,
2049 recording::lvalue
*result
=
2050 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
2051 m_ctxt
->record (result
);
2055 /* Create a recording::get_address_of_lvalue instance and add it to
2056 the lvalue's context's list of mementos.
2058 Implements the post-error-checking part of
2059 gcc_jit_lvalue_get_address. */
2062 recording::lvalue::get_address (recording::location
*loc
)
2064 recording::rvalue
*result
=
2065 new get_address_of_lvalue (m_ctxt
, loc
, this);
2066 m_ctxt
->record (result
);
2070 /* The implementation of class gcc::jit::recording::param. */
2072 /* Implementation of pure virtual hook recording::memento::replay_into
2073 for recording::param. */
2076 recording::param::replay_into (replayer
*r
)
2078 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
2079 m_type
->playback_type (),
2084 /* The implementation of class gcc::jit::recording::function. */
2086 /* gcc::jit::recording::function's constructor. */
2088 recording::function::function (context
*ctxt
,
2089 recording::location
*loc
,
2090 enum gcc_jit_function_kind kind
,
2092 recording::string
*name
,
2094 recording::param
**params
,
2096 enum built_in_function builtin_id
)
2100 m_return_type (return_type
),
2103 m_is_variadic (is_variadic
),
2104 m_builtin_id (builtin_id
),
2108 for (int i
= 0; i
< num_params
; i
++)
2109 m_params
.safe_push (params
[i
]);
2112 /* Implementation of pure virtual hook recording::memento::replay_into
2113 for recording::function. */
2116 recording::function::replay_into (replayer
*r
)
2118 /* Convert m_params to a vec of playback param. */
2119 auto_vec
<playback::param
*> params
;
2121 recording::param
*param
;
2122 params
.create (m_params
.length ());
2123 FOR_EACH_VEC_ELT (m_params
, i
, param
)
2124 params
.safe_push (param
->playback_param ());
2126 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
2128 m_return_type
->playback_type (),
2135 /* Create a recording::local instance and add it to
2136 the functions's context's list of mementos, and to the function's
2139 Implements the post-error-checking part of
2140 gcc_jit_function_new_local. */
2143 recording::function::new_local (recording::location
*loc
,
2147 local
*result
= new local (this, loc
, type
, new_string (name
));
2148 m_ctxt
->record (result
);
2149 m_locals
.safe_push (result
);
2153 /* Create a recording::block instance and add it to
2154 the functions's context's list of mementos, and to the function's
2157 Implements the post-error-checking part of
2158 gcc_jit_function_new_block. */
2161 recording::function::new_block (const char *name
)
2163 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
2165 recording::block
*result
=
2166 new recording::block (this, m_blocks
.length (), new_string (name
));
2167 m_ctxt
->record (result
);
2168 m_blocks
.safe_push (result
);
2172 /* Override the default implementation of
2173 recording::memento::write_to_dump by dumping a C-like
2174 representation of the function; either like a prototype
2175 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
2176 all other kinds of function. */
2179 recording::function::write_to_dump (dump
&d
)
2183 default: gcc_unreachable ();
2184 case GCC_JIT_FUNCTION_EXPORTED
:
2185 case GCC_JIT_FUNCTION_IMPORTED
:
2186 d
.write ("extern ");
2188 case GCC_JIT_FUNCTION_INTERNAL
:
2189 d
.write ("static ");
2191 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
2192 d
.write ("static inline ");
2195 d
.write ("%s\n", m_return_type
->get_debug_string ());
2197 if (d
.update_locations ())
2198 m_loc
= d
.make_location ();
2200 d
.write ("%s (", get_debug_string ());
2203 recording::param
*param
;
2204 FOR_EACH_VEC_ELT (m_params
, i
, param
)
2209 param
->get_type ()->get_debug_string (),
2210 param
->get_debug_string ());
2213 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
2215 d
.write ("; /* (imported) */\n\n");
2225 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
2226 var
->write_to_dump (d
);
2227 if (m_locals
.length ())
2230 /* Write each block: */
2231 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2235 b
->write_to_dump (d
);
2242 /* Pre-compilation validation of a function, for those things we can't
2243 check until the context is (supposedly) fully-populated. */
2246 recording::function::validate ()
2248 /* Complain about empty functions with non-void return type. */
2249 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
2250 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
2251 if (0 == m_blocks
.length ())
2252 m_ctxt
->add_error (m_loc
,
2253 "function %s returns non-void (type: %s)"
2254 " but has no blocks",
2255 get_debug_string (),
2256 m_return_type
->get_debug_string ());
2258 /* Check that all blocks are terminated. */
2259 int num_invalid_blocks
= 0;
2264 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2265 if (!b
->validate ())
2266 num_invalid_blocks
++;
2269 /* Check that all blocks are reachable. */
2270 if (m_blocks
.length () > 0 && 0 == num_invalid_blocks
)
2272 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
2273 flag, starting at the initial block. */
2274 auto_vec
<block
*> worklist (m_blocks
.length ());
2275 worklist
.safe_push (m_blocks
[0]);
2276 while (worklist
.length () > 0)
2278 block
*b
= worklist
.pop ();
2279 b
->m_is_reachable
= true;
2281 /* Add successor blocks that aren't yet marked to the worklist. */
2282 /* We checked that each block has a terminating statement above . */
2283 block
*next1
, *next2
;
2284 int n
= b
->get_successor_blocks (&next1
, &next2
);
2290 if (!next2
->m_is_reachable
)
2291 worklist
.safe_push (next2
);
2294 if (!next1
->m_is_reachable
)
2295 worklist
.safe_push (next1
);
2302 /* Now complain about any blocks that haven't been marked. */
2306 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2307 if (!b
->m_is_reachable
)
2308 m_ctxt
->add_error (b
->get_loc (),
2309 "unreachable block: %s",
2310 b
->get_debug_string ());
2315 /* Implements the post-error-checking part of
2316 gcc_jit_function_dump_to_dot. */
2319 recording::function::dump_to_dot (const char *path
)
2321 FILE *fp
= fopen (path
, "w");
2325 pretty_printer the_pp
;
2326 the_pp
.buffer
->stream
= fp
;
2328 pretty_printer
*pp
= &the_pp
;
2331 "digraph %s {\n", get_debug_string ());
2337 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2338 b
->dump_to_dot (pp
);
2345 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2346 b
->dump_edges_to_dot (pp
);
2349 pp_printf (pp
, "}\n");
2354 /* Implementation of recording::memento::make_debug_string for
2358 recording::function::make_debug_string ()
2363 /* The implementation of class gcc::jit::recording::block. */
2365 /* Create a recording::eval instance and add it to
2366 the block's context's list of mementos, and to the block's
2369 Implements the post-error-checking part of
2370 gcc_jit_block_add_eval. */
2373 recording::block::add_eval (recording::location
*loc
,
2374 recording::rvalue
*rvalue
)
2376 statement
*result
= new eval (this, loc
, rvalue
);
2377 m_ctxt
->record (result
);
2378 m_statements
.safe_push (result
);
2381 /* Create a recording::assignment instance and add it to
2382 the block's context's list of mementos, and to the block's
2385 Implements the post-error-checking part of
2386 gcc_jit_block_add_assignment. */
2389 recording::block::add_assignment (recording::location
*loc
,
2390 recording::lvalue
*lvalue
,
2391 recording::rvalue
*rvalue
)
2393 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
2394 m_ctxt
->record (result
);
2395 m_statements
.safe_push (result
);
2398 /* Create a recording::assignment_op instance and add it to
2399 the block's context's list of mementos, and to the block's
2402 Implements the post-error-checking part of
2403 gcc_jit_block_add_assignment_op. */
2406 recording::block::add_assignment_op (recording::location
*loc
,
2407 recording::lvalue
*lvalue
,
2408 enum gcc_jit_binary_op op
,
2409 recording::rvalue
*rvalue
)
2411 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
2412 m_ctxt
->record (result
);
2413 m_statements
.safe_push (result
);
2416 /* Create a recording::comment instance and add it to
2417 the block's context's list of mementos, and to the block's
2420 Implements the post-error-checking part of
2421 gcc_jit_block_add_comment. */
2424 recording::block::add_comment (recording::location
*loc
,
2427 statement
*result
= new comment (this, loc
, new_string (text
));
2428 m_ctxt
->record (result
);
2429 m_statements
.safe_push (result
);
2432 /* Create a recording::end_with_conditional instance and add it to
2433 the block's context's list of mementos, and to the block's
2436 Implements the post-error-checking part of
2437 gcc_jit_block_end_with_conditional. */
2440 recording::block::end_with_conditional (recording::location
*loc
,
2441 recording::rvalue
*boolval
,
2442 recording::block
*on_true
,
2443 recording::block
*on_false
)
2445 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
2446 m_ctxt
->record (result
);
2447 m_statements
.safe_push (result
);
2448 m_has_been_terminated
= true;
2451 /* Create a recording::end_with_jump instance and add it to
2452 the block's context's list of mementos, and to the block's
2455 Implements the post-error-checking part of
2456 gcc_jit_block_end_with_jump. */
2459 recording::block::end_with_jump (recording::location
*loc
,
2460 recording::block
*target
)
2462 statement
*result
= new jump (this, loc
, target
);
2463 m_ctxt
->record (result
);
2464 m_statements
.safe_push (result
);
2465 m_has_been_terminated
= true;
2468 /* Create a recording::end_with_return instance and add it to
2469 the block's context's list of mementos, and to the block's
2472 Implements the post-error-checking parts of
2473 gcc_jit_block_end_with_return and
2474 gcc_jit_block_end_with_void_return. */
2477 recording::block::end_with_return (recording::location
*loc
,
2478 recording::rvalue
*rvalue
)
2480 /* This is used by both gcc_jit_function_add_return and
2481 gcc_jit_function_add_void_return; rvalue will be non-NULL for
2482 the former and NULL for the latter. */
2483 statement
*result
= new return_ (this, loc
, rvalue
);
2484 m_ctxt
->record (result
);
2485 m_statements
.safe_push (result
);
2486 m_has_been_terminated
= true;
2489 /* Override the default implementation of
2490 recording::memento::write_to_dump for blocks by writing
2491 an unindented block name as a label, followed by the indented
2501 recording::block::write_to_dump (dump
&d
)
2503 d
.write ("%s:\n", get_debug_string ());
2507 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
2508 s
->write_to_dump (d
);
2511 /* Validate a block by ensuring that it has been terminated. */
2514 recording::block::validate ()
2516 if (!has_been_terminated ())
2518 statement
*stmt
= get_last_statement ();
2519 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
2520 m_func
->get_context ()->add_error (loc
,
2521 "unterminated block in %s: %s",
2522 m_func
->get_debug_string (),
2523 get_debug_string ());
2530 /* Get the source-location of a block by using that of the first
2531 statement within it, if any. */
2533 recording::location
*
2534 recording::block::get_loc () const
2536 recording::statement
*stmt
= get_first_statement ();
2538 return stmt
->get_loc ();
2543 /* Get the first statement within a block, if any. */
2545 recording::statement
*
2546 recording::block::get_first_statement () const
2548 if (m_statements
.length ())
2549 return m_statements
[0];
2554 /* Get the last statement within a block, if any. */
2556 recording::statement
*
2557 recording::block::get_last_statement () const
2559 if (m_statements
.length ())
2560 return m_statements
[m_statements
.length () - 1];
2565 /* Assuming that this block has been terminated, get the number of
2566 successor blocks, which will be 0, 1 or 2, for return, unconditional
2567 jump, and conditional jump respectively.
2568 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
2569 is written to NEXT1, and the second (if any) to NEXT2.
2571 Used when validating functions, and when dumping dot representations
2575 recording::block::get_successor_blocks (block
**next1
, block
**next2
) const
2577 gcc_assert (m_has_been_terminated
);
2580 statement
*last_statement
= get_last_statement ();
2581 gcc_assert (last_statement
);
2582 return last_statement
->get_successor_blocks (next1
, next2
);
2585 /* Implementation of pure virtual hook recording::memento::replay_into
2586 for recording::block. */
2589 recording::block::replay_into (replayer
*)
2591 set_playback_obj (m_func
->playback_function ()
2592 ->new_block (playback_string (m_name
)));
2595 /* Implementation of recording::memento::make_debug_string for
2599 recording::block::make_debug_string ()
2604 return string::from_printf (m_ctxt
,
2605 "<UNNAMED BLOCK %p>",
2609 /* Dump a block in graphviz form into PP, capturing the block name (if
2610 any) and the statements. */
2613 recording::block::dump_to_dot (pretty_printer
*pp
)
2617 "[shape=record,style=filled,fillcolor=white,label=\"{"),
2619 pp_write_text_to_stream (pp
);
2622 pp_string (pp
, m_name
->c_str ());
2623 pp_string (pp
, ":");
2625 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
2630 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
2632 pp_string (pp
, s
->get_debug_string ());
2634 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
2642 /* Dump the out-edges of the block in graphviz form into PP. */
2645 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
2648 int num_succs
= get_successor_blocks (&next
[0], &next
[1]);
2649 for (int i
= 0; i
< num_succs
; i
++)
2651 "\tblock_%d:s -> block_%d:n;\n",
2652 m_index
, next
[i
]->m_index
);
2655 /* The implementation of class gcc::jit::recording::global. */
2657 /* Implementation of pure virtual hook recording::memento::replay_into
2658 for recording::global. */
2661 recording::global::replay_into (replayer
*r
)
2663 set_playback_obj (r
->new_global (playback_location (r
, m_loc
),
2665 m_type
->playback_type (),
2666 playback_string (m_name
)));
2669 /* Override the default implementation of
2670 recording::memento::write_to_dump for globals.
2671 This will be of the form:
2673 GCC_JIT_GLOBAL_EXPORTED:
2677 GCC_JIT_GLOBAL_INTERNAL:
2679 e.g. "static int foo;"
2681 GCC_JIT_GLOBAL_IMPORTED:
2683 e.g. "extern int foo;"
2685 These are written to the top of the dump by
2686 recording::context::dump_to_file. */
2689 recording::global::write_to_dump (dump
&d
)
2691 if (d
.update_locations ())
2692 m_loc
= d
.make_location ();
2699 case GCC_JIT_GLOBAL_EXPORTED
:
2702 case GCC_JIT_GLOBAL_INTERNAL
:
2703 d
.write ("static ");
2706 case GCC_JIT_GLOBAL_IMPORTED
:
2707 d
.write ("extern ");
2710 d
.write ("%s %s;\n",
2711 m_type
->get_debug_string (),
2712 get_debug_string ());
2715 /* The implementation of the various const-handling classes:
2716 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
2718 /* Explicit specialization of the various mementos we're interested in. */
2719 template class recording::memento_of_new_rvalue_from_const
<int>;
2720 template class recording::memento_of_new_rvalue_from_const
<long>;
2721 template class recording::memento_of_new_rvalue_from_const
<double>;
2722 template class recording::memento_of_new_rvalue_from_const
<void *>;
2724 /* Implementation of the pure virtual hook recording::memento::replay_into
2725 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
2727 template <typename HOST_TYPE
>
2730 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
2733 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
2737 /* The make_debug_string method varies between the various
2738 memento_of_new_rvalue_from_const <HOST_TYPE> classes, so we explicitly
2739 write specializations of it.
2741 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
2742 namespaces are written out explicitly, which is why most of this file
2743 doesn't abbreviate things by entering the "recording" namespace.
2745 However, these specializations are required to be in the same namespace
2746 as the template, hence we now have to enter the gcc::jit::recording
2752 /* The make_debug_string specialization for <int>, which renders it as
2753 (TARGET_TYPE)LITERAL
2759 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
2761 return string::from_printf (m_ctxt
,
2763 m_type
->get_debug_string (),
2767 /* The make_debug_string specialization for <long>, rendering it as
2768 (TARGET_TYPE)LITERAL
2774 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
2776 return string::from_printf (m_ctxt
,
2778 m_type
->get_debug_string (),
2782 /* The make_debug_string specialization for <double>, rendering it as
2783 (TARGET_TYPE)LITERAL
2789 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
2791 return string::from_printf (m_ctxt
,
2793 m_type
->get_debug_string (),
2797 /* The make_debug_string specialization for <void *>, rendering it as
2802 Zero is rendered as NULL e.g.
2807 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
2809 if (m_value
!= NULL
)
2810 return string::from_printf (m_ctxt
,
2812 m_type
->get_debug_string (), m_value
);
2814 return string::from_printf (m_ctxt
,
2816 m_type
->get_debug_string ());
2819 /* We're done specializing make_debug_string, so we can exit the
2820 gcc::jit::recording namespace. */
2822 } // namespace recording
2824 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
2826 /* Implementation of pure virtual hook recording::memento::replay_into
2827 for recording::memento_of_new_string_literal. */
2830 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
2832 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
2835 /* Implementation of recording::memento::make_debug_string for
2839 recording::memento_of_new_string_literal::make_debug_string ()
2841 return string::from_printf (m_ctxt
,
2842 m_value
->get_debug_string ());
2845 /* The implementation of class gcc::jit::recording::unary_op. */
2847 /* Implementation of pure virtual hook recording::memento::replay_into
2848 for recording::unary_op. */
2851 recording::unary_op::replay_into (replayer
*r
)
2853 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
2855 get_type ()->playback_type (),
2856 m_a
->playback_rvalue ()));
2859 /* Implementation of recording::memento::make_debug_string for
2862 static const char * const unary_op_strings
[] = {
2863 "-", /* GCC_JIT_UNARY_OP_MINUS */
2864 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
2865 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
2866 "abs ", /* GCC_JIT_UNARY_OP_ABS */
2870 recording::unary_op::make_debug_string ()
2872 return string::from_printf (m_ctxt
,
2874 unary_op_strings
[m_op
],
2875 m_a
->get_debug_string ());
2878 /* The implementation of class gcc::jit::recording::binary_op. */
2880 /* Implementation of pure virtual hook recording::memento::replay_into
2881 for recording::binary_op. */
2884 recording::binary_op::replay_into (replayer
*r
)
2886 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
2888 get_type ()->playback_type (),
2889 m_a
->playback_rvalue (),
2890 m_b
->playback_rvalue ()));
2893 /* Implementation of recording::memento::make_debug_string for
2896 static const char * const binary_op_strings
[] = {
2897 "+", /* GCC_JIT_BINARY_OP_PLUS */
2898 "-", /* GCC_JIT_BINARY_OP_MINUS */
2899 "*", /* GCC_JIT_BINARY_OP_MULT */
2900 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
2901 "%", /* GCC_JIT_BINARY_OP_MODULO */
2902 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
2903 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
2904 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
2905 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
2906 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
2907 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
2908 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
2912 recording::binary_op::make_debug_string ()
2914 return string::from_printf (m_ctxt
,
2916 m_a
->get_debug_string (),
2917 binary_op_strings
[m_op
],
2918 m_b
->get_debug_string ());
2921 /* The implementation of class gcc::jit::recording::comparison. */
2923 /* Implementation of recording::memento::make_debug_string for
2926 static const char * const comparison_strings
[] =
2928 "==", /* GCC_JIT_COMPARISON_EQ */
2929 "!=", /* GCC_JIT_COMPARISON_NE */
2930 "<", /* GCC_JIT_COMPARISON_LT */
2931 "<=", /* GCC_JIT_COMPARISON_LE */
2932 ">", /* GCC_JIT_COMPARISON_GT */
2933 ">=", /* GCC_JIT_COMPARISON_GE */
2937 recording::comparison::make_debug_string ()
2939 return string::from_printf (m_ctxt
,
2941 m_a
->get_debug_string (),
2942 comparison_strings
[m_op
],
2943 m_b
->get_debug_string ());
2946 /* Implementation of pure virtual hook recording::memento::replay_into
2947 for recording::comparison. */
2950 recording::comparison::replay_into (replayer
*r
)
2952 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
2954 m_a
->playback_rvalue (),
2955 m_b
->playback_rvalue ()));
2958 /* Implementation of pure virtual hook recording::memento::replay_into
2959 for recording::cast. */
2962 recording::cast::replay_into (replayer
*r
)
2964 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
2965 m_rvalue
->playback_rvalue (),
2966 get_type ()->playback_type ()));
2969 /* Implementation of recording::memento::make_debug_string for
2973 recording::cast::make_debug_string ()
2975 return string::from_printf (m_ctxt
,
2977 get_type ()->get_debug_string (),
2978 m_rvalue
->get_debug_string ());
2981 /* The implementation of class gcc::jit::recording::call. */
2983 /* The constructor for gcc::jit::recording::call. */
2985 recording::call::call (recording::context
*ctxt
,
2986 recording::location
*loc
,
2987 recording::function
*func
,
2990 : rvalue (ctxt
, loc
, func
->get_return_type ()),
2994 for (int i
= 0; i
< numargs
; i
++)
2995 m_args
.safe_push (args
[i
]);
2998 /* Implementation of pure virtual hook recording::memento::replay_into
2999 for recording::call. */
3002 recording::call::replay_into (replayer
*r
)
3004 auto_vec
<playback::rvalue
*> playback_args
;
3005 playback_args
.create (m_args
.length ());
3006 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3007 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
3009 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
3010 m_func
->playback_function (),
3014 /* Implementation of recording::memento::make_debug_string for
3018 recording::call::make_debug_string ()
3020 /* First, build a buffer for the arguments. */
3021 /* Calculate length of said buffer. */
3022 size_t sz
= 1; /* nil terminator */
3023 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3025 sz
+= strlen (m_args
[i
]->get_debug_string ());
3026 sz
+= 2; /* ", " separator */
3029 /* Now allocate and populate the buffer. */
3030 char *argbuf
= new char[sz
];
3033 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3035 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string ());
3036 len
+= strlen (m_args
[i
]->get_debug_string ());
3037 if (i
+ 1 < m_args
.length ())
3039 strcpy (argbuf
+ len
, ", ");
3045 /* ...and use it to get the string for the call as a whole. */
3046 string
*result
= string::from_printf (m_ctxt
,
3048 m_func
->get_debug_string (),
3056 /* The implementation of class gcc::jit::recording::call_through_ptr. */
3058 /* The constructor for recording::call_through_ptr. */
3060 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
3061 recording::location
*loc
,
3062 recording::rvalue
*fn_ptr
,
3065 : rvalue (ctxt
, loc
,
3066 fn_ptr
->get_type ()->dereference ()
3067 ->as_a_function_type ()->get_return_type ()),
3071 for (int i
= 0; i
< numargs
; i
++)
3072 m_args
.safe_push (args
[i
]);
3075 /* Implementation of pure virtual hook recording::memento::replay_into
3076 for recording::call_through_ptr. */
3079 recording::call_through_ptr::replay_into (replayer
*r
)
3081 auto_vec
<playback::rvalue
*> playback_args
;
3082 playback_args
.create (m_args
.length ());
3083 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3084 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
3086 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
3087 m_fn_ptr
->playback_rvalue (),
3091 /* Implementation of recording::memento::make_debug_string for
3092 calls through function ptrs. */
3095 recording::call_through_ptr::make_debug_string ()
3097 /* First, build a buffer for the arguments. */
3098 /* Calculate length of said buffer. */
3099 size_t sz
= 1; /* nil terminator */
3100 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3102 sz
+= strlen (m_args
[i
]->get_debug_string ());
3103 sz
+= 2; /* ", " separator */
3106 /* Now allocate and populate the buffer. */
3107 char *argbuf
= new char[sz
];
3110 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3112 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string ());
3113 len
+= strlen (m_args
[i
]->get_debug_string ());
3114 if (i
+ 1 < m_args
.length ())
3116 strcpy (argbuf
+ len
, ", ");
3122 /* ...and use it to get the string for the call as a whole. */
3123 string
*result
= string::from_printf (m_ctxt
,
3125 m_fn_ptr
->get_debug_string (),
3133 /* The implementation of class gcc::jit::recording::array_access. */
3135 /* Implementation of pure virtual hook recording::memento::replay_into
3136 for recording::array_access. */
3139 recording::array_access::replay_into (replayer
*r
)
3142 r
->new_array_access (playback_location (r
, m_loc
),
3143 m_ptr
->playback_rvalue (),
3144 m_index
->playback_rvalue ()));
3147 /* Implementation of recording::memento::make_debug_string for
3151 recording::array_access::make_debug_string ()
3153 return string::from_printf (m_ctxt
,
3155 m_ptr
->get_debug_string (),
3156 m_index
->get_debug_string ());
3159 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
3161 /* Implementation of pure virtual hook recording::memento::replay_into
3162 for recording::access_field_of_lvalue. */
3165 recording::access_field_of_lvalue::replay_into (replayer
*r
)
3168 m_lvalue
->playback_lvalue ()
3169 ->access_field (playback_location (r
, m_loc
),
3170 m_field
->playback_field ()));
3174 /* Implementation of recording::memento::make_debug_string for
3175 accessing a field of an lvalue. */
3178 recording::access_field_of_lvalue::make_debug_string ()
3180 return string::from_printf (m_ctxt
,
3182 m_lvalue
->get_debug_string (),
3183 m_field
->get_debug_string ());
3186 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
3188 /* Implementation of pure virtual hook recording::memento::replay_into
3189 for recording::access_field_rvalue. */
3192 recording::access_field_rvalue::replay_into (replayer
*r
)
3195 m_rvalue
->playback_rvalue ()
3196 ->access_field (playback_location (r
, m_loc
),
3197 m_field
->playback_field ()));
3200 /* Implementation of recording::memento::make_debug_string for
3201 accessing a field of an rvalue. */
3204 recording::access_field_rvalue::make_debug_string ()
3206 return string::from_printf (m_ctxt
,
3208 m_rvalue
->get_debug_string (),
3209 m_field
->get_debug_string ());
3212 /* The implementation of class
3213 gcc::jit::recording::dereference_field_rvalue. */
3215 /* Implementation of pure virtual hook recording::memento::replay_into
3216 for recording::dereference_field_rvalue. */
3219 recording::dereference_field_rvalue::replay_into (replayer
*r
)
3222 m_rvalue
->playback_rvalue ()->
3223 dereference_field (playback_location (r
, m_loc
),
3224 m_field
->playback_field ()));
3227 /* Implementation of recording::memento::make_debug_string for
3228 dereferencing a field of an rvalue. */
3231 recording::dereference_field_rvalue::make_debug_string ()
3233 return string::from_printf (m_ctxt
,
3235 m_rvalue
->get_debug_string (),
3236 m_field
->get_debug_string ());
3239 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
3241 /* Implementation of pure virtual hook recording::memento::replay_into
3242 for recording::dereference_rvalue. */
3245 recording::dereference_rvalue::replay_into (replayer
*r
)
3248 m_rvalue
->playback_rvalue ()->
3249 dereference (playback_location (r
, m_loc
)));
3252 /* Implementation of recording::memento::make_debug_string for
3253 dereferencing an rvalue. */
3256 recording::dereference_rvalue::make_debug_string ()
3258 return string::from_printf (m_ctxt
,
3260 m_rvalue
->get_debug_string ());
3263 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
3265 /* Implementation of pure virtual hook recording::memento::replay_into
3266 for recording::get_address_of_lvalue. */
3269 recording::get_address_of_lvalue::replay_into (replayer
*r
)
3272 m_lvalue
->playback_lvalue ()->
3273 get_address (playback_location (r
, m_loc
)));
3276 /* Implementation of recording::memento::make_debug_string for
3277 getting the address of an lvalue. */
3280 recording::get_address_of_lvalue::make_debug_string ()
3282 return string::from_printf (m_ctxt
,
3284 m_lvalue
->get_debug_string ());
3287 /* The implementation of class gcc::jit::recording::local. */
3289 /* Implementation of pure virtual hook recording::memento::replay_into
3290 for recording::local. */
3293 recording::local::replay_into (replayer
*r
)
3296 m_func
->playback_function ()
3297 ->new_local (playback_location (r
, m_loc
),
3298 m_type
->playback_type (),
3299 playback_string (m_name
)));
3302 /* Override the default implementation of
3303 recording::memento::write_to_dump for locals by writing
3305 for use at the top of the function body as if it were a
3309 recording::local::write_to_dump (dump
&d
)
3311 if (d
.update_locations ())
3312 m_loc
= d
.make_location ();
3313 d
.write(" %s %s;\n",
3314 m_type
->get_debug_string (),
3315 get_debug_string ());
3318 /* The implementation of class gcc::jit::recording::statement. */
3320 /* We poison the default implementation of
3321 gcc::jit::recording::statement::get_successor_blocks
3322 since this vfunc must only ever be called on terminator
3326 recording::statement::get_successor_blocks (block
**/
*out_next1*/
,
3327 block
**/
*out_next2*/
) const
3329 /* The base class implementation is for non-terminating statements,
3330 and thus should never be called. */
3335 /* Extend the default implementation of
3336 recording::memento::write_to_dump for statements by (if requested)
3337 updating the location of the statement to the current location in
3341 recording::statement::write_to_dump (dump
&d
)
3343 memento::write_to_dump (d
);
3344 if (d
.update_locations ())
3345 m_loc
= d
.make_location ();
3348 /* The implementation of class gcc::jit::recording::eval. */
3350 /* Implementation of pure virtual hook recording::memento::replay_into
3351 for recording::eval. */
3354 recording::eval::replay_into (replayer
*r
)
3356 playback_block (get_block ())
3357 ->add_eval (playback_location (r
),
3358 m_rvalue
->playback_rvalue ());
3361 /* Implementation of recording::memento::make_debug_string for
3362 an eval statement. */
3365 recording::eval::make_debug_string ()
3367 return string::from_printf (m_ctxt
,
3369 m_rvalue
->get_debug_string ());
3372 /* The implementation of class gcc::jit::recording::assignment. */
3374 /* Implementation of pure virtual hook recording::memento::replay_into
3375 for recording::assignment. */
3378 recording::assignment::replay_into (replayer
*r
)
3380 playback_block (get_block ())
3381 ->add_assignment (playback_location (r
),
3382 m_lvalue
->playback_lvalue (),
3383 m_rvalue
->playback_rvalue ());
3386 /* Implementation of recording::memento::make_debug_string for
3387 an assignment statement. */
3390 recording::assignment::make_debug_string ()
3392 return string::from_printf (m_ctxt
,
3394 m_lvalue
->get_debug_string (),
3395 m_rvalue
->get_debug_string ());
3398 /* The implementation of class gcc::jit::recording::assignment_op. */
3400 /* Implementation of pure virtual hook recording::memento::replay_into
3401 for recording::assignment_op. */
3404 recording::assignment_op::replay_into (replayer
*r
)
3406 playback::type
*result_type
=
3407 m_lvalue
->playback_lvalue ()->get_type ();
3409 playback::rvalue
*binary_op
=
3410 r
->new_binary_op (playback_location (r
),
3413 m_lvalue
->playback_rvalue (),
3414 m_rvalue
->playback_rvalue ());
3416 playback_block (get_block ())
3417 ->add_assignment (playback_location (r
),
3418 m_lvalue
->playback_lvalue (),
3422 /* Implementation of recording::memento::make_debug_string for
3423 an assignment_op statement. */
3426 recording::assignment_op::make_debug_string ()
3428 return string::from_printf (m_ctxt
,
3430 m_lvalue
->get_debug_string (),
3431 binary_op_strings
[m_op
],
3432 m_rvalue
->get_debug_string ());
3435 /* The implementation of class gcc::jit::recording::comment. */
3437 /* Implementation of pure virtual hook recording::memento::replay_into
3438 for recording::comment. */
3441 recording::comment::replay_into (replayer
*r
)
3443 playback_block (get_block ())
3444 ->add_comment (playback_location (r
),
3448 /* Implementation of recording::memento::make_debug_string for
3449 a comment "statement". */
3452 recording::comment::make_debug_string ()
3454 return string::from_printf (m_ctxt
,
3459 /* The implementation of class gcc::jit::recording::conditional. */
3461 /* Implementation of pure virtual hook recording::memento::replay_into
3462 for recording::conditional. */
3465 recording::conditional::replay_into (replayer
*r
)
3467 playback_block (get_block ())
3468 ->add_conditional (playback_location (r
),
3469 m_boolval
->playback_rvalue (),
3470 playback_block (m_on_true
),
3471 playback_block (m_on_false
));
3474 /* Override the poisoned default implementation of
3475 gcc::jit::recording::statement::get_successor_blocks
3477 A conditional jump has 2 successor blocks. */
3480 recording::conditional::get_successor_blocks (block
**out_next1
,
3481 block
**out_next2
) const
3483 *out_next1
= m_on_true
;
3484 *out_next2
= m_on_false
;
3488 /* Implementation of recording::memento::make_debug_string for
3489 a conditional jump statement. */
3492 recording::conditional::make_debug_string ()
3495 return string::from_printf (m_ctxt
,
3496 "if (%s) goto %s; else goto %s;",
3497 m_boolval
->get_debug_string (),
3498 m_on_true
->get_debug_string (),
3499 m_on_false
->get_debug_string ());
3501 return string::from_printf (m_ctxt
,
3503 m_boolval
->get_debug_string (),
3504 m_on_true
->get_debug_string ());
3507 /* The implementation of class gcc::jit::recording::jump. */
3509 /* Implementation of pure virtual hook recording::memento::replay_into
3510 for recording::jump. */
3513 recording::jump::replay_into (replayer
*r
)
3515 playback_block (get_block ())
3516 ->add_jump (playback_location (r
),
3517 m_target
->playback_block ());
3520 /* Override the poisoned default implementation of
3521 gcc::jit::recording::statement::get_successor_blocks
3523 An unconditional jump has 1 successor block. */
3526 recording::jump::get_successor_blocks (block
**out_next1
,
3527 block
**/
*out_next2*/
) const
3529 *out_next1
= m_target
;
3533 /* Implementation of recording::memento::make_debug_string for
3534 a unconditional jump statement. */
3537 recording::jump::make_debug_string ()
3539 return string::from_printf (m_ctxt
,
3541 m_target
->get_debug_string ());
3544 /* The implementation of class gcc::jit::recording::return_. */
3546 /* Implementation of pure virtual hook recording::memento::replay_into
3547 for recording::return_. */
3550 recording::return_::replay_into (replayer
*r
)
3552 playback_block (get_block ())
3553 ->add_return (playback_location (r
),
3554 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
3557 /* Override the poisoned default implementation of
3558 gcc::jit::recording::statement::get_successor_blocks
3560 A return statement has no successor block. */
3563 recording::return_::get_successor_blocks (block
**/
*out_next1*/
,
3564 block
**/
*out_next2*/
) const
3569 /* Implementation of recording::memento::make_debug_string for
3570 a return statement (covers both those with and without rvalues). */
3573 recording::return_::make_debug_string ()
3576 return string::from_printf (m_ctxt
,
3578 m_rvalue
->get_debug_string ());
3580 return string::from_printf (m_ctxt
,
3584 } // namespace gcc::jit