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-recording.h"
34 #include "jit-playback.h"
41 dump::dump (recording::context
&ctxt
,
43 bool update_locations
)
45 m_filename (filename
),
46 m_update_locations (update_locations
),
50 m_file
= fopen (filename
, "w");
53 "error opening dump file %s for writing: %s",
62 int err
= fclose (m_file
);
64 m_ctxt
.add_error (NULL
,
65 "error closing dump file %s: %s",
71 /* Write the given message to the dump, using printf-formatting
72 conventions, updating the line/column within the dump.
74 Emit an error on the context if a failure occurs. */
77 dump::write (const char *fmt
, ...)
82 /* If there was an error opening the file, we've already reported it.
83 Don't attempt further work. */
88 vasprintf (&buf
, fmt
, ap
);
93 m_ctxt
.add_error (NULL
, "malloc failure writing to dumpfile %s",
98 if (fwrite (buf
, strlen (buf
), 1, m_file
) != 1)
99 m_ctxt
.add_error (NULL
, "error writing to dump file %s",
102 /* Update line/column: */
103 for (const char *ptr
= buf
; *ptr
; ptr
++)
117 /* Construct a gcc::jit::recording::location instance for the current
118 location within the dump. */
120 recording::location
*
121 dump::make_location () const
123 return m_ctxt
.new_location (m_filename
, m_line
, m_column
);
126 /**********************************************************************
128 **********************************************************************/
130 /* Get the playback::location for the given recording::location,
131 handling a NULL input with a NULL output. */
134 recording::playback_location (replayer
*r
, recording::location
*loc
)
137 return loc
->playback_location (r
);
142 /* Get a const char * for the given recording::string
143 handling a NULL input with a NULL output. */
146 recording::playback_string (recording::string
*str
)
149 return str
->c_str ();
154 /* Get the playback::block for the given recording::block,
155 handling a NULL input with a NULL output. */
158 recording::playback_block (recording::block
*b
)
161 return b
->playback_block ();
166 /* Methods of cc::jit::recording::context. */
168 /* The constructor for gcc::jit::recording::context, used by
169 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
171 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),
180 m_builtins_manager(NULL
)
184 /* Inherit options from parent. */
186 i
< sizeof (m_str_options
) / sizeof (m_str_options
[0]);
189 const char *parent_opt
= parent_ctxt
->m_str_options
[i
];
190 m_str_options
[i
] = parent_opt
? xstrdup (parent_opt
) : NULL
;
192 memcpy (m_int_options
,
193 parent_ctxt
->m_int_options
,
194 sizeof (m_int_options
));
195 memcpy (m_bool_options
,
196 parent_ctxt
->m_bool_options
,
197 sizeof (m_bool_options
));
201 memset (m_str_options
, 0, sizeof (m_str_options
));
202 memset (m_int_options
, 0, sizeof (m_int_options
));
203 memset (m_bool_options
, 0, sizeof (m_bool_options
));
206 memset (m_basic_types
, 0, sizeof (m_basic_types
));
209 /* The destructor for gcc::jit::recording::context, implicitly used by
210 gcc_jit_context_release. */
212 recording::context::~context ()
216 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
221 for (i
= 0; i
< GCC_JIT_NUM_STR_OPTIONS
; ++i
)
222 free (m_str_options
[i
]);
224 if (m_builtins_manager
)
225 delete m_builtins_manager
;
227 if (m_owns_first_error_str
)
228 free (m_first_error_str
);
231 /* Add the given mememto to the list of those tracked by this
232 gcc::jit::recording::context, so that e.g. it can be deleted
233 when this context is released. */
236 recording::context::record (memento
*m
)
240 m_mementos
.safe_push (m
);
243 /* Replay this context (and any parents) into the given replayer. */
246 recording::context::replay_into (replayer
*r
)
251 /* If we have a parent context, we must replay it. This will
252 recursively walk backwards up the historical tree, then replay things
253 forwards "in historical order", starting with the ultimate parent
254 context, until we reach the "this" context.
256 Note that we fully replay the parent, then fully replay the child,
257 which means that inter-context references can only exist from child
258 to parent, not the other way around.
260 All of this replaying is suboptimal - it would be better to do the
261 work for the parent context *once*, rather than replaying the parent
262 every time we replay each child. However, fixing this requires deep
263 surgery to lifetime-management: we'd need every context family tree
264 to have its own GC heap, and to initialize the GCC code to use that
265 heap (with a mutex on such a heap). */
267 m_parent_ctxt
->replay_into (r
);
269 if (r
->errors_occurred ())
272 /* Replay this context's saved operations into r. */
273 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
275 /* Disabled low-level debugging, here if we need it: print what
277 Note that the calls to get_debug_string might lead to more
278 mementos being created for the strings.
279 This can also be used to exercise the debug_string
282 printf ("context %p replaying (%p): %s\n",
283 (void *)this, (void *)m
, m
->get_debug_string ());
287 if (r
->errors_occurred ())
292 /* During a playback, we associate objects from the recording with
293 their counterparts during this playback.
295 For simplicity, we store this within the recording objects.
297 The following method cleans away these associations, to ensure that
298 we never have out-of-date associations lingering on subsequent
299 playbacks (the objects pointed to are GC-managed, but the
300 recording objects don't own refs to them). */
303 recording::context::disassociate_from_playback ()
309 m_parent_ctxt
->disassociate_from_playback ();
311 FOR_EACH_VEC_ELT (m_mementos
, i
, m
)
313 m
->set_playback_obj (NULL
);
317 /* Create a recording::string instance and add it to this context's list
320 This creates a fresh copy of the given 0-terminated buffer. */
323 recording::context::new_string (const char *text
)
328 recording::string
*result
= new string (this, text
);
333 /* Create a recording::location instance and add it to this context's
336 Implements the post-error-checking part of
337 gcc_jit_context_new_location. */
339 recording::location
*
340 recording::context::new_location (const char *filename
,
344 recording::location
*result
=
345 new recording::location (this,
346 new_string (filename
),
352 /* If we haven't seen this enum value yet, create a recording::type
353 instance and add it to this context's list of mementos.
355 If we have seen it before, reuse our cached value, so that repeated
356 calls on the context give the same object.
358 If we have a parent context, the cache is within the ultimate
361 Implements the post-error-checking part of
362 gcc_jit_context_get_type. */
365 recording::context::get_type (enum gcc_jit_types kind
)
367 if (!m_basic_types
[kind
])
370 m_basic_types
[kind
] = m_parent_ctxt
->get_type (kind
);
373 recording::type
*result
= new memento_of_get_type (this, kind
);
375 m_basic_types
[kind
] = result
;
379 return m_basic_types
[kind
];
382 /* Get a recording::type instance for the given size and signedness.
383 This is implemented in terms of recording::context::get_type
386 Implements the post-error-checking part of
387 gcc_jit_context_get_int_type. */
390 recording::context::get_int_type (int num_bytes
, int is_signed
)
392 /* We can't use a switch here since some of the values are macros affected
393 by options; e.g. i386.h has
394 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
395 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
396 are in bits, rather than bytes.
398 const int num_bits
= num_bytes
* 8;
399 if (num_bits
== INT_TYPE_SIZE
)
400 return get_type (is_signed
402 : GCC_JIT_TYPE_UNSIGNED_INT
);
403 if (num_bits
== CHAR_TYPE_SIZE
)
404 return get_type (is_signed
405 ? GCC_JIT_TYPE_SIGNED_CHAR
406 : GCC_JIT_TYPE_UNSIGNED_CHAR
);
407 if (num_bits
== SHORT_TYPE_SIZE
)
408 return get_type (is_signed
410 : GCC_JIT_TYPE_UNSIGNED_SHORT
);
411 if (num_bits
== LONG_TYPE_SIZE
)
412 return get_type (is_signed
414 : GCC_JIT_TYPE_UNSIGNED_LONG
);
415 if (num_bits
== LONG_LONG_TYPE_SIZE
)
416 return get_type (is_signed
417 ? GCC_JIT_TYPE_LONG_LONG
418 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG
);
420 /* Some other size, not corresponding to the C int types. */
421 /* To be written: support arbitrary other sizes, sharing by
422 memoizing at the recording::context level? */
426 /* Create a recording::type instance and add it to this context's list
429 Implements the post-error-checking part of
430 gcc_jit_context_new_array_type. */
433 recording::context::new_array_type (recording::location
*loc
,
434 recording::type
*element_type
,
437 if (struct_
*s
= element_type
->dyn_cast_struct ())
438 if (!s
->get_fields ())
441 "cannot create an array of type %s"
442 " until the fields have been set",
443 s
->get_name ()->c_str ());
446 recording::type
*result
=
447 new recording::array_type (this, loc
, element_type
, num_elements
);
452 /* Create a recording::field instance and add it to this context's list
455 Implements the post-error-checking part of
456 gcc_jit_context_new_field. */
459 recording::context::new_field (recording::location
*loc
,
460 recording::type
*type
,
463 recording::field
*result
=
464 new recording::field (this, loc
, type
, new_string (name
));
469 /* Create a recording::struct_ instance and add it to this context's
470 list of mementos and list of compound types.
472 Implements the post-error-checking part of
473 gcc_jit_context_new_struct_type. */
476 recording::context::new_struct_type (recording::location
*loc
,
479 recording::struct_
*result
= new struct_ (this, loc
, new_string (name
));
481 m_compound_types
.safe_push (result
);
485 /* Create a recording::union_ instance and add it to this context's
486 list of mementos and list of compound types.
488 Implements the first post-error-checking part of
489 gcc_jit_context_new_union_type. */
492 recording::context::new_union_type (recording::location
*loc
,
495 recording::union_
*result
= new union_ (this, loc
, new_string (name
));
497 m_compound_types
.safe_push (result
);
501 /* Create a recording::function_type instance and add it to this context's
504 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
506 recording::function_type
*
507 recording::context::new_function_type (recording::type
*return_type
,
509 recording::type
**param_types
,
512 recording::function_type
*fn_type
513 = new function_type (this,
522 /* Create a recording::type instance and add it to this context's list
525 Implements the post-error-checking part of
526 gcc_jit_context_new_function_ptr_type. */
529 recording::context::new_function_ptr_type (recording::location
*, /* unused loc */
530 recording::type
*return_type
,
532 recording::type
**param_types
,
535 recording::function_type
*fn_type
536 = new_function_type (return_type
,
541 /* Return a pointer-type to the the function type. */
542 return fn_type
->get_pointer ();
545 /* Create a recording::param instance and add it to this context's list
548 Implements the post-error-checking part of
549 gcc_jit_context_new_param. */
552 recording::context::new_param (recording::location
*loc
,
553 recording::type
*type
,
556 recording::param
*result
= new recording::param (this, loc
, type
, new_string (name
));
561 /* Create a recording::function instance and add it to this context's list
562 of mementos and list of functions.
564 Implements the post-error-checking part of
565 gcc_jit_context_new_function. */
567 recording::function
*
568 recording::context::new_function (recording::location
*loc
,
569 enum gcc_jit_function_kind kind
,
570 recording::type
*return_type
,
573 recording::param
**params
,
575 enum built_in_function builtin_id
)
577 recording::function
*result
=
578 new recording::function (this,
579 loc
, kind
, return_type
,
581 num_params
, params
, is_variadic
,
584 m_functions
.safe_push (result
);
589 /* Locate the builtins_manager (if any) for this family of contexts,
590 creating it if it doesn't exist already.
592 All of the recording contexts in a family share one builtins_manager:
593 if we have a child context, follow the parent links to get the
594 ultimate ancestor context, and look for it/store it there. */
597 recording::context::get_builtins_manager ()
600 return m_parent_ctxt
->get_builtins_manager ();
602 if (!m_builtins_manager
)
603 m_builtins_manager
= new builtins_manager (this);
605 return m_builtins_manager
;
608 /* Get a recording::function instance, which is lazily-created and added
609 to the context's lists of mementos.
611 Implements the post-error-checking part of
612 gcc_jit_context_get_builtin_function. */
614 recording::function
*
615 recording::context::get_builtin_function (const char *name
)
617 builtins_manager
*bm
= get_builtins_manager ();
618 return bm
->get_builtin_function (name
);
621 /* Create a recording::global instance and add it to this context's list
624 Implements the post-error-checking part of
625 gcc_jit_context_new_global. */
628 recording::context::new_global (recording::location
*loc
,
629 recording::type
*type
,
632 recording::lvalue
*result
=
633 new recording::global (this, loc
, type
, new_string (name
));
638 /* Create a recording::memento_of_new_rvalue_from_int instance and add
639 it to this context's list of mementos.
641 Implements the post-error-checking part of
642 gcc_jit_context_new_rvalue_from_int. */
645 recording::context::new_rvalue_from_int (recording::type
*type
,
648 recording::rvalue
*result
=
649 new memento_of_new_rvalue_from_int (this, NULL
, type
, value
);
654 /* Create a recording::memento_of_new_rvalue_from_double instance and
655 add it to this context's list of mementos.
657 Implements the post-error-checking part of
658 gcc_jit_context_new_rvalue_from_double. */
661 recording::context::new_rvalue_from_double (recording::type
*type
,
664 recording::rvalue
*result
=
665 new memento_of_new_rvalue_from_double (this, NULL
, type
, value
);
670 /* Create a recording::memento_of_new_rvalue_from_ptr instance and add
671 it to this context's list of mementos.
673 Implements the post-error-checking part of
674 gcc_jit_context_new_rvalue_from_ptr. */
677 recording::context::new_rvalue_from_ptr (recording::type
*type
,
680 recording::rvalue
*result
=
681 new memento_of_new_rvalue_from_ptr (this, NULL
, type
, value
);
686 /* Create a recording::memento_of_new_string_literal instance and add it
687 to this context's list of mementos.
689 Implements the post-error-checking part of
690 gcc_jit_context_new_string_literal. */
693 recording::context::new_string_literal (const char *value
)
695 recording::rvalue
*result
=
696 new memento_of_new_string_literal (this, NULL
, new_string (value
));
701 /* Create a recording::unary_op instance and add it to this context's
704 Implements the post-error-checking part of
705 gcc_jit_context_new_unary_op. */
708 recording::context::new_unary_op (recording::location
*loc
,
709 enum gcc_jit_unary_op op
,
710 recording::type
*result_type
,
711 recording::rvalue
*a
)
713 recording::rvalue
*result
=
714 new unary_op (this, loc
, op
, result_type
, a
);
719 /* Create a recording::binary_op instance and add it to this context's
722 Implements the post-error-checking part of
723 gcc_jit_context_new_binary_op. */
726 recording::context::new_binary_op (recording::location
*loc
,
727 enum gcc_jit_binary_op op
,
728 recording::type
*result_type
,
729 recording::rvalue
*a
,
730 recording::rvalue
*b
)
732 recording::rvalue
*result
=
733 new binary_op (this, loc
, op
, result_type
, a
, b
);
738 /* Create a recording::comparison instance and add it to this context's
741 Implements the post-error-checking part of
742 gcc_jit_context_new_comparison. */
745 recording::context::new_comparison (recording::location
*loc
,
746 enum gcc_jit_comparison op
,
747 recording::rvalue
*a
,
748 recording::rvalue
*b
)
750 recording::rvalue
*result
= new comparison (this, loc
, op
, a
, b
);
755 /* Create a recording::cast instance and add it to this context's list
758 Implements the post-error-checking part of
759 gcc_jit_context_new_cast. */
762 recording::context::new_cast (recording::location
*loc
,
763 recording::rvalue
*expr
,
764 recording::type
*type_
)
766 recording::rvalue
*result
= new cast (this, loc
, expr
, type_
);
771 /* Create a recording::call instance and add it to this context's list
774 Implements the post-error-checking part of
775 gcc_jit_context_new_call. */
778 recording::context::new_call (recording::location
*loc
,
780 int numargs
, recording::rvalue
**args
)
782 recording::rvalue
*result
= new call (this, loc
, func
, numargs
, args
);
787 /* Create a recording::call_through_ptr instance and add it to this
788 context's list of mementos.
790 Implements the post-error-checking part of
791 gcc_jit_context_new_call_through_ptr. */
794 recording::context::new_call_through_ptr (recording::location
*loc
,
795 recording::rvalue
*fn_ptr
,
797 recording::rvalue
**args
)
799 recording::rvalue
*result
= new call_through_ptr (this, loc
, fn_ptr
, numargs
, args
);
804 /* Create a recording::array_access instance and add it to this context's list
807 Implements the post-error-checking part of
808 gcc_jit_context_new_array_access. */
811 recording::context::new_array_access (recording::location
*loc
,
812 recording::rvalue
*ptr
,
813 recording::rvalue
*index
)
815 recording::lvalue
*result
= new array_access (this, loc
, ptr
, index
);
820 /* Set the given string option for this context, or add an error if
823 Implements the post-error-checking part of
824 gcc_jit_context_set_str_option. */
827 recording::context::set_str_option (enum gcc_jit_str_option opt
,
830 if (opt
< 0 || opt
>= GCC_JIT_NUM_STR_OPTIONS
)
833 "unrecognized (enum gcc_jit_str_option) value: %i", opt
);
836 free (m_str_options
[opt
]);
837 m_str_options
[opt
] = value
? xstrdup (value
) : NULL
;
840 /* Set the given integer option for this context, or add an error if
843 Implements the post-error-checking part of
844 gcc_jit_context_set_int_option. */
847 recording::context::set_int_option (enum gcc_jit_int_option opt
,
850 if (opt
< 0 || opt
>= GCC_JIT_NUM_INT_OPTIONS
)
853 "unrecognized (enum gcc_jit_int_option) value: %i", opt
);
856 m_int_options
[opt
] = value
;
859 /* Set the given boolean option for this context, or add an error if
862 Implements the post-error-checking part of
863 gcc_jit_context_set_bool_option. */
866 recording::context::set_bool_option (enum gcc_jit_bool_option opt
,
869 if (opt
< 0 || opt
>= GCC_JIT_NUM_BOOL_OPTIONS
)
872 "unrecognized (enum gcc_jit_bool_option) value: %i", opt
);
875 m_bool_options
[opt
] = value
? true : false;
878 /* Add the given dumpname/out_ptr pair to this context's list of requested
881 Implements the post-error-checking part of
882 gcc_jit_context_enable_dump. */
885 recording::context::enable_dump (const char *dumpname
,
889 gcc_assert (dumpname
);
890 gcc_assert (out_ptr
);
892 d
.m_dumpname
= dumpname
;
893 d
.m_out_ptr
= out_ptr
;
895 m_requested_dumps
.safe_push (d
);
898 /* Validate this context, and if it passes, compile it within a
901 Implements the post-error-checking part of
902 gcc_jit_context_compile. */
905 recording::context::compile ()
909 if (errors_occurred ())
912 /* Set up a playback context. */
913 ::gcc::jit::playback::context
replayer (this);
916 result
*result_obj
= replayer
.compile ();
921 /* Format the given error using printf's conventions, print
922 it to stderr, and add it to the context. */
925 recording::context::add_error (location
*loc
, const char *fmt
, ...)
929 add_error_va (loc
, fmt
, ap
);
933 /* Format the given error using printf's conventions, print
934 it to stderr, and add it to the context. */
937 recording::context::add_error_va (location
*loc
, const char *fmt
, va_list ap
)
943 vasprintf (&malloced_msg
, fmt
, ap
);
946 errmsg
= malloced_msg
;
947 has_ownership
= true;
951 errmsg
= "out of memory generating error message";
952 has_ownership
= false;
955 const char *ctxt_progname
=
956 get_str_option (GCC_JIT_STR_OPTION_PROGNAME
);
958 ctxt_progname
= "libgccjit.so";
961 fprintf (stderr
, "%s: %s: error: %s\n",
963 loc
->get_debug_string (),
966 fprintf (stderr
, "%s: error: %s\n",
972 m_first_error_str
= const_cast <char *> (errmsg
);
973 m_owns_first_error_str
= has_ownership
;
982 /* Get the message for the first error that occurred on this context, or
983 NULL if no errors have occurred on it.
985 Implements the post-error-checking part of
986 gcc_jit_context_get_first_error. */
989 recording::context::get_first_error () const
991 return m_first_error_str
;
994 /* Lazily generate and record a recording::type representing an opaque
997 For use if client code tries to dereference the result of
998 get_type (GCC_JIT_TYPE_FILE_PTR). */
1001 recording::context::get_opaque_FILE_type ()
1004 m_FILE_type
= new_struct_type (NULL
, "FILE");
1008 /* Dump a C-like representation of the given context to the given path.
1009 If UPDATE_LOCATIONS is true, update the locations within the
1010 context's mementos to point to the dumpfile.
1012 Implements the post-error-checking part of
1013 gcc_jit_context_dump_to_file. */
1016 recording::context::dump_to_file (const char *path
, bool update_locations
)
1019 dump
d (*this, path
, update_locations
);
1021 /* Forward declaration of structs and unions. */
1023 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1025 d
.write ("%s;\n\n", st
->get_debug_string ());
1028 /* Content of structs, where set. */
1029 FOR_EACH_VEC_ELT (m_compound_types
, i
, st
)
1030 if (st
->get_fields ())
1032 st
->get_fields ()->write_to_dump (d
);
1037 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1039 fn
->write_to_dump (d
);
1043 /* Copy the requested dumps within this context and all ancestors into
1047 recording::context::get_all_requested_dumps (vec
<recording::requested_dump
> *out
)
1050 m_parent_ctxt
->get_all_requested_dumps (out
);
1052 out
->reserve (m_requested_dumps
.length ());
1053 out
->splice (m_requested_dumps
);
1056 /* This is a pre-compilation check for the context (and any parents).
1058 Detect errors within the context, adding errors if any are found. */
1061 recording::context::validate ()
1064 m_parent_ctxt
->validate ();
1068 FOR_EACH_VEC_ELT (m_functions
, i
, fn
)
1072 /* The implementation of class gcc::jit::recording::memento. */
1074 /* Get a (const char *) debug description of the given memento, by
1075 calling the pure-virtual make_debug_string hook, caching the
1078 It is intended that this should only be called in debugging and
1079 error-handling paths, so this doesn't need to be particularly
1083 recording::memento::get_debug_string ()
1085 if (!m_debug_string
)
1086 m_debug_string
= make_debug_string ();
1087 return m_debug_string
->c_str ();
1090 /* Default implementation of recording::memento::write_to_dump, writing
1091 an indented form of the memento's debug string to the dump. */
1094 recording::memento::write_to_dump (dump
&d
)
1096 d
.write(" %s\n", get_debug_string ());
1099 /* The implementation of class gcc::jit::recording::string. */
1101 /* Constructor for gcc::jit::recording::string::string, allocating a
1102 copy of the given text using new char[]. */
1104 recording::string::string (context
*ctxt
, const char *text
)
1107 m_len
= strlen (text
);
1108 m_buffer
= new char[m_len
+ 1];
1109 strcpy (m_buffer
, text
);
1112 /* Destructor for gcc::jit::recording::string::string. */
1114 recording::string::~string ()
1119 /* Function for making gcc::jit::recording::string instances on a
1120 context via printf-style formatting.
1122 It is intended that this should only be called in debugging and
1123 error-handling paths, so this doesn't need to be particularly
1124 optimized, hence the double-copy of the string is acceptable. */
1127 recording::string::from_printf (context
*ctxt
, const char *fmt
, ...)
1131 recording::string
*result
;
1134 vasprintf (&buf
, fmt
, ap
);
1139 ctxt
->add_error (NULL
, "malloc failure");
1143 result
= ctxt
->new_string (buf
);
1148 /* Implementation of recording::memento::make_debug_string for strings,
1149 wrapping the given string in quotes and escaping as necessary. */
1152 recording::string::make_debug_string ()
1154 /* Hack to avoid infinite recursion into strings when logging all
1155 mementos: don't re-escape strings: */
1156 if (m_buffer
[0] == '"')
1159 /* Wrap in quotes and do escaping etc */
1161 size_t sz
= (1 /* opening quote */
1162 + (m_len
* 2) /* each char might get escaped */
1163 + 1 /* closing quote */
1164 + 1); /* nil termintator */
1165 char *tmp
= new char[sz
];
1168 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1169 APPEND('"'); /* opening quote */
1170 for (size_t i
= 0; i
< m_len
; i
++)
1172 char ch
= m_buffer
[i
];
1173 if (ch
== '\t' || ch
== '\n' || ch
== '\\' || ch
== '"')
1177 APPEND('"'); /* closing quote */
1179 tmp
[len
] = '\0'; /* nil termintator */
1181 string
*result
= m_ctxt
->new_string (tmp
);
1187 /* The implementation of class gcc::jit::recording::location. */
1189 /* Implementation of recording::memento::replay_into for locations.
1191 Create a new playback::location and store it into the
1192 recording::location's m_playback_obj field. */
1195 recording::location::replay_into (replayer
*r
)
1197 m_playback_obj
= r
->new_location (this,
1198 m_filename
->c_str (),
1203 /* Implementation of recording::memento::make_debug_string for locations,
1204 turning them into the usual form:
1205 FILENAME:LINE:COLUMN
1206 like we do when emitting diagnostics. */
1209 recording::location::make_debug_string ()
1211 return string::from_printf (m_ctxt
,
1213 m_filename
->c_str (), m_line
, m_column
);
1216 /* The implementation of class gcc::jit::recording::type. */
1218 /* Given a type T, get the type T*.
1220 If this doesn't already exist, generate a new memento_of_get_pointer
1221 instance and add it to this type's context's list of mementos.
1223 Otherwise, use the cached type.
1225 Implements the post-error-checking part of
1226 gcc_jit_type_get_pointer. */
1229 recording::type::get_pointer ()
1231 if (!m_pointer_to_this_type
)
1233 m_pointer_to_this_type
= new memento_of_get_pointer (this);
1234 m_ctxt
->record (m_pointer_to_this_type
);
1236 return m_pointer_to_this_type
;
1239 /* Given a type T, get the type const T.
1241 Implements the post-error-checking part of
1242 gcc_jit_type_get_const. */
1245 recording::type::get_const ()
1247 recording::type
*result
= new memento_of_get_const (this);
1248 m_ctxt
->record (result
);
1252 /* Given a type T, get the type volatile T.
1254 Implements the post-error-checking part of
1255 gcc_jit_type_get_volatile. */
1258 recording::type::get_volatile ()
1260 recording::type
*result
= new memento_of_get_volatile (this);
1261 m_ctxt
->record (result
);
1265 /* Implementation of pure virtual hook recording::type::dereference for
1266 recording::memento_of_get_type. */
1269 recording::memento_of_get_type::dereference ()
1273 default: gcc_unreachable ();
1275 case GCC_JIT_TYPE_VOID
:
1278 case GCC_JIT_TYPE_VOID_PTR
:
1279 return m_ctxt
->get_type (GCC_JIT_TYPE_VOID
);
1281 case GCC_JIT_TYPE_BOOL
:
1282 case GCC_JIT_TYPE_CHAR
:
1283 case GCC_JIT_TYPE_SIGNED_CHAR
:
1284 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1285 case GCC_JIT_TYPE_SHORT
:
1286 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1287 case GCC_JIT_TYPE_INT
:
1288 case GCC_JIT_TYPE_UNSIGNED_INT
:
1289 case GCC_JIT_TYPE_LONG
:
1290 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1291 case GCC_JIT_TYPE_LONG_LONG
:
1292 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1293 case GCC_JIT_TYPE_FLOAT
:
1294 case GCC_JIT_TYPE_DOUBLE
:
1295 case GCC_JIT_TYPE_LONG_DOUBLE
:
1296 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1297 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1298 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1299 /* Not a pointer: */
1302 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1303 return m_ctxt
->get_type (GCC_JIT_TYPE_CHAR
)->get_const ();
1305 case GCC_JIT_TYPE_SIZE_T
:
1306 /* Not a pointer: */
1309 case GCC_JIT_TYPE_FILE_PTR
:
1310 /* Give the client code back an opaque "struct FILE". */
1311 return m_ctxt
->get_opaque_FILE_type ();
1315 /* Implementation of pure virtual hook recording::type::is_int for
1316 recording::memento_of_get_type. */
1319 recording::memento_of_get_type::is_int () const
1323 default: gcc_unreachable ();
1325 case GCC_JIT_TYPE_VOID
:
1328 case GCC_JIT_TYPE_VOID_PTR
:
1331 case GCC_JIT_TYPE_BOOL
:
1334 case GCC_JIT_TYPE_CHAR
:
1335 case GCC_JIT_TYPE_SIGNED_CHAR
:
1336 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1337 case GCC_JIT_TYPE_SHORT
:
1338 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1339 case GCC_JIT_TYPE_INT
:
1340 case GCC_JIT_TYPE_UNSIGNED_INT
:
1341 case GCC_JIT_TYPE_LONG
:
1342 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1343 case GCC_JIT_TYPE_LONG_LONG
:
1344 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1347 case GCC_JIT_TYPE_FLOAT
:
1348 case GCC_JIT_TYPE_DOUBLE
:
1349 case GCC_JIT_TYPE_LONG_DOUBLE
:
1352 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1355 case GCC_JIT_TYPE_SIZE_T
:
1358 case GCC_JIT_TYPE_FILE_PTR
:
1361 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1362 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1363 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1368 /* Implementation of pure virtual hook recording::type::is_float for
1369 recording::memento_of_get_type. */
1372 recording::memento_of_get_type::is_float () const
1376 default: gcc_unreachable ();
1378 case GCC_JIT_TYPE_VOID
:
1381 case GCC_JIT_TYPE_VOID_PTR
:
1384 case GCC_JIT_TYPE_BOOL
:
1387 case GCC_JIT_TYPE_CHAR
:
1388 case GCC_JIT_TYPE_SIGNED_CHAR
:
1389 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1390 case GCC_JIT_TYPE_SHORT
:
1391 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1392 case GCC_JIT_TYPE_INT
:
1393 case GCC_JIT_TYPE_UNSIGNED_INT
:
1394 case GCC_JIT_TYPE_LONG
:
1395 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1396 case GCC_JIT_TYPE_LONG_LONG
:
1397 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1400 case GCC_JIT_TYPE_FLOAT
:
1401 case GCC_JIT_TYPE_DOUBLE
:
1402 case GCC_JIT_TYPE_LONG_DOUBLE
:
1405 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1408 case GCC_JIT_TYPE_SIZE_T
:
1411 case GCC_JIT_TYPE_FILE_PTR
:
1414 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1415 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1416 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1421 /* Implementation of pure virtual hook recording::type::is_bool for
1422 recording::memento_of_get_type. */
1425 recording::memento_of_get_type::is_bool () const
1429 default: gcc_unreachable ();
1431 case GCC_JIT_TYPE_VOID
:
1434 case GCC_JIT_TYPE_VOID_PTR
:
1437 case GCC_JIT_TYPE_BOOL
:
1440 case GCC_JIT_TYPE_CHAR
:
1441 case GCC_JIT_TYPE_SIGNED_CHAR
:
1442 case GCC_JIT_TYPE_UNSIGNED_CHAR
:
1443 case GCC_JIT_TYPE_SHORT
:
1444 case GCC_JIT_TYPE_UNSIGNED_SHORT
:
1445 case GCC_JIT_TYPE_INT
:
1446 case GCC_JIT_TYPE_UNSIGNED_INT
:
1447 case GCC_JIT_TYPE_LONG
:
1448 case GCC_JIT_TYPE_UNSIGNED_LONG
:
1449 case GCC_JIT_TYPE_LONG_LONG
:
1450 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG
:
1453 case GCC_JIT_TYPE_FLOAT
:
1454 case GCC_JIT_TYPE_DOUBLE
:
1455 case GCC_JIT_TYPE_LONG_DOUBLE
:
1458 case GCC_JIT_TYPE_CONST_CHAR_PTR
:
1461 case GCC_JIT_TYPE_SIZE_T
:
1464 case GCC_JIT_TYPE_FILE_PTR
:
1467 case GCC_JIT_TYPE_COMPLEX_FLOAT
:
1468 case GCC_JIT_TYPE_COMPLEX_DOUBLE
:
1469 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE
:
1474 /* Implementation of pure virtual hook recording::memento::replay_into
1475 for recording::memento_of_get_type. */
1478 recording::memento_of_get_type::replay_into (replayer
*r
)
1480 set_playback_obj (r
->get_type (m_kind
));
1483 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
1485 /* Descriptive strings for each of enum gcc_jit_types. */
1487 static const char * const get_type_strings
[] = {
1488 "void", /* GCC_JIT_TYPE_VOID */
1489 "void *", /* GCC_JIT_TYPE_VOID_PTR */
1491 "bool", /* GCC_JIT_TYPE_BOOL */
1493 "char", /* GCC_JIT_TYPE_CHAR */
1494 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
1495 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
1497 "short", /* GCC_JIT_TYPE_SHORT */
1498 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
1500 "int", /* GCC_JIT_TYPE_INT */
1501 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
1503 "long", /* GCC_JIT_TYPE_LONG */
1504 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
1506 "long long", /* GCC_JIT_TYPE_LONG_LONG */
1507 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
1509 "float", /* GCC_JIT_TYPE_FLOAT */
1510 "double", /* GCC_JIT_TYPE_DOUBLE */
1511 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
1513 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
1515 "size_t", /* GCC_JIT_TYPE_SIZE_T */
1517 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
1519 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
1520 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
1521 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
1525 /* Implementation of recording::memento::make_debug_string for
1526 results of get_type, using a simple table of type names. */
1529 recording::memento_of_get_type::make_debug_string ()
1531 return m_ctxt
->new_string (get_type_strings
[m_kind
]);
1534 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
1536 /* Override of default implementation of
1537 recording::type::accepts_writes_from for get_pointer.
1539 Require a pointer type, and allowing writes to
1540 (const T *) from a (T*), but not the other way around. */
1543 recording::memento_of_get_pointer::accepts_writes_from (type
*rtype
)
1545 /* Must be a pointer type: */
1546 type
*rtype_points_to
= rtype
->is_pointer ();
1547 if (!rtype_points_to
)
1550 /* It's OK to assign to a (const T *) from a (T *). */
1551 return m_other_type
->unqualified ()
1552 ->accepts_writes_from (rtype_points_to
);
1555 /* Implementation of pure virtual hook recording::memento::replay_into
1556 for recording::memento_of_get_pointer. */
1559 recording::memento_of_get_pointer::replay_into (replayer
*)
1561 set_playback_obj (m_other_type
->playback_type ()->get_pointer ());
1564 /* Implementation of recording::memento::make_debug_string for
1565 results of get_pointer, adding " *" to the underlying type,
1566 with special-casing to handle function pointer types. */
1569 recording::memento_of_get_pointer::make_debug_string ()
1571 /* Special-case function pointer types, to put the "*" in parens between
1572 the return type and the params (for one level of dereferencing, at
1574 if (function_type
*fn_type
= m_other_type
->dyn_cast_function_type ())
1575 return fn_type
->make_debug_string_with_ptr ();
1577 return string::from_printf (m_ctxt
,
1578 "%s *", m_other_type
->get_debug_string ());
1581 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
1583 /* Implementation of pure virtual hook recording::memento::replay_into
1584 for recording::memento_of_get_const. */
1587 recording::memento_of_get_const::replay_into (replayer
*)
1589 set_playback_obj (m_other_type
->playback_type ()->get_const ());
1592 /* Implementation of recording::memento::make_debug_string for
1593 results of get_const, prepending "const ". */
1596 recording::memento_of_get_const::make_debug_string ()
1598 return string::from_printf (m_ctxt
,
1599 "const %s", m_other_type
->get_debug_string ());
1602 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
1604 /* Implementation of pure virtual hook recording::memento::replay_into
1605 for recording::memento_of_get_volatile. */
1608 recording::memento_of_get_volatile::replay_into (replayer
*)
1610 set_playback_obj (m_other_type
->playback_type ()->get_volatile ());
1613 /* Implementation of recording::memento::make_debug_string for
1614 results of get_volatile, prepending "volatile ". */
1617 recording::memento_of_get_volatile::make_debug_string ()
1619 return string::from_printf (m_ctxt
,
1620 "volatile %s", m_other_type
->get_debug_string ());
1623 /* The implementation of class gcc::jit::recording::array_type */
1625 /* Implementation of pure virtual hook recording::type::dereference for
1626 recording::array_type. */
1629 recording::array_type::dereference ()
1631 return m_element_type
;
1634 /* Implementation of pure virtual hook recording::memento::replay_into
1635 for recording::array_type. */
1638 recording::array_type::replay_into (replayer
*r
)
1640 set_playback_obj (r
->new_array_type (playback_location (r
, m_loc
),
1641 m_element_type
->playback_type (),
1645 /* Implementation of recording::memento::make_debug_string for
1646 results of new_array_type. */
1649 recording::array_type::make_debug_string ()
1651 return string::from_printf (m_ctxt
,
1653 m_element_type
->get_debug_string (),
1657 /* The implementation of class gcc::jit::recording::function_type */
1659 /* Constructor for gcc::jit::recording::function_type. */
1661 recording::function_type::function_type (context
*ctxt
,
1667 m_return_type (return_type
),
1669 m_is_variadic (is_variadic
)
1671 for (int i
= 0; i
< num_params
; i
++)
1672 m_param_types
.safe_push (param_types
[i
]);
1675 /* Implementation of pure virtual hook recording::type::dereference for
1676 recording::function_type. */
1679 recording::function_type::dereference ()
1684 /* Implementation of pure virtual hook recording::memento::replay_into
1685 for recording::function_type. */
1688 recording::function_type::replay_into (replayer
*r
)
1690 /* Convert m_param_types to a vec of playback type. */
1691 auto_vec
<playback::type
*> param_types
;
1693 recording::type
*type
;
1694 param_types
.create (m_param_types
.length ());
1695 FOR_EACH_VEC_ELT (m_param_types
, i
, type
)
1696 param_types
.safe_push (type
->playback_type ());
1698 set_playback_obj (r
->new_function_type (m_return_type
->playback_type (),
1703 /* Special-casing for make_debug_string for get_pointer results for
1704 handling (one level) of pointers to functions. */
1707 recording::function_type::make_debug_string_with_ptr ()
1709 return make_debug_string_with ("(*) ");
1712 /* Implementation of recording::memento::make_debug_string for
1713 results of new_function_type. */
1716 recording::function_type::make_debug_string ()
1718 return make_debug_string_with ("");
1721 /* Build a debug string representation of the form:
1723 RESULT_TYPE INSERT (PARAM_TYPES)
1725 for use when handling 0 and 1 level of indirection to this
1729 recording::function_type::make_debug_string_with (const char *insert
)
1731 /* First, build a buffer for the arguments. */
1732 /* Calculate length of said buffer. */
1733 size_t sz
= 1; /* nil terminator */
1734 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
1736 sz
+= strlen (m_param_types
[i
]->get_debug_string ());
1737 sz
+= 2; /* ", " separator */
1740 sz
+= 5; /* ", ..." separator and ellipsis */
1742 /* Now allocate and populate the buffer. */
1743 char *argbuf
= new char[sz
];
1746 for (unsigned i
= 0; i
< m_param_types
.length (); i
++)
1748 strcpy (argbuf
+ len
, m_param_types
[i
]->get_debug_string ());
1749 len
+= strlen (m_param_types
[i
]->get_debug_string ());
1750 if (i
+ 1 < m_param_types
.length ())
1752 strcpy (argbuf
+ len
, ", ");
1758 if (m_param_types
.length ())
1760 strcpy (argbuf
+ len
, ", ");
1763 strcpy (argbuf
+ len
, "...");
1768 /* ...and use it to get the string for the call as a whole. */
1769 string
*result
= string::from_printf (m_ctxt
,
1771 m_return_type
->get_debug_string (),
1780 /* The implementation of class gcc::jit::recording::field. */
1782 /* Implementation of pure virtual hook recording::memento::replay_into
1783 for recording::field. */
1786 recording::field::replay_into (replayer
*r
)
1788 set_playback_obj (r
->new_field (playback_location (r
, m_loc
),
1789 m_type
->playback_type (),
1790 playback_string (m_name
)));
1793 /* Override the default implementation of
1794 recording::memento::write_to_dump. Dump each field
1795 by dumping a line of the form:
1797 so that we can build up a struct/union field-byfield. */
1800 recording::field::write_to_dump (dump
&d
)
1802 d
.write (" %s %s;\n",
1803 m_type
->get_debug_string (),
1807 /* Implementation of recording::memento::make_debug_string for
1808 results of new_field. */
1811 recording::field::make_debug_string ()
1816 /* The implementation of class gcc::jit::recording::compound_type */
1818 /* The constructor for gcc::jit::recording::compound_type. */
1820 recording::compound_type::compound_type (context
*ctxt
,
1830 /* Set the fields of a compound type.
1832 Implements the post-error-checking part of
1833 gcc_jit_struct_set_fields, and is also used by
1834 gcc_jit_context_new_union_type. */
1837 recording::compound_type::set_fields (location
*loc
,
1839 field
**field_array
)
1842 gcc_assert (NULL
== m_fields
);
1844 m_fields
= new fields (this, num_fields
, field_array
);
1845 m_ctxt
->record (m_fields
);
1848 /* Implementation of pure virtual hook recording::type::dereference for
1849 recording::compound_type. */
1852 recording::compound_type::dereference ()
1854 return NULL
; /* not a pointer */
1857 /* The implementation of class gcc::jit::recording::struct_. */
1859 /* The constructor for gcc::jit::recording::struct_. */
1861 recording::struct_::struct_ (context
*ctxt
,
1864 : compound_type (ctxt
, loc
, name
)
1868 /* Implementation of pure virtual hook recording::memento::replay_into
1869 for recording::struct_. */
1872 recording::struct_::replay_into (replayer
*r
)
1875 r
->new_compound_type (playback_location (r
, get_loc ()),
1876 get_name ()->c_str (),
1877 true /* is_struct */));
1880 /* Implementation of recording::memento::make_debug_string for
1884 recording::struct_::make_debug_string ()
1886 return string::from_printf (m_ctxt
,
1887 "struct %s", get_name ()->c_str ());
1890 /* The implementation of class gcc::jit::recording::union_. */
1892 /* The constructor for gcc::jit::recording::union_. */
1894 recording::union_::union_ (context
*ctxt
,
1897 : compound_type (ctxt
, loc
, name
)
1901 /* Implementation of pure virtual hook recording::memento::replay_into
1902 for recording::union_. */
1905 recording::union_::replay_into (replayer
*r
)
1908 r
->new_compound_type (playback_location (r
, get_loc ()),
1909 get_name ()->c_str (),
1910 false /* is_struct */));
1913 /* Implementation of recording::memento::make_debug_string for
1917 recording::union_::make_debug_string ()
1919 return string::from_printf (m_ctxt
,
1920 "union %s", get_name ()->c_str ());
1923 /* The implementation of class gcc::jit::recording::fields. */
1925 /* The constructor for gcc::jit::recording::fields. */
1927 recording::fields::fields (compound_type
*struct_or_union
,
1930 : memento (struct_or_union
->m_ctxt
),
1931 m_struct_or_union (struct_or_union
),
1934 for (int i
= 0; i
< num_fields
; i
++)
1936 gcc_assert (fields
[i
]->get_container () == NULL
);
1937 fields
[i
]->set_container (m_struct_or_union
);
1938 m_fields
.safe_push (fields
[i
]);
1942 /* Implementation of pure virtual hook recording::memento::replay_into
1943 for recording::fields. */
1946 recording::fields::replay_into (replayer
*)
1948 auto_vec
<playback::field
*> playback_fields
;
1949 playback_fields
.create (m_fields
.length ());
1950 for (unsigned i
= 0; i
< m_fields
.length (); i
++)
1951 playback_fields
.safe_push (m_fields
[i
]->playback_field ());
1952 m_struct_or_union
->playback_compound_type ()->set_fields (&playback_fields
);
1955 /* Override the default implementation of
1956 recording::memento::write_to_dump by writing a union/struct
1957 declaration of this form:
1969 recording::fields::write_to_dump (dump
&d
)
1974 d
.write ("%s\n{\n", m_struct_or_union
->get_debug_string ());
1975 FOR_EACH_VEC_ELT (m_fields
, i
, f
)
1976 f
->write_to_dump (d
);
1980 /* Implementation of recording::memento::make_debug_string for
1984 recording::fields::make_debug_string ()
1986 return string::from_printf (m_ctxt
,
1990 /* The implementation of class gcc::jit::recording::rvalue. */
1992 /* Create a recording::access_field_rvalue instance and add it to
1993 the rvalue's context's list of mementos.
1995 Implements the post-error-checking part of
1996 gcc_jit_rvalue_access_field. */
1999 recording::rvalue::access_field (recording::location
*loc
,
2002 recording::rvalue
*result
=
2003 new access_field_rvalue (m_ctxt
, loc
, this, field
);
2004 m_ctxt
->record (result
);
2008 /* Create a recording::dereference_field_rvalue instance and add it to
2009 the rvalue's context's list of mementos.
2011 Implements the post-error-checking part of
2012 gcc_jit_rvalue_dereference_field. */
2015 recording::rvalue::dereference_field (recording::location
*loc
,
2018 recording::lvalue
*result
=
2019 new dereference_field_rvalue (m_ctxt
, loc
, this, field
);
2020 m_ctxt
->record (result
);
2024 /* Create a recording::dereference_rvalue instance and add it to the
2025 rvalue's context's list of mementos.
2027 Implements the post-error-checking part of
2028 gcc_jit_rvalue_dereference. */
2031 recording::rvalue::dereference (recording::location
*loc
)
2033 recording::lvalue
*result
=
2034 new dereference_rvalue (m_ctxt
, loc
, this);
2035 m_ctxt
->record (result
);
2039 /* The implementation of class gcc::jit::recording::lvalue. */
2041 /* Create a recording::new_access_field_of_lvalue instance and add it to
2042 the lvalue's context's list of mementos.
2044 Implements the post-error-checking part of
2045 gcc_jit_lvalue_access_field. */
2048 recording::lvalue::access_field (recording::location
*loc
,
2051 recording::lvalue
*result
=
2052 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
2053 m_ctxt
->record (result
);
2057 /* Create a recording::get_address_of_lvalue instance and add it to
2058 the lvalue's context's list of mementos.
2060 Implements the post-error-checking part of
2061 gcc_jit_lvalue_get_address. */
2064 recording::lvalue::get_address (recording::location
*loc
)
2066 recording::rvalue
*result
=
2067 new get_address_of_lvalue (m_ctxt
, loc
, this);
2068 m_ctxt
->record (result
);
2072 /* The implementation of class gcc::jit::recording::param. */
2074 /* Implementation of pure virtual hook recording::memento::replay_into
2075 for recording::param. */
2078 recording::param::replay_into (replayer
*r
)
2080 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
2081 m_type
->playback_type (),
2086 /* The implementation of class gcc::jit::recording::function. */
2088 /* gcc::jit::recording::function's constructor. */
2090 recording::function::function (context
*ctxt
,
2091 recording::location
*loc
,
2092 enum gcc_jit_function_kind kind
,
2094 recording::string
*name
,
2096 recording::param
**params
,
2098 enum built_in_function builtin_id
)
2102 m_return_type (return_type
),
2105 m_is_variadic (is_variadic
),
2106 m_builtin_id (builtin_id
),
2110 for (int i
= 0; i
< num_params
; i
++)
2111 m_params
.safe_push (params
[i
]);
2114 /* Implementation of pure virtual hook recording::memento::replay_into
2115 for recording::function. */
2118 recording::function::replay_into (replayer
*r
)
2120 /* Convert m_params to a vec of playback param. */
2121 auto_vec
<playback::param
*> params
;
2123 recording::param
*param
;
2124 params
.create (m_params
.length ());
2125 FOR_EACH_VEC_ELT (m_params
, i
, param
)
2126 params
.safe_push (param
->playback_param ());
2128 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
2130 m_return_type
->playback_type (),
2137 /* Create a recording::local instance and add it to
2138 the functions's context's list of mementos, and to the function's
2141 Implements the post-error-checking part of
2142 gcc_jit_function_new_local. */
2145 recording::function::new_local (recording::location
*loc
,
2149 local
*result
= new local (this, loc
, type
, new_string (name
));
2150 m_ctxt
->record (result
);
2151 m_locals
.safe_push (result
);
2155 /* Create a recording::block instance and add it to
2156 the functions's context's list of mementos, and to the function's
2159 Implements the post-error-checking part of
2160 gcc_jit_function_new_block. */
2163 recording::function::new_block (const char *name
)
2165 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
2167 recording::block
*result
=
2168 new recording::block (this, m_blocks
.length (), new_string (name
));
2169 m_ctxt
->record (result
);
2170 m_blocks
.safe_push (result
);
2174 /* Override the default implementation of
2175 recording::memento::write_to_dump by dumping a C-like
2176 representation of the function; either like a prototype
2177 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
2178 all other kinds of function. */
2181 recording::function::write_to_dump (dump
&d
)
2185 default: gcc_unreachable ();
2186 case GCC_JIT_FUNCTION_EXPORTED
:
2187 case GCC_JIT_FUNCTION_IMPORTED
:
2188 d
.write ("extern ");
2190 case GCC_JIT_FUNCTION_INTERNAL
:
2191 d
.write ("static ");
2193 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
2194 d
.write ("static inline ");
2197 d
.write ("%s\n", m_return_type
->get_debug_string ());
2199 if (d
.update_locations ())
2200 m_loc
= d
.make_location ();
2202 d
.write ("%s (", get_debug_string ());
2205 recording::param
*param
;
2206 FOR_EACH_VEC_ELT (m_params
, i
, param
)
2211 param
->get_type ()->get_debug_string (),
2212 param
->get_debug_string ());
2215 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
2217 d
.write ("; /* (imported) */\n\n");
2227 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
2228 var
->write_to_dump (d
);
2229 if (m_locals
.length ())
2232 /* Write each block: */
2233 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2237 b
->write_to_dump (d
);
2244 /* Pre-compilation validation of a function, for those things we can't
2245 check until the context is (supposedly) fully-populated. */
2248 recording::function::validate ()
2250 /* Complain about empty functions with non-void return type. */
2251 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
2252 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
2253 if (0 == m_blocks
.length ())
2254 m_ctxt
->add_error (m_loc
,
2255 "function %s returns non-void (type: %s)"
2256 " but has no blocks",
2257 get_debug_string (),
2258 m_return_type
->get_debug_string ());
2260 /* Check that all blocks are terminated. */
2261 int num_invalid_blocks
= 0;
2266 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2267 if (!b
->validate ())
2268 num_invalid_blocks
++;
2271 /* Check that all blocks are reachable. */
2272 if (m_blocks
.length () > 0 && 0 == num_invalid_blocks
)
2274 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
2275 flag, starting at the initial block. */
2276 auto_vec
<block
*> worklist (m_blocks
.length ());
2277 worklist
.safe_push (m_blocks
[0]);
2278 while (worklist
.length () > 0)
2280 block
*b
= worklist
.pop ();
2281 b
->m_is_reachable
= true;
2283 /* Add successor blocks that aren't yet marked to the worklist. */
2284 /* We checked that each block has a terminating statement above . */
2285 block
*next1
, *next2
;
2286 int n
= b
->get_successor_blocks (&next1
, &next2
);
2292 if (!next2
->m_is_reachable
)
2293 worklist
.safe_push (next2
);
2296 if (!next1
->m_is_reachable
)
2297 worklist
.safe_push (next1
);
2304 /* Now complain about any blocks that haven't been marked. */
2308 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2309 if (!b
->m_is_reachable
)
2310 m_ctxt
->add_error (b
->get_loc (),
2311 "unreachable block: %s",
2312 b
->get_debug_string ());
2317 /* Implements the post-error-checking part of
2318 gcc_jit_function_dump_to_dot. */
2321 recording::function::dump_to_dot (const char *path
)
2323 FILE *fp
= fopen (path
, "w");
2327 pretty_printer the_pp
;
2328 the_pp
.buffer
->stream
= fp
;
2330 pretty_printer
*pp
= &the_pp
;
2333 "digraph %s {\n", get_debug_string ());
2339 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2340 b
->dump_to_dot (pp
);
2347 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2348 b
->dump_edges_to_dot (pp
);
2351 pp_printf (pp
, "}\n");
2356 /* Implementation of recording::memento::make_debug_string for
2360 recording::function::make_debug_string ()
2365 /* The implementation of class gcc::jit::recording::block. */
2367 /* Create a recording::eval instance and add it to
2368 the block's context's list of mementos, and to the block's
2371 Implements the post-error-checking part of
2372 gcc_jit_block_add_eval. */
2375 recording::block::add_eval (recording::location
*loc
,
2376 recording::rvalue
*rvalue
)
2378 statement
*result
= new eval (this, loc
, rvalue
);
2379 m_ctxt
->record (result
);
2380 m_statements
.safe_push (result
);
2383 /* Create a recording::assignment instance and add it to
2384 the block's context's list of mementos, and to the block's
2387 Implements the post-error-checking part of
2388 gcc_jit_block_add_assignment. */
2391 recording::block::add_assignment (recording::location
*loc
,
2392 recording::lvalue
*lvalue
,
2393 recording::rvalue
*rvalue
)
2395 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
2396 m_ctxt
->record (result
);
2397 m_statements
.safe_push (result
);
2400 /* Create a recording::assignment_op instance and add it to
2401 the block's context's list of mementos, and to the block's
2404 Implements the post-error-checking part of
2405 gcc_jit_block_add_assignment_op. */
2408 recording::block::add_assignment_op (recording::location
*loc
,
2409 recording::lvalue
*lvalue
,
2410 enum gcc_jit_binary_op op
,
2411 recording::rvalue
*rvalue
)
2413 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
2414 m_ctxt
->record (result
);
2415 m_statements
.safe_push (result
);
2418 /* Create a recording::comment instance and add it to
2419 the block's context's list of mementos, and to the block's
2422 Implements the post-error-checking part of
2423 gcc_jit_block_add_comment. */
2426 recording::block::add_comment (recording::location
*loc
,
2429 statement
*result
= new comment (this, loc
, new_string (text
));
2430 m_ctxt
->record (result
);
2431 m_statements
.safe_push (result
);
2434 /* Create a recording::end_with_conditional instance and add it to
2435 the block's context's list of mementos, and to the block's
2438 Implements the post-error-checking part of
2439 gcc_jit_block_end_with_conditional. */
2442 recording::block::end_with_conditional (recording::location
*loc
,
2443 recording::rvalue
*boolval
,
2444 recording::block
*on_true
,
2445 recording::block
*on_false
)
2447 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
2448 m_ctxt
->record (result
);
2449 m_statements
.safe_push (result
);
2450 m_has_been_terminated
= true;
2453 /* Create a recording::end_with_jump instance and add it to
2454 the block's context's list of mementos, and to the block's
2457 Implements the post-error-checking part of
2458 gcc_jit_block_end_with_jump. */
2461 recording::block::end_with_jump (recording::location
*loc
,
2462 recording::block
*target
)
2464 statement
*result
= new jump (this, loc
, target
);
2465 m_ctxt
->record (result
);
2466 m_statements
.safe_push (result
);
2467 m_has_been_terminated
= true;
2470 /* Create a recording::end_with_return instance and add it to
2471 the block's context's list of mementos, and to the block's
2474 Implements the post-error-checking parts of
2475 gcc_jit_block_end_with_return and
2476 gcc_jit_block_end_with_void_return. */
2479 recording::block::end_with_return (recording::location
*loc
,
2480 recording::rvalue
*rvalue
)
2482 /* This is used by both gcc_jit_function_add_return and
2483 gcc_jit_function_add_void_return; rvalue will be non-NULL for
2484 the former and NULL for the latter. */
2485 statement
*result
= new return_ (this, loc
, rvalue
);
2486 m_ctxt
->record (result
);
2487 m_statements
.safe_push (result
);
2488 m_has_been_terminated
= true;
2491 /* Override the default implementation of
2492 recording::memento::write_to_dump for blocks by writing
2493 an unindented block name as a label, followed by the indented
2503 recording::block::write_to_dump (dump
&d
)
2505 d
.write ("%s:\n", get_debug_string ());
2509 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
2510 s
->write_to_dump (d
);
2513 /* Validate a block by ensuring that it has been terminated. */
2516 recording::block::validate ()
2518 if (!has_been_terminated ())
2520 statement
*stmt
= get_last_statement ();
2521 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
2522 m_func
->get_context ()->add_error (loc
,
2523 "unterminated block in %s: %s",
2524 m_func
->get_debug_string (),
2525 get_debug_string ());
2532 /* Get the source-location of a block by using that of the first
2533 statement within it, if any. */
2535 recording::location
*
2536 recording::block::get_loc () const
2538 recording::statement
*stmt
= get_first_statement ();
2540 return stmt
->get_loc ();
2545 /* Get the first statement within a block, if any. */
2547 recording::statement
*
2548 recording::block::get_first_statement () const
2550 if (m_statements
.length ())
2551 return m_statements
[0];
2556 /* Get the last statement within a block, if any. */
2558 recording::statement
*
2559 recording::block::get_last_statement () const
2561 if (m_statements
.length ())
2562 return m_statements
[m_statements
.length () - 1];
2567 /* Assuming that this block has been terminated, get the number of
2568 successor blocks, which will be 0, 1 or 2, for return, unconditional
2569 jump, and conditional jump respectively.
2570 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
2571 is written to NEXT1, and the second (if any) to NEXT2.
2573 Used when validating functions, and when dumping dot representations
2577 recording::block::get_successor_blocks (block
**next1
, block
**next2
) const
2579 gcc_assert (m_has_been_terminated
);
2582 statement
*last_statement
= get_last_statement ();
2583 gcc_assert (last_statement
);
2584 return last_statement
->get_successor_blocks (next1
, next2
);
2587 /* Implementation of pure virtual hook recording::memento::replay_into
2588 for recording::block. */
2591 recording::block::replay_into (replayer
*)
2593 set_playback_obj (m_func
->playback_function ()
2594 ->new_block (playback_string (m_name
)));
2597 /* Implementation of recording::memento::make_debug_string for
2601 recording::block::make_debug_string ()
2606 return string::from_printf (m_ctxt
,
2607 "<UNNAMED BLOCK %p>",
2611 /* Dump a block in graphviz form into PP, capturing the block name (if
2612 any) and the statements. */
2615 recording::block::dump_to_dot (pretty_printer
*pp
)
2619 "[shape=record,style=filled,fillcolor=white,label=\"{"),
2621 pp_write_text_to_stream (pp
);
2624 pp_string (pp
, m_name
->c_str ());
2625 pp_string (pp
, ":");
2627 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
2632 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
2634 pp_string (pp
, s
->get_debug_string ());
2636 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
2644 /* Dump the out-edges of the block in graphviz form into PP. */
2647 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
2650 int num_succs
= get_successor_blocks (&next
[0], &next
[1]);
2651 for (int i
= 0; i
< num_succs
; i
++)
2653 "\tblock_%d:s -> block_%d:n;\n",
2654 m_index
, next
[i
]->m_index
);
2657 /* The implementation of class gcc::jit::recording::global. */
2659 /* Implementation of pure virtual hook recording::memento::replay_into
2660 for recording::global. */
2663 recording::global::replay_into (replayer
*r
)
2665 set_playback_obj (r
->new_global (playback_location (r
, m_loc
),
2666 m_type
->playback_type (),
2667 playback_string (m_name
)));
2670 /* The implementation of class gcc::jit::recording::memento_of_new_rvalue_from_int. */
2672 /* Implementation of pure virtual hook recording::memento::replay_into
2673 for recording::memento_of_new_rvalue_from_int. */
2676 recording::memento_of_new_rvalue_from_int::replay_into (replayer
*r
)
2678 set_playback_obj (r
->new_rvalue_from_int (m_type
->playback_type (),
2682 /* Implementation of recording::memento::make_debug_string for
2683 rvalue_from_int, rendering it as
2689 recording::memento_of_new_rvalue_from_int::make_debug_string ()
2691 return string::from_printf (m_ctxt
,
2693 m_type
->get_debug_string (),
2697 /* The implementation of class gcc::jit::recording::memento_of_new_rvalue_from_double. */
2699 /* Implementation of pure virtual hook recording::memento::replay_into
2700 for recording::memento_of_new_rvalue_from_double. */
2703 recording::memento_of_new_rvalue_from_double::replay_into (replayer
*r
)
2705 set_playback_obj (r
->new_rvalue_from_double (m_type
->playback_type (),
2709 /* Implementation of recording::memento::make_debug_string for
2710 rvalue_from_double, rendering it as
2716 recording::memento_of_new_rvalue_from_double::make_debug_string ()
2718 return string::from_printf (m_ctxt
,
2720 m_type
->get_debug_string (),
2724 /* The implementation of class gcc::jit::recording::memento_of_new_rvalue_from_ptr. */
2726 /* Implementation of pure virtual hook recording::memento::replay_into
2727 for recording::memento_of_new_rvalue_from_ptr. */
2730 recording::memento_of_new_rvalue_from_ptr::replay_into (replayer
*r
)
2732 set_playback_obj (r
->new_rvalue_from_ptr (m_type
->playback_type (),
2736 /* Implementation of recording::memento::make_debug_string for
2737 rvalue_from_ptr, rendering it as
2742 Zero is rendered as NULL e.g.
2746 recording::memento_of_new_rvalue_from_ptr::make_debug_string ()
2748 if (m_value
!= NULL
)
2749 return string::from_printf (m_ctxt
,
2751 m_type
->get_debug_string (), m_value
);
2753 return string::from_printf (m_ctxt
,
2755 m_type
->get_debug_string ());
2758 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
2760 /* Implementation of pure virtual hook recording::memento::replay_into
2761 for recording::memento_of_new_string_literal. */
2764 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
2766 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
2769 /* Implementation of recording::memento::make_debug_string for
2773 recording::memento_of_new_string_literal::make_debug_string ()
2775 return string::from_printf (m_ctxt
,
2776 m_value
->get_debug_string ());
2779 /* The implementation of class gcc::jit::recording::unary_op. */
2781 /* Implementation of pure virtual hook recording::memento::replay_into
2782 for recording::unary_op. */
2785 recording::unary_op::replay_into (replayer
*r
)
2787 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
2789 get_type ()->playback_type (),
2790 m_a
->playback_rvalue ()));
2793 /* Implementation of recording::memento::make_debug_string for
2796 static const char * const unary_op_strings
[] = {
2797 "-", /* GCC_JIT_UNARY_OP_MINUS */
2798 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
2799 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
2800 "abs ", /* GCC_JIT_UNARY_OP_ABS */
2804 recording::unary_op::make_debug_string ()
2806 return string::from_printf (m_ctxt
,
2808 unary_op_strings
[m_op
],
2809 m_a
->get_debug_string ());
2812 /* The implementation of class gcc::jit::recording::binary_op. */
2814 /* Implementation of pure virtual hook recording::memento::replay_into
2815 for recording::binary_op. */
2818 recording::binary_op::replay_into (replayer
*r
)
2820 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
2822 get_type ()->playback_type (),
2823 m_a
->playback_rvalue (),
2824 m_b
->playback_rvalue ()));
2827 /* Implementation of recording::memento::make_debug_string for
2830 static const char * const binary_op_strings
[] = {
2831 "+", /* GCC_JIT_BINARY_OP_PLUS */
2832 "-", /* GCC_JIT_BINARY_OP_MINUS */
2833 "*", /* GCC_JIT_BINARY_OP_MULT */
2834 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
2835 "%", /* GCC_JIT_BINARY_OP_MODULO */
2836 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
2837 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
2838 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
2839 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
2840 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
2841 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
2842 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
2846 recording::binary_op::make_debug_string ()
2848 return string::from_printf (m_ctxt
,
2850 m_a
->get_debug_string (),
2851 binary_op_strings
[m_op
],
2852 m_b
->get_debug_string ());
2855 /* The implementation of class gcc::jit::recording::comparison. */
2857 /* Implementation of recording::memento::make_debug_string for
2860 static const char * const comparison_strings
[] =
2862 "==", /* GCC_JIT_COMPARISON_EQ */
2863 "!=", /* GCC_JIT_COMPARISON_NE */
2864 "<", /* GCC_JIT_COMPARISON_LT */
2865 "<=", /* GCC_JIT_COMPARISON_LE */
2866 ">", /* GCC_JIT_COMPARISON_GT */
2867 ">=", /* GCC_JIT_COMPARISON_GE */
2871 recording::comparison::make_debug_string ()
2873 return string::from_printf (m_ctxt
,
2875 m_a
->get_debug_string (),
2876 comparison_strings
[m_op
],
2877 m_b
->get_debug_string ());
2880 /* Implementation of pure virtual hook recording::memento::replay_into
2881 for recording::comparison. */
2884 recording::comparison::replay_into (replayer
*r
)
2886 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
2888 m_a
->playback_rvalue (),
2889 m_b
->playback_rvalue ()));
2892 /* Implementation of pure virtual hook recording::memento::replay_into
2893 for recording::cast. */
2896 recording::cast::replay_into (replayer
*r
)
2898 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
2899 m_rvalue
->playback_rvalue (),
2900 get_type ()->playback_type ()));
2903 /* Implementation of recording::memento::make_debug_string for
2907 recording::cast::make_debug_string ()
2909 return string::from_printf (m_ctxt
,
2911 get_type ()->get_debug_string (),
2912 m_rvalue
->get_debug_string ());
2915 /* The implementation of class gcc::jit::recording::call. */
2917 /* The constructor for gcc::jit::recording::call. */
2919 recording::call::call (recording::context
*ctxt
,
2920 recording::location
*loc
,
2921 recording::function
*func
,
2924 : rvalue (ctxt
, loc
, func
->get_return_type ()),
2928 for (int i
= 0; i
< numargs
; i
++)
2929 m_args
.safe_push (args
[i
]);
2932 /* Implementation of pure virtual hook recording::memento::replay_into
2933 for recording::call. */
2936 recording::call::replay_into (replayer
*r
)
2938 auto_vec
<playback::rvalue
*> playback_args
;
2939 playback_args
.create (m_args
.length ());
2940 for (unsigned i
= 0; i
< m_args
.length (); i
++)
2941 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
2943 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
2944 m_func
->playback_function (),
2948 /* Implementation of recording::memento::make_debug_string for
2952 recording::call::make_debug_string ()
2954 /* First, build a buffer for the arguments. */
2955 /* Calculate length of said buffer. */
2956 size_t sz
= 1; /* nil terminator */
2957 for (unsigned i
= 0; i
< m_args
.length (); i
++)
2959 sz
+= strlen (m_args
[i
]->get_debug_string ());
2960 sz
+= 2; /* ", " separator */
2963 /* Now allocate and populate the buffer. */
2964 char *argbuf
= new char[sz
];
2967 for (unsigned i
= 0; i
< m_args
.length (); i
++)
2969 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string ());
2970 len
+= strlen (m_args
[i
]->get_debug_string ());
2971 if (i
+ 1 < m_args
.length ())
2973 strcpy (argbuf
+ len
, ", ");
2979 /* ...and use it to get the string for the call as a whole. */
2980 string
*result
= string::from_printf (m_ctxt
,
2982 m_func
->get_debug_string (),
2990 /* The implementation of class gcc::jit::recording::call_through_ptr. */
2992 /* The constructor for recording::call_through_ptr. */
2994 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
2995 recording::location
*loc
,
2996 recording::rvalue
*fn_ptr
,
2999 : rvalue (ctxt
, loc
,
3000 fn_ptr
->get_type ()->dereference ()
3001 ->as_a_function_type ()->get_return_type ()),
3005 for (int i
= 0; i
< numargs
; i
++)
3006 m_args
.safe_push (args
[i
]);
3009 /* Implementation of pure virtual hook recording::memento::replay_into
3010 for recording::call_through_ptr. */
3013 recording::call_through_ptr::replay_into (replayer
*r
)
3015 auto_vec
<playback::rvalue
*> playback_args
;
3016 playback_args
.create (m_args
.length ());
3017 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3018 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
3020 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
3021 m_fn_ptr
->playback_rvalue (),
3025 /* Implementation of recording::memento::make_debug_string for
3026 calls through function ptrs. */
3029 recording::call_through_ptr::make_debug_string ()
3031 /* First, build a buffer for the arguments. */
3032 /* Calculate length of said buffer. */
3033 size_t sz
= 1; /* nil terminator */
3034 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3036 sz
+= strlen (m_args
[i
]->get_debug_string ());
3037 sz
+= 2; /* ", " separator */
3040 /* Now allocate and populate the buffer. */
3041 char *argbuf
= new char[sz
];
3044 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3046 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string ());
3047 len
+= strlen (m_args
[i
]->get_debug_string ());
3048 if (i
+ 1 < m_args
.length ())
3050 strcpy (argbuf
+ len
, ", ");
3056 /* ...and use it to get the string for the call as a whole. */
3057 string
*result
= string::from_printf (m_ctxt
,
3059 m_fn_ptr
->get_debug_string (),
3067 /* The implementation of class gcc::jit::recording::array_access. */
3069 /* Implementation of pure virtual hook recording::memento::replay_into
3070 for recording::array_access. */
3073 recording::array_access::replay_into (replayer
*r
)
3076 r
->new_array_access (playback_location (r
, m_loc
),
3077 m_ptr
->playback_rvalue (),
3078 m_index
->playback_rvalue ()));
3081 /* Implementation of recording::memento::make_debug_string for
3085 recording::array_access::make_debug_string ()
3087 return string::from_printf (m_ctxt
,
3089 m_ptr
->get_debug_string (),
3090 m_index
->get_debug_string ());
3093 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
3095 /* Implementation of pure virtual hook recording::memento::replay_into
3096 for recording::access_field_of_lvalue. */
3099 recording::access_field_of_lvalue::replay_into (replayer
*r
)
3102 m_lvalue
->playback_lvalue ()
3103 ->access_field (playback_location (r
, m_loc
),
3104 m_field
->playback_field ()));
3108 /* Implementation of recording::memento::make_debug_string for
3109 accessing a field of an lvalue. */
3112 recording::access_field_of_lvalue::make_debug_string ()
3114 return string::from_printf (m_ctxt
,
3116 m_lvalue
->get_debug_string (),
3117 m_field
->get_debug_string ());
3120 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
3122 /* Implementation of pure virtual hook recording::memento::replay_into
3123 for recording::access_field_rvalue. */
3126 recording::access_field_rvalue::replay_into (replayer
*r
)
3129 m_rvalue
->playback_rvalue ()
3130 ->access_field (playback_location (r
, m_loc
),
3131 m_field
->playback_field ()));
3134 /* Implementation of recording::memento::make_debug_string for
3135 accessing a field of an rvalue. */
3138 recording::access_field_rvalue::make_debug_string ()
3140 return string::from_printf (m_ctxt
,
3142 m_rvalue
->get_debug_string (),
3143 m_field
->get_debug_string ());
3146 /* The implementation of class
3147 gcc::jit::recording::dereference_field_rvalue. */
3149 /* Implementation of pure virtual hook recording::memento::replay_into
3150 for recording::dereference_field_rvalue. */
3153 recording::dereference_field_rvalue::replay_into (replayer
*r
)
3156 m_rvalue
->playback_rvalue ()->
3157 dereference_field (playback_location (r
, m_loc
),
3158 m_field
->playback_field ()));
3161 /* Implementation of recording::memento::make_debug_string for
3162 dereferencing a field of an rvalue. */
3165 recording::dereference_field_rvalue::make_debug_string ()
3167 return string::from_printf (m_ctxt
,
3169 m_rvalue
->get_debug_string (),
3170 m_field
->get_debug_string ());
3173 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
3175 /* Implementation of pure virtual hook recording::memento::replay_into
3176 for recording::dereference_rvalue. */
3179 recording::dereference_rvalue::replay_into (replayer
*r
)
3182 m_rvalue
->playback_rvalue ()->
3183 dereference (playback_location (r
, m_loc
)));
3186 /* Implementation of recording::memento::make_debug_string for
3187 dereferencing an rvalue. */
3190 recording::dereference_rvalue::make_debug_string ()
3192 return string::from_printf (m_ctxt
,
3194 m_rvalue
->get_debug_string ());
3197 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
3199 /* Implementation of pure virtual hook recording::memento::replay_into
3200 for recording::get_address_of_lvalue. */
3203 recording::get_address_of_lvalue::replay_into (replayer
*r
)
3206 m_lvalue
->playback_lvalue ()->
3207 get_address (playback_location (r
, m_loc
)));
3210 /* Implementation of recording::memento::make_debug_string for
3211 getting the address of an lvalue. */
3214 recording::get_address_of_lvalue::make_debug_string ()
3216 return string::from_printf (m_ctxt
,
3218 m_lvalue
->get_debug_string ());
3221 /* The implementation of class gcc::jit::recording::local. */
3223 /* Implementation of pure virtual hook recording::memento::replay_into
3224 for recording::local. */
3227 recording::local::replay_into (replayer
*r
)
3230 m_func
->playback_function ()
3231 ->new_local (playback_location (r
, m_loc
),
3232 m_type
->playback_type (),
3233 playback_string (m_name
)));
3236 /* Override the default implementation of
3237 recording::memento::write_to_dump for locals by writing
3239 for use at the top of the function body as if it were a
3243 recording::local::write_to_dump (dump
&d
)
3245 if (d
.update_locations ())
3246 m_loc
= d
.make_location ();
3247 d
.write(" %s %s;\n",
3248 m_type
->get_debug_string (),
3249 get_debug_string ());
3252 /* The implementation of class gcc::jit::recording::statement. */
3254 /* We poison the default implementation of
3255 gcc::jit::recording::statement::get_successor_blocks
3256 since this vfunc must only ever be called on terminator
3260 recording::statement::get_successor_blocks (block
**/
*out_next1*/
,
3261 block
**/
*out_next2*/
) const
3263 /* The base class implementation is for non-terminating statements,
3264 and thus should never be called. */
3269 /* Extend the default implementation of
3270 recording::memento::write_to_dump for statements by (if requested)
3271 updating the location of the statement to the current location in
3275 recording::statement::write_to_dump (dump
&d
)
3277 memento::write_to_dump (d
);
3278 if (d
.update_locations ())
3279 m_loc
= d
.make_location ();
3282 /* The implementation of class gcc::jit::recording::eval. */
3284 /* Implementation of pure virtual hook recording::memento::replay_into
3285 for recording::eval. */
3288 recording::eval::replay_into (replayer
*r
)
3290 playback_block (get_block ())
3291 ->add_eval (playback_location (r
),
3292 m_rvalue
->playback_rvalue ());
3295 /* Implementation of recording::memento::make_debug_string for
3296 an eval statement. */
3299 recording::eval::make_debug_string ()
3301 return string::from_printf (m_ctxt
,
3303 m_rvalue
->get_debug_string ());
3306 /* The implementation of class gcc::jit::recording::assignment. */
3308 /* Implementation of pure virtual hook recording::memento::replay_into
3309 for recording::assignment. */
3312 recording::assignment::replay_into (replayer
*r
)
3314 playback_block (get_block ())
3315 ->add_assignment (playback_location (r
),
3316 m_lvalue
->playback_lvalue (),
3317 m_rvalue
->playback_rvalue ());
3320 /* Implementation of recording::memento::make_debug_string for
3321 an assignment statement. */
3324 recording::assignment::make_debug_string ()
3326 return string::from_printf (m_ctxt
,
3328 m_lvalue
->get_debug_string (),
3329 m_rvalue
->get_debug_string ());
3332 /* The implementation of class gcc::jit::recording::assignment_op. */
3334 /* Implementation of pure virtual hook recording::memento::replay_into
3335 for recording::assignment_op. */
3338 recording::assignment_op::replay_into (replayer
*r
)
3340 playback::type
*result_type
=
3341 m_lvalue
->playback_lvalue ()->get_type ();
3343 playback::rvalue
*binary_op
=
3344 r
->new_binary_op (playback_location (r
),
3347 m_lvalue
->playback_rvalue (),
3348 m_rvalue
->playback_rvalue ());
3350 playback_block (get_block ())
3351 ->add_assignment (playback_location (r
),
3352 m_lvalue
->playback_lvalue (),
3356 /* Implementation of recording::memento::make_debug_string for
3357 an assignment_op statement. */
3360 recording::assignment_op::make_debug_string ()
3362 return string::from_printf (m_ctxt
,
3364 m_lvalue
->get_debug_string (),
3365 binary_op_strings
[m_op
],
3366 m_rvalue
->get_debug_string ());
3369 /* The implementation of class gcc::jit::recording::comment. */
3371 /* Implementation of pure virtual hook recording::memento::replay_into
3372 for recording::comment. */
3375 recording::comment::replay_into (replayer
*r
)
3377 playback_block (get_block ())
3378 ->add_comment (playback_location (r
),
3382 /* Implementation of recording::memento::make_debug_string for
3383 a comment "statement". */
3386 recording::comment::make_debug_string ()
3388 return string::from_printf (m_ctxt
,
3393 /* The implementation of class gcc::jit::recording::conditional. */
3395 /* Implementation of pure virtual hook recording::memento::replay_into
3396 for recording::conditional. */
3399 recording::conditional::replay_into (replayer
*r
)
3401 playback_block (get_block ())
3402 ->add_conditional (playback_location (r
),
3403 m_boolval
->playback_rvalue (),
3404 playback_block (m_on_true
),
3405 playback_block (m_on_false
));
3408 /* Override the poisoned default implementation of
3409 gcc::jit::recording::statement::get_successor_blocks
3411 A conditional jump has 2 successor blocks. */
3414 recording::conditional::get_successor_blocks (block
**out_next1
,
3415 block
**out_next2
) const
3417 *out_next1
= m_on_true
;
3418 *out_next2
= m_on_false
;
3422 /* Implementation of recording::memento::make_debug_string for
3423 a conditional jump statement. */
3426 recording::conditional::make_debug_string ()
3429 return string::from_printf (m_ctxt
,
3430 "if (%s) goto %s; else goto %s;",
3431 m_boolval
->get_debug_string (),
3432 m_on_true
->get_debug_string (),
3433 m_on_false
->get_debug_string ());
3435 return string::from_printf (m_ctxt
,
3437 m_boolval
->get_debug_string (),
3438 m_on_true
->get_debug_string ());
3441 /* The implementation of class gcc::jit::recording::jump. */
3443 /* Implementation of pure virtual hook recording::memento::replay_into
3444 for recording::jump. */
3447 recording::jump::replay_into (replayer
*r
)
3449 playback_block (get_block ())
3450 ->add_jump (playback_location (r
),
3451 m_target
->playback_block ());
3454 /* Override the poisoned default implementation of
3455 gcc::jit::recording::statement::get_successor_blocks
3457 An unconditional jump has 1 successor block. */
3460 recording::jump::get_successor_blocks (block
**out_next1
,
3461 block
**/
*out_next2*/
) const
3463 *out_next1
= m_target
;
3467 /* Implementation of recording::memento::make_debug_string for
3468 a unconditional jump statement. */
3471 recording::jump::make_debug_string ()
3473 return string::from_printf (m_ctxt
,
3475 m_target
->get_debug_string ());
3478 /* The implementation of class gcc::jit::recording::return_. */
3480 /* Implementation of pure virtual hook recording::memento::replay_into
3481 for recording::return_. */
3484 recording::return_::replay_into (replayer
*r
)
3486 playback_block (get_block ())
3487 ->add_return (playback_location (r
),
3488 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
3491 /* Override the poisoned default implementation of
3492 gcc::jit::recording::statement::get_successor_blocks
3494 A return statement has no successor block. */
3497 recording::return_::get_successor_blocks (block
**/
*out_next1*/
,
3498 block
**/
*out_next2*/
) const
3503 /* Implementation of recording::memento::make_debug_string for
3504 a return statement (covers both those with and without rvalues). */
3507 recording::return_::make_debug_string ()
3510 return string::from_printf (m_ctxt
,
3512 m_rvalue
->get_debug_string ());
3514 return string::from_printf (m_ctxt
,
3518 } // namespace gcc::jit