2014-11-20 Robert Dewar <dewar@adacore.com>
[official-gcc.git] / gcc / jit / jit-recording.c
blob8069afc7558d3adc5c1af14ae1b32697cfe38b41
1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2014 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)
10 any later version.
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/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "opts.h"
26 #include "tree.h"
27 #include "pretty-print.h"
29 #include <pthread.h>
31 #include "jit-common.h"
32 #include "jit-builtins.h"
33 #include "jit-recording.h"
34 #include "jit-playback.h"
36 namespace gcc {
37 namespace jit {
39 // class dump
41 dump::dump (recording::context &ctxt,
42 const char *filename,
43 bool update_locations)
44 : m_ctxt (ctxt),
45 m_filename (filename),
46 m_update_locations (update_locations),
47 m_line (0),
48 m_column (0)
50 m_file = fopen (filename, "w");
51 if (!m_file)
52 ctxt.add_error (NULL,
53 "error opening dump file %s for writing: %s",
54 filename,
55 xstrerror (errno));
58 dump::~dump ()
60 if (m_file)
62 int err = fclose (m_file);
63 if (err)
64 m_ctxt.add_error (NULL,
65 "error closing dump file %s: %s",
66 m_filename,
67 xstrerror (errno));
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. */
76 void
77 dump::write (const char *fmt, ...)
79 va_list ap;
80 char *buf = NULL;
82 /* If there was an error opening the file, we've already reported it.
83 Don't attempt further work. */
84 if (!m_file)
85 return;
87 va_start (ap, fmt);
88 vasprintf (&buf, fmt, ap);
89 va_end (ap);
91 if (!buf)
93 m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
94 m_filename);
95 return;
98 if (fwrite (buf, strlen (buf), 1, m_file) != 1)
99 m_ctxt.add_error (NULL, "error writing to dump file %s",
100 m_filename);
102 /* Update line/column: */
103 for (const char *ptr = buf; *ptr; ptr++)
105 if ('\n' == *ptr)
107 m_line++;
108 m_column = 0;
110 else
111 m_column++;
114 free (buf);
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 /**********************************************************************
127 Recording.
128 **********************************************************************/
130 /* Get the playback::location for the given recording::location,
131 handling a NULL input with a NULL output. */
133 playback::location *
134 recording::playback_location (replayer *r, recording::location *loc)
136 if (loc)
137 return loc->playback_location (r);
138 else
139 return NULL;
142 /* Get a const char * for the given recording::string
143 handling a NULL input with a NULL output. */
145 const char *
146 recording::playback_string (recording::string *str)
148 if (str)
149 return str->c_str ();
150 else
151 return NULL;
154 /* Get the playback::block for the given recording::block,
155 handling a NULL input with a NULL output. */
157 playback::block *
158 recording::playback_block (recording::block *b)
160 if (b)
161 return b->playback_block ();
162 else
163 return NULL;
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),
173 m_error_count (0),
174 m_first_error_str (NULL),
175 m_owns_first_error_str (false),
176 m_mementos (),
177 m_compound_types (),
178 m_functions (),
179 m_FILE_type (NULL),
180 m_builtins_manager(NULL)
182 if (parent_ctxt)
184 /* Inherit options from parent.
185 Note that the first memcpy means copying pointers to strings. */
186 memcpy (m_str_options,
187 parent_ctxt->m_str_options,
188 sizeof (m_str_options));
189 memcpy (m_int_options,
190 parent_ctxt->m_int_options,
191 sizeof (m_int_options));
192 memcpy (m_bool_options,
193 parent_ctxt->m_bool_options,
194 sizeof (m_bool_options));
196 else
198 memset (m_str_options, 0, sizeof (m_str_options));
199 memset (m_int_options, 0, sizeof (m_int_options));
200 memset (m_bool_options, 0, sizeof (m_bool_options));
203 memset (m_basic_types, 0, sizeof (m_basic_types));
206 /* The destructor for gcc::jit::recording::context, implicitly used by
207 gcc_jit_context_release. */
209 recording::context::~context ()
211 int i;
212 memento *m;
213 FOR_EACH_VEC_ELT (m_mementos, i, m)
215 delete m;
218 if (m_builtins_manager)
219 delete m_builtins_manager;
221 if (m_owns_first_error_str)
222 free (m_first_error_str);
225 /* Add the given mememto to the list of those tracked by this
226 gcc::jit::recording::context, so that e.g. it can be deleted
227 when this context is released. */
229 void
230 recording::context::record (memento *m)
232 gcc_assert (m);
234 m_mementos.safe_push (m);
237 /* Replay this context (and any parents) into the given replayer. */
239 void
240 recording::context::replay_into (replayer *r)
242 int i;
243 memento *m;
245 /* If we have a parent context, we must replay it. This will
246 recursively walk backwards up the historical tree, then replay things
247 forwards "in historical order", starting with the ultimate parent
248 context, until we reach the "this" context.
250 Note that we fully replay the parent, then fully replay the child,
251 which means that inter-context references can only exist from child
252 to parent, not the other way around.
254 All of this replaying is suboptimal - it would be better to do the
255 work for the parent context *once*, rather than replaying the parent
256 every time we replay each child. However, fixing this requires deep
257 surgery to lifetime-management: we'd need every context family tree
258 to have its own GC heap, and to initialize the GCC code to use that
259 heap (with a mutex on such a heap). */
260 if (m_parent_ctxt)
261 m_parent_ctxt->replay_into (r);
263 if (r->errors_occurred ())
264 return;
266 /* Replay this context's saved operations into r. */
267 FOR_EACH_VEC_ELT (m_mementos, i, m)
269 /* Disabled low-level debugging, here if we need it: print what
270 we're replaying.
271 Note that the calls to get_debug_string might lead to more
272 mementos being created for the strings.
273 This can also be used to exercise the debug_string
274 machinery. */
275 if (0)
276 printf ("context %p replaying (%p): %s\n",
277 (void *)this, (void *)m, m->get_debug_string ());
279 m->replay_into (r);
281 if (r->errors_occurred ())
282 return;
286 /* During a playback, we associate objects from the recording with
287 their counterparts during this playback.
289 For simplicity, we store this within the recording objects.
291 The following method cleans away these associations, to ensure that
292 we never have out-of-date associations lingering on subsequent
293 playbacks (the objects pointed to are GC-managed, but the
294 recording objects don't own refs to them). */
296 void
297 recording::context::disassociate_from_playback ()
299 int i;
300 memento *m;
302 if (m_parent_ctxt)
303 m_parent_ctxt->disassociate_from_playback ();
305 FOR_EACH_VEC_ELT (m_mementos, i, m)
307 m->set_playback_obj (NULL);
311 /* Create a recording::string instance and add it to this context's list
312 of mementos.
314 This creates a fresh copy of the given 0-terminated buffer. */
316 recording::string *
317 recording::context::new_string (const char *text)
319 if (!text)
320 return NULL;
322 recording::string *result = new string (this, text);
323 record (result);
324 return result;
327 /* Create a recording::location instance and add it to this context's
328 list of mementos.
330 Implements the post-error-checking part of
331 gcc_jit_context_new_location. */
333 recording::location *
334 recording::context::new_location (const char *filename,
335 int line,
336 int column)
338 recording::location *result =
339 new recording::location (this,
340 new_string (filename),
341 line, column);
342 record (result);
343 return result;
346 /* If we haven't seen this enum value yet, create a recording::type
347 instance and add it to this context's list of mementos.
349 If we have seen it before, reuse our cached value, so that repeated
350 calls on the context give the same object.
352 If we have a parent context, the cache is within the ultimate
353 ancestor context.
355 Implements the post-error-checking part of
356 gcc_jit_context_get_type. */
358 recording::type *
359 recording::context::get_type (enum gcc_jit_types kind)
361 if (!m_basic_types[kind])
363 if (m_parent_ctxt)
364 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
365 else
367 recording::type *result = new memento_of_get_type (this, kind);
368 record (result);
369 m_basic_types[kind] = result;
373 return m_basic_types[kind];
376 /* Get a recording::type instance for the given size and signedness.
377 This is implemented in terms of recording::context::get_type
378 above.
380 Implements the post-error-checking part of
381 gcc_jit_context_get_int_type. */
383 recording::type *
384 recording::context::get_int_type (int num_bytes, int is_signed)
386 /* We can't use a switch here since some of the values are macros affected
387 by options; e.g. i386.h has
388 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
389 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
390 are in bits, rather than bytes.
392 const int num_bits = num_bytes * 8;
393 if (num_bits == INT_TYPE_SIZE)
394 return get_type (is_signed
395 ? GCC_JIT_TYPE_INT
396 : GCC_JIT_TYPE_UNSIGNED_INT);
397 if (num_bits == CHAR_TYPE_SIZE)
398 return get_type (is_signed
399 ? GCC_JIT_TYPE_SIGNED_CHAR
400 : GCC_JIT_TYPE_UNSIGNED_CHAR);
401 if (num_bits == SHORT_TYPE_SIZE)
402 return get_type (is_signed
403 ? GCC_JIT_TYPE_SHORT
404 : GCC_JIT_TYPE_UNSIGNED_SHORT);
405 if (num_bits == LONG_TYPE_SIZE)
406 return get_type (is_signed
407 ? GCC_JIT_TYPE_LONG
408 : GCC_JIT_TYPE_UNSIGNED_LONG);
409 if (num_bits == LONG_LONG_TYPE_SIZE)
410 return get_type (is_signed
411 ? GCC_JIT_TYPE_LONG_LONG
412 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
414 /* Some other size, not corresponding to the C int types. */
415 /* To be written: support arbitrary other sizes, sharing by
416 memoizing at the recording::context level? */
417 gcc_unreachable ();
420 /* Create a recording::type instance and add it to this context's list
421 of mementos.
423 Implements the post-error-checking part of
424 gcc_jit_context_new_array_type. */
426 recording::type *
427 recording::context::new_array_type (recording::location *loc,
428 recording::type *element_type,
429 int num_elements)
431 if (struct_ *s = element_type->dyn_cast_struct ())
432 if (!s->get_fields ())
434 add_error (NULL,
435 "cannot create an array of type %s"
436 " until the fields have been set",
437 s->get_name ()->c_str ());
438 return NULL;
440 recording::type *result =
441 new recording::array_type (this, loc, element_type, num_elements);
442 record (result);
443 return result;
446 /* Create a recording::field instance and add it to this context's list
447 of mementos.
449 Implements the post-error-checking part of
450 gcc_jit_context_new_field. */
452 recording::field *
453 recording::context::new_field (recording::location *loc,
454 recording::type *type,
455 const char *name)
457 recording::field *result =
458 new recording::field (this, loc, type, new_string (name));
459 record (result);
460 return result;
463 /* Create a recording::struct_ instance and add it to this context's
464 list of mementos and list of compound types.
466 Implements the post-error-checking part of
467 gcc_jit_context_new_struct_type. */
469 recording::struct_ *
470 recording::context::new_struct_type (recording::location *loc,
471 const char *name)
473 recording::struct_ *result = new struct_ (this, loc, new_string (name));
474 record (result);
475 m_compound_types.safe_push (result);
476 return result;
479 /* Create a recording::union_ instance and add it to this context's
480 list of mementos and list of compound types.
482 Implements the first post-error-checking part of
483 gcc_jit_context_new_union_type. */
485 recording::union_ *
486 recording::context::new_union_type (recording::location *loc,
487 const char *name)
489 recording::union_ *result = new union_ (this, loc, new_string (name));
490 record (result);
491 m_compound_types.safe_push (result);
492 return result;
495 /* Create a recording::type instance and add it to this context's list
496 of mementos.
498 Implements the post-error-checking part of
499 gcc_jit_context_new_function_ptr_type. */
501 recording::type *
502 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
503 recording::type *return_type,
504 int num_params,
505 recording::type **param_types,
506 int is_variadic)
508 recording::function_type *fn_type =
509 new function_type (this,
510 return_type,
511 num_params,
512 param_types,
513 is_variadic);
514 record (fn_type);
516 /* Return a pointer-type to the the function type. */
517 return fn_type->get_pointer ();
520 /* Create a recording::param instance and add it to this context's list
521 of mementos.
523 Implements the post-error-checking part of
524 gcc_jit_context_new_param. */
526 recording::param *
527 recording::context::new_param (recording::location *loc,
528 recording::type *type,
529 const char *name)
531 recording::param *result = new recording::param (this, loc, type, new_string (name));
532 record (result);
533 return result;
536 /* Create a recording::function instance and add it to this context's list
537 of mementos and list of functions.
539 Implements the post-error-checking part of
540 gcc_jit_context_new_function. */
542 recording::function *
543 recording::context::new_function (recording::location *loc,
544 enum gcc_jit_function_kind kind,
545 recording::type *return_type,
546 const char *name,
547 int num_params,
548 recording::param **params,
549 int is_variadic,
550 enum built_in_function builtin_id)
552 recording::function *result =
553 new recording::function (this,
554 loc, kind, return_type,
555 new_string (name),
556 num_params, params, is_variadic,
557 builtin_id);
558 record (result);
559 m_functions.safe_push (result);
561 return result;
564 /* Get a recording::function instance, which is lazily-created and added
565 to the context's lists of mementos.
567 Implements the post-error-checking part of
568 gcc_jit_context_get_builtin_function. */
570 recording::function *
571 recording::context::get_builtin_function (const char *name)
573 if (!m_builtins_manager)
574 m_builtins_manager = new builtins_manager (this);
575 return m_builtins_manager->get_builtin_function (name);
578 /* Create a recording::global instance and add it to this context's list
579 of mementos.
581 Implements the post-error-checking part of
582 gcc_jit_context_new_global. */
584 recording::lvalue *
585 recording::context::new_global (recording::location *loc,
586 recording::type *type,
587 const char *name)
589 recording::lvalue *result =
590 new recording::global (this, loc, type, new_string (name));
591 record (result);
592 return result;
595 /* Create a recording::memento_of_new_rvalue_from_int instance and add
596 it to this context's list of mementos.
598 Implements the post-error-checking part of
599 gcc_jit_context_new_rvalue_from_int. */
601 recording::rvalue *
602 recording::context::new_rvalue_from_int (recording::type *type,
603 int value)
605 recording::rvalue *result =
606 new memento_of_new_rvalue_from_int (this, NULL, type, value);
607 record (result);
608 return result;
611 /* Create a recording::memento_of_new_rvalue_from_double instance and
612 add it to this context's list of mementos.
614 Implements the post-error-checking part of
615 gcc_jit_context_new_rvalue_from_double. */
617 recording::rvalue *
618 recording::context::new_rvalue_from_double (recording::type *type,
619 double value)
621 recording::rvalue *result =
622 new memento_of_new_rvalue_from_double (this, NULL, type, value);
623 record (result);
624 return result;
627 /* Create a recording::memento_of_new_rvalue_from_ptr instance and add
628 it to this context's list of mementos.
630 Implements the post-error-checking part of
631 gcc_jit_context_new_rvalue_from_ptr. */
633 recording::rvalue *
634 recording::context::new_rvalue_from_ptr (recording::type *type,
635 void *value)
637 recording::rvalue *result =
638 new memento_of_new_rvalue_from_ptr (this, NULL, type, value);
639 record (result);
640 return result;
643 /* Create a recording::memento_of_new_string_literal instance and add it
644 to this context's list of mementos.
646 Implements the post-error-checking part of
647 gcc_jit_context_new_string_literal. */
649 recording::rvalue *
650 recording::context::new_string_literal (const char *value)
652 recording::rvalue *result =
653 new memento_of_new_string_literal (this, NULL, new_string (value));
654 record (result);
655 return result;
658 /* Create a recording::unary_op instance and add it to this context's
659 list of mementos.
661 Implements the post-error-checking part of
662 gcc_jit_context_new_unary_op. */
664 recording::rvalue *
665 recording::context::new_unary_op (recording::location *loc,
666 enum gcc_jit_unary_op op,
667 recording::type *result_type,
668 recording::rvalue *a)
670 recording::rvalue *result =
671 new unary_op (this, loc, op, result_type, a);
672 record (result);
673 return result;
676 /* Create a recording::binary_op instance and add it to this context's
677 list of mementos.
679 Implements the post-error-checking part of
680 gcc_jit_context_new_binary_op. */
682 recording::rvalue *
683 recording::context::new_binary_op (recording::location *loc,
684 enum gcc_jit_binary_op op,
685 recording::type *result_type,
686 recording::rvalue *a,
687 recording::rvalue *b)
689 recording::rvalue *result =
690 new binary_op (this, loc, op, result_type, a, b);
691 record (result);
692 return result;
695 /* Create a recording::comparison instance and add it to this context's
696 list of mementos.
698 Implements the post-error-checking part of
699 gcc_jit_context_new_comparison. */
701 recording::rvalue *
702 recording::context::new_comparison (recording::location *loc,
703 enum gcc_jit_comparison op,
704 recording::rvalue *a,
705 recording::rvalue *b)
707 recording::rvalue *result = new comparison (this, loc, op, a, b);
708 record (result);
709 return result;
712 /* Create a recording::cast instance and add it to this context's list
713 of mementos.
715 Implements the post-error-checking part of
716 gcc_jit_context_new_cast. */
718 recording::rvalue *
719 recording::context::new_cast (recording::location *loc,
720 recording::rvalue *expr,
721 recording::type *type_)
723 recording::rvalue *result = new cast (this, loc, expr, type_);
724 record (result);
725 return result;
728 /* Create a recording::call instance and add it to this context's list
729 of mementos.
731 Implements the post-error-checking part of
732 gcc_jit_context_new_call. */
734 recording::rvalue *
735 recording::context::new_call (recording::location *loc,
736 function *func,
737 int numargs , recording::rvalue **args)
739 recording::rvalue *result = new call (this, loc, func, numargs, args);
740 record (result);
741 return result;
744 /* Create a recording::call_through_ptr instance and add it to this
745 context's list of mementos.
747 Implements the post-error-checking part of
748 gcc_jit_context_new_call_through_ptr. */
750 recording::rvalue *
751 recording::context::new_call_through_ptr (recording::location *loc,
752 recording::rvalue *fn_ptr,
753 int numargs,
754 recording::rvalue **args)
756 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
757 record (result);
758 return result;
761 /* Create a recording::array_access instance and add it to this context's list
762 of mementos.
764 Implements the post-error-checking part of
765 gcc_jit_context_new_array_access. */
767 recording::lvalue *
768 recording::context::new_array_access (recording::location *loc,
769 recording::rvalue *ptr,
770 recording::rvalue *index)
772 recording::lvalue *result = new array_access (this, loc, ptr, index);
773 record (result);
774 return result;
777 /* Set the given string option for this context, or add an error if
778 it's not recognized.
780 Implements the post-error-checking part of
781 gcc_jit_context_set_str_option. */
783 void
784 recording::context::set_str_option (enum gcc_jit_str_option opt,
785 const char *value)
787 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
789 add_error (NULL,
790 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
791 return;
793 m_str_options[opt] = value;
796 /* Set the given integer option for this context, or add an error if
797 it's not recognized.
799 Implements the post-error-checking part of
800 gcc_jit_context_set_int_option. */
802 void
803 recording::context::set_int_option (enum gcc_jit_int_option opt,
804 int value)
806 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
808 add_error (NULL,
809 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
810 return;
812 m_int_options[opt] = value;
815 /* Set the given boolean option for this context, or add an error if
816 it's not recognized.
818 Implements the post-error-checking part of
819 gcc_jit_context_set_bool_option. */
821 void
822 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
823 int value)
825 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
827 add_error (NULL,
828 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
829 return;
831 m_bool_options[opt] = value ? true : false;
834 /* This mutex guards gcc::jit::recording::context::compile, so that only
835 one thread can be accessing the bulk of GCC's state at once. */
837 static pthread_mutex_t jit_mutex = PTHREAD_MUTEX_INITIALIZER;
839 /* Validate this context, and if it passes, compile it within a
840 mutex.
842 Implements the post-error-checking part of
843 gcc_jit_context_compile. */
845 result *
846 recording::context::compile ()
848 validate ();
850 if (errors_occurred ())
851 return NULL;
853 /* Acquire the big GCC mutex. */
854 pthread_mutex_lock (&jit_mutex);
855 gcc_assert (NULL == ::gcc::jit::active_playback_ctxt);
857 /* Set up a playback context. */
858 ::gcc::jit::playback::context replayer (this);
859 ::gcc::jit::active_playback_ctxt = &replayer;
861 result *result_obj = replayer.compile ();
863 /* Release the big GCC mutex. */
864 ::gcc::jit::active_playback_ctxt = NULL;
865 pthread_mutex_unlock (&jit_mutex);
867 return result_obj;
870 /* Format the given error using printf's conventions, print
871 it to stderr, and add it to the context. */
873 void
874 recording::context::add_error (location *loc, const char *fmt, ...)
876 va_list ap;
877 va_start (ap, fmt);
878 add_error_va (loc, fmt, ap);
879 va_end (ap);
882 /* Format the given error using printf's conventions, print
883 it to stderr, and add it to the context. */
885 void
886 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
888 char *malloced_msg;
889 const char *errmsg;
890 bool has_ownership;
892 vasprintf (&malloced_msg, fmt, ap);
893 if (malloced_msg)
895 errmsg = malloced_msg;
896 has_ownership = true;
898 else
900 errmsg = "out of memory generating error message";
901 has_ownership = false;
904 const char *ctxt_progname =
905 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
906 if (!ctxt_progname)
907 ctxt_progname = "libgccjit.so";
909 if (loc)
910 fprintf (stderr, "%s: %s: error: %s\n",
911 ctxt_progname,
912 loc->get_debug_string (),
913 errmsg);
914 else
915 fprintf (stderr, "%s: error: %s\n",
916 ctxt_progname,
917 errmsg);
919 if (!m_error_count)
921 m_first_error_str = const_cast <char *> (errmsg);
922 m_owns_first_error_str = has_ownership;
924 else
925 if (has_ownership)
926 free (malloced_msg);
928 m_error_count++;
931 /* Get the message for the first error that occurred on this context, or
932 NULL if no errors have occurred on it.
934 Implements the post-error-checking part of
935 gcc_jit_context_get_first_error. */
937 const char *
938 recording::context::get_first_error () const
940 return m_first_error_str;
943 /* Lazily generate and record a recording::type representing an opaque
944 struct named "FILE".
946 For use if client code tries to dereference the result of
947 get_type (GCC_JIT_TYPE_FILE_PTR). */
949 recording::type *
950 recording::context::get_opaque_FILE_type ()
952 if (!m_FILE_type)
953 m_FILE_type = new_struct_type (NULL, "FILE");
954 return m_FILE_type;
957 /* Dump a C-like representation of the given context to the given path.
958 If UPDATE_LOCATIONS is true, update the locations within the
959 context's mementos to point to the dumpfile.
961 Implements the post-error-checking part of
962 gcc_jit_context_dump_to_file. */
964 void
965 recording::context::dump_to_file (const char *path, bool update_locations)
967 int i;
968 dump d (*this, path, update_locations);
970 /* Forward declaration of structs and unions. */
971 compound_type *st;
972 FOR_EACH_VEC_ELT (m_compound_types, i, st)
974 d.write ("%s;\n\n", st->get_debug_string ());
977 /* Content of structs, where set. */
978 FOR_EACH_VEC_ELT (m_compound_types, i, st)
979 if (st->get_fields ())
981 st->get_fields ()->write_to_dump (d);
982 d.write ("\n");
985 function *fn;
986 FOR_EACH_VEC_ELT (m_functions, i, fn)
988 fn->write_to_dump (d);
992 /* This is a pre-compilation check for the context (and any parents).
994 Detect errors within the context, adding errors if any are found. */
996 void
997 recording::context::validate ()
999 if (m_parent_ctxt)
1000 m_parent_ctxt->validate ();
1002 int i;
1003 function *fn;
1004 FOR_EACH_VEC_ELT (m_functions, i, fn)
1005 fn->validate ();
1008 /* The implementation of class gcc::jit::recording::memento. */
1010 /* Get a (const char *) debug description of the given memento, by
1011 calling the pure-virtual make_debug_string hook, caching the
1012 result.
1014 It is intended that this should only be called in debugging and
1015 error-handling paths, so this doesn't need to be particularly
1016 optimized. */
1018 const char *
1019 recording::memento::get_debug_string ()
1021 if (!m_debug_string)
1022 m_debug_string = make_debug_string ();
1023 return m_debug_string->c_str ();
1026 /* Default implementation of recording::memento::write_to_dump, writing
1027 an indented form of the memento's debug string to the dump. */
1029 void
1030 recording::memento::write_to_dump (dump &d)
1032 d.write(" %s\n", get_debug_string ());
1035 /* The implementation of class gcc::jit::recording::string. */
1037 /* Constructor for gcc::jit::recording::string::string, allocating a
1038 copy of the given text using new char[]. */
1040 recording::string::string (context *ctxt, const char *text)
1041 : memento (ctxt)
1043 m_len = strlen (text);
1044 m_buffer = new char[m_len + 1];
1045 strcpy (m_buffer, text);
1048 /* Destructor for gcc::jit::recording::string::string. */
1050 recording::string::~string ()
1052 delete[] m_buffer;
1055 /* Function for making gcc::jit::recording::string instances on a
1056 context via printf-style formatting.
1058 It is intended that this should only be called in debugging and
1059 error-handling paths, so this doesn't need to be particularly
1060 optimized, hence the double-copy of the string is acceptable. */
1062 recording::string *
1063 recording::string::from_printf (context *ctxt, const char *fmt, ...)
1065 va_list ap;
1066 char *buf = NULL;
1067 recording::string *result;
1069 va_start (ap, fmt);
1070 vasprintf (&buf, fmt, ap);
1071 va_end (ap);
1073 if (!buf)
1075 ctxt->add_error (NULL, "malloc failure");
1076 return NULL;
1079 result = ctxt->new_string (buf);
1080 free (buf);
1081 return result;
1084 /* Implementation of recording::memento::make_debug_string for strings,
1085 wrapping the given string in quotes and escaping as necessary. */
1087 recording::string *
1088 recording::string::make_debug_string ()
1090 /* Hack to avoid infinite recursion into strings when logging all
1091 mementos: don't re-escape strings: */
1092 if (m_buffer[0] == '"')
1093 return this;
1095 /* Wrap in quotes and do escaping etc */
1097 size_t sz = (1 /* opening quote */
1098 + (m_len * 2) /* each char might get escaped */
1099 + 1 /* closing quote */
1100 + 1); /* nil termintator */
1101 char *tmp = new char[sz];
1102 size_t len = 0;
1104 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1105 APPEND('"'); /* opening quote */
1106 for (size_t i = 0; i < m_len ; i++)
1108 char ch = m_buffer[i];
1109 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
1110 APPEND('\\');
1111 APPEND(ch);
1113 APPEND('"'); /* closing quote */
1114 #undef APPEND
1115 tmp[len] = '\0'; /* nil termintator */
1117 string *result = m_ctxt->new_string (tmp);
1119 delete[] tmp;
1120 return result;
1123 /* The implementation of class gcc::jit::recording::location. */
1125 /* Implementation of recording::memento::replay_into for locations.
1127 Create a new playback::location and store it into the
1128 recording::location's m_playback_obj field. */
1130 void
1131 recording::location::replay_into (replayer *r)
1133 m_playback_obj = r->new_location (this,
1134 m_filename->c_str (),
1135 m_line,
1136 m_column);
1139 /* Implementation of recording::memento::make_debug_string for locations,
1140 turning them into the usual form:
1141 FILENAME:LINE:COLUMN
1142 like we do when emitting diagnostics. */
1144 recording::string *
1145 recording::location::make_debug_string ()
1147 return string::from_printf (m_ctxt,
1148 "%s:%i:%i",
1149 m_filename->c_str (), m_line, m_column);
1152 /* The implementation of class gcc::jit::recording::type. */
1154 /* Given a type T, get the type T*.
1156 If this doesn't already exist, generate a new memento_of_get_pointer
1157 instance and add it to this type's context's list of mementos.
1159 Otherwise, use the cached type.
1161 Implements the post-error-checking part of
1162 gcc_jit_type_get_pointer. */
1164 recording::type *
1165 recording::type::get_pointer ()
1167 if (!m_pointer_to_this_type)
1169 m_pointer_to_this_type = new memento_of_get_pointer (this);
1170 m_ctxt->record (m_pointer_to_this_type);
1172 return m_pointer_to_this_type;
1175 /* Given a type T, get the type const T.
1177 Implements the post-error-checking part of
1178 gcc_jit_type_get_const. */
1180 recording::type *
1181 recording::type::get_const ()
1183 recording::type *result = new memento_of_get_const (this);
1184 m_ctxt->record (result);
1185 return result;
1188 /* Given a type T, get the type volatile T.
1190 Implements the post-error-checking part of
1191 gcc_jit_type_get_volatile. */
1193 recording::type *
1194 recording::type::get_volatile ()
1196 recording::type *result = new memento_of_get_volatile (this);
1197 m_ctxt->record (result);
1198 return result;
1201 /* Implementation of pure virtual hook recording::type::dereference for
1202 recording::memento_of_get_type. */
1204 recording::type *
1205 recording::memento_of_get_type::dereference ()
1207 switch (m_kind)
1209 default: gcc_unreachable ();
1211 case GCC_JIT_TYPE_VOID:
1212 return NULL;
1214 case GCC_JIT_TYPE_VOID_PTR:
1215 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
1217 case GCC_JIT_TYPE_BOOL:
1218 case GCC_JIT_TYPE_CHAR:
1219 case GCC_JIT_TYPE_SIGNED_CHAR:
1220 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1221 case GCC_JIT_TYPE_SHORT:
1222 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1223 case GCC_JIT_TYPE_INT:
1224 case GCC_JIT_TYPE_UNSIGNED_INT:
1225 case GCC_JIT_TYPE_LONG:
1226 case GCC_JIT_TYPE_UNSIGNED_LONG:
1227 case GCC_JIT_TYPE_LONG_LONG:
1228 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1229 case GCC_JIT_TYPE_FLOAT:
1230 case GCC_JIT_TYPE_DOUBLE:
1231 case GCC_JIT_TYPE_LONG_DOUBLE:
1232 /* Not a pointer: */
1233 return NULL;
1235 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1236 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
1238 case GCC_JIT_TYPE_SIZE_T:
1239 /* Not a pointer: */
1240 return NULL;
1242 case GCC_JIT_TYPE_FILE_PTR:
1243 /* Give the client code back an opaque "struct FILE". */
1244 return m_ctxt->get_opaque_FILE_type ();
1248 /* Implementation of pure virtual hook recording::type::is_int for
1249 recording::memento_of_get_type. */
1251 bool
1252 recording::memento_of_get_type::is_int () const
1254 switch (m_kind)
1256 default: gcc_unreachable ();
1258 case GCC_JIT_TYPE_VOID:
1259 return false;
1261 case GCC_JIT_TYPE_VOID_PTR:
1262 return false;
1264 case GCC_JIT_TYPE_BOOL:
1265 return false;
1267 case GCC_JIT_TYPE_CHAR:
1268 case GCC_JIT_TYPE_SIGNED_CHAR:
1269 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1270 case GCC_JIT_TYPE_SHORT:
1271 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1272 case GCC_JIT_TYPE_INT:
1273 case GCC_JIT_TYPE_UNSIGNED_INT:
1274 case GCC_JIT_TYPE_LONG:
1275 case GCC_JIT_TYPE_UNSIGNED_LONG:
1276 case GCC_JIT_TYPE_LONG_LONG:
1277 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1278 return true;
1280 case GCC_JIT_TYPE_FLOAT:
1281 case GCC_JIT_TYPE_DOUBLE:
1282 case GCC_JIT_TYPE_LONG_DOUBLE:
1283 return false;
1285 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1286 return false;
1288 case GCC_JIT_TYPE_SIZE_T:
1289 return true;
1291 case GCC_JIT_TYPE_FILE_PTR:
1292 return false;
1296 /* Implementation of pure virtual hook recording::type::is_float for
1297 recording::memento_of_get_type. */
1299 bool
1300 recording::memento_of_get_type::is_float () const
1302 switch (m_kind)
1304 default: gcc_unreachable ();
1306 case GCC_JIT_TYPE_VOID:
1307 return false;
1309 case GCC_JIT_TYPE_VOID_PTR:
1310 return false;
1312 case GCC_JIT_TYPE_BOOL:
1313 return false;
1315 case GCC_JIT_TYPE_CHAR:
1316 case GCC_JIT_TYPE_SIGNED_CHAR:
1317 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1318 case GCC_JIT_TYPE_SHORT:
1319 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1320 case GCC_JIT_TYPE_INT:
1321 case GCC_JIT_TYPE_UNSIGNED_INT:
1322 case GCC_JIT_TYPE_LONG:
1323 case GCC_JIT_TYPE_UNSIGNED_LONG:
1324 case GCC_JIT_TYPE_LONG_LONG:
1325 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1326 return false;
1328 case GCC_JIT_TYPE_FLOAT:
1329 case GCC_JIT_TYPE_DOUBLE:
1330 case GCC_JIT_TYPE_LONG_DOUBLE:
1331 return true;
1333 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1334 return false;
1336 case GCC_JIT_TYPE_SIZE_T:
1337 return false;
1339 case GCC_JIT_TYPE_FILE_PTR:
1340 return false;
1344 /* Implementation of pure virtual hook recording::type::is_bool for
1345 recording::memento_of_get_type. */
1347 bool
1348 recording::memento_of_get_type::is_bool () const
1350 switch (m_kind)
1352 default: gcc_unreachable ();
1354 case GCC_JIT_TYPE_VOID:
1355 return false;
1357 case GCC_JIT_TYPE_VOID_PTR:
1358 return false;
1360 case GCC_JIT_TYPE_BOOL:
1361 return true;
1363 case GCC_JIT_TYPE_CHAR:
1364 case GCC_JIT_TYPE_SIGNED_CHAR:
1365 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1366 case GCC_JIT_TYPE_SHORT:
1367 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1368 case GCC_JIT_TYPE_INT:
1369 case GCC_JIT_TYPE_UNSIGNED_INT:
1370 case GCC_JIT_TYPE_LONG:
1371 case GCC_JIT_TYPE_UNSIGNED_LONG:
1372 case GCC_JIT_TYPE_LONG_LONG:
1373 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1374 return false;
1376 case GCC_JIT_TYPE_FLOAT:
1377 case GCC_JIT_TYPE_DOUBLE:
1378 case GCC_JIT_TYPE_LONG_DOUBLE:
1379 return false;
1381 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1382 return false;
1384 case GCC_JIT_TYPE_SIZE_T:
1385 return false;
1387 case GCC_JIT_TYPE_FILE_PTR:
1388 return false;
1392 /* Implementation of pure virtual hook recording::memento::replay_into
1393 for recording::memento_of_get_type. */
1395 void
1396 recording::memento_of_get_type::replay_into (replayer *r)
1398 set_playback_obj (r->get_type (m_kind));
1401 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
1403 /* Descriptive strings for each of enum gcc_jit_types. */
1405 static const char * const get_type_strings[] = {
1406 "void", /* GCC_JIT_TYPE_VOID */
1407 "void *", /* GCC_JIT_TYPE_VOID_PTR */
1409 "bool", /* GCC_JIT_TYPE_BOOL */
1411 "char", /* GCC_JIT_TYPE_CHAR */
1412 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
1413 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
1415 "short", /* GCC_JIT_TYPE_SHORT */
1416 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
1418 "int", /* GCC_JIT_TYPE_INT */
1419 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
1421 "long", /* GCC_JIT_TYPE_LONG */
1422 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
1424 "long long", /* GCC_JIT_TYPE_LONG_LONG */
1425 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
1427 "float", /* GCC_JIT_TYPE_FLOAT */
1428 "double", /* GCC_JIT_TYPE_DOUBLE */
1429 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
1431 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
1433 "size_t", /* GCC_JIT_TYPE_SIZE_T */
1435 "FILE *" /* GCC_JIT_TYPE_FILE_PTR */
1439 /* Implementation of recording::memento::make_debug_string for
1440 results of get_type, using a simple table of type names. */
1442 recording::string *
1443 recording::memento_of_get_type::make_debug_string ()
1445 return m_ctxt->new_string (get_type_strings[m_kind]);
1448 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
1450 /* Override of default implementation of
1451 recording::type::accepts_writes_from for get_pointer.
1453 Require a pointer type, and allowing writes to
1454 (const T *) from a (T*), but not the other way around. */
1456 bool
1457 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
1459 /* Must be a pointer type: */
1460 type *rtype_points_to = rtype->is_pointer ();
1461 if (!rtype_points_to)
1462 return false;
1464 /* It's OK to assign to a (const T *) from a (T *). */
1465 return m_other_type->unqualified ()
1466 ->accepts_writes_from (rtype_points_to);
1469 /* Implementation of pure virtual hook recording::memento::replay_into
1470 for recording::memento_of_get_pointer. */
1472 void
1473 recording::memento_of_get_pointer::replay_into (replayer *)
1475 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
1478 /* Implementation of recording::memento::make_debug_string for
1479 results of get_pointer, adding " *" to the underlying type,
1480 with special-casing to handle function pointer types. */
1482 recording::string *
1483 recording::memento_of_get_pointer::make_debug_string ()
1485 /* Special-case function pointer types, to put the "*" in parens between
1486 the return type and the params (for one level of dereferencing, at
1487 least). */
1488 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
1489 return fn_type->make_debug_string_with_ptr ();
1491 return string::from_printf (m_ctxt,
1492 "%s *", m_other_type->get_debug_string ());
1495 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
1497 /* Implementation of pure virtual hook recording::memento::replay_into
1498 for recording::memento_of_get_const. */
1500 void
1501 recording::memento_of_get_const::replay_into (replayer *)
1503 set_playback_obj (m_other_type->playback_type ()->get_const ());
1506 /* Implementation of recording::memento::make_debug_string for
1507 results of get_const, prepending "const ". */
1509 recording::string *
1510 recording::memento_of_get_const::make_debug_string ()
1512 return string::from_printf (m_ctxt,
1513 "const %s", m_other_type->get_debug_string ());
1516 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
1518 /* Implementation of pure virtual hook recording::memento::replay_into
1519 for recording::memento_of_get_volatile. */
1521 void
1522 recording::memento_of_get_volatile::replay_into (replayer *)
1524 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
1527 /* Implementation of recording::memento::make_debug_string for
1528 results of get_volatile, prepending "volatile ". */
1530 recording::string *
1531 recording::memento_of_get_volatile::make_debug_string ()
1533 return string::from_printf (m_ctxt,
1534 "volatile %s", m_other_type->get_debug_string ());
1537 /* The implementation of class gcc::jit::recording::array_type */
1539 /* Implementation of pure virtual hook recording::type::dereference for
1540 recording::array_type. */
1542 recording::type *
1543 recording::array_type::dereference ()
1545 return m_element_type;
1548 /* Implementation of pure virtual hook recording::memento::replay_into
1549 for recording::array_type. */
1551 void
1552 recording::array_type::replay_into (replayer *r)
1554 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
1555 m_element_type->playback_type (),
1556 m_num_elements));
1559 /* Implementation of recording::memento::make_debug_string for
1560 results of new_array_type. */
1562 recording::string *
1563 recording::array_type::make_debug_string ()
1565 return string::from_printf (m_ctxt,
1566 "%s[%d]",
1567 m_element_type->get_debug_string (),
1568 m_num_elements);
1571 /* The implementation of class gcc::jit::recording::function_type */
1573 /* Constructor for gcc::jit::recording::function_type. */
1575 recording::function_type::function_type (context *ctxt,
1576 type *return_type,
1577 int num_params,
1578 type **param_types,
1579 int is_variadic)
1580 : type (ctxt),
1581 m_return_type (return_type),
1582 m_param_types (),
1583 m_is_variadic (is_variadic)
1585 for (int i = 0; i< num_params; i++)
1586 m_param_types.safe_push (param_types[i]);
1589 /* Implementation of pure virtual hook recording::type::dereference for
1590 recording::function_type. */
1592 recording::type *
1593 recording::function_type::dereference ()
1595 return NULL;
1598 /* Implementation of pure virtual hook recording::memento::replay_into
1599 for recording::function_type. */
1601 void
1602 recording::function_type::replay_into (replayer *r)
1604 /* Convert m_param_types to a vec of playback type. */
1605 auto_vec <playback::type *> param_types;
1606 int i;
1607 recording::type *type;
1608 param_types.create (m_param_types.length ());
1609 FOR_EACH_VEC_ELT (m_param_types, i, type)
1610 param_types.safe_push (type->playback_type ());
1612 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
1613 &param_types,
1614 m_is_variadic));
1617 /* Special-casing for make_debug_string for get_pointer results for
1618 handling (one level) of pointers to functions. */
1620 recording::string *
1621 recording::function_type::make_debug_string_with_ptr ()
1623 return make_debug_string_with ("(*) ");
1626 /* Implementation of recording::memento::make_debug_string for
1627 results of new_function_type. */
1629 recording::string *
1630 recording::function_type::make_debug_string ()
1632 return make_debug_string_with ("");
1635 /* Build a debug string representation of the form:
1637 RESULT_TYPE INSERT (PARAM_TYPES)
1639 for use when handling 0 and 1 level of indirection to this
1640 function type. */
1642 recording::string *
1643 recording::function_type::make_debug_string_with (const char *insert)
1645 /* First, build a buffer for the arguments. */
1646 /* Calculate length of said buffer. */
1647 size_t sz = 1; /* nil terminator */
1648 for (unsigned i = 0; i< m_param_types.length (); i++)
1650 sz += strlen (m_param_types[i]->get_debug_string ());
1651 sz += 2; /* ", " separator */
1653 if (m_is_variadic)
1654 sz += 5; /* ", ..." separator and ellipsis */
1656 /* Now allocate and populate the buffer. */
1657 char *argbuf = new char[sz];
1658 size_t len = 0;
1660 for (unsigned i = 0; i< m_param_types.length (); i++)
1662 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
1663 len += strlen (m_param_types[i]->get_debug_string ());
1664 if (i + 1 < m_param_types.length ())
1666 strcpy (argbuf + len, ", ");
1667 len += 2;
1670 if (m_is_variadic)
1672 if (m_param_types.length ())
1674 strcpy (argbuf + len, ", ");
1675 len += 2;
1677 strcpy (argbuf + len, "...");
1678 len += 3;
1680 argbuf[len] = '\0';
1682 /* ...and use it to get the string for the call as a whole. */
1683 string *result = string::from_printf (m_ctxt,
1684 "%s %s(%s)",
1685 m_return_type->get_debug_string (),
1686 insert,
1687 argbuf);
1689 delete[] argbuf;
1691 return result;
1694 /* The implementation of class gcc::jit::recording::field. */
1696 /* Implementation of pure virtual hook recording::memento::replay_into
1697 for recording::field. */
1699 void
1700 recording::field::replay_into (replayer *r)
1702 set_playback_obj (r->new_field (playback_location (r, m_loc),
1703 m_type->playback_type (),
1704 playback_string (m_name)));
1707 /* Override the default implementation of
1708 recording::memento::write_to_dump. Dump each field
1709 by dumping a line of the form:
1710 TYPE NAME;
1711 so that we can build up a struct/union field-byfield. */
1713 void
1714 recording::field::write_to_dump (dump &d)
1716 d.write (" %s %s;\n",
1717 m_type->get_debug_string (),
1718 m_name->c_str ());
1721 /* Implementation of recording::memento::make_debug_string for
1722 results of new_field. */
1724 recording::string *
1725 recording::field::make_debug_string ()
1727 return m_name;
1730 /* The implementation of class gcc::jit::recording::compound_type */
1732 /* The constructor for gcc::jit::recording::compound_type. */
1734 recording::compound_type::compound_type (context *ctxt,
1735 location *loc,
1736 string *name)
1737 : type (ctxt),
1738 m_loc (loc),
1739 m_name (name),
1740 m_fields (NULL)
1744 /* Set the fields of a compound type.
1746 Implements the post-error-checking part of
1747 gcc_jit_struct_set_fields, and is also used by
1748 gcc_jit_context_new_union_type. */
1750 void
1751 recording::compound_type::set_fields (location *loc,
1752 int num_fields,
1753 field **field_array)
1755 m_loc = loc;
1756 gcc_assert (NULL == m_fields);
1758 m_fields = new fields (this, num_fields, field_array);
1759 m_ctxt->record (m_fields);
1762 /* Implementation of pure virtual hook recording::type::dereference for
1763 recording::compound_type. */
1765 recording::type *
1766 recording::compound_type::dereference ()
1768 return NULL; /* not a pointer */
1771 /* The implementation of class gcc::jit::recording::struct_. */
1773 /* The constructor for gcc::jit::recording::struct_. */
1775 recording::struct_::struct_ (context *ctxt,
1776 location *loc,
1777 string *name)
1778 : compound_type (ctxt, loc, name)
1782 /* Implementation of pure virtual hook recording::memento::replay_into
1783 for recording::struct_. */
1785 void
1786 recording::struct_::replay_into (replayer *r)
1788 set_playback_obj (
1789 r->new_compound_type (playback_location (r, get_loc ()),
1790 get_name ()->c_str (),
1791 true /* is_struct */));
1794 /* Implementation of recording::memento::make_debug_string for
1795 structs. */
1797 recording::string *
1798 recording::struct_::make_debug_string ()
1800 return string::from_printf (m_ctxt,
1801 "struct %s", get_name ()->c_str ());
1804 /* The implementation of class gcc::jit::recording::union_. */
1806 /* The constructor for gcc::jit::recording::union_. */
1808 recording::union_::union_ (context *ctxt,
1809 location *loc,
1810 string *name)
1811 : compound_type (ctxt, loc, name)
1815 /* Implementation of pure virtual hook recording::memento::replay_into
1816 for recording::union_. */
1818 void
1819 recording::union_::replay_into (replayer *r)
1821 set_playback_obj (
1822 r->new_compound_type (playback_location (r, get_loc ()),
1823 get_name ()->c_str (),
1824 false /* is_struct */));
1827 /* Implementation of recording::memento::make_debug_string for
1828 unions. */
1830 recording::string *
1831 recording::union_::make_debug_string ()
1833 return string::from_printf (m_ctxt,
1834 "union %s", get_name ()->c_str ());
1837 /* The implementation of class gcc::jit::recording::fields. */
1839 /* The constructor for gcc::jit::recording::fields. */
1841 recording::fields::fields (compound_type *struct_or_union,
1842 int num_fields,
1843 field **fields)
1844 : memento (struct_or_union->m_ctxt),
1845 m_struct_or_union (struct_or_union),
1846 m_fields ()
1848 for (int i = 0; i < num_fields; i++)
1850 gcc_assert (fields[i]->get_container () == NULL);
1851 fields[i]->set_container (m_struct_or_union);
1852 m_fields.safe_push (fields[i]);
1856 /* Implementation of pure virtual hook recording::memento::replay_into
1857 for recording::fields. */
1859 void
1860 recording::fields::replay_into (replayer *)
1862 auto_vec<playback::field *> playback_fields;
1863 playback_fields.create (m_fields.length ());
1864 for (unsigned i = 0; i < m_fields.length (); i++)
1865 playback_fields.safe_push (m_fields[i]->playback_field ());
1866 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
1869 /* Override the default implementation of
1870 recording::memento::write_to_dump by writing a union/struct
1871 declaration of this form:
1873 struct/union NAME {
1874 TYPE_1 NAME_1;
1875 TYPE_2 NAME_2;
1876 ....
1877 TYPE_N NAME_N;
1880 to the dump. */
1882 void
1883 recording::fields::write_to_dump (dump &d)
1885 int i;
1886 field *f;
1888 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
1889 FOR_EACH_VEC_ELT (m_fields, i, f)
1890 f->write_to_dump (d);
1891 d.write ("};\n");
1894 /* Implementation of recording::memento::make_debug_string for
1895 field tables. */
1897 recording::string *
1898 recording::fields::make_debug_string ()
1900 return string::from_printf (m_ctxt,
1901 "fields");
1904 /* The implementation of class gcc::jit::recording::rvalue. */
1906 /* Create a recording::access_field_rvalue instance and add it to
1907 the rvalue's context's list of mementos.
1909 Implements the post-error-checking part of
1910 gcc_jit_rvalue_access_field. */
1912 recording::rvalue *
1913 recording::rvalue::access_field (recording::location *loc,
1914 field *field)
1916 recording::rvalue *result =
1917 new access_field_rvalue (m_ctxt, loc, this, field);
1918 m_ctxt->record (result);
1919 return result;
1922 /* Create a recording::dereference_field_rvalue instance and add it to
1923 the rvalue's context's list of mementos.
1925 Implements the post-error-checking part of
1926 gcc_jit_rvalue_dereference_field. */
1928 recording::lvalue *
1929 recording::rvalue::dereference_field (recording::location *loc,
1930 field *field)
1932 recording::lvalue *result =
1933 new dereference_field_rvalue (m_ctxt, loc, this, field);
1934 m_ctxt->record (result);
1935 return result;
1938 /* Create a recording::dereference_rvalue instance and add it to the
1939 rvalue's context's list of mementos.
1941 Implements the post-error-checking part of
1942 gcc_jit_rvalue_dereference. */
1944 recording::lvalue *
1945 recording::rvalue::dereference (recording::location *loc)
1947 recording::lvalue *result =
1948 new dereference_rvalue (m_ctxt, loc, this);
1949 m_ctxt->record (result);
1950 return result;
1953 /* The implementation of class gcc::jit::recording::lvalue. */
1955 /* Create a recording::new_access_field_of_lvalue instance and add it to
1956 the lvalue's context's list of mementos.
1958 Implements the post-error-checking part of
1959 gcc_jit_lvalue_access_field. */
1961 recording::lvalue *
1962 recording::lvalue::access_field (recording::location *loc,
1963 field *field)
1965 recording::lvalue *result =
1966 new access_field_of_lvalue (m_ctxt, loc, this, field);
1967 m_ctxt->record (result);
1968 return result;
1971 /* Create a recording::get_address_of_lvalue instance and add it to
1972 the lvalue's context's list of mementos.
1974 Implements the post-error-checking part of
1975 gcc_jit_lvalue_get_address. */
1977 recording::rvalue *
1978 recording::lvalue::get_address (recording::location *loc)
1980 recording::rvalue *result =
1981 new get_address_of_lvalue (m_ctxt, loc, this);
1982 m_ctxt->record (result);
1983 return result;
1986 /* The implementation of class gcc::jit::recording::param. */
1988 /* Implementation of pure virtual hook recording::memento::replay_into
1989 for recording::param. */
1991 void
1992 recording::param::replay_into (replayer *r)
1994 set_playback_obj (r->new_param (playback_location (r, m_loc),
1995 m_type->playback_type (),
1996 m_name->c_str ()));
2000 /* The implementation of class gcc::jit::recording::function. */
2002 /* gcc::jit::recording::function's constructor. */
2004 recording::function::function (context *ctxt,
2005 recording::location *loc,
2006 enum gcc_jit_function_kind kind,
2007 type *return_type,
2008 recording::string *name,
2009 int num_params,
2010 recording::param **params,
2011 int is_variadic,
2012 enum built_in_function builtin_id)
2013 : memento (ctxt),
2014 m_loc (loc),
2015 m_kind (kind),
2016 m_return_type (return_type),
2017 m_name (name),
2018 m_params (),
2019 m_is_variadic (is_variadic),
2020 m_builtin_id (builtin_id),
2021 m_locals (),
2022 m_blocks ()
2024 for (int i = 0; i< num_params; i++)
2025 m_params.safe_push (params[i]);
2028 /* Implementation of pure virtual hook recording::memento::replay_into
2029 for recording::function. */
2031 void
2032 recording::function::replay_into (replayer *r)
2034 /* Convert m_params to a vec of playback param. */
2035 auto_vec <playback::param *> params;
2036 int i;
2037 recording::param *param;
2038 params.create (m_params.length ());
2039 FOR_EACH_VEC_ELT (m_params, i, param)
2040 params.safe_push (param->playback_param ());
2042 set_playback_obj (r->new_function (playback_location (r, m_loc),
2043 m_kind,
2044 m_return_type->playback_type (),
2045 m_name->c_str (),
2046 &params,
2047 m_is_variadic,
2048 m_builtin_id));
2051 /* Create a recording::local instance and add it to
2052 the functions's context's list of mementos, and to the function's
2053 list of locals.
2055 Implements the post-error-checking part of
2056 gcc_jit_function_new_local. */
2058 recording::lvalue *
2059 recording::function::new_local (recording::location *loc,
2060 type *type,
2061 const char *name)
2063 local *result = new local (this, loc, type, new_string (name));
2064 m_ctxt->record (result);
2065 m_locals.safe_push (result);
2066 return result;
2069 /* Create a recording::block instance and add it to
2070 the functions's context's list of mementos, and to the function's
2071 list of blocks.
2073 Implements the post-error-checking part of
2074 gcc_jit_function_new_block. */
2076 recording::block*
2077 recording::function::new_block (const char *name)
2079 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
2081 recording::block *result =
2082 new recording::block (this, m_blocks.length (), new_string (name));
2083 m_ctxt->record (result);
2084 m_blocks.safe_push (result);
2085 return result;
2088 /* Override the default implementation of
2089 recording::memento::write_to_dump by dumping a C-like
2090 representation of the function; either like a prototype
2091 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
2092 all other kinds of function. */
2094 void
2095 recording::function::write_to_dump (dump &d)
2097 switch (m_kind)
2099 default: gcc_unreachable ();
2100 case GCC_JIT_FUNCTION_EXPORTED:
2101 case GCC_JIT_FUNCTION_IMPORTED:
2102 d.write ("extern ");
2103 break;
2104 case GCC_JIT_FUNCTION_INTERNAL:
2105 d.write ("static ");
2106 break;
2107 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
2108 d.write ("static inline ");
2109 break;
2111 d.write ("%s\n", m_return_type->get_debug_string ());
2113 if (d.update_locations ())
2114 m_loc = d.make_location ();
2116 d.write ("%s (", get_debug_string ());
2118 int i;
2119 recording::param *param;
2120 FOR_EACH_VEC_ELT (m_params, i, param)
2122 if (i > 0)
2123 d.write (", ");
2124 d.write ("%s %s",
2125 param->get_type ()->get_debug_string (),
2126 param->get_debug_string ());
2128 d.write (")");
2129 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
2131 d.write ("; /* (imported) */\n\n");
2133 else
2135 int i;
2136 local *var = NULL;
2137 block *b;
2138 d.write ("\n{\n");
2140 /* Write locals: */
2141 FOR_EACH_VEC_ELT (m_locals, i, var)
2142 var->write_to_dump (d);
2143 if (m_locals.length ())
2144 d.write ("\n");
2146 /* Write each block: */
2147 FOR_EACH_VEC_ELT (m_blocks, i, b)
2149 if (i > 0)
2150 d.write ("\n");
2151 b->write_to_dump (d);
2154 d.write ("}\n\n");
2158 /* Pre-compilation validation of a function, for those things we can't
2159 check until the context is (supposedly) fully-populated. */
2161 void
2162 recording::function::validate ()
2164 /* Complain about empty functions with non-void return type. */
2165 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
2166 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
2167 if (0 == m_blocks.length ())
2168 m_ctxt->add_error (m_loc,
2169 "function %s returns non-void (type: %s)"
2170 " but has no blocks",
2171 get_debug_string (),
2172 m_return_type->get_debug_string ());
2174 /* Check that all blocks are terminated. */
2175 int num_invalid_blocks = 0;
2177 int i;
2178 block *b;
2180 FOR_EACH_VEC_ELT (m_blocks, i, b)
2181 if (!b->validate ())
2182 num_invalid_blocks++;
2185 /* Check that all blocks are reachable. */
2186 if (m_blocks.length () > 0 && 0 == num_invalid_blocks)
2188 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
2189 flag, starting at the initial block. */
2190 auto_vec<block *> worklist (m_blocks.length ());
2191 worklist.safe_push (m_blocks[0]);
2192 while (worklist.length () > 0)
2194 block *b = worklist.pop ();
2195 b->m_is_reachable = true;
2197 /* Add successor blocks that aren't yet marked to the worklist. */
2198 /* We checked that each block has a terminating statement above . */
2199 block *next1, *next2;
2200 int n = b->get_successor_blocks (&next1, &next2);
2201 switch (n)
2203 default:
2204 gcc_unreachable ();
2205 case 2:
2206 if (!next2->m_is_reachable)
2207 worklist.safe_push (next2);
2208 /* fallthrough */
2209 case 1:
2210 if (!next1->m_is_reachable)
2211 worklist.safe_push (next1);
2212 break;
2213 case 0:
2214 break;
2218 /* Now complain about any blocks that haven't been marked. */
2220 int i;
2221 block *b;
2222 FOR_EACH_VEC_ELT (m_blocks, i, b)
2223 if (!b->m_is_reachable)
2224 m_ctxt->add_error (b->get_loc (),
2225 "unreachable block: %s",
2226 b->get_debug_string ());
2231 /* Implements the post-error-checking part of
2232 gcc_jit_function_dump_to_dot. */
2234 void
2235 recording::function::dump_to_dot (const char *path)
2237 FILE *fp = fopen (path, "w");
2238 if (!fp)
2239 return;
2241 pretty_printer the_pp;
2242 the_pp.buffer->stream = fp;
2244 pretty_printer *pp = &the_pp;
2246 pp_printf (pp,
2247 "digraph %s {\n", get_debug_string ());
2249 /* Blocks: */
2251 int i;
2252 block *b;
2253 FOR_EACH_VEC_ELT (m_blocks, i, b)
2254 b->dump_to_dot (pp);
2257 /* Edges: */
2259 int i;
2260 block *b;
2261 FOR_EACH_VEC_ELT (m_blocks, i, b)
2262 b->dump_edges_to_dot (pp);
2265 pp_printf (pp, "}\n");
2266 pp_flush (pp);
2267 fclose (fp);
2270 /* Implementation of recording::memento::make_debug_string for
2271 functions. */
2273 recording::string *
2274 recording::function::make_debug_string ()
2276 return m_name;
2279 /* The implementation of class gcc::jit::recording::block. */
2281 /* Create a recording::eval instance and add it to
2282 the block's context's list of mementos, and to the block's
2283 list of statements.
2285 Implements the post-error-checking part of
2286 gcc_jit_block_add_eval. */
2288 void
2289 recording::block::add_eval (recording::location *loc,
2290 recording::rvalue *rvalue)
2292 statement *result = new eval (this, loc, rvalue);
2293 m_ctxt->record (result);
2294 m_statements.safe_push (result);
2297 /* Create a recording::assignment instance and add it to
2298 the block's context's list of mementos, and to the block's
2299 list of statements.
2301 Implements the post-error-checking part of
2302 gcc_jit_block_add_assignment. */
2304 void
2305 recording::block::add_assignment (recording::location *loc,
2306 recording::lvalue *lvalue,
2307 recording::rvalue *rvalue)
2309 statement *result = new assignment (this, loc, lvalue, rvalue);
2310 m_ctxt->record (result);
2311 m_statements.safe_push (result);
2314 /* Create a recording::assignment_op instance and add it to
2315 the block's context's list of mementos, and to the block's
2316 list of statements.
2318 Implements the post-error-checking part of
2319 gcc_jit_block_add_assignment_op. */
2321 void
2322 recording::block::add_assignment_op (recording::location *loc,
2323 recording::lvalue *lvalue,
2324 enum gcc_jit_binary_op op,
2325 recording::rvalue *rvalue)
2327 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
2328 m_ctxt->record (result);
2329 m_statements.safe_push (result);
2332 /* Create a recording::comment instance and add it to
2333 the block's context's list of mementos, and to the block's
2334 list of statements.
2336 Implements the post-error-checking part of
2337 gcc_jit_block_add_comment. */
2339 void
2340 recording::block::add_comment (recording::location *loc,
2341 const char *text)
2343 statement *result = new comment (this, loc, new_string (text));
2344 m_ctxt->record (result);
2345 m_statements.safe_push (result);
2348 /* Create a recording::end_with_conditional instance and add it to
2349 the block's context's list of mementos, and to the block's
2350 list of statements.
2352 Implements the post-error-checking part of
2353 gcc_jit_block_end_with_conditional. */
2355 void
2356 recording::block::end_with_conditional (recording::location *loc,
2357 recording::rvalue *boolval,
2358 recording::block *on_true,
2359 recording::block *on_false)
2361 statement *result = new conditional (this, loc, boolval, on_true, on_false);
2362 m_ctxt->record (result);
2363 m_statements.safe_push (result);
2364 m_has_been_terminated = true;
2367 /* Create a recording::end_with_jump instance and add it to
2368 the block's context's list of mementos, and to the block's
2369 list of statements.
2371 Implements the post-error-checking part of
2372 gcc_jit_block_end_with_jump. */
2374 void
2375 recording::block::end_with_jump (recording::location *loc,
2376 recording::block *target)
2378 statement *result = new jump (this, loc, target);
2379 m_ctxt->record (result);
2380 m_statements.safe_push (result);
2381 m_has_been_terminated = true;
2384 /* Create a recording::end_with_return instance and add it to
2385 the block's context's list of mementos, and to the block's
2386 list of statements.
2388 Implements the post-error-checking parts of
2389 gcc_jit_block_end_with_return and
2390 gcc_jit_block_end_with_void_return. */
2392 void
2393 recording::block::end_with_return (recording::location *loc,
2394 recording::rvalue *rvalue)
2396 /* This is used by both gcc_jit_function_add_return and
2397 gcc_jit_function_add_void_return; rvalue will be non-NULL for
2398 the former and NULL for the latter. */
2399 statement *result = new return_ (this, loc, rvalue);
2400 m_ctxt->record (result);
2401 m_statements.safe_push (result);
2402 m_has_been_terminated = true;
2405 /* Override the default implementation of
2406 recording::memento::write_to_dump for blocks by writing
2407 an unindented block name as a label, followed by the indented
2408 statements:
2410 BLOCK_NAME:
2411 STATEMENT_1;
2412 STATEMENT_2;
2414 STATEMENT_N; */
2416 void
2417 recording::block::write_to_dump (dump &d)
2419 d.write ("%s:\n", get_debug_string ());
2421 int i;
2422 statement *s;
2423 FOR_EACH_VEC_ELT (m_statements, i, s)
2424 s->write_to_dump (d);
2427 /* Validate a block by ensuring that it has been terminated. */
2429 bool
2430 recording::block::validate ()
2432 if (!has_been_terminated ())
2434 statement *stmt = get_last_statement ();
2435 location *loc = stmt ? stmt->get_loc () : NULL;
2436 m_func->get_context ()->add_error (loc,
2437 "unterminated block in %s: %s",
2438 m_func->get_debug_string (),
2439 get_debug_string ());
2440 return false;
2443 return true;
2446 /* Get the source-location of a block by using that of the first
2447 statement within it, if any. */
2449 recording::location *
2450 recording::block::get_loc () const
2452 recording::statement *stmt = get_first_statement ();
2453 if (stmt)
2454 return stmt->get_loc ();
2455 else
2456 return NULL;
2459 /* Get the first statement within a block, if any. */
2461 recording::statement *
2462 recording::block::get_first_statement () const
2464 if (m_statements.length ())
2465 return m_statements[0];
2466 else
2467 return NULL;
2470 /* Get the last statement within a block, if any. */
2472 recording::statement *
2473 recording::block::get_last_statement () const
2475 if (m_statements.length ())
2476 return m_statements[m_statements.length () - 1];
2477 else
2478 return NULL;
2481 /* Assuming that this block has been terminated, get the number of
2482 successor blocks, which will be 0, 1 or 2, for return, unconditional
2483 jump, and conditional jump respectively.
2484 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
2485 is written to NEXT1, and the second (if any) to NEXT2.
2487 Used when validating functions, and when dumping dot representations
2488 of them. */
2491 recording::block::get_successor_blocks (block **next1, block **next2) const
2493 gcc_assert (m_has_been_terminated);
2494 gcc_assert (next1);
2495 gcc_assert (next2);
2496 statement *last_statement = get_last_statement ();
2497 gcc_assert (last_statement);
2498 return last_statement->get_successor_blocks (next1, next2);
2501 /* Implementation of pure virtual hook recording::memento::replay_into
2502 for recording::block. */
2504 void
2505 recording::block::replay_into (replayer *)
2507 set_playback_obj (m_func->playback_function ()
2508 ->new_block (playback_string (m_name)));
2511 /* Implementation of recording::memento::make_debug_string for
2512 blocks. */
2514 recording::string *
2515 recording::block::make_debug_string ()
2517 if (m_name)
2518 return m_name;
2519 else
2520 return string::from_printf (m_ctxt,
2521 "<UNNAMED BLOCK %p>",
2522 (void *)this);
2525 /* Dump a block in graphviz form into PP, capturing the block name (if
2526 any) and the statements. */
2528 void
2529 recording::block::dump_to_dot (pretty_printer *pp)
2531 pp_printf (pp,
2532 ("\tblock_%d "
2533 "[shape=record,style=filled,fillcolor=white,label=\"{"),
2534 m_index);
2535 pp_write_text_to_stream (pp);
2536 if (m_name)
2538 pp_string (pp, m_name->c_str ());
2539 pp_string (pp, ":");
2540 pp_newline (pp);
2541 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
2544 int i;
2545 statement *s;
2546 FOR_EACH_VEC_ELT (m_statements, i, s)
2548 pp_string (pp, s->get_debug_string ());
2549 pp_newline (pp);
2550 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
2553 pp_printf (pp,
2554 "}\"];\n\n");
2555 pp_flush (pp);
2558 /* Dump the out-edges of the block in graphviz form into PP. */
2560 void
2561 recording::block::dump_edges_to_dot (pretty_printer *pp)
2563 block *next[2];
2564 int num_succs = get_successor_blocks (&next[0], &next[1]);
2565 for (int i = 0; i < num_succs; i++)
2566 pp_printf (pp,
2567 "\tblock_%d:s -> block_%d:n;\n",
2568 m_index, next[i]->m_index);
2571 /* The implementation of class gcc::jit::recording::global. */
2573 /* Implementation of pure virtual hook recording::memento::replay_into
2574 for recording::global. */
2576 void
2577 recording::global::replay_into (replayer *r)
2579 set_playback_obj (r->new_global (playback_location (r, m_loc),
2580 m_type->playback_type (),
2581 playback_string (m_name)));
2584 /* The implementation of class gcc::jit::recording::memento_of_new_rvalue_from_int. */
2586 /* Implementation of pure virtual hook recording::memento::replay_into
2587 for recording::memento_of_new_rvalue_from_int. */
2589 void
2590 recording::memento_of_new_rvalue_from_int::replay_into (replayer *r)
2592 set_playback_obj (r->new_rvalue_from_int (m_type->playback_type (),
2593 m_value));
2596 /* Implementation of recording::memento::make_debug_string for
2597 rvalue_from_int, rendering it as
2598 (TYPE)LITERAL
2599 e.g.
2600 "(int)42". */
2602 recording::string *
2603 recording::memento_of_new_rvalue_from_int::make_debug_string ()
2605 return string::from_printf (m_ctxt,
2606 "(%s)%i",
2607 m_type->get_debug_string (),
2608 m_value);
2611 /* The implementation of class gcc::jit::recording::memento_of_new_rvalue_from_double. */
2613 /* Implementation of pure virtual hook recording::memento::replay_into
2614 for recording::memento_of_new_rvalue_from_double. */
2616 void
2617 recording::memento_of_new_rvalue_from_double::replay_into (replayer *r)
2619 set_playback_obj (r->new_rvalue_from_double (m_type->playback_type (),
2620 m_value));
2623 /* Implementation of recording::memento::make_debug_string for
2624 rvalue_from_double, rendering it as
2625 (TYPE)LITERAL
2626 e.g.
2627 "(float)42.0". */
2629 recording::string *
2630 recording::memento_of_new_rvalue_from_double::make_debug_string ()
2632 return string::from_printf (m_ctxt,
2633 "(%s)%f",
2634 m_type->get_debug_string (),
2635 m_value);
2638 /* The implementation of class gcc::jit::recording::memento_of_new_rvalue_from_ptr. */
2640 /* Implementation of pure virtual hook recording::memento::replay_into
2641 for recording::memento_of_new_rvalue_from_ptr. */
2643 void
2644 recording::memento_of_new_rvalue_from_ptr::replay_into (replayer *r)
2646 set_playback_obj (r->new_rvalue_from_ptr (m_type->playback_type (),
2647 m_value));
2650 /* Implementation of recording::memento::make_debug_string for
2651 rvalue_from_ptr, rendering it as
2652 (TYPE)HEX
2653 e.g.
2654 "(int *)0xdeadbeef"
2656 Zero is rendered as NULL e.g.
2657 "(int *)NULL". */
2659 recording::string *
2660 recording::memento_of_new_rvalue_from_ptr::make_debug_string ()
2662 if (m_value != NULL)
2663 return string::from_printf (m_ctxt,
2664 "(%s)%p",
2665 m_type->get_debug_string (), m_value);
2666 else
2667 return string::from_printf (m_ctxt,
2668 "(%s)NULL",
2669 m_type->get_debug_string ());
2672 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
2674 /* Implementation of pure virtual hook recording::memento::replay_into
2675 for recording::memento_of_new_string_literal. */
2677 void
2678 recording::memento_of_new_string_literal::replay_into (replayer *r)
2680 set_playback_obj (r->new_string_literal (m_value->c_str ()));
2683 /* Implementation of recording::memento::make_debug_string for
2684 string literals. */
2686 recording::string *
2687 recording::memento_of_new_string_literal::make_debug_string ()
2689 return string::from_printf (m_ctxt,
2690 m_value->get_debug_string ());
2693 /* The implementation of class gcc::jit::recording::unary_op. */
2695 /* Implementation of pure virtual hook recording::memento::replay_into
2696 for recording::unary_op. */
2698 void
2699 recording::unary_op::replay_into (replayer *r)
2701 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
2702 m_op,
2703 get_type ()->playback_type (),
2704 m_a->playback_rvalue ()));
2707 /* Implementation of recording::memento::make_debug_string for
2708 unary ops. */
2710 static const char * const unary_op_strings[] = {
2711 "-", /* GCC_JIT_UNARY_OP_MINUS */
2712 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
2713 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
2716 recording::string *
2717 recording::unary_op::make_debug_string ()
2719 return string::from_printf (m_ctxt,
2720 "%s(%s)",
2721 unary_op_strings[m_op],
2722 m_a->get_debug_string ());
2725 /* The implementation of class gcc::jit::recording::binary_op. */
2727 /* Implementation of pure virtual hook recording::memento::replay_into
2728 for recording::binary_op. */
2730 void
2731 recording::binary_op::replay_into (replayer *r)
2733 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
2734 m_op,
2735 get_type ()->playback_type (),
2736 m_a->playback_rvalue (),
2737 m_b->playback_rvalue ()));
2740 /* Implementation of recording::memento::make_debug_string for
2741 binary ops. */
2743 static const char * const binary_op_strings[] = {
2744 "+", /* GCC_JIT_BINARY_OP_PLUS */
2745 "-", /* GCC_JIT_BINARY_OP_MINUS */
2746 "*", /* GCC_JIT_BINARY_OP_MULT */
2747 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
2748 "%", /* GCC_JIT_BINARY_OP_MODULO */
2749 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
2750 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
2751 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
2752 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
2753 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
2754 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
2755 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
2758 recording::string *
2759 recording::binary_op::make_debug_string ()
2761 return string::from_printf (m_ctxt,
2762 "%s %s %s",
2763 m_a->get_debug_string (),
2764 binary_op_strings[m_op],
2765 m_b->get_debug_string ());
2768 /* The implementation of class gcc::jit::recording::comparison. */
2770 /* Implementation of recording::memento::make_debug_string for
2771 comparisons. */
2773 static const char * const comparison_strings[] =
2775 "==", /* GCC_JIT_COMPARISON_EQ */
2776 "!=", /* GCC_JIT_COMPARISON_NE */
2777 "<", /* GCC_JIT_COMPARISON_LT */
2778 "<=", /* GCC_JIT_COMPARISON_LE */
2779 ">", /* GCC_JIT_COMPARISON_GT */
2780 ">=", /* GCC_JIT_COMPARISON_GE */
2783 recording::string *
2784 recording::comparison::make_debug_string ()
2786 return string::from_printf (m_ctxt,
2787 "%s %s %s",
2788 m_a->get_debug_string (),
2789 comparison_strings[m_op],
2790 m_b->get_debug_string ());
2793 /* Implementation of pure virtual hook recording::memento::replay_into
2794 for recording::comparison. */
2796 void
2797 recording::comparison::replay_into (replayer *r)
2799 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
2800 m_op,
2801 m_a->playback_rvalue (),
2802 m_b->playback_rvalue ()));
2805 /* Implementation of pure virtual hook recording::memento::replay_into
2806 for recording::cast. */
2808 void
2809 recording::cast::replay_into (replayer *r)
2811 set_playback_obj (r->new_cast (playback_location (r, m_loc),
2812 m_rvalue->playback_rvalue (),
2813 get_type ()->playback_type ()));
2816 /* Implementation of recording::memento::make_debug_string for
2817 casts. */
2819 recording::string *
2820 recording::cast::make_debug_string ()
2822 return string::from_printf (m_ctxt,
2823 "(%s)%s",
2824 get_type ()->get_debug_string (),
2825 m_rvalue->get_debug_string ());
2828 /* The implementation of class gcc::jit::recording::call. */
2830 /* The constructor for gcc::jit::recording::call. */
2832 recording::call::call (recording::context *ctxt,
2833 recording::location *loc,
2834 recording::function *func,
2835 int numargs,
2836 rvalue **args)
2837 : rvalue (ctxt, loc, func->get_return_type ()),
2838 m_func (func),
2839 m_args ()
2841 for (int i = 0; i< numargs; i++)
2842 m_args.safe_push (args[i]);
2845 /* Implementation of pure virtual hook recording::memento::replay_into
2846 for recording::call. */
2848 void
2849 recording::call::replay_into (replayer *r)
2851 auto_vec<playback::rvalue *> playback_args;
2852 playback_args.create (m_args.length ());
2853 for (unsigned i = 0; i< m_args.length (); i++)
2854 playback_args.safe_push (m_args[i]->playback_rvalue ());
2856 set_playback_obj (r->new_call (playback_location (r, m_loc),
2857 m_func->playback_function (),
2858 &playback_args));
2861 /* Implementation of recording::memento::make_debug_string for
2862 function calls. */
2864 recording::string *
2865 recording::call::make_debug_string ()
2867 /* First, build a buffer for the arguments. */
2868 /* Calculate length of said buffer. */
2869 size_t sz = 1; /* nil terminator */
2870 for (unsigned i = 0; i< m_args.length (); i++)
2872 sz += strlen (m_args[i]->get_debug_string ());
2873 sz += 2; /* ", " separator */
2876 /* Now allocate and populate the buffer. */
2877 char *argbuf = new char[sz];
2878 size_t len = 0;
2880 for (unsigned i = 0; i< m_args.length (); i++)
2882 strcpy (argbuf + len, m_args[i]->get_debug_string ());
2883 len += strlen (m_args[i]->get_debug_string ());
2884 if (i + 1 < m_args.length ())
2886 strcpy (argbuf + len, ", ");
2887 len += 2;
2890 argbuf[len] = '\0';
2892 /* ...and use it to get the string for the call as a whole. */
2893 string *result = string::from_printf (m_ctxt,
2894 "%s (%s)",
2895 m_func->get_debug_string (),
2896 argbuf);
2898 delete[] argbuf;
2900 return result;
2903 /* The implementation of class gcc::jit::recording::call_through_ptr. */
2905 /* The constructor for recording::call_through_ptr. */
2907 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
2908 recording::location *loc,
2909 recording::rvalue *fn_ptr,
2910 int numargs,
2911 rvalue **args)
2912 : rvalue (ctxt, loc,
2913 fn_ptr->get_type ()->dereference ()
2914 ->as_a_function_type ()->get_return_type ()),
2915 m_fn_ptr (fn_ptr),
2916 m_args ()
2918 for (int i = 0; i< numargs; i++)
2919 m_args.safe_push (args[i]);
2922 /* Implementation of pure virtual hook recording::memento::replay_into
2923 for recording::call_through_ptr. */
2925 void
2926 recording::call_through_ptr::replay_into (replayer *r)
2928 auto_vec<playback::rvalue *> playback_args;
2929 playback_args.create (m_args.length ());
2930 for (unsigned i = 0; i< m_args.length (); i++)
2931 playback_args.safe_push (m_args[i]->playback_rvalue ());
2933 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
2934 m_fn_ptr->playback_rvalue (),
2935 &playback_args));
2938 /* Implementation of recording::memento::make_debug_string for
2939 calls through function ptrs. */
2941 recording::string *
2942 recording::call_through_ptr::make_debug_string ()
2944 /* First, build a buffer for the arguments. */
2945 /* Calculate length of said buffer. */
2946 size_t sz = 1; /* nil terminator */
2947 for (unsigned i = 0; i< m_args.length (); i++)
2949 sz += strlen (m_args[i]->get_debug_string ());
2950 sz += 2; /* ", " separator */
2953 /* Now allocate and populate the buffer. */
2954 char *argbuf = new char[sz];
2955 size_t len = 0;
2957 for (unsigned i = 0; i< m_args.length (); i++)
2959 strcpy (argbuf + len, m_args[i]->get_debug_string ());
2960 len += strlen (m_args[i]->get_debug_string ());
2961 if (i + 1 < m_args.length ())
2963 strcpy (argbuf + len, ", ");
2964 len += 2;
2967 argbuf[len] = '\0';
2969 /* ...and use it to get the string for the call as a whole. */
2970 string *result = string::from_printf (m_ctxt,
2971 "%s (%s)",
2972 m_fn_ptr->get_debug_string (),
2973 argbuf);
2975 delete[] argbuf;
2977 return result;
2980 /* The implementation of class gcc::jit::recording::array_access. */
2982 /* Implementation of pure virtual hook recording::memento::replay_into
2983 for recording::array_access. */
2985 void
2986 recording::array_access::replay_into (replayer *r)
2988 set_playback_obj (
2989 r->new_array_access (playback_location (r, m_loc),
2990 m_ptr->playback_rvalue (),
2991 m_index->playback_rvalue ()));
2994 /* Implementation of recording::memento::make_debug_string for
2995 array accesses. */
2997 recording::string *
2998 recording::array_access::make_debug_string ()
3000 return string::from_printf (m_ctxt,
3001 "%s[%s]",
3002 m_ptr->get_debug_string (),
3003 m_index->get_debug_string ());
3006 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
3008 /* Implementation of pure virtual hook recording::memento::replay_into
3009 for recording::access_field_of_lvalue. */
3011 void
3012 recording::access_field_of_lvalue::replay_into (replayer *r)
3014 set_playback_obj (
3015 m_lvalue->playback_lvalue ()
3016 ->access_field (playback_location (r, m_loc),
3017 m_field->playback_field ()));
3021 /* Implementation of recording::memento::make_debug_string for
3022 accessing a field of an lvalue. */
3024 recording::string *
3025 recording::access_field_of_lvalue::make_debug_string ()
3027 return string::from_printf (m_ctxt,
3028 "%s.%s",
3029 m_lvalue->get_debug_string (),
3030 m_field->get_debug_string ());
3033 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
3035 /* Implementation of pure virtual hook recording::memento::replay_into
3036 for recording::access_field_rvalue. */
3038 void
3039 recording::access_field_rvalue::replay_into (replayer *r)
3041 set_playback_obj (
3042 m_rvalue->playback_rvalue ()
3043 ->access_field (playback_location (r, m_loc),
3044 m_field->playback_field ()));
3047 /* Implementation of recording::memento::make_debug_string for
3048 accessing a field of an rvalue. */
3050 recording::string *
3051 recording::access_field_rvalue::make_debug_string ()
3053 return string::from_printf (m_ctxt,
3054 "%s.%s",
3055 m_rvalue->get_debug_string (),
3056 m_field->get_debug_string ());
3059 /* The implementation of class
3060 gcc::jit::recording::dereference_field_rvalue. */
3062 /* Implementation of pure virtual hook recording::memento::replay_into
3063 for recording::dereference_field_rvalue. */
3065 void
3066 recording::dereference_field_rvalue::replay_into (replayer *r)
3068 set_playback_obj (
3069 m_rvalue->playback_rvalue ()->
3070 dereference_field (playback_location (r, m_loc),
3071 m_field->playback_field ()));
3074 /* Implementation of recording::memento::make_debug_string for
3075 dereferencing a field of an rvalue. */
3077 recording::string *
3078 recording::dereference_field_rvalue::make_debug_string ()
3080 return string::from_printf (m_ctxt,
3081 "%s->%s",
3082 m_rvalue->get_debug_string (),
3083 m_field->get_debug_string ());
3086 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
3088 /* Implementation of pure virtual hook recording::memento::replay_into
3089 for recording::dereference_rvalue. */
3091 void
3092 recording::dereference_rvalue::replay_into (replayer *r)
3094 set_playback_obj (
3095 m_rvalue->playback_rvalue ()->
3096 dereference (playback_location (r, m_loc)));
3099 /* Implementation of recording::memento::make_debug_string for
3100 dereferencing an rvalue. */
3102 recording::string *
3103 recording::dereference_rvalue::make_debug_string ()
3105 return string::from_printf (m_ctxt,
3106 "*%s",
3107 m_rvalue->get_debug_string ());
3110 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
3112 /* Implementation of pure virtual hook recording::memento::replay_into
3113 for recording::get_address_of_lvalue. */
3115 void
3116 recording::get_address_of_lvalue::replay_into (replayer *r)
3118 set_playback_obj (
3119 m_lvalue->playback_lvalue ()->
3120 get_address (playback_location (r, m_loc)));
3123 /* Implementation of recording::memento::make_debug_string for
3124 getting the address of an lvalue. */
3126 recording::string *
3127 recording::get_address_of_lvalue::make_debug_string ()
3129 return string::from_printf (m_ctxt,
3130 "&%s",
3131 m_lvalue->get_debug_string ());
3134 /* The implementation of class gcc::jit::recording::local. */
3136 /* Implementation of pure virtual hook recording::memento::replay_into
3137 for recording::local. */
3139 void
3140 recording::local::replay_into (replayer *r)
3142 set_playback_obj (
3143 m_func->playback_function ()
3144 ->new_local (playback_location (r, m_loc),
3145 m_type->playback_type (),
3146 playback_string (m_name)));
3149 /* Override the default implementation of
3150 recording::memento::write_to_dump for locals by writing
3151 TYPE NAME;
3152 for use at the top of the function body as if it were a
3153 declaration. */
3155 void
3156 recording::local::write_to_dump (dump &d)
3158 if (d.update_locations ())
3159 m_loc = d.make_location ();
3160 d.write(" %s %s;\n",
3161 m_type->get_debug_string (),
3162 get_debug_string ());
3165 /* The implementation of class gcc::jit::recording::statement. */
3167 /* We poison the default implementation of
3168 gcc::jit::recording::statement::get_successor_blocks
3169 since this vfunc must only ever be called on terminator
3170 statements. */
3173 recording::statement::get_successor_blocks (block **/*out_next1*/,
3174 block **/*out_next2*/) const
3176 /* The base class implementation is for non-terminating statements,
3177 and thus should never be called. */
3178 gcc_unreachable ();
3179 return 0;
3182 /* Extend the default implementation of
3183 recording::memento::write_to_dump for statements by (if requested)
3184 updating the location of the statement to the current location in
3185 the dumpfile. */
3187 void
3188 recording::statement::write_to_dump (dump &d)
3190 memento::write_to_dump (d);
3191 if (d.update_locations ())
3192 m_loc = d.make_location ();
3195 /* The implementation of class gcc::jit::recording::eval. */
3197 /* Implementation of pure virtual hook recording::memento::replay_into
3198 for recording::eval. */
3200 void
3201 recording::eval::replay_into (replayer *r)
3203 playback_block (get_block ())
3204 ->add_eval (playback_location (r),
3205 m_rvalue->playback_rvalue ());
3208 /* Implementation of recording::memento::make_debug_string for
3209 an eval statement. */
3211 recording::string *
3212 recording::eval::make_debug_string ()
3214 return string::from_printf (m_ctxt,
3215 "(void)%s;",
3216 m_rvalue->get_debug_string ());
3219 /* The implementation of class gcc::jit::recording::assignment. */
3221 /* Implementation of pure virtual hook recording::memento::replay_into
3222 for recording::assignment. */
3224 void
3225 recording::assignment::replay_into (replayer *r)
3227 playback_block (get_block ())
3228 ->add_assignment (playback_location (r),
3229 m_lvalue->playback_lvalue (),
3230 m_rvalue->playback_rvalue ());
3233 /* Implementation of recording::memento::make_debug_string for
3234 an assignment statement. */
3236 recording::string *
3237 recording::assignment::make_debug_string ()
3239 return string::from_printf (m_ctxt,
3240 "%s = %s;",
3241 m_lvalue->get_debug_string (),
3242 m_rvalue->get_debug_string ());
3245 /* The implementation of class gcc::jit::recording::assignment_op. */
3247 /* Implementation of pure virtual hook recording::memento::replay_into
3248 for recording::assignment_op. */
3250 void
3251 recording::assignment_op::replay_into (replayer *r)
3253 playback::type *result_type =
3254 m_lvalue->playback_lvalue ()->get_type ();
3256 playback::rvalue *binary_op =
3257 r->new_binary_op (playback_location (r),
3258 m_op,
3259 result_type,
3260 m_lvalue->playback_rvalue (),
3261 m_rvalue->playback_rvalue ());
3263 playback_block (get_block ())
3264 ->add_assignment (playback_location (r),
3265 m_lvalue->playback_lvalue (),
3266 binary_op);
3269 /* Implementation of recording::memento::make_debug_string for
3270 an assignment_op statement. */
3272 recording::string *
3273 recording::assignment_op::make_debug_string ()
3275 return string::from_printf (m_ctxt,
3276 "%s %s= %s;",
3277 m_lvalue->get_debug_string (),
3278 binary_op_strings[m_op],
3279 m_rvalue->get_debug_string ());
3282 /* The implementation of class gcc::jit::recording::comment. */
3284 /* Implementation of pure virtual hook recording::memento::replay_into
3285 for recording::comment. */
3287 void
3288 recording::comment::replay_into (replayer *r)
3290 playback_block (get_block ())
3291 ->add_comment (playback_location (r),
3292 m_text->c_str ());
3295 /* Implementation of recording::memento::make_debug_string for
3296 a comment "statement". */
3298 recording::string *
3299 recording::comment::make_debug_string ()
3301 return string::from_printf (m_ctxt,
3302 "/* %s */",
3303 m_text->c_str ());
3306 /* The implementation of class gcc::jit::recording::conditional. */
3308 /* Implementation of pure virtual hook recording::memento::replay_into
3309 for recording::conditional. */
3311 void
3312 recording::conditional::replay_into (replayer *r)
3314 playback_block (get_block ())
3315 ->add_conditional (playback_location (r),
3316 m_boolval->playback_rvalue (),
3317 playback_block (m_on_true),
3318 playback_block (m_on_false));
3321 /* Override the poisoned default implementation of
3322 gcc::jit::recording::statement::get_successor_blocks
3324 A conditional jump has 2 successor blocks. */
3327 recording::conditional::get_successor_blocks (block **out_next1,
3328 block **out_next2) const
3330 *out_next1 = m_on_true;
3331 *out_next2 = m_on_false;
3332 return 2;
3335 /* Implementation of recording::memento::make_debug_string for
3336 a conditional jump statement. */
3338 recording::string *
3339 recording::conditional::make_debug_string ()
3341 if (m_on_false)
3342 return string::from_printf (m_ctxt,
3343 "if (%s) goto %s; else goto %s;",
3344 m_boolval->get_debug_string (),
3345 m_on_true->get_debug_string (),
3346 m_on_false->get_debug_string ());
3347 else
3348 return string::from_printf (m_ctxt,
3349 "if (%s) goto %s;",
3350 m_boolval->get_debug_string (),
3351 m_on_true->get_debug_string ());
3354 /* The implementation of class gcc::jit::recording::jump. */
3356 /* Implementation of pure virtual hook recording::memento::replay_into
3357 for recording::jump. */
3359 void
3360 recording::jump::replay_into (replayer *r)
3362 playback_block (get_block ())
3363 ->add_jump (playback_location (r),
3364 m_target->playback_block ());
3367 /* Override the poisoned default implementation of
3368 gcc::jit::recording::statement::get_successor_blocks
3370 An unconditional jump has 1 successor block. */
3373 recording::jump::get_successor_blocks (block **out_next1,
3374 block **/*out_next2*/) const
3376 *out_next1 = m_target;
3377 return 1;
3380 /* Implementation of recording::memento::make_debug_string for
3381 a unconditional jump statement. */
3383 recording::string *
3384 recording::jump::make_debug_string ()
3386 return string::from_printf (m_ctxt,
3387 "goto %s;",
3388 m_target->get_debug_string ());
3391 /* The implementation of class gcc::jit::recording::return_. */
3393 /* Implementation of pure virtual hook recording::memento::replay_into
3394 for recording::return_. */
3396 void
3397 recording::return_::replay_into (replayer *r)
3399 playback_block (get_block ())
3400 ->add_return (playback_location (r),
3401 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
3404 /* Override the poisoned default implementation of
3405 gcc::jit::recording::statement::get_successor_blocks
3407 A return statement has no successor block. */
3410 recording::return_::get_successor_blocks (block **/*out_next1*/,
3411 block **/*out_next2*/) const
3413 return 0;
3416 /* Implementation of recording::memento::make_debug_string for
3417 a return statement (covers both those with and without rvalues). */
3419 recording::string *
3420 recording::return_::make_debug_string ()
3422 if (m_rvalue)
3423 return string::from_printf (m_ctxt,
3424 "return %s;",
3425 m_rvalue->get_debug_string ());
3426 else
3427 return string::from_printf (m_ctxt,
3428 "return;");
3431 } // namespace gcc::jit
3433 } // namespace gcc