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 /* An rvalue visitor, for validating that every rvalue within an expression
2038 trees within "STMT" has the correct scope (e.g. no access to locals
2039 of a different function). */
2041 class rvalue_usage_validator
: public recording::rvalue_visitor
2044 rvalue_usage_validator (const char *api_funcname
,
2045 recording::context
*ctxt
,
2046 recording::statement
*stmt
);
2049 visit (recording::rvalue
*rvalue
);
2052 const char *m_api_funcname
;
2053 recording::context
*m_ctxt
;
2054 recording::statement
*m_stmt
;
2057 /* The trivial constructor for rvalue_usage_validator. */
2059 rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname
,
2060 recording::context
*ctxt
,
2061 recording::statement
*stmt
)
2062 : m_api_funcname (api_funcname
),
2068 /* Verify that the given rvalue is in the correct scope. */
2071 rvalue_usage_validator::visit (recording::rvalue
*rvalue
)
2073 gcc_assert (m_stmt
->get_block ());
2074 recording::function
*stmt_scope
= m_stmt
->get_block ()->get_function ();
2076 /* Most rvalues don't have a scope (only locals and params). */
2077 if (rvalue
->get_scope ())
2079 if (rvalue
->get_scope () != stmt_scope
)
2081 (rvalue
->get_loc (),
2083 " rvalue %s (type: %s)"
2084 " has scope limited to function %s"
2085 " but was used within function %s"
2086 " (in statement: %s)",
2088 rvalue
->get_debug_string (),
2089 rvalue
->get_type ()->get_debug_string (),
2090 rvalue
->get_scope ()->get_debug_string (),
2091 stmt_scope
->get_debug_string (),
2092 m_stmt
->get_debug_string ());
2096 if (rvalue
->dyn_cast_param ())
2098 (rvalue
->get_loc (),
2100 " param %s (type: %s)"
2101 " was used within function %s"
2102 " (in statement: %s)"
2103 " but is not associated with any function",
2105 rvalue
->get_debug_string (),
2106 rvalue
->get_type ()->get_debug_string (),
2107 stmt_scope
->get_debug_string (),
2108 m_stmt
->get_debug_string ());
2112 /* Verify that it's valid to use this rvalue (and all expressions
2113 in the tree below it) within the given statement.
2115 For example, we must reject attempts to use a local from one
2116 function within a different function here, or we'll get
2117 an ICE deep inside toplev::main. */
2120 recording::rvalue::verify_valid_within_stmt (const char *api_funcname
, statement
*s
)
2122 rvalue_usage_validator
v (api_funcname
,
2126 /* Verify that it's OK to use this rvalue within s. */
2129 /* Traverse the expression tree below "this", verifying all rvalues
2131 visit_children (&v
);
2134 /* Set the scope of this rvalue to be the given function. This can only
2135 be done once on a given rvalue. */
2138 recording::rvalue::set_scope (function
*scope
)
2141 gcc_assert (NULL
== m_scope
);
2146 /* The implementation of class gcc::jit::recording::lvalue. */
2148 /* Create a recording::new_access_field_of_lvalue instance and add it to
2149 the lvalue's context's list of mementos.
2151 Implements the post-error-checking part of
2152 gcc_jit_lvalue_access_field. */
2155 recording::lvalue::access_field (recording::location
*loc
,
2158 recording::lvalue
*result
=
2159 new access_field_of_lvalue (m_ctxt
, loc
, this, field
);
2160 m_ctxt
->record (result
);
2164 /* Create a recording::get_address_of_lvalue instance and add it to
2165 the lvalue's context's list of mementos.
2167 Implements the post-error-checking part of
2168 gcc_jit_lvalue_get_address. */
2171 recording::lvalue::get_address (recording::location
*loc
)
2173 recording::rvalue
*result
=
2174 new get_address_of_lvalue (m_ctxt
, loc
, this);
2175 m_ctxt
->record (result
);
2179 /* The implementation of class gcc::jit::recording::param. */
2181 /* Implementation of pure virtual hook recording::memento::replay_into
2182 for recording::param. */
2185 recording::param::replay_into (replayer
*r
)
2187 set_playback_obj (r
->new_param (playback_location (r
, m_loc
),
2188 m_type
->playback_type (),
2193 /* The implementation of class gcc::jit::recording::function. */
2195 /* gcc::jit::recording::function's constructor. */
2197 recording::function::function (context
*ctxt
,
2198 recording::location
*loc
,
2199 enum gcc_jit_function_kind kind
,
2201 recording::string
*name
,
2203 recording::param
**params
,
2205 enum built_in_function builtin_id
)
2209 m_return_type (return_type
),
2212 m_is_variadic (is_variadic
),
2213 m_builtin_id (builtin_id
),
2217 for (int i
= 0; i
< num_params
; i
++)
2219 param
*param
= params
[i
];
2222 /* Associate each param with this function.
2224 Verify that the param doesn't already have a function. */
2225 if (param
->get_scope ())
2227 /* We've already rejected attempts to reuse a param between
2228 different functions (within gcc_jit_context_new_function), so
2229 if the param *does* already have a function, it must be being
2230 reused within the params array for this function. We must
2231 produce an error for this reuse (blocking the compile), since
2232 otherwise we'd have an ICE later on. */
2233 gcc_assert (this == param
->get_scope ());
2236 "gcc_jit_context_new_function:"
2237 " parameter %s (type: %s)"
2238 " is used more than once when creating function %s",
2239 param
->get_debug_string (),
2240 param
->get_type ()->get_debug_string (),
2245 /* The normal, non-error case: associate this function with the
2247 param
->set_scope (this);
2250 m_params
.safe_push (param
);
2254 /* Implementation of pure virtual hook recording::memento::replay_into
2255 for recording::function. */
2258 recording::function::replay_into (replayer
*r
)
2260 /* Convert m_params to a vec of playback param. */
2261 auto_vec
<playback::param
*> params
;
2263 recording::param
*param
;
2264 params
.create (m_params
.length ());
2265 FOR_EACH_VEC_ELT (m_params
, i
, param
)
2266 params
.safe_push (param
->playback_param ());
2268 set_playback_obj (r
->new_function (playback_location (r
, m_loc
),
2270 m_return_type
->playback_type (),
2277 /* Create a recording::local instance and add it to
2278 the functions's context's list of mementos, and to the function's
2281 Implements the post-error-checking part of
2282 gcc_jit_function_new_local. */
2285 recording::function::new_local (recording::location
*loc
,
2289 local
*result
= new local (this, loc
, type
, new_string (name
));
2290 m_ctxt
->record (result
);
2291 m_locals
.safe_push (result
);
2295 /* Create a recording::block instance and add it to
2296 the functions's context's list of mementos, and to the function's
2299 Implements the post-error-checking part of
2300 gcc_jit_function_new_block. */
2303 recording::function::new_block (const char *name
)
2305 gcc_assert (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
);
2307 recording::block
*result
=
2308 new recording::block (this, m_blocks
.length (), new_string (name
));
2309 m_ctxt
->record (result
);
2310 m_blocks
.safe_push (result
);
2314 /* Override the default implementation of
2315 recording::memento::write_to_dump by dumping a C-like
2316 representation of the function; either like a prototype
2317 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
2318 all other kinds of function. */
2321 recording::function::write_to_dump (dump
&d
)
2325 default: gcc_unreachable ();
2326 case GCC_JIT_FUNCTION_EXPORTED
:
2327 case GCC_JIT_FUNCTION_IMPORTED
:
2328 d
.write ("extern ");
2330 case GCC_JIT_FUNCTION_INTERNAL
:
2331 d
.write ("static ");
2333 case GCC_JIT_FUNCTION_ALWAYS_INLINE
:
2334 d
.write ("static inline ");
2337 d
.write ("%s\n", m_return_type
->get_debug_string ());
2339 if (d
.update_locations ())
2340 m_loc
= d
.make_location ();
2342 d
.write ("%s (", get_debug_string ());
2345 recording::param
*param
;
2346 FOR_EACH_VEC_ELT (m_params
, i
, param
)
2351 param
->get_type ()->get_debug_string (),
2352 param
->get_debug_string ());
2355 if (m_kind
== GCC_JIT_FUNCTION_IMPORTED
)
2357 d
.write ("; /* (imported) */\n\n");
2367 FOR_EACH_VEC_ELT (m_locals
, i
, var
)
2368 var
->write_to_dump (d
);
2369 if (m_locals
.length ())
2372 /* Write each block: */
2373 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2377 b
->write_to_dump (d
);
2384 /* Pre-compilation validation of a function, for those things we can't
2385 check until the context is (supposedly) fully-populated. */
2388 recording::function::validate ()
2390 /* Complain about empty functions with non-void return type. */
2391 if (m_kind
!= GCC_JIT_FUNCTION_IMPORTED
2392 && m_return_type
!= m_ctxt
->get_type (GCC_JIT_TYPE_VOID
))
2393 if (0 == m_blocks
.length ())
2394 m_ctxt
->add_error (m_loc
,
2395 "function %s returns non-void (type: %s)"
2396 " but has no blocks",
2397 get_debug_string (),
2398 m_return_type
->get_debug_string ());
2400 /* Check that all blocks are terminated. */
2401 int num_invalid_blocks
= 0;
2406 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2407 if (!b
->validate ())
2408 num_invalid_blocks
++;
2411 /* Check that all blocks are reachable. */
2412 if (m_blocks
.length () > 0 && 0 == num_invalid_blocks
)
2414 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
2415 flag, starting at the initial block. */
2416 auto_vec
<block
*> worklist (m_blocks
.length ());
2417 worklist
.safe_push (m_blocks
[0]);
2418 while (worklist
.length () > 0)
2420 block
*b
= worklist
.pop ();
2421 b
->m_is_reachable
= true;
2423 /* Add successor blocks that aren't yet marked to the worklist. */
2424 /* We checked that each block has a terminating statement above . */
2425 block
*next1
, *next2
;
2426 int n
= b
->get_successor_blocks (&next1
, &next2
);
2432 if (!next2
->m_is_reachable
)
2433 worklist
.safe_push (next2
);
2436 if (!next1
->m_is_reachable
)
2437 worklist
.safe_push (next1
);
2444 /* Now complain about any blocks that haven't been marked. */
2448 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2449 if (!b
->m_is_reachable
)
2450 m_ctxt
->add_error (b
->get_loc (),
2451 "unreachable block: %s",
2452 b
->get_debug_string ());
2457 /* Implements the post-error-checking part of
2458 gcc_jit_function_dump_to_dot. */
2461 recording::function::dump_to_dot (const char *path
)
2463 FILE *fp
= fopen (path
, "w");
2467 pretty_printer the_pp
;
2468 the_pp
.buffer
->stream
= fp
;
2470 pretty_printer
*pp
= &the_pp
;
2473 "digraph %s {\n", get_debug_string ());
2479 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2480 b
->dump_to_dot (pp
);
2487 FOR_EACH_VEC_ELT (m_blocks
, i
, b
)
2488 b
->dump_edges_to_dot (pp
);
2491 pp_printf (pp
, "}\n");
2496 /* Implementation of recording::memento::make_debug_string for
2500 recording::function::make_debug_string ()
2505 /* The implementation of class gcc::jit::recording::block. */
2507 /* Create a recording::eval instance and add it to
2508 the block's context's list of mementos, and to the block's
2511 Implements the heart of gcc_jit_block_add_eval. */
2513 recording::statement
*
2514 recording::block::add_eval (recording::location
*loc
,
2515 recording::rvalue
*rvalue
)
2517 statement
*result
= new eval (this, loc
, rvalue
);
2518 m_ctxt
->record (result
);
2519 m_statements
.safe_push (result
);
2523 /* Create a recording::assignment instance and add it to
2524 the block's context's list of mementos, and to the block's
2527 Implements the heart of gcc_jit_block_add_assignment. */
2529 recording::statement
*
2530 recording::block::add_assignment (recording::location
*loc
,
2531 recording::lvalue
*lvalue
,
2532 recording::rvalue
*rvalue
)
2534 statement
*result
= new assignment (this, loc
, lvalue
, rvalue
);
2535 m_ctxt
->record (result
);
2536 m_statements
.safe_push (result
);
2540 /* Create a recording::assignment_op instance and add it to
2541 the block's context's list of mementos, and to the block's
2544 Implements the heart of gcc_jit_block_add_assignment_op. */
2546 recording::statement
*
2547 recording::block::add_assignment_op (recording::location
*loc
,
2548 recording::lvalue
*lvalue
,
2549 enum gcc_jit_binary_op op
,
2550 recording::rvalue
*rvalue
)
2552 statement
*result
= new assignment_op (this, loc
, lvalue
, op
, rvalue
);
2553 m_ctxt
->record (result
);
2554 m_statements
.safe_push (result
);
2558 /* Create a recording::comment instance and add it to
2559 the block's context's list of mementos, and to the block's
2562 Implements the heart of gcc_jit_block_add_comment. */
2564 recording::statement
*
2565 recording::block::add_comment (recording::location
*loc
,
2568 statement
*result
= new comment (this, loc
, new_string (text
));
2569 m_ctxt
->record (result
);
2570 m_statements
.safe_push (result
);
2574 /* Create a recording::end_with_conditional instance and add it to
2575 the block's context's list of mementos, and to the block's
2578 Implements the heart of gcc_jit_block_end_with_conditional. */
2580 recording::statement
*
2581 recording::block::end_with_conditional (recording::location
*loc
,
2582 recording::rvalue
*boolval
,
2583 recording::block
*on_true
,
2584 recording::block
*on_false
)
2586 statement
*result
= new conditional (this, loc
, boolval
, on_true
, on_false
);
2587 m_ctxt
->record (result
);
2588 m_statements
.safe_push (result
);
2589 m_has_been_terminated
= true;
2593 /* Create a recording::end_with_jump instance and add it to
2594 the block's context's list of mementos, and to the block's
2597 Implements the heart of gcc_jit_block_end_with_jump. */
2599 recording::statement
*
2600 recording::block::end_with_jump (recording::location
*loc
,
2601 recording::block
*target
)
2603 statement
*result
= new jump (this, loc
, target
);
2604 m_ctxt
->record (result
);
2605 m_statements
.safe_push (result
);
2606 m_has_been_terminated
= true;
2610 /* Create a recording::end_with_return instance and add it to
2611 the block's context's list of mementos, and to the block's
2614 Implements the post-error-checking parts of
2615 gcc_jit_block_end_with_return and
2616 gcc_jit_block_end_with_void_return. */
2618 recording::statement
*
2619 recording::block::end_with_return (recording::location
*loc
,
2620 recording::rvalue
*rvalue
)
2622 /* This is used by both gcc_jit_function_add_return and
2623 gcc_jit_function_add_void_return; rvalue will be non-NULL for
2624 the former and NULL for the latter. */
2625 statement
*result
= new return_ (this, loc
, rvalue
);
2626 m_ctxt
->record (result
);
2627 m_statements
.safe_push (result
);
2628 m_has_been_terminated
= true;
2632 /* Override the default implementation of
2633 recording::memento::write_to_dump for blocks by writing
2634 an unindented block name as a label, followed by the indented
2644 recording::block::write_to_dump (dump
&d
)
2646 d
.write ("%s:\n", get_debug_string ());
2650 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
2651 s
->write_to_dump (d
);
2654 /* Validate a block by ensuring that it has been terminated. */
2657 recording::block::validate ()
2659 /* Check for termination. */
2660 if (!has_been_terminated ())
2662 statement
*stmt
= get_last_statement ();
2663 location
*loc
= stmt
? stmt
->get_loc () : NULL
;
2664 m_func
->get_context ()->add_error (loc
,
2665 "unterminated block in %s: %s",
2666 m_func
->get_debug_string (),
2667 get_debug_string ());
2674 /* Get the source-location of a block by using that of the first
2675 statement within it, if any. */
2677 recording::location
*
2678 recording::block::get_loc () const
2680 recording::statement
*stmt
= get_first_statement ();
2682 return stmt
->get_loc ();
2687 /* Get the first statement within a block, if any. */
2689 recording::statement
*
2690 recording::block::get_first_statement () const
2692 if (m_statements
.length ())
2693 return m_statements
[0];
2698 /* Get the last statement within a block, if any. */
2700 recording::statement
*
2701 recording::block::get_last_statement () const
2703 if (m_statements
.length ())
2704 return m_statements
[m_statements
.length () - 1];
2709 /* Assuming that this block has been terminated, get the number of
2710 successor blocks, which will be 0, 1 or 2, for return, unconditional
2711 jump, and conditional jump respectively.
2712 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
2713 is written to NEXT1, and the second (if any) to NEXT2.
2715 Used when validating functions, and when dumping dot representations
2719 recording::block::get_successor_blocks (block
**next1
, block
**next2
) const
2721 gcc_assert (m_has_been_terminated
);
2724 statement
*last_statement
= get_last_statement ();
2725 gcc_assert (last_statement
);
2726 return last_statement
->get_successor_blocks (next1
, next2
);
2729 /* Implementation of pure virtual hook recording::memento::replay_into
2730 for recording::block. */
2733 recording::block::replay_into (replayer
*)
2735 set_playback_obj (m_func
->playback_function ()
2736 ->new_block (playback_string (m_name
)));
2739 /* Implementation of recording::memento::make_debug_string for
2743 recording::block::make_debug_string ()
2748 return string::from_printf (m_ctxt
,
2749 "<UNNAMED BLOCK %p>",
2753 /* Dump a block in graphviz form into PP, capturing the block name (if
2754 any) and the statements. */
2757 recording::block::dump_to_dot (pretty_printer
*pp
)
2761 "[shape=record,style=filled,fillcolor=white,label=\"{"),
2763 pp_write_text_to_stream (pp
);
2766 pp_string (pp
, m_name
->c_str ());
2767 pp_string (pp
, ":");
2769 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
2774 FOR_EACH_VEC_ELT (m_statements
, i
, s
)
2776 pp_string (pp
, s
->get_debug_string ());
2778 pp_write_text_as_dot_label_to_stream (pp
, true /*for_record*/);
2786 /* Dump the out-edges of the block in graphviz form into PP. */
2789 recording::block::dump_edges_to_dot (pretty_printer
*pp
)
2792 int num_succs
= get_successor_blocks (&next
[0], &next
[1]);
2793 for (int i
= 0; i
< num_succs
; i
++)
2795 "\tblock_%d:s -> block_%d:n;\n",
2796 m_index
, next
[i
]->m_index
);
2799 /* The implementation of class gcc::jit::recording::global. */
2801 /* Implementation of pure virtual hook recording::memento::replay_into
2802 for recording::global. */
2805 recording::global::replay_into (replayer
*r
)
2807 set_playback_obj (r
->new_global (playback_location (r
, m_loc
),
2809 m_type
->playback_type (),
2810 playback_string (m_name
)));
2813 /* Override the default implementation of
2814 recording::memento::write_to_dump for globals.
2815 This will be of the form:
2817 GCC_JIT_GLOBAL_EXPORTED:
2821 GCC_JIT_GLOBAL_INTERNAL:
2823 e.g. "static int foo;"
2825 GCC_JIT_GLOBAL_IMPORTED:
2827 e.g. "extern int foo;"
2829 These are written to the top of the dump by
2830 recording::context::dump_to_file. */
2833 recording::global::write_to_dump (dump
&d
)
2835 if (d
.update_locations ())
2836 m_loc
= d
.make_location ();
2843 case GCC_JIT_GLOBAL_EXPORTED
:
2846 case GCC_JIT_GLOBAL_INTERNAL
:
2847 d
.write ("static ");
2850 case GCC_JIT_GLOBAL_IMPORTED
:
2851 d
.write ("extern ");
2854 d
.write ("%s %s;\n",
2855 m_type
->get_debug_string (),
2856 get_debug_string ());
2859 /* The implementation of the various const-handling classes:
2860 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
2862 /* Explicit specialization of the various mementos we're interested in. */
2863 template class recording::memento_of_new_rvalue_from_const
<int>;
2864 template class recording::memento_of_new_rvalue_from_const
<long>;
2865 template class recording::memento_of_new_rvalue_from_const
<double>;
2866 template class recording::memento_of_new_rvalue_from_const
<void *>;
2868 /* Implementation of the pure virtual hook recording::memento::replay_into
2869 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
2871 template <typename HOST_TYPE
>
2874 memento_of_new_rvalue_from_const
<HOST_TYPE
>::replay_into (replayer
*r
)
2877 (r
->new_rvalue_from_const
<HOST_TYPE
> (m_type
->playback_type (),
2881 /* The make_debug_string method varies between the various
2882 memento_of_new_rvalue_from_const <HOST_TYPE> classes, so we explicitly
2883 write specializations of it.
2885 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
2886 namespaces are written out explicitly, which is why most of this file
2887 doesn't abbreviate things by entering the "recording" namespace.
2889 However, these specializations are required to be in the same namespace
2890 as the template, hence we now have to enter the gcc::jit::recording
2896 /* The make_debug_string specialization for <int>, which renders it as
2897 (TARGET_TYPE)LITERAL
2903 memento_of_new_rvalue_from_const
<int>::make_debug_string ()
2905 return string::from_printf (m_ctxt
,
2907 m_type
->get_debug_string (),
2911 /* The make_debug_string specialization for <long>, rendering it as
2912 (TARGET_TYPE)LITERAL
2918 memento_of_new_rvalue_from_const
<long>::make_debug_string ()
2920 return string::from_printf (m_ctxt
,
2922 m_type
->get_debug_string (),
2926 /* The make_debug_string specialization for <double>, rendering it as
2927 (TARGET_TYPE)LITERAL
2933 memento_of_new_rvalue_from_const
<double>::make_debug_string ()
2935 return string::from_printf (m_ctxt
,
2937 m_type
->get_debug_string (),
2941 /* The make_debug_string specialization for <void *>, rendering it as
2946 Zero is rendered as NULL e.g.
2951 memento_of_new_rvalue_from_const
<void *>::make_debug_string ()
2953 if (m_value
!= NULL
)
2954 return string::from_printf (m_ctxt
,
2956 m_type
->get_debug_string (), m_value
);
2958 return string::from_printf (m_ctxt
,
2960 m_type
->get_debug_string ());
2963 /* We're done specializing make_debug_string, so we can exit the
2964 gcc::jit::recording namespace. */
2966 } // namespace recording
2968 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
2970 /* Implementation of pure virtual hook recording::memento::replay_into
2971 for recording::memento_of_new_string_literal. */
2974 recording::memento_of_new_string_literal::replay_into (replayer
*r
)
2976 set_playback_obj (r
->new_string_literal (m_value
->c_str ()));
2979 /* Implementation of recording::memento::make_debug_string for
2983 recording::memento_of_new_string_literal::make_debug_string ()
2985 return string::from_printf (m_ctxt
,
2986 m_value
->get_debug_string ());
2989 /* The implementation of class gcc::jit::recording::unary_op. */
2991 /* Implementation of pure virtual hook recording::memento::replay_into
2992 for recording::unary_op. */
2995 recording::unary_op::replay_into (replayer
*r
)
2997 set_playback_obj (r
->new_unary_op (playback_location (r
, m_loc
),
2999 get_type ()->playback_type (),
3000 m_a
->playback_rvalue ()));
3003 /* Implementation of pure virtual hook recording::rvalue::visit_children
3004 for recording::unary_op. */
3006 recording::unary_op::visit_children (rvalue_visitor
*v
)
3011 /* Implementation of recording::memento::make_debug_string for
3014 static const char * const unary_op_strings
[] = {
3015 "-", /* GCC_JIT_UNARY_OP_MINUS */
3016 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
3017 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
3018 "abs ", /* GCC_JIT_UNARY_OP_ABS */
3022 recording::unary_op::make_debug_string ()
3024 return string::from_printf (m_ctxt
,
3026 unary_op_strings
[m_op
],
3027 m_a
->get_debug_string ());
3030 /* The implementation of class gcc::jit::recording::binary_op. */
3032 /* Implementation of pure virtual hook recording::memento::replay_into
3033 for recording::binary_op. */
3036 recording::binary_op::replay_into (replayer
*r
)
3038 set_playback_obj (r
->new_binary_op (playback_location (r
, m_loc
),
3040 get_type ()->playback_type (),
3041 m_a
->playback_rvalue (),
3042 m_b
->playback_rvalue ()));
3045 /* Implementation of pure virtual hook recording::rvalue::visit_children
3046 for recording::binary_op. */
3048 recording::binary_op::visit_children (rvalue_visitor
*v
)
3054 /* Implementation of recording::memento::make_debug_string for
3057 static const char * const binary_op_strings
[] = {
3058 "+", /* GCC_JIT_BINARY_OP_PLUS */
3059 "-", /* GCC_JIT_BINARY_OP_MINUS */
3060 "*", /* GCC_JIT_BINARY_OP_MULT */
3061 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
3062 "%", /* GCC_JIT_BINARY_OP_MODULO */
3063 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
3064 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
3065 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
3066 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
3067 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
3068 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
3069 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
3073 recording::binary_op::make_debug_string ()
3075 return string::from_printf (m_ctxt
,
3077 m_a
->get_debug_string (),
3078 binary_op_strings
[m_op
],
3079 m_b
->get_debug_string ());
3082 /* The implementation of class gcc::jit::recording::comparison. */
3084 /* Implementation of recording::memento::make_debug_string for
3087 static const char * const comparison_strings
[] =
3089 "==", /* GCC_JIT_COMPARISON_EQ */
3090 "!=", /* GCC_JIT_COMPARISON_NE */
3091 "<", /* GCC_JIT_COMPARISON_LT */
3092 "<=", /* GCC_JIT_COMPARISON_LE */
3093 ">", /* GCC_JIT_COMPARISON_GT */
3094 ">=", /* GCC_JIT_COMPARISON_GE */
3098 recording::comparison::make_debug_string ()
3100 return string::from_printf (m_ctxt
,
3102 m_a
->get_debug_string (),
3103 comparison_strings
[m_op
],
3104 m_b
->get_debug_string ());
3107 /* Implementation of pure virtual hook recording::memento::replay_into
3108 for recording::comparison. */
3111 recording::comparison::replay_into (replayer
*r
)
3113 set_playback_obj (r
->new_comparison (playback_location (r
, m_loc
),
3115 m_a
->playback_rvalue (),
3116 m_b
->playback_rvalue ()));
3119 /* Implementation of pure virtual hook recording::rvalue::visit_children
3120 for recording::comparison. */
3123 recording::comparison::visit_children (rvalue_visitor
*v
)
3129 /* Implementation of pure virtual hook recording::memento::replay_into
3130 for recording::cast. */
3133 recording::cast::replay_into (replayer
*r
)
3135 set_playback_obj (r
->new_cast (playback_location (r
, m_loc
),
3136 m_rvalue
->playback_rvalue (),
3137 get_type ()->playback_type ()));
3140 /* Implementation of pure virtual hook recording::rvalue::visit_children
3141 for recording::cast. */
3143 recording::cast::visit_children (rvalue_visitor
*v
)
3145 v
->visit (m_rvalue
);
3148 /* Implementation of recording::memento::make_debug_string for
3152 recording::cast::make_debug_string ()
3154 return string::from_printf (m_ctxt
,
3156 get_type ()->get_debug_string (),
3157 m_rvalue
->get_debug_string ());
3160 /* The implementation of class gcc::jit::recording::call. */
3162 /* The constructor for gcc::jit::recording::call. */
3164 recording::call::call (recording::context
*ctxt
,
3165 recording::location
*loc
,
3166 recording::function
*func
,
3169 : rvalue (ctxt
, loc
, func
->get_return_type ()),
3173 for (int i
= 0; i
< numargs
; i
++)
3174 m_args
.safe_push (args
[i
]);
3177 /* Implementation of pure virtual hook recording::memento::replay_into
3178 for recording::call. */
3181 recording::call::replay_into (replayer
*r
)
3183 auto_vec
<playback::rvalue
*> playback_args
;
3184 playback_args
.create (m_args
.length ());
3185 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3186 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
3188 set_playback_obj (r
->new_call (playback_location (r
, m_loc
),
3189 m_func
->playback_function (),
3193 /* Implementation of pure virtual hook recording::rvalue::visit_children
3194 for recording::call. */
3197 recording::call::visit_children (rvalue_visitor
*v
)
3199 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3200 v
->visit (m_args
[i
]);
3203 /* Implementation of recording::memento::make_debug_string for
3207 recording::call::make_debug_string ()
3209 /* First, build a buffer for the arguments. */
3210 /* Calculate length of said buffer. */
3211 size_t sz
= 1; /* nil terminator */
3212 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3214 sz
+= strlen (m_args
[i
]->get_debug_string ());
3215 sz
+= 2; /* ", " separator */
3218 /* Now allocate and populate the buffer. */
3219 char *argbuf
= new char[sz
];
3222 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3224 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string ());
3225 len
+= strlen (m_args
[i
]->get_debug_string ());
3226 if (i
+ 1 < m_args
.length ())
3228 strcpy (argbuf
+ len
, ", ");
3234 /* ...and use it to get the string for the call as a whole. */
3235 string
*result
= string::from_printf (m_ctxt
,
3237 m_func
->get_debug_string (),
3245 /* The implementation of class gcc::jit::recording::call_through_ptr. */
3247 /* The constructor for recording::call_through_ptr. */
3249 recording::call_through_ptr::call_through_ptr (recording::context
*ctxt
,
3250 recording::location
*loc
,
3251 recording::rvalue
*fn_ptr
,
3254 : rvalue (ctxt
, loc
,
3255 fn_ptr
->get_type ()->dereference ()
3256 ->as_a_function_type ()->get_return_type ()),
3260 for (int i
= 0; i
< numargs
; i
++)
3261 m_args
.safe_push (args
[i
]);
3264 /* Implementation of pure virtual hook recording::memento::replay_into
3265 for recording::call_through_ptr. */
3268 recording::call_through_ptr::replay_into (replayer
*r
)
3270 auto_vec
<playback::rvalue
*> playback_args
;
3271 playback_args
.create (m_args
.length ());
3272 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3273 playback_args
.safe_push (m_args
[i
]->playback_rvalue ());
3275 set_playback_obj (r
->new_call_through_ptr (playback_location (r
, m_loc
),
3276 m_fn_ptr
->playback_rvalue (),
3280 /* Implementation of pure virtual hook recording::rvalue::visit_children
3281 for recording::call_through_ptr. */
3284 recording::call_through_ptr::visit_children (rvalue_visitor
*v
)
3286 v
->visit (m_fn_ptr
);
3287 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3288 v
->visit (m_args
[i
]);
3291 /* Implementation of recording::memento::make_debug_string for
3292 calls through function ptrs. */
3295 recording::call_through_ptr::make_debug_string ()
3297 /* First, build a buffer for the arguments. */
3298 /* Calculate length of said buffer. */
3299 size_t sz
= 1; /* nil terminator */
3300 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3302 sz
+= strlen (m_args
[i
]->get_debug_string ());
3303 sz
+= 2; /* ", " separator */
3306 /* Now allocate and populate the buffer. */
3307 char *argbuf
= new char[sz
];
3310 for (unsigned i
= 0; i
< m_args
.length (); i
++)
3312 strcpy (argbuf
+ len
, m_args
[i
]->get_debug_string ());
3313 len
+= strlen (m_args
[i
]->get_debug_string ());
3314 if (i
+ 1 < m_args
.length ())
3316 strcpy (argbuf
+ len
, ", ");
3322 /* ...and use it to get the string for the call as a whole. */
3323 string
*result
= string::from_printf (m_ctxt
,
3325 m_fn_ptr
->get_debug_string (),
3333 /* The implementation of class gcc::jit::recording::array_access. */
3335 /* Implementation of pure virtual hook recording::memento::replay_into
3336 for recording::array_access. */
3339 recording::array_access::replay_into (replayer
*r
)
3342 r
->new_array_access (playback_location (r
, m_loc
),
3343 m_ptr
->playback_rvalue (),
3344 m_index
->playback_rvalue ()));
3347 /* Implementation of pure virtual hook recording::rvalue::visit_children
3348 for recording::array_access. */
3351 recording::array_access::visit_children (rvalue_visitor
*v
)
3357 /* Implementation of recording::memento::make_debug_string for
3361 recording::array_access::make_debug_string ()
3363 return string::from_printf (m_ctxt
,
3365 m_ptr
->get_debug_string (),
3366 m_index
->get_debug_string ());
3369 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
3371 /* Implementation of pure virtual hook recording::memento::replay_into
3372 for recording::access_field_of_lvalue. */
3375 recording::access_field_of_lvalue::replay_into (replayer
*r
)
3378 m_lvalue
->playback_lvalue ()
3379 ->access_field (playback_location (r
, m_loc
),
3380 m_field
->playback_field ()));
3384 /* Implementation of pure virtual hook recording::rvalue::visit_children
3385 for recording::access_field_of_lvalue. */
3388 recording::access_field_of_lvalue::visit_children (rvalue_visitor
*v
)
3390 v
->visit (m_lvalue
);
3393 /* Implementation of recording::memento::make_debug_string for
3394 accessing a field of an lvalue. */
3397 recording::access_field_of_lvalue::make_debug_string ()
3399 return string::from_printf (m_ctxt
,
3401 m_lvalue
->get_debug_string (),
3402 m_field
->get_debug_string ());
3405 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
3407 /* Implementation of pure virtual hook recording::memento::replay_into
3408 for recording::access_field_rvalue. */
3411 recording::access_field_rvalue::replay_into (replayer
*r
)
3414 m_rvalue
->playback_rvalue ()
3415 ->access_field (playback_location (r
, m_loc
),
3416 m_field
->playback_field ()));
3419 /* Implementation of pure virtual hook recording::rvalue::visit_children
3420 for recording::access_field_rvalue. */
3423 recording::access_field_rvalue::visit_children (rvalue_visitor
*v
)
3425 v
->visit (m_rvalue
);
3428 /* Implementation of recording::memento::make_debug_string for
3429 accessing a field of an rvalue. */
3432 recording::access_field_rvalue::make_debug_string ()
3434 return string::from_printf (m_ctxt
,
3436 m_rvalue
->get_debug_string (),
3437 m_field
->get_debug_string ());
3440 /* The implementation of class
3441 gcc::jit::recording::dereference_field_rvalue. */
3443 /* Implementation of pure virtual hook recording::memento::replay_into
3444 for recording::dereference_field_rvalue. */
3447 recording::dereference_field_rvalue::replay_into (replayer
*r
)
3450 m_rvalue
->playback_rvalue ()->
3451 dereference_field (playback_location (r
, m_loc
),
3452 m_field
->playback_field ()));
3455 /* Implementation of pure virtual hook recording::rvalue::visit_children
3456 for recording::dereference_field_rvalue. */
3459 recording::dereference_field_rvalue::visit_children (rvalue_visitor
*v
)
3461 v
->visit (m_rvalue
);
3464 /* Implementation of recording::memento::make_debug_string for
3465 dereferencing a field of an rvalue. */
3468 recording::dereference_field_rvalue::make_debug_string ()
3470 return string::from_printf (m_ctxt
,
3472 m_rvalue
->get_debug_string (),
3473 m_field
->get_debug_string ());
3476 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
3478 /* Implementation of pure virtual hook recording::memento::replay_into
3479 for recording::dereference_rvalue. */
3482 recording::dereference_rvalue::replay_into (replayer
*r
)
3485 m_rvalue
->playback_rvalue ()->
3486 dereference (playback_location (r
, m_loc
)));
3489 /* Implementation of pure virtual hook recording::rvalue::visit_children
3490 for recording::dereference_rvalue. */
3493 recording::dereference_rvalue::visit_children (rvalue_visitor
*v
)
3495 v
->visit (m_rvalue
);
3498 /* Implementation of recording::memento::make_debug_string for
3499 dereferencing an rvalue. */
3502 recording::dereference_rvalue::make_debug_string ()
3504 return string::from_printf (m_ctxt
,
3506 m_rvalue
->get_debug_string ());
3509 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
3511 /* Implementation of pure virtual hook recording::memento::replay_into
3512 for recording::get_address_of_lvalue. */
3515 recording::get_address_of_lvalue::replay_into (replayer
*r
)
3518 m_lvalue
->playback_lvalue ()->
3519 get_address (playback_location (r
, m_loc
)));
3522 /* Implementation of pure virtual hook recording::rvalue::visit_children
3523 for recording::get_address_of_lvalue. */
3526 recording::get_address_of_lvalue::visit_children (rvalue_visitor
*v
)
3528 v
->visit (m_lvalue
);
3531 /* Implementation of recording::memento::make_debug_string for
3532 getting the address of an lvalue. */
3535 recording::get_address_of_lvalue::make_debug_string ()
3537 return string::from_printf (m_ctxt
,
3539 m_lvalue
->get_debug_string ());
3542 /* The implementation of class gcc::jit::recording::local. */
3544 /* Implementation of pure virtual hook recording::memento::replay_into
3545 for recording::local. */
3548 recording::local::replay_into (replayer
*r
)
3551 m_func
->playback_function ()
3552 ->new_local (playback_location (r
, m_loc
),
3553 m_type
->playback_type (),
3554 playback_string (m_name
)));
3557 /* Override the default implementation of
3558 recording::memento::write_to_dump for locals by writing
3560 for use at the top of the function body as if it were a
3564 recording::local::write_to_dump (dump
&d
)
3566 if (d
.update_locations ())
3567 m_loc
= d
.make_location ();
3568 d
.write(" %s %s;\n",
3569 m_type
->get_debug_string (),
3570 get_debug_string ());
3573 /* The implementation of class gcc::jit::recording::statement. */
3575 /* We poison the default implementation of
3576 gcc::jit::recording::statement::get_successor_blocks
3577 since this vfunc must only ever be called on terminator
3581 recording::statement::get_successor_blocks (block
**/
*out_next1*/
,
3582 block
**/
*out_next2*/
) const
3584 /* The base class implementation is for non-terminating statements,
3585 and thus should never be called. */
3590 /* Extend the default implementation of
3591 recording::memento::write_to_dump for statements by (if requested)
3592 updating the location of the statement to the current location in
3596 recording::statement::write_to_dump (dump
&d
)
3598 memento::write_to_dump (d
);
3599 if (d
.update_locations ())
3600 m_loc
= d
.make_location ();
3603 /* The implementation of class gcc::jit::recording::eval. */
3605 /* Implementation of pure virtual hook recording::memento::replay_into
3606 for recording::eval. */
3609 recording::eval::replay_into (replayer
*r
)
3611 playback_block (get_block ())
3612 ->add_eval (playback_location (r
),
3613 m_rvalue
->playback_rvalue ());
3616 /* Implementation of recording::memento::make_debug_string for
3617 an eval statement. */
3620 recording::eval::make_debug_string ()
3622 return string::from_printf (m_ctxt
,
3624 m_rvalue
->get_debug_string ());
3627 /* The implementation of class gcc::jit::recording::assignment. */
3629 /* Implementation of pure virtual hook recording::memento::replay_into
3630 for recording::assignment. */
3633 recording::assignment::replay_into (replayer
*r
)
3635 playback_block (get_block ())
3636 ->add_assignment (playback_location (r
),
3637 m_lvalue
->playback_lvalue (),
3638 m_rvalue
->playback_rvalue ());
3641 /* Implementation of recording::memento::make_debug_string for
3642 an assignment statement. */
3645 recording::assignment::make_debug_string ()
3647 return string::from_printf (m_ctxt
,
3649 m_lvalue
->get_debug_string (),
3650 m_rvalue
->get_debug_string ());
3653 /* The implementation of class gcc::jit::recording::assignment_op. */
3655 /* Implementation of pure virtual hook recording::memento::replay_into
3656 for recording::assignment_op. */
3659 recording::assignment_op::replay_into (replayer
*r
)
3661 playback::type
*result_type
=
3662 m_lvalue
->playback_lvalue ()->get_type ();
3664 playback::rvalue
*binary_op
=
3665 r
->new_binary_op (playback_location (r
),
3668 m_lvalue
->playback_rvalue (),
3669 m_rvalue
->playback_rvalue ());
3671 playback_block (get_block ())
3672 ->add_assignment (playback_location (r
),
3673 m_lvalue
->playback_lvalue (),
3677 /* Implementation of recording::memento::make_debug_string for
3678 an assignment_op statement. */
3681 recording::assignment_op::make_debug_string ()
3683 return string::from_printf (m_ctxt
,
3685 m_lvalue
->get_debug_string (),
3686 binary_op_strings
[m_op
],
3687 m_rvalue
->get_debug_string ());
3690 /* The implementation of class gcc::jit::recording::comment. */
3692 /* Implementation of pure virtual hook recording::memento::replay_into
3693 for recording::comment. */
3696 recording::comment::replay_into (replayer
*r
)
3698 playback_block (get_block ())
3699 ->add_comment (playback_location (r
),
3703 /* Implementation of recording::memento::make_debug_string for
3704 a comment "statement". */
3707 recording::comment::make_debug_string ()
3709 return string::from_printf (m_ctxt
,
3714 /* The implementation of class gcc::jit::recording::conditional. */
3716 /* Implementation of pure virtual hook recording::memento::replay_into
3717 for recording::conditional. */
3720 recording::conditional::replay_into (replayer
*r
)
3722 playback_block (get_block ())
3723 ->add_conditional (playback_location (r
),
3724 m_boolval
->playback_rvalue (),
3725 playback_block (m_on_true
),
3726 playback_block (m_on_false
));
3729 /* Override the poisoned default implementation of
3730 gcc::jit::recording::statement::get_successor_blocks
3732 A conditional jump has 2 successor blocks. */
3735 recording::conditional::get_successor_blocks (block
**out_next1
,
3736 block
**out_next2
) const
3738 *out_next1
= m_on_true
;
3739 *out_next2
= m_on_false
;
3743 /* Implementation of recording::memento::make_debug_string for
3744 a conditional jump statement. */
3747 recording::conditional::make_debug_string ()
3750 return string::from_printf (m_ctxt
,
3751 "if (%s) goto %s; else goto %s;",
3752 m_boolval
->get_debug_string (),
3753 m_on_true
->get_debug_string (),
3754 m_on_false
->get_debug_string ());
3756 return string::from_printf (m_ctxt
,
3758 m_boolval
->get_debug_string (),
3759 m_on_true
->get_debug_string ());
3762 /* The implementation of class gcc::jit::recording::jump. */
3764 /* Implementation of pure virtual hook recording::memento::replay_into
3765 for recording::jump. */
3768 recording::jump::replay_into (replayer
*r
)
3770 playback_block (get_block ())
3771 ->add_jump (playback_location (r
),
3772 m_target
->playback_block ());
3775 /* Override the poisoned default implementation of
3776 gcc::jit::recording::statement::get_successor_blocks
3778 An unconditional jump has 1 successor block. */
3781 recording::jump::get_successor_blocks (block
**out_next1
,
3782 block
**/
*out_next2*/
) const
3784 *out_next1
= m_target
;
3788 /* Implementation of recording::memento::make_debug_string for
3789 a unconditional jump statement. */
3792 recording::jump::make_debug_string ()
3794 return string::from_printf (m_ctxt
,
3796 m_target
->get_debug_string ());
3799 /* The implementation of class gcc::jit::recording::return_. */
3801 /* Implementation of pure virtual hook recording::memento::replay_into
3802 for recording::return_. */
3805 recording::return_::replay_into (replayer
*r
)
3807 playback_block (get_block ())
3808 ->add_return (playback_location (r
),
3809 m_rvalue
? m_rvalue
->playback_rvalue () : NULL
);
3812 /* Override the poisoned default implementation of
3813 gcc::jit::recording::statement::get_successor_blocks
3815 A return statement has no successor block. */
3818 recording::return_::get_successor_blocks (block
**/
*out_next1*/
,
3819 block
**/
*out_next2*/
) const
3824 /* Implementation of recording::memento::make_debug_string for
3825 a return statement (covers both those with and without rvalues). */
3828 recording::return_::make_debug_string ()
3831 return string::from_printf (m_ctxt
,
3833 m_rvalue
->get_debug_string ());
3835 return string::from_printf (m_ctxt
,
3839 } // namespace gcc::jit