libgccjit: detect various kinds of errors relating to params and locals
[official-gcc.git] / gcc / jit / jit-recording.c
blobec247e5a70b07fc5451a300ffc97820fc80e34e5
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)
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 "pretty-print.h"
27 #include <pthread.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"
35 namespace gcc {
36 namespace jit {
38 // class dump
40 dump::dump (recording::context &ctxt,
41 const char *filename,
42 bool update_locations)
43 : m_ctxt (ctxt),
44 m_filename (filename),
45 m_update_locations (update_locations),
46 m_line (0),
47 m_column (0)
49 m_file = fopen (filename, "w");
50 if (!m_file)
51 ctxt.add_error (NULL,
52 "error opening dump file %s for writing: %s",
53 filename,
54 xstrerror (errno));
57 dump::~dump ()
59 if (m_file)
61 int err = fclose (m_file);
62 if (err)
63 m_ctxt.add_error (NULL,
64 "error closing dump file %s: %s",
65 m_filename,
66 xstrerror (errno));
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. */
75 void
76 dump::write (const char *fmt, ...)
78 va_list ap;
79 char *buf = NULL;
81 /* If there was an error opening the file, we've already reported it.
82 Don't attempt further work. */
83 if (!m_file)
84 return;
86 va_start (ap, fmt);
87 vasprintf (&buf, fmt, ap);
88 va_end (ap);
90 if (!buf)
92 m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
93 m_filename);
94 return;
97 if (fwrite (buf, strlen (buf), 1, m_file) != 1)
98 m_ctxt.add_error (NULL, "error writing to dump file %s",
99 m_filename);
101 /* Update line/column: */
102 for (const char *ptr = buf; *ptr; ptr++)
104 if ('\n' == *ptr)
106 m_line++;
107 m_column = 0;
109 else
110 m_column++;
113 free (buf);
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 /**********************************************************************
126 Recording.
127 **********************************************************************/
129 /* Get the playback::location for the given recording::location,
130 handling a NULL input with a NULL output. */
132 playback::location *
133 recording::playback_location (replayer *r, recording::location *loc)
135 if (loc)
136 return loc->playback_location (r);
137 else
138 return NULL;
141 /* Get a const char * for the given recording::string
142 handling a NULL input with a NULL output. */
144 const char *
145 recording::playback_string (recording::string *str)
147 if (str)
148 return str->c_str ();
149 else
150 return NULL;
153 /* Get the playback::block for the given recording::block,
154 handling a NULL input with a NULL output. */
156 playback::block *
157 recording::playback_block (recording::block *b)
159 if (b)
160 return b->playback_block ();
161 else
162 return NULL;
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)
171 : log_user (NULL),
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_last_error_str (NULL),
177 m_owns_last_error_str (false),
178 m_mementos (),
179 m_compound_types (),
180 m_globals (),
181 m_functions (),
182 m_FILE_type (NULL),
183 m_builtins_manager(NULL)
185 if (parent_ctxt)
187 /* Inherit options from parent. */
188 for (unsigned i = 0;
189 i < sizeof (m_str_options) / sizeof (m_str_options[0]);
190 i++)
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 ());
203 else
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 ());
219 int i;
220 memento *m;
221 FOR_EACH_VEC_ELT (m_mementos, i, m)
223 delete 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. */
244 void
245 recording::context::record (memento *m)
247 gcc_assert (m);
249 m_mementos.safe_push (m);
252 /* Replay this context (and any parents) into the given replayer. */
254 void
255 recording::context::replay_into (replayer *r)
257 JIT_LOG_SCOPE (get_logger ());
258 int i;
259 memento *m;
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). */
276 if (m_parent_ctxt)
277 m_parent_ctxt->replay_into (r);
279 if (r->errors_occurred ())
280 return;
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
286 we're replaying.
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
290 machinery. */
291 if (0)
292 printf ("context %p replaying (%p): %s\n",
293 (void *)this, (void *)m, m->get_debug_string ());
295 m->replay_into (r);
297 if (r->errors_occurred ())
298 return;
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). */
312 void
313 recording::context::disassociate_from_playback ()
315 JIT_LOG_SCOPE (get_logger ());
316 int i;
317 memento *m;
319 if (m_parent_ctxt)
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
329 of mementos.
331 This creates a fresh copy of the given 0-terminated buffer. */
333 recording::string *
334 recording::context::new_string (const char *text)
336 if (!text)
337 return NULL;
339 recording::string *result = new string (this, text);
340 record (result);
341 return result;
344 /* Create a recording::location instance and add it to this context's
345 list of mementos.
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,
352 int line,
353 int column)
355 recording::location *result =
356 new recording::location (this,
357 new_string (filename),
358 line, column);
359 record (result);
360 return result;
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
370 ancestor context.
372 Implements the post-error-checking part of
373 gcc_jit_context_get_type. */
375 recording::type *
376 recording::context::get_type (enum gcc_jit_types kind)
378 if (!m_basic_types[kind])
380 if (m_parent_ctxt)
381 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
382 else
384 recording::type *result = new memento_of_get_type (this, kind);
385 record (result);
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
395 above.
397 Implements the post-error-checking part of
398 gcc_jit_context_get_int_type. */
400 recording::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
412 ? GCC_JIT_TYPE_INT
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
420 ? GCC_JIT_TYPE_SHORT
421 : GCC_JIT_TYPE_UNSIGNED_SHORT);
422 if (num_bits == LONG_TYPE_SIZE)
423 return get_type (is_signed
424 ? GCC_JIT_TYPE_LONG
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? */
434 gcc_unreachable ();
437 /* Create a recording::type instance and add it to this context's list
438 of mementos.
440 Implements the post-error-checking part of
441 gcc_jit_context_new_array_type. */
443 recording::type *
444 recording::context::new_array_type (recording::location *loc,
445 recording::type *element_type,
446 int num_elements)
448 if (struct_ *s = element_type->dyn_cast_struct ())
449 if (!s->get_fields ())
451 add_error (NULL,
452 "cannot create an array of type %s"
453 " until the fields have been set",
454 s->get_name ()->c_str ());
455 return NULL;
457 recording::type *result =
458 new recording::array_type (this, loc, element_type, num_elements);
459 record (result);
460 return result;
463 /* Create a recording::field instance and add it to this context's list
464 of mementos.
466 Implements the post-error-checking part of
467 gcc_jit_context_new_field. */
469 recording::field *
470 recording::context::new_field (recording::location *loc,
471 recording::type *type,
472 const char *name)
474 recording::field *result =
475 new recording::field (this, loc, type, new_string (name));
476 record (result);
477 return result;
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. */
486 recording::struct_ *
487 recording::context::new_struct_type (recording::location *loc,
488 const char *name)
490 recording::struct_ *result = new struct_ (this, loc, new_string (name));
491 record (result);
492 m_compound_types.safe_push (result);
493 return 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. */
502 recording::union_ *
503 recording::context::new_union_type (recording::location *loc,
504 const char *name)
506 recording::union_ *result = new union_ (this, loc, new_string (name));
507 record (result);
508 m_compound_types.safe_push (result);
509 return result;
512 /* Create a recording::function_type instance and add it to this context's
513 list of mementos.
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,
519 int num_params,
520 recording::type **param_types,
521 int is_variadic)
523 recording::function_type *fn_type
524 = new function_type (this,
525 return_type,
526 num_params,
527 param_types,
528 is_variadic);
529 record (fn_type);
530 return fn_type;
533 /* Create a recording::type instance and add it to this context's list
534 of mementos.
536 Implements the post-error-checking part of
537 gcc_jit_context_new_function_ptr_type. */
539 recording::type *
540 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
541 recording::type *return_type,
542 int num_params,
543 recording::type **param_types,
544 int is_variadic)
546 recording::function_type *fn_type
547 = new_function_type (return_type,
548 num_params,
549 param_types,
550 is_variadic);
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
557 of mementos.
559 Implements the post-error-checking part of
560 gcc_jit_context_new_param. */
562 recording::param *
563 recording::context::new_param (recording::location *loc,
564 recording::type *type,
565 const char *name)
567 recording::param *result = new recording::param (this, loc, type, new_string (name));
568 record (result);
569 return result;
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,
582 const char *name,
583 int num_params,
584 recording::param **params,
585 int is_variadic,
586 enum built_in_function builtin_id)
588 recording::function *result =
589 new recording::function (this,
590 loc, kind, return_type,
591 new_string (name),
592 num_params, params, is_variadic,
593 builtin_id);
594 record (result);
595 m_functions.safe_push (result);
597 return 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. */
607 builtins_manager *
608 recording::context::get_builtins_manager ()
610 if (m_parent_ctxt)
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
633 of mementos.
635 Implements the post-error-checking part of
636 gcc_jit_context_new_global. */
638 recording::lvalue *
639 recording::context::new_global (recording::location *loc,
640 enum gcc_jit_global_kind kind,
641 recording::type *type,
642 const char *name)
644 recording::global *result =
645 new recording::global (this, loc, kind, type, new_string (name));
646 record (result);
647 m_globals.safe_push (result);
649 return 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. */
658 recording::rvalue *
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));
663 record (result);
664 return result;
667 /* Create a recording::unary_op instance and add it to this context's
668 list of mementos.
670 Implements the post-error-checking part of
671 gcc_jit_context_new_unary_op. */
673 recording::rvalue *
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);
681 record (result);
682 return result;
685 /* Create a recording::binary_op instance and add it to this context's
686 list of mementos.
688 Implements the post-error-checking part of
689 gcc_jit_context_new_binary_op. */
691 recording::rvalue *
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);
700 record (result);
701 return result;
704 /* Create a recording::comparison instance and add it to this context's
705 list of mementos.
707 Implements the post-error-checking part of
708 gcc_jit_context_new_comparison. */
710 recording::rvalue *
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);
717 record (result);
718 return result;
721 /* Create a recording::cast instance and add it to this context's list
722 of mementos.
724 Implements the post-error-checking part of
725 gcc_jit_context_new_cast. */
727 recording::rvalue *
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_);
733 record (result);
734 return result;
737 /* Create a recording::call instance and add it to this context's list
738 of mementos.
740 Implements the post-error-checking part of
741 gcc_jit_context_new_call. */
743 recording::rvalue *
744 recording::context::new_call (recording::location *loc,
745 function *func,
746 int numargs , recording::rvalue **args)
748 recording::rvalue *result = new call (this, loc, func, numargs, args);
749 record (result);
750 return result;
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. */
759 recording::rvalue *
760 recording::context::new_call_through_ptr (recording::location *loc,
761 recording::rvalue *fn_ptr,
762 int numargs,
763 recording::rvalue **args)
765 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
766 record (result);
767 return result;
770 /* Create a recording::array_access instance and add it to this context's list
771 of mementos.
773 Implements the post-error-checking part of
774 gcc_jit_context_new_array_access. */
776 recording::lvalue *
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);
782 record (result);
783 return result;
786 /* Set the given string option for this context, or add an error if
787 it's not recognized.
789 Implements the post-error-checking part of
790 gcc_jit_context_set_str_option. */
792 void
793 recording::context::set_str_option (enum gcc_jit_str_option opt,
794 const char *value)
796 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
798 add_error (NULL,
799 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
800 return;
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
807 it's not recognized.
809 Implements the post-error-checking part of
810 gcc_jit_context_set_int_option. */
812 void
813 recording::context::set_int_option (enum gcc_jit_int_option opt,
814 int value)
816 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
818 add_error (NULL,
819 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
820 return;
822 m_int_options[opt] = value;
825 /* Set the given boolean option for this context, or add an error if
826 it's not recognized.
828 Implements the post-error-checking part of
829 gcc_jit_context_set_bool_option. */
831 void
832 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
833 int value)
835 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
837 add_error (NULL,
838 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
839 return;
841 m_bool_options[opt] = value ? true : false;
844 /* Add the given dumpname/out_ptr pair to this context's list of requested
845 dumps.
847 Implements the post-error-checking part of
848 gcc_jit_context_enable_dump. */
850 void
851 recording::context::enable_dump (const char *dumpname,
852 char **out_ptr)
854 requested_dump d;
855 gcc_assert (dumpname);
856 gcc_assert (out_ptr);
858 d.m_dumpname = dumpname;
859 d.m_out_ptr = out_ptr;
860 *out_ptr = NULL;
861 m_requested_dumps.safe_push (d);
864 /* Validate this context, and if it passes, compile it within a
865 mutex.
867 Implements the post-error-checking part of
868 gcc_jit_context_compile. */
870 result *
871 recording::context::compile ()
873 JIT_LOG_SCOPE (get_logger ());
875 validate ();
877 if (errors_occurred ())
878 return NULL;
880 /* Set up a playback context. */
881 ::gcc::jit::playback::context replayer (this);
883 /* Use it. */
884 result *result_obj = replayer.compile ();
886 return result_obj;
889 /* Format the given error using printf's conventions, print
890 it to stderr, and add it to the context. */
892 void
893 recording::context::add_error (location *loc, const char *fmt, ...)
895 va_list ap;
896 va_start (ap, fmt);
897 add_error_va (loc, fmt, ap);
898 va_end (ap);
901 /* Format the given error using printf's conventions, print
902 it to stderr, and add it to the context. */
904 void
905 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
907 char *malloced_msg;
908 const char *errmsg;
909 bool has_ownership;
911 JIT_LOG_SCOPE (get_logger ());
913 vasprintf (&malloced_msg, fmt, ap);
914 if (malloced_msg)
916 errmsg = malloced_msg;
917 has_ownership = true;
919 else
921 errmsg = "out of memory generating error message";
922 has_ownership = false;
924 if (get_logger ())
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);
929 if (!ctxt_progname)
930 ctxt_progname = "libgccjit.so";
932 if (loc)
933 fprintf (stderr, "%s: %s: error: %s\n",
934 ctxt_progname,
935 loc->get_debug_string (),
936 errmsg);
937 else
938 fprintf (stderr, "%s: error: %s\n",
939 ctxt_progname,
940 errmsg);
942 if (!m_error_count)
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;
954 m_error_count++;
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. */
963 const char *
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. */
975 const char *
976 recording::context::get_last_error () const
978 return m_last_error_str;
981 /* Lazily generate and record a recording::type representing an opaque
982 struct named "FILE".
984 For use if client code tries to dereference the result of
985 get_type (GCC_JIT_TYPE_FILE_PTR). */
987 recording::type *
988 recording::context::get_opaque_FILE_type ()
990 if (!m_FILE_type)
991 m_FILE_type = new_struct_type (NULL, "FILE");
992 return m_FILE_type;
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. */
1002 void
1003 recording::context::dump_to_file (const char *path, bool update_locations)
1005 int i;
1006 dump d (*this, path, update_locations);
1008 /* Forward declaration of structs and unions. */
1009 compound_type *st;
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);
1020 d.write ("\n");
1023 /* Globals. */
1024 global *g;
1025 FOR_EACH_VEC_ELT (m_globals, i, g)
1027 g->write_to_dump (d);
1029 if (!m_globals.is_empty ())
1030 d.write ("\n");
1032 function *fn;
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
1040 OUT. */
1042 void
1043 recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
1045 if (m_parent_ctxt)
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. */
1056 void
1057 recording::context::validate ()
1059 JIT_LOG_SCOPE (get_logger ());
1061 if (m_parent_ctxt)
1062 m_parent_ctxt->validate ();
1064 int i;
1065 function *fn;
1066 FOR_EACH_VEC_ELT (m_functions, i, fn)
1067 fn->validate ();
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
1074 result.
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
1078 optimized. */
1080 const char *
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. */
1091 void
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)
1103 : memento (ctxt)
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 ()
1114 delete[] m_buffer;
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. */
1124 recording::string *
1125 recording::string::from_printf (context *ctxt, const char *fmt, ...)
1127 va_list ap;
1128 char *buf = NULL;
1129 recording::string *result;
1131 va_start (ap, fmt);
1132 vasprintf (&buf, fmt, ap);
1133 va_end (ap);
1135 if (!buf)
1137 ctxt->add_error (NULL, "malloc failure");
1138 return NULL;
1141 result = ctxt->new_string (buf);
1142 free (buf);
1143 return result;
1146 /* Implementation of recording::memento::make_debug_string for strings,
1147 wrapping the given string in quotes and escaping as necessary. */
1149 recording::string *
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] == '"')
1155 return this;
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];
1164 size_t len = 0;
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 == '"')
1172 APPEND('\\');
1173 APPEND(ch);
1175 APPEND('"'); /* closing quote */
1176 #undef APPEND
1177 tmp[len] = '\0'; /* nil termintator */
1179 string *result = m_ctxt->new_string (tmp);
1181 delete[] tmp;
1182 return result;
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. */
1192 void
1193 recording::location::replay_into (replayer *r)
1195 m_playback_obj = r->new_location (this,
1196 m_filename->c_str (),
1197 m_line,
1198 m_column);
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. */
1206 recording::string *
1207 recording::location::make_debug_string ()
1209 return string::from_printf (m_ctxt,
1210 "%s:%i:%i",
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. */
1226 recording::type *
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. */
1242 recording::type *
1243 recording::type::get_const ()
1245 recording::type *result = new memento_of_get_const (this);
1246 m_ctxt->record (result);
1247 return 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. */
1255 recording::type *
1256 recording::type::get_volatile ()
1258 recording::type *result = new memento_of_get_volatile (this);
1259 m_ctxt->record (result);
1260 return result;
1263 /* Implementation of pure virtual hook recording::type::dereference for
1264 recording::memento_of_get_type. */
1266 recording::type *
1267 recording::memento_of_get_type::dereference ()
1269 switch (m_kind)
1271 default: gcc_unreachable ();
1273 case GCC_JIT_TYPE_VOID:
1274 return NULL;
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: */
1298 return NULL;
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: */
1305 return NULL;
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. */
1316 bool
1317 recording::memento_of_get_type::is_int () const
1319 switch (m_kind)
1321 default: gcc_unreachable ();
1323 case GCC_JIT_TYPE_VOID:
1324 return false;
1326 case GCC_JIT_TYPE_VOID_PTR:
1327 return false;
1329 case GCC_JIT_TYPE_BOOL:
1330 return false;
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:
1343 return true;
1345 case GCC_JIT_TYPE_FLOAT:
1346 case GCC_JIT_TYPE_DOUBLE:
1347 case GCC_JIT_TYPE_LONG_DOUBLE:
1348 return false;
1350 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1351 return false;
1353 case GCC_JIT_TYPE_SIZE_T:
1354 return true;
1356 case GCC_JIT_TYPE_FILE_PTR:
1357 return false;
1359 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1360 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1361 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
1362 return false;
1366 /* Implementation of pure virtual hook recording::type::is_float for
1367 recording::memento_of_get_type. */
1369 bool
1370 recording::memento_of_get_type::is_float () const
1372 switch (m_kind)
1374 default: gcc_unreachable ();
1376 case GCC_JIT_TYPE_VOID:
1377 return false;
1379 case GCC_JIT_TYPE_VOID_PTR:
1380 return false;
1382 case GCC_JIT_TYPE_BOOL:
1383 return false;
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:
1396 return false;
1398 case GCC_JIT_TYPE_FLOAT:
1399 case GCC_JIT_TYPE_DOUBLE:
1400 case GCC_JIT_TYPE_LONG_DOUBLE:
1401 return true;
1403 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1404 return false;
1406 case GCC_JIT_TYPE_SIZE_T:
1407 return false;
1409 case GCC_JIT_TYPE_FILE_PTR:
1410 return false;
1412 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1413 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1414 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
1415 return true;
1419 /* Implementation of pure virtual hook recording::type::is_bool for
1420 recording::memento_of_get_type. */
1422 bool
1423 recording::memento_of_get_type::is_bool () const
1425 switch (m_kind)
1427 default: gcc_unreachable ();
1429 case GCC_JIT_TYPE_VOID:
1430 return false;
1432 case GCC_JIT_TYPE_VOID_PTR:
1433 return false;
1435 case GCC_JIT_TYPE_BOOL:
1436 return true;
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:
1449 return false;
1451 case GCC_JIT_TYPE_FLOAT:
1452 case GCC_JIT_TYPE_DOUBLE:
1453 case GCC_JIT_TYPE_LONG_DOUBLE:
1454 return false;
1456 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1457 return false;
1459 case GCC_JIT_TYPE_SIZE_T:
1460 return false;
1462 case GCC_JIT_TYPE_FILE_PTR:
1463 return false;
1465 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1466 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1467 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
1468 return false;
1472 /* Implementation of pure virtual hook recording::memento::replay_into
1473 for recording::memento_of_get_type. */
1475 void
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. */
1526 recording::string *
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. */
1540 bool
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)
1546 return false;
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. */
1556 void
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. */
1566 recording::string *
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
1571 least). */
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. */
1584 void
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 ". */
1593 recording::string *
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. */
1605 void
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 ". */
1614 recording::string *
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. */
1626 recording::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. */
1635 void
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 (),
1640 m_num_elements));
1643 /* Implementation of recording::memento::make_debug_string for
1644 results of new_array_type. */
1646 recording::string *
1647 recording::array_type::make_debug_string ()
1649 return string::from_printf (m_ctxt,
1650 "%s[%d]",
1651 m_element_type->get_debug_string (),
1652 m_num_elements);
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,
1660 type *return_type,
1661 int num_params,
1662 type **param_types,
1663 int is_variadic)
1664 : type (ctxt),
1665 m_return_type (return_type),
1666 m_param_types (),
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. */
1676 recording::type *
1677 recording::function_type::dereference ()
1679 return NULL;
1682 /* Implementation of pure virtual hook recording::memento::replay_into
1683 for recording::function_type. */
1685 void
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;
1690 int i;
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 (),
1697 &param_types,
1698 m_is_variadic));
1701 /* Special-casing for make_debug_string for get_pointer results for
1702 handling (one level) of pointers to functions. */
1704 recording::string *
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. */
1713 recording::string *
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
1724 function type. */
1726 recording::string *
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 */
1737 if (m_is_variadic)
1738 sz += 5; /* ", ..." separator and ellipsis */
1740 /* Now allocate and populate the buffer. */
1741 char *argbuf = new char[sz];
1742 size_t len = 0;
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, ", ");
1751 len += 2;
1754 if (m_is_variadic)
1756 if (m_param_types.length ())
1758 strcpy (argbuf + len, ", ");
1759 len += 2;
1761 strcpy (argbuf + len, "...");
1762 len += 3;
1764 argbuf[len] = '\0';
1766 /* ...and use it to get the string for the call as a whole. */
1767 string *result = string::from_printf (m_ctxt,
1768 "%s %s(%s)",
1769 m_return_type->get_debug_string (),
1770 insert,
1771 argbuf);
1773 delete[] argbuf;
1775 return result;
1778 /* The implementation of class gcc::jit::recording::field. */
1780 /* Implementation of pure virtual hook recording::memento::replay_into
1781 for recording::field. */
1783 void
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:
1794 TYPE NAME;
1795 so that we can build up a struct/union field-byfield. */
1797 void
1798 recording::field::write_to_dump (dump &d)
1800 d.write (" %s %s;\n",
1801 m_type->get_debug_string (),
1802 m_name->c_str ());
1805 /* Implementation of recording::memento::make_debug_string for
1806 results of new_field. */
1808 recording::string *
1809 recording::field::make_debug_string ()
1811 return m_name;
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,
1819 location *loc,
1820 string *name)
1821 : type (ctxt),
1822 m_loc (loc),
1823 m_name (name),
1824 m_fields (NULL)
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. */
1834 void
1835 recording::compound_type::set_fields (location *loc,
1836 int num_fields,
1837 field **field_array)
1839 m_loc = loc;
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. */
1849 recording::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,
1860 location *loc,
1861 string *name)
1862 : compound_type (ctxt, loc, name)
1866 /* Implementation of pure virtual hook recording::memento::replay_into
1867 for recording::struct_. */
1869 void
1870 recording::struct_::replay_into (replayer *r)
1872 set_playback_obj (
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
1879 structs. */
1881 recording::string *
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,
1893 location *loc,
1894 string *name)
1895 : compound_type (ctxt, loc, name)
1899 /* Implementation of pure virtual hook recording::memento::replay_into
1900 for recording::union_. */
1902 void
1903 recording::union_::replay_into (replayer *r)
1905 set_playback_obj (
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
1912 unions. */
1914 recording::string *
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,
1926 int num_fields,
1927 field **fields)
1928 : memento (struct_or_union->m_ctxt),
1929 m_struct_or_union (struct_or_union),
1930 m_fields ()
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. */
1943 void
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:
1957 struct/union NAME {
1958 TYPE_1 NAME_1;
1959 TYPE_2 NAME_2;
1960 ....
1961 TYPE_N NAME_N;
1964 to the dump. */
1966 void
1967 recording::fields::write_to_dump (dump &d)
1969 int i;
1970 field *f;
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);
1975 d.write ("};\n");
1978 /* Implementation of recording::memento::make_debug_string for
1979 field tables. */
1981 recording::string *
1982 recording::fields::make_debug_string ()
1984 return string::from_printf (m_ctxt,
1985 "fields");
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. */
1996 recording::rvalue *
1997 recording::rvalue::access_field (recording::location *loc,
1998 field *field)
2000 recording::rvalue *result =
2001 new access_field_rvalue (m_ctxt, loc, this, field);
2002 m_ctxt->record (result);
2003 return 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. */
2012 recording::lvalue *
2013 recording::rvalue::dereference_field (recording::location *loc,
2014 field *field)
2016 recording::lvalue *result =
2017 new dereference_field_rvalue (m_ctxt, loc, this, field);
2018 m_ctxt->record (result);
2019 return 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. */
2028 recording::lvalue *
2029 recording::rvalue::dereference (recording::location *loc)
2031 recording::lvalue *result =
2032 new dereference_rvalue (m_ctxt, loc, this);
2033 m_ctxt->record (result);
2034 return 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
2043 public:
2044 rvalue_usage_validator (const char *api_funcname,
2045 recording::context *ctxt,
2046 recording::statement *stmt);
2048 void
2049 visit (recording::rvalue *rvalue);
2051 private:
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),
2063 m_ctxt (ctxt),
2064 m_stmt (stmt)
2068 /* Verify that the given rvalue is in the correct scope. */
2070 void
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)
2080 m_ctxt->add_error
2081 (rvalue->get_loc (),
2082 "%s:"
2083 " rvalue %s (type: %s)"
2084 " has scope limited to function %s"
2085 " but was used within function %s"
2086 " (in statement: %s)",
2087 m_api_funcname,
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 ());
2094 else
2096 if (rvalue->dyn_cast_param ())
2097 m_ctxt->add_error
2098 (rvalue->get_loc (),
2099 "%s:"
2100 " param %s (type: %s)"
2101 " was used within function %s"
2102 " (in statement: %s)"
2103 " but is not associated with any function",
2104 m_api_funcname,
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. */
2119 void
2120 recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
2122 rvalue_usage_validator v (api_funcname,
2123 s->get_context (),
2126 /* Verify that it's OK to use this rvalue within s. */
2127 v.visit (this);
2129 /* Traverse the expression tree below "this", verifying all rvalues
2130 within it. */
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. */
2137 void
2138 recording::rvalue::set_scope (function *scope)
2140 gcc_assert (scope);
2141 gcc_assert (NULL == m_scope);
2142 m_scope = 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. */
2154 recording::lvalue *
2155 recording::lvalue::access_field (recording::location *loc,
2156 field *field)
2158 recording::lvalue *result =
2159 new access_field_of_lvalue (m_ctxt, loc, this, field);
2160 m_ctxt->record (result);
2161 return 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. */
2170 recording::rvalue *
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);
2176 return result;
2179 /* The implementation of class gcc::jit::recording::param. */
2181 /* Implementation of pure virtual hook recording::memento::replay_into
2182 for recording::param. */
2184 void
2185 recording::param::replay_into (replayer *r)
2187 set_playback_obj (r->new_param (playback_location (r, m_loc),
2188 m_type->playback_type (),
2189 m_name->c_str ()));
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,
2200 type *return_type,
2201 recording::string *name,
2202 int num_params,
2203 recording::param **params,
2204 int is_variadic,
2205 enum built_in_function builtin_id)
2206 : memento (ctxt),
2207 m_loc (loc),
2208 m_kind (kind),
2209 m_return_type (return_type),
2210 m_name (name),
2211 m_params (),
2212 m_is_variadic (is_variadic),
2213 m_builtin_id (builtin_id),
2214 m_locals (),
2215 m_blocks ()
2217 for (int i = 0; i< num_params; i++)
2219 param *param = params[i];
2220 gcc_assert (param);
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 ());
2234 ctxt->add_error
2235 (loc,
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 (),
2241 name->c_str ());
2243 else
2245 /* The normal, non-error case: associate this function with the
2246 param. */
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. */
2257 void
2258 recording::function::replay_into (replayer *r)
2260 /* Convert m_params to a vec of playback param. */
2261 auto_vec <playback::param *> params;
2262 int i;
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),
2269 m_kind,
2270 m_return_type->playback_type (),
2271 m_name->c_str (),
2272 &params,
2273 m_is_variadic,
2274 m_builtin_id));
2277 /* Create a recording::local instance and add it to
2278 the functions's context's list of mementos, and to the function's
2279 list of locals.
2281 Implements the post-error-checking part of
2282 gcc_jit_function_new_local. */
2284 recording::lvalue *
2285 recording::function::new_local (recording::location *loc,
2286 type *type,
2287 const char *name)
2289 local *result = new local (this, loc, type, new_string (name));
2290 m_ctxt->record (result);
2291 m_locals.safe_push (result);
2292 return 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
2297 list of blocks.
2299 Implements the post-error-checking part of
2300 gcc_jit_function_new_block. */
2302 recording::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);
2311 return 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. */
2320 void
2321 recording::function::write_to_dump (dump &d)
2323 switch (m_kind)
2325 default: gcc_unreachable ();
2326 case GCC_JIT_FUNCTION_EXPORTED:
2327 case GCC_JIT_FUNCTION_IMPORTED:
2328 d.write ("extern ");
2329 break;
2330 case GCC_JIT_FUNCTION_INTERNAL:
2331 d.write ("static ");
2332 break;
2333 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
2334 d.write ("static inline ");
2335 break;
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 ());
2344 int i;
2345 recording::param *param;
2346 FOR_EACH_VEC_ELT (m_params, i, param)
2348 if (i > 0)
2349 d.write (", ");
2350 d.write ("%s %s",
2351 param->get_type ()->get_debug_string (),
2352 param->get_debug_string ());
2354 d.write (")");
2355 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
2357 d.write ("; /* (imported) */\n\n");
2359 else
2361 int i;
2362 local *var = NULL;
2363 block *b;
2364 d.write ("\n{\n");
2366 /* Write locals: */
2367 FOR_EACH_VEC_ELT (m_locals, i, var)
2368 var->write_to_dump (d);
2369 if (m_locals.length ())
2370 d.write ("\n");
2372 /* Write each block: */
2373 FOR_EACH_VEC_ELT (m_blocks, i, b)
2375 if (i > 0)
2376 d.write ("\n");
2377 b->write_to_dump (d);
2380 d.write ("}\n\n");
2384 /* Pre-compilation validation of a function, for those things we can't
2385 check until the context is (supposedly) fully-populated. */
2387 void
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;
2403 int i;
2404 block *b;
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);
2427 switch (n)
2429 default:
2430 gcc_unreachable ();
2431 case 2:
2432 if (!next2->m_is_reachable)
2433 worklist.safe_push (next2);
2434 /* fallthrough */
2435 case 1:
2436 if (!next1->m_is_reachable)
2437 worklist.safe_push (next1);
2438 break;
2439 case 0:
2440 break;
2444 /* Now complain about any blocks that haven't been marked. */
2446 int i;
2447 block *b;
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. */
2460 void
2461 recording::function::dump_to_dot (const char *path)
2463 FILE *fp = fopen (path, "w");
2464 if (!fp)
2465 return;
2467 pretty_printer the_pp;
2468 the_pp.buffer->stream = fp;
2470 pretty_printer *pp = &the_pp;
2472 pp_printf (pp,
2473 "digraph %s {\n", get_debug_string ());
2475 /* Blocks: */
2477 int i;
2478 block *b;
2479 FOR_EACH_VEC_ELT (m_blocks, i, b)
2480 b->dump_to_dot (pp);
2483 /* Edges: */
2485 int i;
2486 block *b;
2487 FOR_EACH_VEC_ELT (m_blocks, i, b)
2488 b->dump_edges_to_dot (pp);
2491 pp_printf (pp, "}\n");
2492 pp_flush (pp);
2493 fclose (fp);
2496 /* Implementation of recording::memento::make_debug_string for
2497 functions. */
2499 recording::string *
2500 recording::function::make_debug_string ()
2502 return m_name;
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
2509 list of statements.
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);
2520 return 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
2525 list of statements.
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);
2537 return 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
2542 list of statements.
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);
2555 return 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
2560 list of statements.
2562 Implements the heart of gcc_jit_block_add_comment. */
2564 recording::statement *
2565 recording::block::add_comment (recording::location *loc,
2566 const char *text)
2568 statement *result = new comment (this, loc, new_string (text));
2569 m_ctxt->record (result);
2570 m_statements.safe_push (result);
2571 return 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
2576 list of statements.
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;
2590 return result;
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
2595 list of statements.
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;
2607 return result;
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
2612 list of statements.
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;
2629 return result;
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
2635 statements:
2637 BLOCK_NAME:
2638 STATEMENT_1;
2639 STATEMENT_2;
2641 STATEMENT_N; */
2643 void
2644 recording::block::write_to_dump (dump &d)
2646 d.write ("%s:\n", get_debug_string ());
2648 int i;
2649 statement *s;
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. */
2656 bool
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 ());
2668 return false;
2671 return true;
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 ();
2681 if (stmt)
2682 return stmt->get_loc ();
2683 else
2684 return NULL;
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];
2694 else
2695 return NULL;
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];
2705 else
2706 return NULL;
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
2716 of them. */
2719 recording::block::get_successor_blocks (block **next1, block **next2) const
2721 gcc_assert (m_has_been_terminated);
2722 gcc_assert (next1);
2723 gcc_assert (next2);
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. */
2732 void
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
2740 blocks. */
2742 recording::string *
2743 recording::block::make_debug_string ()
2745 if (m_name)
2746 return m_name;
2747 else
2748 return string::from_printf (m_ctxt,
2749 "<UNNAMED BLOCK %p>",
2750 (void *)this);
2753 /* Dump a block in graphviz form into PP, capturing the block name (if
2754 any) and the statements. */
2756 void
2757 recording::block::dump_to_dot (pretty_printer *pp)
2759 pp_printf (pp,
2760 ("\tblock_%d "
2761 "[shape=record,style=filled,fillcolor=white,label=\"{"),
2762 m_index);
2763 pp_write_text_to_stream (pp);
2764 if (m_name)
2766 pp_string (pp, m_name->c_str ());
2767 pp_string (pp, ":");
2768 pp_newline (pp);
2769 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
2772 int i;
2773 statement *s;
2774 FOR_EACH_VEC_ELT (m_statements, i, s)
2776 pp_string (pp, s->get_debug_string ());
2777 pp_newline (pp);
2778 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
2781 pp_printf (pp,
2782 "}\"];\n\n");
2783 pp_flush (pp);
2786 /* Dump the out-edges of the block in graphviz form into PP. */
2788 void
2789 recording::block::dump_edges_to_dot (pretty_printer *pp)
2791 block *next[2];
2792 int num_succs = get_successor_blocks (&next[0], &next[1]);
2793 for (int i = 0; i < num_succs; i++)
2794 pp_printf (pp,
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. */
2804 void
2805 recording::global::replay_into (replayer *r)
2807 set_playback_obj (r->new_global (playback_location (r, m_loc),
2808 m_kind,
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:
2818 "TYPE NAME;"
2819 e.g. "int foo;"
2821 GCC_JIT_GLOBAL_INTERNAL:
2822 "static TYPE NAME;"
2823 e.g. "static int foo;"
2825 GCC_JIT_GLOBAL_IMPORTED:
2826 "extern TYPE NAME;"
2827 e.g. "extern int foo;"
2829 These are written to the top of the dump by
2830 recording::context::dump_to_file. */
2832 void
2833 recording::global::write_to_dump (dump &d)
2835 if (d.update_locations ())
2836 m_loc = d.make_location ();
2838 switch (m_kind)
2840 default:
2841 gcc_unreachable ();
2843 case GCC_JIT_GLOBAL_EXPORTED:
2844 break;
2846 case GCC_JIT_GLOBAL_INTERNAL:
2847 d.write ("static ");
2848 break;
2850 case GCC_JIT_GLOBAL_IMPORTED:
2851 d.write ("extern ");
2852 break;
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>
2872 void
2873 recording::
2874 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
2876 set_playback_obj
2877 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
2878 m_value));
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
2891 namespace. */
2893 namespace recording
2896 /* The make_debug_string specialization for <int>, which renders it as
2897 (TARGET_TYPE)LITERAL
2898 e.g.
2899 "(int)42". */
2901 template <>
2902 string *
2903 memento_of_new_rvalue_from_const <int>::make_debug_string ()
2905 return string::from_printf (m_ctxt,
2906 "(%s)%i",
2907 m_type->get_debug_string (),
2908 m_value);
2911 /* The make_debug_string specialization for <long>, rendering it as
2912 (TARGET_TYPE)LITERAL
2913 e.g.
2914 "(long)42". */
2916 template <>
2917 string *
2918 memento_of_new_rvalue_from_const <long>::make_debug_string ()
2920 return string::from_printf (m_ctxt,
2921 "(%s)%li",
2922 m_type->get_debug_string (),
2923 m_value);
2926 /* The make_debug_string specialization for <double>, rendering it as
2927 (TARGET_TYPE)LITERAL
2928 e.g.
2929 "(float)42.0". */
2931 template <>
2932 string *
2933 memento_of_new_rvalue_from_const <double>::make_debug_string ()
2935 return string::from_printf (m_ctxt,
2936 "(%s)%f",
2937 m_type->get_debug_string (),
2938 m_value);
2941 /* The make_debug_string specialization for <void *>, rendering it as
2942 (TARGET_TYPE)HEX
2943 e.g.
2944 "(int *)0xdeadbeef"
2946 Zero is rendered as NULL e.g.
2947 "(int *)NULL". */
2949 template <>
2950 string *
2951 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
2953 if (m_value != NULL)
2954 return string::from_printf (m_ctxt,
2955 "(%s)%p",
2956 m_type->get_debug_string (), m_value);
2957 else
2958 return string::from_printf (m_ctxt,
2959 "(%s)NULL",
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. */
2973 void
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
2980 string literals. */
2982 recording::string *
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. */
2994 void
2995 recording::unary_op::replay_into (replayer *r)
2997 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
2998 m_op,
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. */
3005 void
3006 recording::unary_op::visit_children (rvalue_visitor *v)
3008 v->visit (m_a);
3011 /* Implementation of recording::memento::make_debug_string for
3012 unary ops. */
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 */
3021 recording::string *
3022 recording::unary_op::make_debug_string ()
3024 return string::from_printf (m_ctxt,
3025 "%s(%s)",
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. */
3035 void
3036 recording::binary_op::replay_into (replayer *r)
3038 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
3039 m_op,
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. */
3047 void
3048 recording::binary_op::visit_children (rvalue_visitor *v)
3050 v->visit (m_a);
3051 v->visit (m_b);
3054 /* Implementation of recording::memento::make_debug_string for
3055 binary ops. */
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 */
3072 recording::string *
3073 recording::binary_op::make_debug_string ()
3075 return string::from_printf (m_ctxt,
3076 "%s %s %s",
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
3085 comparisons. */
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 */
3097 recording::string *
3098 recording::comparison::make_debug_string ()
3100 return string::from_printf (m_ctxt,
3101 "%s %s %s",
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. */
3110 void
3111 recording::comparison::replay_into (replayer *r)
3113 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
3114 m_op,
3115 m_a->playback_rvalue (),
3116 m_b->playback_rvalue ()));
3119 /* Implementation of pure virtual hook recording::rvalue::visit_children
3120 for recording::comparison. */
3122 void
3123 recording::comparison::visit_children (rvalue_visitor *v)
3125 v->visit (m_a);
3126 v->visit (m_b);
3129 /* Implementation of pure virtual hook recording::memento::replay_into
3130 for recording::cast. */
3132 void
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. */
3142 void
3143 recording::cast::visit_children (rvalue_visitor *v)
3145 v->visit (m_rvalue);
3148 /* Implementation of recording::memento::make_debug_string for
3149 casts. */
3151 recording::string *
3152 recording::cast::make_debug_string ()
3154 return string::from_printf (m_ctxt,
3155 "(%s)%s",
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,
3167 int numargs,
3168 rvalue **args)
3169 : rvalue (ctxt, loc, func->get_return_type ()),
3170 m_func (func),
3171 m_args ()
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. */
3180 void
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 (),
3190 &playback_args));
3193 /* Implementation of pure virtual hook recording::rvalue::visit_children
3194 for recording::call. */
3196 void
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
3204 function calls. */
3206 recording::string *
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];
3220 size_t len = 0;
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, ", ");
3229 len += 2;
3232 argbuf[len] = '\0';
3234 /* ...and use it to get the string for the call as a whole. */
3235 string *result = string::from_printf (m_ctxt,
3236 "%s (%s)",
3237 m_func->get_debug_string (),
3238 argbuf);
3240 delete[] argbuf;
3242 return result;
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,
3252 int numargs,
3253 rvalue **args)
3254 : rvalue (ctxt, loc,
3255 fn_ptr->get_type ()->dereference ()
3256 ->as_a_function_type ()->get_return_type ()),
3257 m_fn_ptr (fn_ptr),
3258 m_args ()
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. */
3267 void
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 (),
3277 &playback_args));
3280 /* Implementation of pure virtual hook recording::rvalue::visit_children
3281 for recording::call_through_ptr. */
3283 void
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. */
3294 recording::string *
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];
3308 size_t len = 0;
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, ", ");
3317 len += 2;
3320 argbuf[len] = '\0';
3322 /* ...and use it to get the string for the call as a whole. */
3323 string *result = string::from_printf (m_ctxt,
3324 "%s (%s)",
3325 m_fn_ptr->get_debug_string (),
3326 argbuf);
3328 delete[] argbuf;
3330 return result;
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. */
3338 void
3339 recording::array_access::replay_into (replayer *r)
3341 set_playback_obj (
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. */
3350 void
3351 recording::array_access::visit_children (rvalue_visitor *v)
3353 v->visit (m_ptr);
3354 v->visit (m_index);
3357 /* Implementation of recording::memento::make_debug_string for
3358 array accesses. */
3360 recording::string *
3361 recording::array_access::make_debug_string ()
3363 return string::from_printf (m_ctxt,
3364 "%s[%s]",
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. */
3374 void
3375 recording::access_field_of_lvalue::replay_into (replayer *r)
3377 set_playback_obj (
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. */
3387 void
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. */
3396 recording::string *
3397 recording::access_field_of_lvalue::make_debug_string ()
3399 return string::from_printf (m_ctxt,
3400 "%s.%s",
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. */
3410 void
3411 recording::access_field_rvalue::replay_into (replayer *r)
3413 set_playback_obj (
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. */
3422 void
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. */
3431 recording::string *
3432 recording::access_field_rvalue::make_debug_string ()
3434 return string::from_printf (m_ctxt,
3435 "%s.%s",
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. */
3446 void
3447 recording::dereference_field_rvalue::replay_into (replayer *r)
3449 set_playback_obj (
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. */
3458 void
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. */
3467 recording::string *
3468 recording::dereference_field_rvalue::make_debug_string ()
3470 return string::from_printf (m_ctxt,
3471 "%s->%s",
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. */
3481 void
3482 recording::dereference_rvalue::replay_into (replayer *r)
3484 set_playback_obj (
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. */
3492 void
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. */
3501 recording::string *
3502 recording::dereference_rvalue::make_debug_string ()
3504 return string::from_printf (m_ctxt,
3505 "*%s",
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. */
3514 void
3515 recording::get_address_of_lvalue::replay_into (replayer *r)
3517 set_playback_obj (
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. */
3525 void
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. */
3534 recording::string *
3535 recording::get_address_of_lvalue::make_debug_string ()
3537 return string::from_printf (m_ctxt,
3538 "&%s",
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. */
3547 void
3548 recording::local::replay_into (replayer *r)
3550 set_playback_obj (
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
3559 TYPE NAME;
3560 for use at the top of the function body as if it were a
3561 declaration. */
3563 void
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
3578 statements. */
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. */
3586 gcc_unreachable ();
3587 return 0;
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
3593 the dumpfile. */
3595 void
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. */
3608 void
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. */
3619 recording::string *
3620 recording::eval::make_debug_string ()
3622 return string::from_printf (m_ctxt,
3623 "(void)%s;",
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. */
3632 void
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. */
3644 recording::string *
3645 recording::assignment::make_debug_string ()
3647 return string::from_printf (m_ctxt,
3648 "%s = %s;",
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. */
3658 void
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),
3666 m_op,
3667 result_type,
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 (),
3674 binary_op);
3677 /* Implementation of recording::memento::make_debug_string for
3678 an assignment_op statement. */
3680 recording::string *
3681 recording::assignment_op::make_debug_string ()
3683 return string::from_printf (m_ctxt,
3684 "%s %s= %s;",
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. */
3695 void
3696 recording::comment::replay_into (replayer *r)
3698 playback_block (get_block ())
3699 ->add_comment (playback_location (r),
3700 m_text->c_str ());
3703 /* Implementation of recording::memento::make_debug_string for
3704 a comment "statement". */
3706 recording::string *
3707 recording::comment::make_debug_string ()
3709 return string::from_printf (m_ctxt,
3710 "/* %s */",
3711 m_text->c_str ());
3714 /* The implementation of class gcc::jit::recording::conditional. */
3716 /* Implementation of pure virtual hook recording::memento::replay_into
3717 for recording::conditional. */
3719 void
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;
3740 return 2;
3743 /* Implementation of recording::memento::make_debug_string for
3744 a conditional jump statement. */
3746 recording::string *
3747 recording::conditional::make_debug_string ()
3749 if (m_on_false)
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 ());
3755 else
3756 return string::from_printf (m_ctxt,
3757 "if (%s) goto %s;",
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. */
3767 void
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;
3785 return 1;
3788 /* Implementation of recording::memento::make_debug_string for
3789 a unconditional jump statement. */
3791 recording::string *
3792 recording::jump::make_debug_string ()
3794 return string::from_printf (m_ctxt,
3795 "goto %s;",
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_. */
3804 void
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
3821 return 0;
3824 /* Implementation of recording::memento::make_debug_string for
3825 a return statement (covers both those with and without rvalues). */
3827 recording::string *
3828 recording::return_::make_debug_string ()
3830 if (m_rvalue)
3831 return string::from_printf (m_ctxt,
3832 "return %s;",
3833 m_rvalue->get_debug_string ());
3834 else
3835 return string::from_printf (m_ctxt,
3836 "return;");
3839 } // namespace gcc::jit
3841 } // namespace gcc