]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/jit/jit-recording.c
PR jit/63854: Fix leak in tree-ssa-math-opts.c
[thirdparty/gcc.git] / gcc / jit / jit-recording.c
CommitLineData
35485da9
DM
1/* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2014 Free Software Foundation, Inc.
3 Contributed by David Malcolm <dmalcolm@redhat.com>.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "tm.h"
25#include "opts.h"
26#include "tree.h"
27#include "pretty-print.h"
28
29#include <pthread.h>
30
31#include "jit-common.h"
32#include "jit-builtins.h"
33#include "jit-recording.h"
34#include "jit-playback.h"
35
36namespace gcc {
37namespace jit {
38
39// class dump
40
41dump::dump (recording::context &ctxt,
42 const char *filename,
43 bool update_locations)
44: m_ctxt (ctxt),
45 m_filename (filename),
46 m_update_locations (update_locations),
47 m_line (0),
48 m_column (0)
49{
50 m_file = fopen (filename, "w");
51 if (!m_file)
52 ctxt.add_error (NULL,
53 "error opening dump file %s for writing: %s",
54 filename,
55 xstrerror (errno));
56}
57
58dump::~dump ()
59{
60 if (m_file)
61 {
62 int err = fclose (m_file);
63 if (err)
64 m_ctxt.add_error (NULL,
65 "error closing dump file %s: %s",
66 m_filename,
67 xstrerror (errno));
68 }
69}
70
71/* Write the given message to the dump, using printf-formatting
72 conventions, updating the line/column within the dump.
73
74 Emit an error on the context if a failure occurs. */
75
76void
77dump::write (const char *fmt, ...)
78{
79 va_list ap;
80 char *buf = NULL;
81
82 /* If there was an error opening the file, we've already reported it.
83 Don't attempt further work. */
84 if (!m_file)
85 return;
86
87 va_start (ap, fmt);
88 vasprintf (&buf, fmt, ap);
89 va_end (ap);
90
91 if (!buf)
92 {
93 m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
94 m_filename);
95 return;
96 }
97
98 if (fwrite (buf, strlen (buf), 1, m_file) != 1)
99 m_ctxt.add_error (NULL, "error writing to dump file %s",
100 m_filename);
101
102 /* Update line/column: */
103 for (const char *ptr = buf; *ptr; ptr++)
104 {
105 if ('\n' == *ptr)
106 {
107 m_line++;
108 m_column = 0;
109 }
110 else
111 m_column++;
112 }
113
114 free (buf);
115}
116
117/* Construct a gcc::jit::recording::location instance for the current
118 location within the dump. */
119
120recording::location *
121dump::make_location () const
122{
123 return m_ctxt.new_location (m_filename, m_line, m_column);
124}
125
126/**********************************************************************
127 Recording.
128 **********************************************************************/
129
130/* Get the playback::location for the given recording::location,
131 handling a NULL input with a NULL output. */
132
133playback::location *
134recording::playback_location (replayer *r, recording::location *loc)
135{
136 if (loc)
137 return loc->playback_location (r);
138 else
139 return NULL;
140}
141
142/* Get a const char * for the given recording::string
143 handling a NULL input with a NULL output. */
144
145const char *
146recording::playback_string (recording::string *str)
147{
148 if (str)
149 return str->c_str ();
150 else
151 return NULL;
152}
153
154/* Get the playback::block for the given recording::block,
155 handling a NULL input with a NULL output. */
156
157playback::block *
158recording::playback_block (recording::block *b)
159{
160 if (b)
161 return b->playback_block ();
162 else
163 return NULL;
164}
165
166/* Methods of cc::jit::recording::context. */
167
168/* The constructor for gcc::jit::recording::context, used by
169 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
170
171recording::context::context (context *parent_ctxt)
172 : m_parent_ctxt (parent_ctxt),
173 m_error_count (0),
174 m_first_error_str (NULL),
175 m_owns_first_error_str (false),
176 m_mementos (),
177 m_compound_types (),
178 m_functions (),
179 m_FILE_type (NULL),
180 m_builtins_manager(NULL)
181{
182 if (parent_ctxt)
183 {
184 /* Inherit options from parent.
185 Note that the first memcpy means copying pointers to strings. */
186 memcpy (m_str_options,
187 parent_ctxt->m_str_options,
188 sizeof (m_str_options));
189 memcpy (m_int_options,
190 parent_ctxt->m_int_options,
191 sizeof (m_int_options));
192 memcpy (m_bool_options,
193 parent_ctxt->m_bool_options,
194 sizeof (m_bool_options));
195 }
196 else
197 {
198 memset (m_str_options, 0, sizeof (m_str_options));
199 memset (m_int_options, 0, sizeof (m_int_options));
200 memset (m_bool_options, 0, sizeof (m_bool_options));
201 }
202
203 memset (m_basic_types, 0, sizeof (m_basic_types));
204}
205
206/* The destructor for gcc::jit::recording::context, implicitly used by
207 gcc_jit_context_release. */
208
209recording::context::~context ()
210{
211 int i;
212 memento *m;
213 FOR_EACH_VEC_ELT (m_mementos, i, m)
214 {
215 delete m;
216 }
217
218 if (m_builtins_manager)
219 delete m_builtins_manager;
220
221 if (m_owns_first_error_str)
222 free (m_first_error_str);
223}
224
225/* Add the given mememto to the list of those tracked by this
226 gcc::jit::recording::context, so that e.g. it can be deleted
227 when this context is released. */
228
229void
230recording::context::record (memento *m)
231{
232 gcc_assert (m);
233
234 m_mementos.safe_push (m);
235}
236
237/* Replay this context (and any parents) into the given replayer. */
238
239void
240recording::context::replay_into (replayer *r)
241{
242 int i;
243 memento *m;
244
245 /* If we have a parent context, we must replay it. This will
246 recursively walk backwards up the historical tree, then replay things
247 forwards "in historical order", starting with the ultimate parent
248 context, until we reach the "this" context.
249
250 Note that we fully replay the parent, then fully replay the child,
251 which means that inter-context references can only exist from child
252 to parent, not the other way around.
253
254 All of this replaying is suboptimal - it would be better to do the
255 work for the parent context *once*, rather than replaying the parent
256 every time we replay each child. However, fixing this requires deep
257 surgery to lifetime-management: we'd need every context family tree
258 to have its own GC heap, and to initialize the GCC code to use that
259 heap (with a mutex on such a heap). */
260 if (m_parent_ctxt)
261 m_parent_ctxt->replay_into (r);
262
263 if (r->errors_occurred ())
264 return;
265
266 /* Replay this context's saved operations into r. */
267 FOR_EACH_VEC_ELT (m_mementos, i, m)
268 {
269 /* Disabled low-level debugging, here if we need it: print what
270 we're replaying.
271 Note that the calls to get_debug_string might lead to more
272 mementos being created for the strings.
273 This can also be used to exercise the debug_string
274 machinery. */
275 if (0)
276 printf ("context %p replaying (%p): %s\n",
277 (void *)this, (void *)m, m->get_debug_string ());
278
279 m->replay_into (r);
280
281 if (r->errors_occurred ())
282 return;
283 }
284}
285
286/* During a playback, we associate objects from the recording with
287 their counterparts during this playback.
288
289 For simplicity, we store this within the recording objects.
290
291 The following method cleans away these associations, to ensure that
292 we never have out-of-date associations lingering on subsequent
293 playbacks (the objects pointed to are GC-managed, but the
294 recording objects don't own refs to them). */
295
296void
297recording::context::disassociate_from_playback ()
298{
299 int i;
300 memento *m;
301
302 if (m_parent_ctxt)
303 m_parent_ctxt->disassociate_from_playback ();
304
305 FOR_EACH_VEC_ELT (m_mementos, i, m)
306 {
307 m->set_playback_obj (NULL);
308 }
309}
310
311/* Create a recording::string instance and add it to this context's list
312 of mementos.
313
314 This creates a fresh copy of the given 0-terminated buffer. */
315
316recording::string *
317recording::context::new_string (const char *text)
318{
319 if (!text)
320 return NULL;
321
322 recording::string *result = new string (this, text);
323 record (result);
324 return result;
325}
326
327/* Create a recording::location instance and add it to this context's
328 list of mementos.
329
330 Implements the post-error-checking part of
331 gcc_jit_context_new_location. */
332
333recording::location *
334recording::context::new_location (const char *filename,
335 int line,
336 int column)
337{
338 recording::location *result =
339 new recording::location (this,
340 new_string (filename),
341 line, column);
342 record (result);
343 return result;
344}
345
346/* If we haven't seen this enum value yet, create a recording::type
347 instance and add it to this context's list of mementos.
348
349 If we have seen it before, reuse our cached value, so that repeated
350 calls on the context give the same object.
351
352 If we have a parent context, the cache is within the ultimate
353 ancestor context.
354
355 Implements the post-error-checking part of
356 gcc_jit_context_get_type. */
357
358recording::type *
359recording::context::get_type (enum gcc_jit_types kind)
360{
361 if (!m_basic_types[kind])
362 {
363 if (m_parent_ctxt)
364 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
365 else
366 {
367 recording::type *result = new memento_of_get_type (this, kind);
368 record (result);
369 m_basic_types[kind] = result;
370 }
371 }
372
373 return m_basic_types[kind];
374}
375
376/* Get a recording::type instance for the given size and signedness.
377 This is implemented in terms of recording::context::get_type
378 above.
379
380 Implements the post-error-checking part of
381 gcc_jit_context_get_int_type. */
382
383recording::type *
384recording::context::get_int_type (int num_bytes, int is_signed)
385{
386 /* We can't use a switch here since some of the values are macros affected
387 by options; e.g. i386.h has
388 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
389 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
390 are in bits, rather than bytes.
391 */
392 const int num_bits = num_bytes * 8;
393 if (num_bits == INT_TYPE_SIZE)
394 return get_type (is_signed
395 ? GCC_JIT_TYPE_INT
396 : GCC_JIT_TYPE_UNSIGNED_INT);
397 if (num_bits == CHAR_TYPE_SIZE)
398 return get_type (is_signed
399 ? GCC_JIT_TYPE_SIGNED_CHAR
400 : GCC_JIT_TYPE_UNSIGNED_CHAR);
401 if (num_bits == SHORT_TYPE_SIZE)
402 return get_type (is_signed
403 ? GCC_JIT_TYPE_SHORT
404 : GCC_JIT_TYPE_UNSIGNED_SHORT);
405 if (num_bits == LONG_TYPE_SIZE)
406 return get_type (is_signed
407 ? GCC_JIT_TYPE_LONG
408 : GCC_JIT_TYPE_UNSIGNED_LONG);
409 if (num_bits == LONG_LONG_TYPE_SIZE)
410 return get_type (is_signed
411 ? GCC_JIT_TYPE_LONG_LONG
412 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
413
414 /* Some other size, not corresponding to the C int types. */
415 /* To be written: support arbitrary other sizes, sharing by
416 memoizing at the recording::context level? */
417 gcc_unreachable ();
418}
419
420/* Create a recording::type instance and add it to this context's list
421 of mementos.
422
423 Implements the post-error-checking part of
424 gcc_jit_context_new_array_type. */
425
426recording::type *
427recording::context::new_array_type (recording::location *loc,
428 recording::type *element_type,
429 int num_elements)
430{
431 if (struct_ *s = element_type->dyn_cast_struct ())
432 if (!s->get_fields ())
433 {
434 add_error (NULL,
435 "cannot create an array of type %s"
436 " until the fields have been set",
437 s->get_name ()->c_str ());
438 return NULL;
439 }
440 recording::type *result =
441 new recording::array_type (this, loc, element_type, num_elements);
442 record (result);
443 return result;
444}
445
446/* Create a recording::field instance and add it to this context's list
447 of mementos.
448
449 Implements the post-error-checking part of
450 gcc_jit_context_new_field. */
451
452recording::field *
453recording::context::new_field (recording::location *loc,
454 recording::type *type,
455 const char *name)
456{
457 recording::field *result =
458 new recording::field (this, loc, type, new_string (name));
459 record (result);
460 return result;
461}
462
463/* Create a recording::struct_ instance and add it to this context's
464 list of mementos and list of compound types.
465
466 Implements the post-error-checking part of
467 gcc_jit_context_new_struct_type. */
468
469recording::struct_ *
470recording::context::new_struct_type (recording::location *loc,
471 const char *name)
472{
473 recording::struct_ *result = new struct_ (this, loc, new_string (name));
474 record (result);
475 m_compound_types.safe_push (result);
476 return result;
477}
478
479/* Create a recording::union_ instance and add it to this context's
480 list of mementos and list of compound types.
481
482 Implements the first post-error-checking part of
483 gcc_jit_context_new_union_type. */
484
485recording::union_ *
486recording::context::new_union_type (recording::location *loc,
487 const char *name)
488{
489 recording::union_ *result = new union_ (this, loc, new_string (name));
490 record (result);
491 m_compound_types.safe_push (result);
492 return result;
493}
494
495/* Create a recording::type instance and add it to this context's list
496 of mementos.
497
498 Implements the post-error-checking part of
499 gcc_jit_context_new_function_ptr_type. */
500
501recording::type *
502recording::context::new_function_ptr_type (recording::location *, /* unused loc */
503 recording::type *return_type,
504 int num_params,
505 recording::type **param_types,
506 int is_variadic)
507{
508 recording::function_type *fn_type =
509 new function_type (this,
510 return_type,
511 num_params,
512 param_types,
513 is_variadic);
514 record (fn_type);
515
516 /* Return a pointer-type to the the function type. */
517 return fn_type->get_pointer ();
518}
519
520/* Create a recording::param instance and add it to this context's list
521 of mementos.
522
523 Implements the post-error-checking part of
524 gcc_jit_context_new_param. */
525
526recording::param *
527recording::context::new_param (recording::location *loc,
528 recording::type *type,
529 const char *name)
530{
531 recording::param *result = new recording::param (this, loc, type, new_string (name));
532 record (result);
533 return result;
534}
535
536/* Create a recording::function instance and add it to this context's list
537 of mementos and list of functions.
538
539 Implements the post-error-checking part of
540 gcc_jit_context_new_function. */
541
542recording::function *
543recording::context::new_function (recording::location *loc,
544 enum gcc_jit_function_kind kind,
545 recording::type *return_type,
546 const char *name,
547 int num_params,
548 recording::param **params,
549 int is_variadic,
550 enum built_in_function builtin_id)
551{
552 recording::function *result =
553 new recording::function (this,
554 loc, kind, return_type,
555 new_string (name),
556 num_params, params, is_variadic,
557 builtin_id);
558 record (result);
559 m_functions.safe_push (result);
560
561 return result;
562}
563
564/* Get a recording::function instance, which is lazily-created and added
565 to the context's lists of mementos.
566
567 Implements the post-error-checking part of
568 gcc_jit_context_get_builtin_function. */
569
570recording::function *
571recording::context::get_builtin_function (const char *name)
572{
573 if (!m_builtins_manager)
574 m_builtins_manager = new builtins_manager (this);
575 return m_builtins_manager->get_builtin_function (name);
576}
577
578/* Create a recording::global instance and add it to this context's list
579 of mementos.
580
581 Implements the post-error-checking part of
582 gcc_jit_context_new_global. */
583
584recording::lvalue *
585recording::context::new_global (recording::location *loc,
586 recording::type *type,
587 const char *name)
588{
589 recording::lvalue *result =
590 new recording::global (this, loc, type, new_string (name));
591 record (result);
592 return result;
593}
594
595/* Create a recording::memento_of_new_rvalue_from_int instance and add
596 it to this context's list of mementos.
597
598 Implements the post-error-checking part of
599 gcc_jit_context_new_rvalue_from_int. */
600
601recording::rvalue *
602recording::context::new_rvalue_from_int (recording::type *type,
603 int value)
604{
605 recording::rvalue *result =
606 new memento_of_new_rvalue_from_int (this, NULL, type, value);
607 record (result);
608 return result;
609}
610
611/* Create a recording::memento_of_new_rvalue_from_double instance and
612 add it to this context's list of mementos.
613
614 Implements the post-error-checking part of
615 gcc_jit_context_new_rvalue_from_double. */
616
617recording::rvalue *
618recording::context::new_rvalue_from_double (recording::type *type,
619 double value)
620{
621 recording::rvalue *result =
622 new memento_of_new_rvalue_from_double (this, NULL, type, value);
623 record (result);
624 return result;
625}
626
627/* Create a recording::memento_of_new_rvalue_from_ptr instance and add
628 it to this context's list of mementos.
629
630 Implements the post-error-checking part of
631 gcc_jit_context_new_rvalue_from_ptr. */
632
633recording::rvalue *
634recording::context::new_rvalue_from_ptr (recording::type *type,
635 void *value)
636{
637 recording::rvalue *result =
638 new memento_of_new_rvalue_from_ptr (this, NULL, type, value);
639 record (result);
640 return result;
641}
642
643/* Create a recording::memento_of_new_string_literal instance and add it
644 to this context's list of mementos.
645
646 Implements the post-error-checking part of
647 gcc_jit_context_new_string_literal. */
648
649recording::rvalue *
650recording::context::new_string_literal (const char *value)
651{
652 recording::rvalue *result =
653 new memento_of_new_string_literal (this, NULL, new_string (value));
654 record (result);
655 return result;
656}
657
658/* Create a recording::unary_op instance and add it to this context's
659 list of mementos.
660
661 Implements the post-error-checking part of
662 gcc_jit_context_new_unary_op. */
663
664recording::rvalue *
665recording::context::new_unary_op (recording::location *loc,
666 enum gcc_jit_unary_op op,
667 recording::type *result_type,
668 recording::rvalue *a)
669{
670 recording::rvalue *result =
671 new unary_op (this, loc, op, result_type, a);
672 record (result);
673 return result;
674}
675
676/* Create a recording::binary_op instance and add it to this context's
677 list of mementos.
678
679 Implements the post-error-checking part of
680 gcc_jit_context_new_binary_op. */
681
682recording::rvalue *
683recording::context::new_binary_op (recording::location *loc,
684 enum gcc_jit_binary_op op,
685 recording::type *result_type,
686 recording::rvalue *a,
687 recording::rvalue *b)
688{
689 recording::rvalue *result =
690 new binary_op (this, loc, op, result_type, a, b);
691 record (result);
692 return result;
693}
694
695/* Create a recording::comparison instance and add it to this context's
696 list of mementos.
697
698 Implements the post-error-checking part of
699 gcc_jit_context_new_comparison. */
700
701recording::rvalue *
702recording::context::new_comparison (recording::location *loc,
703 enum gcc_jit_comparison op,
704 recording::rvalue *a,
705 recording::rvalue *b)
706{
707 recording::rvalue *result = new comparison (this, loc, op, a, b);
708 record (result);
709 return result;
710}
711
712/* Create a recording::cast instance and add it to this context's list
713 of mementos.
714
715 Implements the post-error-checking part of
716 gcc_jit_context_new_cast. */
717
718recording::rvalue *
719recording::context::new_cast (recording::location *loc,
720 recording::rvalue *expr,
721 recording::type *type_)
722{
723 recording::rvalue *result = new cast (this, loc, expr, type_);
724 record (result);
725 return result;
726}
727
728/* Create a recording::call instance and add it to this context's list
729 of mementos.
730
731 Implements the post-error-checking part of
732 gcc_jit_context_new_call. */
733
734recording::rvalue *
735recording::context::new_call (recording::location *loc,
736 function *func,
737 int numargs , recording::rvalue **args)
738{
739 recording::rvalue *result = new call (this, loc, func, numargs, args);
740 record (result);
741 return result;
742}
743
744/* Create a recording::call_through_ptr instance and add it to this
745 context's list of mementos.
746
747 Implements the post-error-checking part of
748 gcc_jit_context_new_call_through_ptr. */
749
750recording::rvalue *
751recording::context::new_call_through_ptr (recording::location *loc,
752 recording::rvalue *fn_ptr,
753 int numargs,
754 recording::rvalue **args)
755 {
756 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
757 record (result);
758 return result;
759}
760
761/* Create a recording::array_access instance and add it to this context's list
762 of mementos.
763
764 Implements the post-error-checking part of
765 gcc_jit_context_new_array_access. */
766
767recording::lvalue *
768recording::context::new_array_access (recording::location *loc,
769 recording::rvalue *ptr,
770 recording::rvalue *index)
771{
772 recording::lvalue *result = new array_access (this, loc, ptr, index);
773 record (result);
774 return result;
775}
776
777/* Set the given string option for this context, or add an error if
778 it's not recognized.
779
780 Implements the post-error-checking part of
781 gcc_jit_context_set_str_option. */
782
783void
784recording::context::set_str_option (enum gcc_jit_str_option opt,
785 const char *value)
786{
787 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
788 {
789 add_error (NULL,
790 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
791 return;
792 }
793 m_str_options[opt] = value;
794}
795
796/* Set the given integer option for this context, or add an error if
797 it's not recognized.
798
799 Implements the post-error-checking part of
800 gcc_jit_context_set_int_option. */
801
802void
803recording::context::set_int_option (enum gcc_jit_int_option opt,
804 int value)
805{
806 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
807 {
808 add_error (NULL,
809 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
810 return;
811 }
812 m_int_options[opt] = value;
813}
814
815/* Set the given boolean option for this context, or add an error if
816 it's not recognized.
817
818 Implements the post-error-checking part of
819 gcc_jit_context_set_bool_option. */
820
821void
822recording::context::set_bool_option (enum gcc_jit_bool_option opt,
823 int value)
824{
825 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
826 {
827 add_error (NULL,
828 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
829 return;
830 }
831 m_bool_options[opt] = value ? true : false;
832}
833
834/* This mutex guards gcc::jit::recording::context::compile, so that only
835 one thread can be accessing the bulk of GCC's state at once. */
836
837static pthread_mutex_t jit_mutex = PTHREAD_MUTEX_INITIALIZER;
838
839/* Validate this context, and if it passes, compile it within a
840 mutex.
841
842 Implements the post-error-checking part of
843 gcc_jit_context_compile. */
844
845result *
846recording::context::compile ()
847{
848 validate ();
849
850 if (errors_occurred ())
851 return NULL;
852
853 /* Acquire the big GCC mutex. */
854 pthread_mutex_lock (&jit_mutex);
855 gcc_assert (NULL == ::gcc::jit::active_playback_ctxt);
856
857 /* Set up a playback context. */
858 ::gcc::jit::playback::context replayer (this);
859 ::gcc::jit::active_playback_ctxt = &replayer;
860
861 result *result_obj = replayer.compile ();
862
863 /* Release the big GCC mutex. */
864 ::gcc::jit::active_playback_ctxt = NULL;
865 pthread_mutex_unlock (&jit_mutex);
866
867 return result_obj;
868}
869
870/* Format the given error using printf's conventions, print
871 it to stderr, and add it to the context. */
872
873void
874recording::context::add_error (location *loc, const char *fmt, ...)
875{
876 va_list ap;
877 va_start (ap, fmt);
878 add_error_va (loc, fmt, ap);
879 va_end (ap);
880}
881
882/* Format the given error using printf's conventions, print
883 it to stderr, and add it to the context. */
884
885void
886recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
887{
888 char *malloced_msg;
889 const char *errmsg;
890 bool has_ownership;
891
892 vasprintf (&malloced_msg, fmt, ap);
893 if (malloced_msg)
894 {
895 errmsg = malloced_msg;
896 has_ownership = true;
897 }
898 else
899 {
900 errmsg = "out of memory generating error message";
901 has_ownership = false;
902 }
903
904 const char *ctxt_progname =
905 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
906 if (!ctxt_progname)
907 ctxt_progname = "libgccjit.so";
908
909 if (loc)
910 fprintf (stderr, "%s: %s: error: %s\n",
911 ctxt_progname,
912 loc->get_debug_string (),
913 errmsg);
914 else
915 fprintf (stderr, "%s: error: %s\n",
916 ctxt_progname,
917 errmsg);
918
919 if (!m_error_count)
920 {
921 m_first_error_str = const_cast <char *> (errmsg);
922 m_owns_first_error_str = has_ownership;
923 }
924 else
925 if (has_ownership)
926 free (malloced_msg);
927
928 m_error_count++;
929}
930
931/* Get the message for the first error that occurred on this context, or
932 NULL if no errors have occurred on it.
933
934 Implements the post-error-checking part of
935 gcc_jit_context_get_first_error. */
936
937const char *
938recording::context::get_first_error () const
939{
940 return m_first_error_str;
941}
942
943/* Lazily generate and record a recording::type representing an opaque
944 struct named "FILE".
945
946 For use if client code tries to dereference the result of
947 get_type (GCC_JIT_TYPE_FILE_PTR). */
948
949recording::type *
950recording::context::get_opaque_FILE_type ()
951{
952 if (!m_FILE_type)
953 m_FILE_type = new_struct_type (NULL, "FILE");
954 return m_FILE_type;
955}
956
957/* Dump a C-like representation of the given context to the given path.
958 If UPDATE_LOCATIONS is true, update the locations within the
959 context's mementos to point to the dumpfile.
960
961 Implements the post-error-checking part of
962 gcc_jit_context_dump_to_file. */
963
964void
965recording::context::dump_to_file (const char *path, bool update_locations)
966{
967 int i;
968 dump d (*this, path, update_locations);
969
970 /* Forward declaration of structs and unions. */
971 compound_type *st;
972 FOR_EACH_VEC_ELT (m_compound_types, i, st)
973 {
974 d.write ("%s;\n\n", st->get_debug_string ());
975 }
976
977 /* Content of structs, where set. */
978 FOR_EACH_VEC_ELT (m_compound_types, i, st)
979 if (st->get_fields ())
980 {
981 st->get_fields ()->write_to_dump (d);
982 d.write ("\n");
983 }
984
985 function *fn;
986 FOR_EACH_VEC_ELT (m_functions, i, fn)
987 {
988 fn->write_to_dump (d);
989 }
990}
991
992/* This is a pre-compilation check for the context (and any parents).
993
994 Detect errors within the context, adding errors if any are found. */
995
996void
997recording::context::validate ()
998{
999 if (m_parent_ctxt)
1000 m_parent_ctxt->validate ();
1001
1002 int i;
1003 function *fn;
1004 FOR_EACH_VEC_ELT (m_functions, i, fn)
1005 fn->validate ();
1006}
1007
1008/* The implementation of class gcc::jit::recording::memento. */
1009
1010/* Get a (const char *) debug description of the given memento, by
1011 calling the pure-virtual make_debug_string hook, caching the
1012 result.
1013
1014 It is intended that this should only be called in debugging and
1015 error-handling paths, so this doesn't need to be particularly
1016 optimized. */
1017
1018const char *
1019recording::memento::get_debug_string ()
1020{
1021 if (!m_debug_string)
1022 m_debug_string = make_debug_string ();
1023 return m_debug_string->c_str ();
1024}
1025
1026/* Default implementation of recording::memento::write_to_dump, writing
1027 an indented form of the memento's debug string to the dump. */
1028
1029void
1030recording::memento::write_to_dump (dump &d)
1031{
1032 d.write(" %s\n", get_debug_string ());
1033}
1034
1035/* The implementation of class gcc::jit::recording::string. */
1036
1037/* Constructor for gcc::jit::recording::string::string, allocating a
1038 copy of the given text using new char[]. */
1039
1040recording::string::string (context *ctxt, const char *text)
1041 : memento (ctxt)
1042{
1043 m_len = strlen (text);
1044 m_buffer = new char[m_len + 1];
1045 strcpy (m_buffer, text);
1046}
1047
1048/* Destructor for gcc::jit::recording::string::string. */
1049
1050recording::string::~string ()
1051{
1052 delete[] m_buffer;
1053}
1054
1055/* Function for making gcc::jit::recording::string instances on a
1056 context via printf-style formatting.
1057
1058 It is intended that this should only be called in debugging and
1059 error-handling paths, so this doesn't need to be particularly
1060 optimized, hence the double-copy of the string is acceptable. */
1061
1062recording::string *
1063recording::string::from_printf (context *ctxt, const char *fmt, ...)
1064{
1065 va_list ap;
1066 char *buf = NULL;
1067 recording::string *result;
1068
1069 va_start (ap, fmt);
1070 vasprintf (&buf, fmt, ap);
1071 va_end (ap);
1072
1073 if (!buf)
1074 {
1075 ctxt->add_error (NULL, "malloc failure");
1076 return NULL;
1077 }
1078
1079 result = ctxt->new_string (buf);
1080 free (buf);
1081 return result;
1082}
1083
1084/* Implementation of recording::memento::make_debug_string for strings,
1085 wrapping the given string in quotes and escaping as necessary. */
1086
1087recording::string *
1088recording::string::make_debug_string ()
1089{
1090 /* Hack to avoid infinite recursion into strings when logging all
1091 mementos: don't re-escape strings: */
1092 if (m_buffer[0] == '"')
1093 return this;
1094
1095 /* Wrap in quotes and do escaping etc */
1096
1097 size_t sz = (1 /* opening quote */
1098 + (m_len * 2) /* each char might get escaped */
1099 + 1 /* closing quote */
1100 + 1); /* nil termintator */
1101 char *tmp = new char[sz];
1102 size_t len = 0;
1103
1104#define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1105 APPEND('"'); /* opening quote */
1106 for (size_t i = 0; i < m_len ; i++)
1107 {
1108 char ch = m_buffer[i];
1109 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
1110 APPEND('\\');
1111 APPEND(ch);
1112 }
1113 APPEND('"'); /* closing quote */
1114#undef APPEND
1115 tmp[len] = '\0'; /* nil termintator */
1116
1117 string *result = m_ctxt->new_string (tmp);
1118
1119 delete[] tmp;
1120 return result;
1121}
1122
1123/* The implementation of class gcc::jit::recording::location. */
1124
1125/* Implementation of recording::memento::replay_into for locations.
1126
1127 Create a new playback::location and store it into the
1128 recording::location's m_playback_obj field. */
1129
1130void
1131recording::location::replay_into (replayer *r)
1132{
1133 m_playback_obj = r->new_location (this,
1134 m_filename->c_str (),
1135 m_line,
1136 m_column);
1137}
1138
1139/* Implementation of recording::memento::make_debug_string for locations,
1140 turning them into the usual form:
1141 FILENAME:LINE:COLUMN
1142 like we do when emitting diagnostics. */
1143
1144recording::string *
1145recording::location::make_debug_string ()
1146{
1147 return string::from_printf (m_ctxt,
1148 "%s:%i:%i",
1149 m_filename->c_str (), m_line, m_column);
1150}
1151
1152/* The implementation of class gcc::jit::recording::type. */
1153
1154/* Given a type T, get the type T*.
1155
1156 If this doesn't already exist, generate a new memento_of_get_pointer
1157 instance and add it to this type's context's list of mementos.
1158
1159 Otherwise, use the cached type.
1160
1161 Implements the post-error-checking part of
1162 gcc_jit_type_get_pointer. */
1163
1164recording::type *
1165recording::type::get_pointer ()
1166{
1167 if (!m_pointer_to_this_type)
1168 {
1169 m_pointer_to_this_type = new memento_of_get_pointer (this);
1170 m_ctxt->record (m_pointer_to_this_type);
1171 }
1172 return m_pointer_to_this_type;
1173}
1174
1175/* Given a type T, get the type const T.
1176
1177 Implements the post-error-checking part of
1178 gcc_jit_type_get_const. */
1179
1180recording::type *
1181recording::type::get_const ()
1182{
1183 recording::type *result = new memento_of_get_const (this);
1184 m_ctxt->record (result);
1185 return result;
1186}
1187
1188/* Given a type T, get the type volatile T.
1189
1190 Implements the post-error-checking part of
1191 gcc_jit_type_get_volatile. */
1192
1193recording::type *
1194recording::type::get_volatile ()
1195{
1196 recording::type *result = new memento_of_get_volatile (this);
1197 m_ctxt->record (result);
1198 return result;
1199}
1200
1201/* Implementation of pure virtual hook recording::type::dereference for
1202 recording::memento_of_get_type. */
1203
1204recording::type *
1205recording::memento_of_get_type::dereference ()
1206{
1207 switch (m_kind)
1208 {
1209 default: gcc_unreachable ();
1210
1211 case GCC_JIT_TYPE_VOID:
1212 return NULL;
1213
1214 case GCC_JIT_TYPE_VOID_PTR:
1215 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
1216
1217 case GCC_JIT_TYPE_BOOL:
1218 case GCC_JIT_TYPE_CHAR:
1219 case GCC_JIT_TYPE_SIGNED_CHAR:
1220 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1221 case GCC_JIT_TYPE_SHORT:
1222 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1223 case GCC_JIT_TYPE_INT:
1224 case GCC_JIT_TYPE_UNSIGNED_INT:
1225 case GCC_JIT_TYPE_LONG:
1226 case GCC_JIT_TYPE_UNSIGNED_LONG:
1227 case GCC_JIT_TYPE_LONG_LONG:
1228 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1229 case GCC_JIT_TYPE_FLOAT:
1230 case GCC_JIT_TYPE_DOUBLE:
1231 case GCC_JIT_TYPE_LONG_DOUBLE:
1232 /* Not a pointer: */
1233 return NULL;
1234
1235 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1236 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
1237
1238 case GCC_JIT_TYPE_SIZE_T:
1239 /* Not a pointer: */
1240 return NULL;
1241
1242 case GCC_JIT_TYPE_FILE_PTR:
1243 /* Give the client code back an opaque "struct FILE". */
1244 return m_ctxt->get_opaque_FILE_type ();
1245 }
1246}
1247
1248/* Implementation of pure virtual hook recording::type::is_int for
1249 recording::memento_of_get_type. */
1250
1251bool
1252recording::memento_of_get_type::is_int () const
1253{
1254 switch (m_kind)
1255 {
1256 default: gcc_unreachable ();
1257
1258 case GCC_JIT_TYPE_VOID:
1259 return false;
1260
1261 case GCC_JIT_TYPE_VOID_PTR:
1262 return false;
1263
1264 case GCC_JIT_TYPE_BOOL:
1265 return false;
1266
1267 case GCC_JIT_TYPE_CHAR:
1268 case GCC_JIT_TYPE_SIGNED_CHAR:
1269 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1270 case GCC_JIT_TYPE_SHORT:
1271 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1272 case GCC_JIT_TYPE_INT:
1273 case GCC_JIT_TYPE_UNSIGNED_INT:
1274 case GCC_JIT_TYPE_LONG:
1275 case GCC_JIT_TYPE_UNSIGNED_LONG:
1276 case GCC_JIT_TYPE_LONG_LONG:
1277 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1278 return true;
1279
1280 case GCC_JIT_TYPE_FLOAT:
1281 case GCC_JIT_TYPE_DOUBLE:
1282 case GCC_JIT_TYPE_LONG_DOUBLE:
1283 return false;
1284
1285 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1286 return false;
1287
1288 case GCC_JIT_TYPE_SIZE_T:
1289 return true;
1290
1291 case GCC_JIT_TYPE_FILE_PTR:
1292 return false;
1293 }
1294}
1295
1296/* Implementation of pure virtual hook recording::type::is_float for
1297 recording::memento_of_get_type. */
1298
1299bool
1300recording::memento_of_get_type::is_float () const
1301{
1302 switch (m_kind)
1303 {
1304 default: gcc_unreachable ();
1305
1306 case GCC_JIT_TYPE_VOID:
1307 return false;
1308
1309 case GCC_JIT_TYPE_VOID_PTR:
1310 return false;
1311
1312 case GCC_JIT_TYPE_BOOL:
1313 return false;
1314
1315 case GCC_JIT_TYPE_CHAR:
1316 case GCC_JIT_TYPE_SIGNED_CHAR:
1317 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1318 case GCC_JIT_TYPE_SHORT:
1319 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1320 case GCC_JIT_TYPE_INT:
1321 case GCC_JIT_TYPE_UNSIGNED_INT:
1322 case GCC_JIT_TYPE_LONG:
1323 case GCC_JIT_TYPE_UNSIGNED_LONG:
1324 case GCC_JIT_TYPE_LONG_LONG:
1325 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1326 return false;
1327
1328 case GCC_JIT_TYPE_FLOAT:
1329 case GCC_JIT_TYPE_DOUBLE:
1330 case GCC_JIT_TYPE_LONG_DOUBLE:
1331 return true;
1332
1333 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1334 return false;
1335
1336 case GCC_JIT_TYPE_SIZE_T:
1337 return false;
1338
1339 case GCC_JIT_TYPE_FILE_PTR:
1340 return false;
1341 }
1342}
1343
1344/* Implementation of pure virtual hook recording::type::is_bool for
1345 recording::memento_of_get_type. */
1346
1347bool
1348recording::memento_of_get_type::is_bool () const
1349{
1350 switch (m_kind)
1351 {
1352 default: gcc_unreachable ();
1353
1354 case GCC_JIT_TYPE_VOID:
1355 return false;
1356
1357 case GCC_JIT_TYPE_VOID_PTR:
1358 return false;
1359
1360 case GCC_JIT_TYPE_BOOL:
1361 return true;
1362
1363 case GCC_JIT_TYPE_CHAR:
1364 case GCC_JIT_TYPE_SIGNED_CHAR:
1365 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1366 case GCC_JIT_TYPE_SHORT:
1367 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1368 case GCC_JIT_TYPE_INT:
1369 case GCC_JIT_TYPE_UNSIGNED_INT:
1370 case GCC_JIT_TYPE_LONG:
1371 case GCC_JIT_TYPE_UNSIGNED_LONG:
1372 case GCC_JIT_TYPE_LONG_LONG:
1373 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1374 return false;
1375
1376 case GCC_JIT_TYPE_FLOAT:
1377 case GCC_JIT_TYPE_DOUBLE:
1378 case GCC_JIT_TYPE_LONG_DOUBLE:
1379 return false;
1380
1381 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1382 return false;
1383
1384 case GCC_JIT_TYPE_SIZE_T:
1385 return false;
1386
1387 case GCC_JIT_TYPE_FILE_PTR:
1388 return false;
1389 }
1390}
1391
1392/* Implementation of pure virtual hook recording::memento::replay_into
1393 for recording::memento_of_get_type. */
1394
1395void
1396recording::memento_of_get_type::replay_into (replayer *r)
1397{
1398 set_playback_obj (r->get_type (m_kind));
1399}
1400
1401/* The implementation of class gcc::jit::recording::memento_of_get_type. */
1402
1403/* Descriptive strings for each of enum gcc_jit_types. */
1404
1405static const char * const get_type_strings[] = {
1406 "void", /* GCC_JIT_TYPE_VOID */
1407 "void *", /* GCC_JIT_TYPE_VOID_PTR */
1408
1409 "bool", /* GCC_JIT_TYPE_BOOL */
1410
1411 "char", /* GCC_JIT_TYPE_CHAR */
1412 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
1413 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
1414
1415 "short", /* GCC_JIT_TYPE_SHORT */
1416 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
1417
1418 "int", /* GCC_JIT_TYPE_INT */
1419 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
1420
1421 "long", /* GCC_JIT_TYPE_LONG */
1422 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
1423
1424 "long long", /* GCC_JIT_TYPE_LONG_LONG */
1425 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
1426
1427 "float", /* GCC_JIT_TYPE_FLOAT */
1428 "double", /* GCC_JIT_TYPE_DOUBLE */
1429 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
1430
1431 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
1432
1433 "size_t", /* GCC_JIT_TYPE_SIZE_T */
1434
1435 "FILE *" /* GCC_JIT_TYPE_FILE_PTR */
1436
1437};
1438
1439/* Implementation of recording::memento::make_debug_string for
1440 results of get_type, using a simple table of type names. */
1441
1442recording::string *
1443recording::memento_of_get_type::make_debug_string ()
1444{
1445 return m_ctxt->new_string (get_type_strings[m_kind]);
1446}
1447
1448/* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
1449
1450/* Override of default implementation of
1451 recording::type::accepts_writes_from for get_pointer.
1452
1453 Require a pointer type, and allowing writes to
1454 (const T *) from a (T*), but not the other way around. */
1455
1456bool
1457recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
1458{
1459 /* Must be a pointer type: */
1460 type *rtype_points_to = rtype->is_pointer ();
1461 if (!rtype_points_to)
1462 return false;
1463
1464 /* It's OK to assign to a (const T *) from a (T *). */
1465 return m_other_type->unqualified ()
1466 ->accepts_writes_from (rtype_points_to);
1467}
1468
1469/* Implementation of pure virtual hook recording::memento::replay_into
1470 for recording::memento_of_get_pointer. */
1471
1472void
1473recording::memento_of_get_pointer::replay_into (replayer *)
1474{
1475 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
1476}
1477
1478/* Implementation of recording::memento::make_debug_string for
1479 results of get_pointer, adding " *" to the underlying type,
1480 with special-casing to handle function pointer types. */
1481
1482recording::string *
1483recording::memento_of_get_pointer::make_debug_string ()
1484{
1485 /* Special-case function pointer types, to put the "*" in parens between
1486 the return type and the params (for one level of dereferencing, at
1487 least). */
1488 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
1489 return fn_type->make_debug_string_with_ptr ();
1490
1491 return string::from_printf (m_ctxt,
1492 "%s *", m_other_type->get_debug_string ());
1493}
1494
1495/* The implementation of class gcc::jit::recording::memento_of_get_const. */
1496
1497/* Implementation of pure virtual hook recording::memento::replay_into
1498 for recording::memento_of_get_const. */
1499
1500void
1501recording::memento_of_get_const::replay_into (replayer *)
1502{
1503 set_playback_obj (m_other_type->playback_type ()->get_const ());
1504}
1505
1506/* Implementation of recording::memento::make_debug_string for
1507 results of get_const, prepending "const ". */
1508
1509recording::string *
1510recording::memento_of_get_const::make_debug_string ()
1511{
1512 return string::from_printf (m_ctxt,
1513 "const %s", m_other_type->get_debug_string ());
1514}
1515
1516/* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
1517
1518/* Implementation of pure virtual hook recording::memento::replay_into
1519 for recording::memento_of_get_volatile. */
1520
1521void
1522recording::memento_of_get_volatile::replay_into (replayer *)
1523{
1524 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
1525}
1526
1527/* Implementation of recording::memento::make_debug_string for
1528 results of get_volatile, prepending "volatile ". */
1529
1530recording::string *
1531recording::memento_of_get_volatile::make_debug_string ()
1532{
1533 return string::from_printf (m_ctxt,
1534 "volatile %s", m_other_type->get_debug_string ());
1535}
1536
1537/* The implementation of class gcc::jit::recording::array_type */
1538
1539/* Implementation of pure virtual hook recording::type::dereference for
1540 recording::array_type. */
1541
1542recording::type *
1543recording::array_type::dereference ()
1544{
1545 return m_element_type;
1546}
1547
1548/* Implementation of pure virtual hook recording::memento::replay_into
1549 for recording::array_type. */
1550
1551void
1552recording::array_type::replay_into (replayer *r)
1553{
1554 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
1555 m_element_type->playback_type (),
1556 m_num_elements));
1557}
1558
1559/* Implementation of recording::memento::make_debug_string for
1560 results of new_array_type. */
1561
1562recording::string *
1563recording::array_type::make_debug_string ()
1564{
1565 return string::from_printf (m_ctxt,
1566 "%s[%d]",
1567 m_element_type->get_debug_string (),
1568 m_num_elements);
1569}
1570
1571/* The implementation of class gcc::jit::recording::function_type */
1572
1573/* Constructor for gcc::jit::recording::function_type. */
1574
1575recording::function_type::function_type (context *ctxt,
1576 type *return_type,
1577 int num_params,
1578 type **param_types,
1579 int is_variadic)
1580: type (ctxt),
1581 m_return_type (return_type),
1582 m_param_types (),
1583 m_is_variadic (is_variadic)
1584{
1585 for (int i = 0; i< num_params; i++)
1586 m_param_types.safe_push (param_types[i]);
1587}
1588
1589/* Implementation of pure virtual hook recording::type::dereference for
1590 recording::function_type. */
1591
1592recording::type *
1593recording::function_type::dereference ()
1594{
1595 return NULL;
1596}
1597
1598/* Implementation of pure virtual hook recording::memento::replay_into
1599 for recording::function_type. */
1600
1601void
1602recording::function_type::replay_into (replayer *r)
1603{
1604 /* Convert m_param_types to a vec of playback type. */
b957b2e0 1605 auto_vec <playback::type *> param_types;
35485da9
DM
1606 int i;
1607 recording::type *type;
1608 param_types.create (m_param_types.length ());
1609 FOR_EACH_VEC_ELT (m_param_types, i, type)
1610 param_types.safe_push (type->playback_type ());
1611
1612 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
1613 &param_types,
1614 m_is_variadic));
1615}
1616
1617/* Special-casing for make_debug_string for get_pointer results for
1618 handling (one level) of pointers to functions. */
1619
1620recording::string *
1621recording::function_type::make_debug_string_with_ptr ()
1622{
1623 return make_debug_string_with ("(*) ");
1624}
1625
1626/* Implementation of recording::memento::make_debug_string for
1627 results of new_function_type. */
1628
1629recording::string *
1630recording::function_type::make_debug_string ()
1631{
1632 return make_debug_string_with ("");
1633}
1634
1635/* Build a debug string representation of the form:
1636
1637 RESULT_TYPE INSERT (PARAM_TYPES)
1638
1639 for use when handling 0 and 1 level of indirection to this
1640 function type. */
1641
1642recording::string *
1643recording::function_type::make_debug_string_with (const char *insert)
1644{
1645 /* First, build a buffer for the arguments. */
1646 /* Calculate length of said buffer. */
1647 size_t sz = 1; /* nil terminator */
1648 for (unsigned i = 0; i< m_param_types.length (); i++)
1649 {
1650 sz += strlen (m_param_types[i]->get_debug_string ());
1651 sz += 2; /* ", " separator */
1652 }
1653 if (m_is_variadic)
1654 sz += 5; /* ", ..." separator and ellipsis */
1655
1656 /* Now allocate and populate the buffer. */
1657 char *argbuf = new char[sz];
1658 size_t len = 0;
1659
1660 for (unsigned i = 0; i< m_param_types.length (); i++)
1661 {
1662 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
1663 len += strlen (m_param_types[i]->get_debug_string ());
1664 if (i + 1 < m_param_types.length ())
1665 {
1666 strcpy (argbuf + len, ", ");
1667 len += 2;
1668 }
1669 }
1670 if (m_is_variadic)
1671 {
1672 if (m_param_types.length ())
1673 {
1674 strcpy (argbuf + len, ", ");
1675 len += 2;
1676 }
1677 strcpy (argbuf + len, "...");
1678 len += 3;
1679 }
1680 argbuf[len] = '\0';
1681
1682 /* ...and use it to get the string for the call as a whole. */
1683 string *result = string::from_printf (m_ctxt,
1684 "%s %s(%s)",
1685 m_return_type->get_debug_string (),
1686 insert,
1687 argbuf);
1688
1689 delete[] argbuf;
1690
1691 return result;
1692}
1693
1694/* The implementation of class gcc::jit::recording::field. */
1695
1696/* Implementation of pure virtual hook recording::memento::replay_into
1697 for recording::field. */
1698
1699void
1700recording::field::replay_into (replayer *r)
1701{
1702 set_playback_obj (r->new_field (playback_location (r, m_loc),
1703 m_type->playback_type (),
1704 playback_string (m_name)));
1705}
1706
1707/* Override the default implementation of
1708 recording::memento::write_to_dump. Dump each field
1709 by dumping a line of the form:
1710 TYPE NAME;
1711 so that we can build up a struct/union field-byfield. */
1712
1713void
1714recording::field::write_to_dump (dump &d)
1715{
1716 d.write (" %s %s;\n",
1717 m_type->get_debug_string (),
1718 m_name->c_str ());
1719}
1720
1721/* Implementation of recording::memento::make_debug_string for
1722 results of new_field. */
1723
1724recording::string *
1725recording::field::make_debug_string ()
1726{
1727 return m_name;
1728}
1729
1730/* The implementation of class gcc::jit::recording::compound_type */
1731
1732/* The constructor for gcc::jit::recording::compound_type. */
1733
1734recording::compound_type::compound_type (context *ctxt,
1735 location *loc,
1736 string *name)
1737: type (ctxt),
1738 m_loc (loc),
1739 m_name (name),
1740 m_fields (NULL)
1741{
1742}
1743
1744/* Set the fields of a compound type.
1745
1746 Implements the post-error-checking part of
1747 gcc_jit_struct_set_fields, and is also used by
1748 gcc_jit_context_new_union_type. */
1749
1750void
1751recording::compound_type::set_fields (location *loc,
1752 int num_fields,
1753 field **field_array)
1754{
1755 m_loc = loc;
1756 gcc_assert (NULL == m_fields);
1757
1758 m_fields = new fields (this, num_fields, field_array);
1759 m_ctxt->record (m_fields);
1760}
1761
1762/* Implementation of pure virtual hook recording::type::dereference for
1763 recording::compound_type. */
1764
1765recording::type *
1766recording::compound_type::dereference ()
1767{
1768 return NULL; /* not a pointer */
1769}
1770
1771/* The implementation of class gcc::jit::recording::struct_. */
1772
1773/* The constructor for gcc::jit::recording::struct_. */
1774
1775recording::struct_::struct_ (context *ctxt,
1776 location *loc,
1777 string *name)
1778: compound_type (ctxt, loc, name)
1779{
1780}
1781
1782/* Implementation of pure virtual hook recording::memento::replay_into
1783 for recording::struct_. */
1784
1785void
1786recording::struct_::replay_into (replayer *r)
1787{
1788 set_playback_obj (
1789 r->new_compound_type (playback_location (r, get_loc ()),
1790 get_name ()->c_str (),
1791 true /* is_struct */));
1792}
1793
1794/* Implementation of recording::memento::make_debug_string for
1795 structs. */
1796
1797recording::string *
1798recording::struct_::make_debug_string ()
1799{
1800 return string::from_printf (m_ctxt,
1801 "struct %s", get_name ()->c_str ());
1802}
1803
1804/* The implementation of class gcc::jit::recording::union_. */
1805
1806/* The constructor for gcc::jit::recording::union_. */
1807
1808recording::union_::union_ (context *ctxt,
1809 location *loc,
1810 string *name)
1811: compound_type (ctxt, loc, name)
1812{
1813}
1814
1815/* Implementation of pure virtual hook recording::memento::replay_into
1816 for recording::union_. */
1817
1818void
1819recording::union_::replay_into (replayer *r)
1820{
1821 set_playback_obj (
1822 r->new_compound_type (playback_location (r, get_loc ()),
1823 get_name ()->c_str (),
1824 false /* is_struct */));
1825}
1826
1827/* Implementation of recording::memento::make_debug_string for
1828 unions. */
1829
1830recording::string *
1831recording::union_::make_debug_string ()
1832{
1833 return string::from_printf (m_ctxt,
1834 "union %s", get_name ()->c_str ());
1835}
1836
1837/* The implementation of class gcc::jit::recording::fields. */
1838
1839/* The constructor for gcc::jit::recording::fields. */
1840
1841recording::fields::fields (compound_type *struct_or_union,
1842 int num_fields,
1843 field **fields)
1844: memento (struct_or_union->m_ctxt),
1845 m_struct_or_union (struct_or_union),
1846 m_fields ()
1847{
1848 for (int i = 0; i < num_fields; i++)
1849 {
1850 gcc_assert (fields[i]->get_container () == NULL);
1851 fields[i]->set_container (m_struct_or_union);
1852 m_fields.safe_push (fields[i]);
1853 }
1854}
1855
1856/* Implementation of pure virtual hook recording::memento::replay_into
1857 for recording::fields. */
1858
1859void
1860recording::fields::replay_into (replayer *)
1861{
b957b2e0 1862 auto_vec<playback::field *> playback_fields;
35485da9
DM
1863 playback_fields.create (m_fields.length ());
1864 for (unsigned i = 0; i < m_fields.length (); i++)
1865 playback_fields.safe_push (m_fields[i]->playback_field ());
b957b2e0 1866 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
35485da9
DM
1867}
1868
1869/* Override the default implementation of
1870 recording::memento::write_to_dump by writing a union/struct
1871 declaration of this form:
1872
1873 struct/union NAME {
1874 TYPE_1 NAME_1;
1875 TYPE_2 NAME_2;
1876 ....
1877 TYPE_N NAME_N;
1878 };
1879
1880 to the dump. */
1881
1882void
1883recording::fields::write_to_dump (dump &d)
1884{
1885 int i;
1886 field *f;
1887
1888 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
1889 FOR_EACH_VEC_ELT (m_fields, i, f)
1890 f->write_to_dump (d);
1891 d.write ("};\n");
1892}
1893
1894/* Implementation of recording::memento::make_debug_string for
1895 field tables. */
1896
1897recording::string *
1898recording::fields::make_debug_string ()
1899{
1900 return string::from_printf (m_ctxt,
1901 "fields");
1902}
1903
1904/* The implementation of class gcc::jit::recording::rvalue. */
1905
1906/* Create a recording::access_field_rvalue instance and add it to
1907 the rvalue's context's list of mementos.
1908
1909 Implements the post-error-checking part of
1910 gcc_jit_rvalue_access_field. */
1911
1912recording::rvalue *
1913recording::rvalue::access_field (recording::location *loc,
1914 field *field)
1915{
1916 recording::rvalue *result =
1917 new access_field_rvalue (m_ctxt, loc, this, field);
1918 m_ctxt->record (result);
1919 return result;
1920}
1921
1922/* Create a recording::dereference_field_rvalue instance and add it to
1923 the rvalue's context's list of mementos.
1924
1925 Implements the post-error-checking part of
1926 gcc_jit_rvalue_dereference_field. */
1927
1928recording::lvalue *
1929recording::rvalue::dereference_field (recording::location *loc,
1930 field *field)
1931{
1932 recording::lvalue *result =
1933 new dereference_field_rvalue (m_ctxt, loc, this, field);
1934 m_ctxt->record (result);
1935 return result;
1936}
1937
1938/* Create a recording::dereference_rvalue instance and add it to the
1939 rvalue's context's list of mementos.
1940
1941 Implements the post-error-checking part of
1942 gcc_jit_rvalue_dereference. */
1943
1944recording::lvalue *
1945recording::rvalue::dereference (recording::location *loc)
1946{
1947 recording::lvalue *result =
1948 new dereference_rvalue (m_ctxt, loc, this);
1949 m_ctxt->record (result);
1950 return result;
1951}
1952
1953/* The implementation of class gcc::jit::recording::lvalue. */
1954
1955/* Create a recording::new_access_field_of_lvalue instance and add it to
1956 the lvalue's context's list of mementos.
1957
1958 Implements the post-error-checking part of
1959 gcc_jit_lvalue_access_field. */
1960
1961recording::lvalue *
1962recording::lvalue::access_field (recording::location *loc,
1963 field *field)
1964{
1965 recording::lvalue *result =
1966 new access_field_of_lvalue (m_ctxt, loc, this, field);
1967 m_ctxt->record (result);
1968 return result;
1969}
1970
1971/* Create a recording::get_address_of_lvalue instance and add it to
1972 the lvalue's context's list of mementos.
1973
1974 Implements the post-error-checking part of
1975 gcc_jit_lvalue_get_address. */
1976
1977recording::rvalue *
1978recording::lvalue::get_address (recording::location *loc)
1979{
1980 recording::rvalue *result =
1981 new get_address_of_lvalue (m_ctxt, loc, this);
1982 m_ctxt->record (result);
1983 return result;
1984}
1985
1986/* The implementation of class gcc::jit::recording::param. */
1987
1988/* Implementation of pure virtual hook recording::memento::replay_into
1989 for recording::param. */
1990
1991void
1992recording::param::replay_into (replayer *r)
1993{
1994 set_playback_obj (r->new_param (playback_location (r, m_loc),
1995 m_type->playback_type (),
1996 m_name->c_str ()));
1997}
1998
1999
2000/* The implementation of class gcc::jit::recording::function. */
2001
2002/* gcc::jit::recording::function's constructor. */
2003
2004recording::function::function (context *ctxt,
2005 recording::location *loc,
2006 enum gcc_jit_function_kind kind,
2007 type *return_type,
2008 recording::string *name,
2009 int num_params,
2010 recording::param **params,
2011 int is_variadic,
2012 enum built_in_function builtin_id)
2013: memento (ctxt),
2014 m_loc (loc),
2015 m_kind (kind),
2016 m_return_type (return_type),
2017 m_name (name),
2018 m_params (),
2019 m_is_variadic (is_variadic),
2020 m_builtin_id (builtin_id),
2021 m_locals (),
2022 m_blocks ()
2023{
2024 for (int i = 0; i< num_params; i++)
2025 m_params.safe_push (params[i]);
2026}
2027
2028/* Implementation of pure virtual hook recording::memento::replay_into
2029 for recording::function. */
2030
2031void
2032recording::function::replay_into (replayer *r)
2033{
2034 /* Convert m_params to a vec of playback param. */
b957b2e0 2035 auto_vec <playback::param *> params;
35485da9
DM
2036 int i;
2037 recording::param *param;
2038 params.create (m_params.length ());
2039 FOR_EACH_VEC_ELT (m_params, i, param)
2040 params.safe_push (param->playback_param ());
2041
2042 set_playback_obj (r->new_function (playback_location (r, m_loc),
2043 m_kind,
2044 m_return_type->playback_type (),
2045 m_name->c_str (),
2046 &params,
2047 m_is_variadic,
2048 m_builtin_id));
2049}
2050
2051/* Create a recording::local instance and add it to
2052 the functions's context's list of mementos, and to the function's
2053 list of locals.
2054
2055 Implements the post-error-checking part of
2056 gcc_jit_function_new_local. */
2057
2058recording::lvalue *
2059recording::function::new_local (recording::location *loc,
2060 type *type,
2061 const char *name)
2062{
2063 local *result = new local (this, loc, type, new_string (name));
2064 m_ctxt->record (result);
2065 m_locals.safe_push (result);
2066 return result;
2067}
2068
2069/* Create a recording::block instance and add it to
2070 the functions's context's list of mementos, and to the function's
2071 list of blocks.
2072
2073 Implements the post-error-checking part of
2074 gcc_jit_function_new_block. */
2075
2076recording::block*
2077recording::function::new_block (const char *name)
2078{
2079 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
2080
2081 recording::block *result =
2082 new recording::block (this, m_blocks.length (), new_string (name));
2083 m_ctxt->record (result);
2084 m_blocks.safe_push (result);
2085 return result;
2086}
2087
2088/* Override the default implementation of
2089 recording::memento::write_to_dump by dumping a C-like
2090 representation of the function; either like a prototype
2091 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
2092 all other kinds of function. */
2093
2094void
2095recording::function::write_to_dump (dump &d)
2096{
2097 switch (m_kind)
2098 {
2099 default: gcc_unreachable ();
2100 case GCC_JIT_FUNCTION_EXPORTED:
2101 case GCC_JIT_FUNCTION_IMPORTED:
2102 d.write ("extern ");
2103 break;
2104 case GCC_JIT_FUNCTION_INTERNAL:
2105 d.write ("static ");
2106 break;
2107 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
2108 d.write ("static inline ");
2109 break;
2110 }
2111 d.write ("%s\n", m_return_type->get_debug_string ());
2112
2113 if (d.update_locations ())
2114 m_loc = d.make_location ();
2115
2116 d.write ("%s (", get_debug_string ());
2117
2118 int i;
2119 recording::param *param;
2120 FOR_EACH_VEC_ELT (m_params, i, param)
2121 {
2122 if (i > 0)
2123 d.write (", ");
2124 d.write ("%s %s",
2125 param->get_type ()->get_debug_string (),
2126 param->get_debug_string ());
2127 }
2128 d.write (")");
2129 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
2130 {
2131 d.write ("; /* (imported) */\n\n");
2132 }
2133 else
2134 {
2135 int i;
2136 local *var = NULL;
2137 block *b;
2138 d.write ("\n{\n");
2139
2140 /* Write locals: */
2141 FOR_EACH_VEC_ELT (m_locals, i, var)
2142 var->write_to_dump (d);
2143 if (m_locals.length ())
2144 d.write ("\n");
2145
2146 /* Write each block: */
2147 FOR_EACH_VEC_ELT (m_blocks, i, b)
2148 {
2149 if (i > 0)
2150 d.write ("\n");
2151 b->write_to_dump (d);
2152 }
2153
2154 d.write ("}\n\n");
2155 }
2156}
2157
2158/* Pre-compilation validation of a function, for those things we can't
2159 check until the context is (supposedly) fully-populated. */
2160
2161void
2162recording::function::validate ()
2163{
2164 /* Complain about empty functions with non-void return type. */
2165 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
2166 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
2167 if (0 == m_blocks.length ())
2168 m_ctxt->add_error (m_loc,
2169 "function %s returns non-void (type: %s)"
2170 " but has no blocks",
2171 get_debug_string (),
2172 m_return_type->get_debug_string ());
2173
2174 /* Check that all blocks are terminated. */
2175 int num_invalid_blocks = 0;
2176 {
2177 int i;
2178 block *b;
2179
2180 FOR_EACH_VEC_ELT (m_blocks, i, b)
2181 if (!b->validate ())
2182 num_invalid_blocks++;
2183 }
2184
2185 /* Check that all blocks are reachable. */
2186 if (m_blocks.length () > 0 && 0 == num_invalid_blocks)
2187 {
2188 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
2189 flag, starting at the initial block. */
79cafc7a 2190 auto_vec<block *> worklist (m_blocks.length ());
35485da9
DM
2191 worklist.safe_push (m_blocks[0]);
2192 while (worklist.length () > 0)
2193 {
2194 block *b = worklist.pop ();
2195 b->m_is_reachable = true;
2196
2197 /* Add successor blocks that aren't yet marked to the worklist. */
2198 /* We checked that each block has a terminating statement above . */
2199 block *next1, *next2;
2200 int n = b->get_successor_blocks (&next1, &next2);
2201 switch (n)
2202 {
2203 default:
2204 gcc_unreachable ();
2205 case 2:
2206 if (!next2->m_is_reachable)
2207 worklist.safe_push (next2);
2208 /* fallthrough */
2209 case 1:
2210 if (!next1->m_is_reachable)
2211 worklist.safe_push (next1);
2212 break;
2213 case 0:
2214 break;
2215 }
2216 }
2217
2218 /* Now complain about any blocks that haven't been marked. */
2219 {
2220 int i;
2221 block *b;
2222 FOR_EACH_VEC_ELT (m_blocks, i, b)
2223 if (!b->m_is_reachable)
2224 m_ctxt->add_error (b->get_loc (),
2225 "unreachable block: %s",
2226 b->get_debug_string ());
2227 }
2228 }
2229}
2230
2231/* Implements the post-error-checking part of
2232 gcc_jit_function_dump_to_dot. */
2233
2234void
2235recording::function::dump_to_dot (const char *path)
2236{
2237 FILE *fp = fopen (path, "w");
2238 if (!fp)
2239 return;
2240
2241 pretty_printer the_pp;
2242 the_pp.buffer->stream = fp;
2243
2244 pretty_printer *pp = &the_pp;
2245
2246 pp_printf (pp,
2247 "digraph %s {\n", get_debug_string ());
2248
2249 /* Blocks: */
2250 {
2251 int i;
2252 block *b;
2253 FOR_EACH_VEC_ELT (m_blocks, i, b)
2254 b->dump_to_dot (pp);
2255 }
2256
2257 /* Edges: */
2258 {
2259 int i;
2260 block *b;
2261 FOR_EACH_VEC_ELT (m_blocks, i, b)
2262 b->dump_edges_to_dot (pp);
2263 }
2264
2265 pp_printf (pp, "}\n");
2266 pp_flush (pp);
2267 fclose (fp);
2268}
2269
2270/* Implementation of recording::memento::make_debug_string for
2271 functions. */
2272
2273recording::string *
2274recording::function::make_debug_string ()
2275{
2276 return m_name;
2277}
2278
2279/* The implementation of class gcc::jit::recording::block. */
2280
2281/* Create a recording::eval instance and add it to
2282 the block's context's list of mementos, and to the block's
2283 list of statements.
2284
2285 Implements the post-error-checking part of
2286 gcc_jit_block_add_eval. */
2287
2288void
2289recording::block::add_eval (recording::location *loc,
2290 recording::rvalue *rvalue)
2291{
2292 statement *result = new eval (this, loc, rvalue);
2293 m_ctxt->record (result);
2294 m_statements.safe_push (result);
2295}
2296
2297/* Create a recording::assignment instance and add it to
2298 the block's context's list of mementos, and to the block's
2299 list of statements.
2300
2301 Implements the post-error-checking part of
2302 gcc_jit_block_add_assignment. */
2303
2304void
2305recording::block::add_assignment (recording::location *loc,
2306 recording::lvalue *lvalue,
2307 recording::rvalue *rvalue)
2308{
2309 statement *result = new assignment (this, loc, lvalue, rvalue);
2310 m_ctxt->record (result);
2311 m_statements.safe_push (result);
2312}
2313
2314/* Create a recording::assignment_op instance and add it to
2315 the block's context's list of mementos, and to the block's
2316 list of statements.
2317
2318 Implements the post-error-checking part of
2319 gcc_jit_block_add_assignment_op. */
2320
2321void
2322recording::block::add_assignment_op (recording::location *loc,
2323 recording::lvalue *lvalue,
2324 enum gcc_jit_binary_op op,
2325 recording::rvalue *rvalue)
2326{
2327 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
2328 m_ctxt->record (result);
2329 m_statements.safe_push (result);
2330}
2331
2332/* Create a recording::comment instance and add it to
2333 the block's context's list of mementos, and to the block's
2334 list of statements.
2335
2336 Implements the post-error-checking part of
2337 gcc_jit_block_add_comment. */
2338
2339void
2340recording::block::add_comment (recording::location *loc,
2341 const char *text)
2342{
2343 statement *result = new comment (this, loc, new_string (text));
2344 m_ctxt->record (result);
2345 m_statements.safe_push (result);
2346}
2347
2348/* Create a recording::end_with_conditional instance and add it to
2349 the block's context's list of mementos, and to the block's
2350 list of statements.
2351
2352 Implements the post-error-checking part of
2353 gcc_jit_block_end_with_conditional. */
2354
2355void
2356recording::block::end_with_conditional (recording::location *loc,
2357 recording::rvalue *boolval,
2358 recording::block *on_true,
2359 recording::block *on_false)
2360{
2361 statement *result = new conditional (this, loc, boolval, on_true, on_false);
2362 m_ctxt->record (result);
2363 m_statements.safe_push (result);
2364 m_has_been_terminated = true;
2365}
2366
2367/* Create a recording::end_with_jump instance and add it to
2368 the block's context's list of mementos, and to the block's
2369 list of statements.
2370
2371 Implements the post-error-checking part of
2372 gcc_jit_block_end_with_jump. */
2373
2374void
2375recording::block::end_with_jump (recording::location *loc,
2376 recording::block *target)
2377{
2378 statement *result = new jump (this, loc, target);
2379 m_ctxt->record (result);
2380 m_statements.safe_push (result);
2381 m_has_been_terminated = true;
2382}
2383
2384/* Create a recording::end_with_return instance and add it to
2385 the block's context's list of mementos, and to the block's
2386 list of statements.
2387
2388 Implements the post-error-checking parts of
2389 gcc_jit_block_end_with_return and
2390 gcc_jit_block_end_with_void_return. */
2391
2392void
2393recording::block::end_with_return (recording::location *loc,
2394 recording::rvalue *rvalue)
2395{
2396 /* This is used by both gcc_jit_function_add_return and
2397 gcc_jit_function_add_void_return; rvalue will be non-NULL for
2398 the former and NULL for the latter. */
2399 statement *result = new return_ (this, loc, rvalue);
2400 m_ctxt->record (result);
2401 m_statements.safe_push (result);
2402 m_has_been_terminated = true;
2403}
2404
2405/* Override the default implementation of
2406 recording::memento::write_to_dump for blocks by writing
2407 an unindented block name as a label, followed by the indented
2408 statements:
2409
2410 BLOCK_NAME:
2411 STATEMENT_1;
2412 STATEMENT_2;
2413 ...
2414 STATEMENT_N; */
2415
2416void
2417recording::block::write_to_dump (dump &d)
2418{
2419 d.write ("%s:\n", get_debug_string ());
2420
2421 int i;
2422 statement *s;
2423 FOR_EACH_VEC_ELT (m_statements, i, s)
2424 s->write_to_dump (d);
2425}
2426
2427/* Validate a block by ensuring that it has been terminated. */
2428
2429bool
2430recording::block::validate ()
2431{
2432 if (!has_been_terminated ())
2433 {
2434 statement *stmt = get_last_statement ();
2435 location *loc = stmt ? stmt->get_loc () : NULL;
2436 m_func->get_context ()->add_error (loc,
2437 "unterminated block in %s: %s",
2438 m_func->get_debug_string (),
2439 get_debug_string ());
2440 return false;
2441 }
2442
2443 return true;
2444}
2445
2446/* Get the source-location of a block by using that of the first
2447 statement within it, if any. */
2448
2449recording::location *
2450recording::block::get_loc () const
2451{
2452 recording::statement *stmt = get_first_statement ();
2453 if (stmt)
2454 return stmt->get_loc ();
2455 else
2456 return NULL;
2457}
2458
2459/* Get the first statement within a block, if any. */
2460
2461recording::statement *
2462recording::block::get_first_statement () const
2463{
2464 if (m_statements.length ())
2465 return m_statements[0];
2466 else
2467 return NULL;
2468}
2469
2470/* Get the last statement within a block, if any. */
2471
2472recording::statement *
2473recording::block::get_last_statement () const
2474{
2475 if (m_statements.length ())
2476 return m_statements[m_statements.length () - 1];
2477 else
2478 return NULL;
2479}
2480
2481/* Assuming that this block has been terminated, get the number of
2482 successor blocks, which will be 0, 1 or 2, for return, unconditional
2483 jump, and conditional jump respectively.
2484 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
2485 is written to NEXT1, and the second (if any) to NEXT2.
2486
2487 Used when validating functions, and when dumping dot representations
2488 of them. */
2489
2490int
2491recording::block::get_successor_blocks (block **next1, block **next2) const
2492{
2493 gcc_assert (m_has_been_terminated);
2494 gcc_assert (next1);
2495 gcc_assert (next2);
2496 statement *last_statement = get_last_statement ();
2497 gcc_assert (last_statement);
2498 return last_statement->get_successor_blocks (next1, next2);
2499}
2500
2501/* Implementation of pure virtual hook recording::memento::replay_into
2502 for recording::block. */
2503
2504void
2505recording::block::replay_into (replayer *)
2506{
2507 set_playback_obj (m_func->playback_function ()
2508 ->new_block (playback_string (m_name)));
2509}
2510
2511/* Implementation of recording::memento::make_debug_string for
2512 blocks. */
2513
2514recording::string *
2515recording::block::make_debug_string ()
2516{
2517 if (m_name)
2518 return m_name;
2519 else
2520 return string::from_printf (m_ctxt,
2521 "<UNNAMED BLOCK %p>",
2522 (void *)this);
2523}
2524
2525/* Dump a block in graphviz form into PP, capturing the block name (if
2526 any) and the statements. */
2527
2528void
2529recording::block::dump_to_dot (pretty_printer *pp)
2530{
2531 pp_printf (pp,
2532 ("\tblock_%d "
2533 "[shape=record,style=filled,fillcolor=white,label=\"{"),
2534 m_index);
2535 pp_write_text_to_stream (pp);
2536 if (m_name)
2537 {
2538 pp_string (pp, m_name->c_str ());
2539 pp_string (pp, ":");
2540 pp_newline (pp);
2541 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
2542 }
2543
2544 int i;
2545 statement *s;
2546 FOR_EACH_VEC_ELT (m_statements, i, s)
2547 {
2548 pp_string (pp, s->get_debug_string ());
2549 pp_newline (pp);
2550 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
2551 }
2552
2553 pp_printf (pp,
2554 "}\"];\n\n");
2555 pp_flush (pp);
2556}
2557
2558/* Dump the out-edges of the block in graphviz form into PP. */
2559
2560void
2561recording::block::dump_edges_to_dot (pretty_printer *pp)
2562{
2563 block *next[2];
2564 int num_succs = get_successor_blocks (&next[0], &next[1]);
2565 for (int i = 0; i < num_succs; i++)
2566 pp_printf (pp,
2567 "\tblock_%d:s -> block_%d:n;\n",
2568 m_index, next[i]->m_index);
2569}
2570
2571/* The implementation of class gcc::jit::recording::global. */
2572
2573/* Implementation of pure virtual hook recording::memento::replay_into
2574 for recording::global. */
2575
2576void
2577recording::global::replay_into (replayer *r)
2578{
2579 set_playback_obj (r->new_global (playback_location (r, m_loc),
2580 m_type->playback_type (),
2581 playback_string (m_name)));
2582}
2583
2584/* The implementation of class gcc::jit::recording::memento_of_new_rvalue_from_int. */
2585
2586/* Implementation of pure virtual hook recording::memento::replay_into
2587 for recording::memento_of_new_rvalue_from_int. */
2588
2589void
2590recording::memento_of_new_rvalue_from_int::replay_into (replayer *r)
2591{
2592 set_playback_obj (r->new_rvalue_from_int (m_type->playback_type (),
2593 m_value));
2594}
2595
2596/* Implementation of recording::memento::make_debug_string for
2597 rvalue_from_int, rendering it as
2598 (TYPE)LITERAL
2599 e.g.
2600 "(int)42". */
2601
2602recording::string *
2603recording::memento_of_new_rvalue_from_int::make_debug_string ()
2604{
2605 return string::from_printf (m_ctxt,
2606 "(%s)%i",
2607 m_type->get_debug_string (),
2608 m_value);
2609}
2610
2611/* The implementation of class gcc::jit::recording::memento_of_new_rvalue_from_double. */
2612
2613/* Implementation of pure virtual hook recording::memento::replay_into
2614 for recording::memento_of_new_rvalue_from_double. */
2615
2616void
2617recording::memento_of_new_rvalue_from_double::replay_into (replayer *r)
2618{
2619 set_playback_obj (r->new_rvalue_from_double (m_type->playback_type (),
2620 m_value));
2621}
2622
2623/* Implementation of recording::memento::make_debug_string for
2624 rvalue_from_double, rendering it as
2625 (TYPE)LITERAL
2626 e.g.
2627 "(float)42.0". */
2628
2629recording::string *
2630recording::memento_of_new_rvalue_from_double::make_debug_string ()
2631{
2632 return string::from_printf (m_ctxt,
2633 "(%s)%f",
2634 m_type->get_debug_string (),
2635 m_value);
2636}
2637
2638/* The implementation of class gcc::jit::recording::memento_of_new_rvalue_from_ptr. */
2639
2640/* Implementation of pure virtual hook recording::memento::replay_into
2641 for recording::memento_of_new_rvalue_from_ptr. */
2642
2643void
2644recording::memento_of_new_rvalue_from_ptr::replay_into (replayer *r)
2645{
2646 set_playback_obj (r->new_rvalue_from_ptr (m_type->playback_type (),
2647 m_value));
2648}
2649
2650/* Implementation of recording::memento::make_debug_string for
2651 rvalue_from_ptr, rendering it as
2652 (TYPE)HEX
2653 e.g.
2654 "(int *)0xdeadbeef"
2655
2656 Zero is rendered as NULL e.g.
2657 "(int *)NULL". */
2658
2659recording::string *
2660recording::memento_of_new_rvalue_from_ptr::make_debug_string ()
2661{
2662 if (m_value != NULL)
2663 return string::from_printf (m_ctxt,
2664 "(%s)%p",
2665 m_type->get_debug_string (), m_value);
2666 else
2667 return string::from_printf (m_ctxt,
2668 "(%s)NULL",
2669 m_type->get_debug_string ());
2670}
2671
2672/* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
2673
2674/* Implementation of pure virtual hook recording::memento::replay_into
2675 for recording::memento_of_new_string_literal. */
2676
2677void
2678recording::memento_of_new_string_literal::replay_into (replayer *r)
2679{
2680 set_playback_obj (r->new_string_literal (m_value->c_str ()));
2681}
2682
2683/* Implementation of recording::memento::make_debug_string for
2684 string literals. */
2685
2686recording::string *
2687recording::memento_of_new_string_literal::make_debug_string ()
2688{
2689 return string::from_printf (m_ctxt,
2690 m_value->get_debug_string ());
2691}
2692
2693/* The implementation of class gcc::jit::recording::unary_op. */
2694
2695/* Implementation of pure virtual hook recording::memento::replay_into
2696 for recording::unary_op. */
2697
2698void
2699recording::unary_op::replay_into (replayer *r)
2700{
2701 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
2702 m_op,
2703 get_type ()->playback_type (),
2704 m_a->playback_rvalue ()));
2705}
2706
2707/* Implementation of recording::memento::make_debug_string for
2708 unary ops. */
2709
2710static const char * const unary_op_strings[] = {
2711 "-", /* GCC_JIT_UNARY_OP_MINUS */
2712 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
2713 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
2714};
2715
2716recording::string *
2717recording::unary_op::make_debug_string ()
2718{
2719 return string::from_printf (m_ctxt,
2720 "%s(%s)",
2721 unary_op_strings[m_op],
2722 m_a->get_debug_string ());
2723}
2724
2725/* The implementation of class gcc::jit::recording::binary_op. */
2726
2727/* Implementation of pure virtual hook recording::memento::replay_into
2728 for recording::binary_op. */
2729
2730void
2731recording::binary_op::replay_into (replayer *r)
2732{
2733 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
2734 m_op,
2735 get_type ()->playback_type (),
2736 m_a->playback_rvalue (),
2737 m_b->playback_rvalue ()));
2738}
2739
2740/* Implementation of recording::memento::make_debug_string for
2741 binary ops. */
2742
2743static const char * const binary_op_strings[] = {
2744 "+", /* GCC_JIT_BINARY_OP_PLUS */
2745 "-", /* GCC_JIT_BINARY_OP_MINUS */
2746 "*", /* GCC_JIT_BINARY_OP_MULT */
2747 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
2748 "%", /* GCC_JIT_BINARY_OP_MODULO */
2749 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
2750 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
2751 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
2752 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
2753 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
2754 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
2755 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
2756};
2757
2758recording::string *
2759recording::binary_op::make_debug_string ()
2760{
2761 return string::from_printf (m_ctxt,
2762 "%s %s %s",
2763 m_a->get_debug_string (),
2764 binary_op_strings[m_op],
2765 m_b->get_debug_string ());
2766}
2767
2768/* The implementation of class gcc::jit::recording::comparison. */
2769
2770/* Implementation of recording::memento::make_debug_string for
2771 comparisons. */
2772
2773static const char * const comparison_strings[] =
2774{
2775 "==", /* GCC_JIT_COMPARISON_EQ */
2776 "!=", /* GCC_JIT_COMPARISON_NE */
2777 "<", /* GCC_JIT_COMPARISON_LT */
2778 "<=", /* GCC_JIT_COMPARISON_LE */
2779 ">", /* GCC_JIT_COMPARISON_GT */
2780 ">=", /* GCC_JIT_COMPARISON_GE */
2781};
2782
2783recording::string *
2784recording::comparison::make_debug_string ()
2785{
2786 return string::from_printf (m_ctxt,
2787 "%s %s %s",
2788 m_a->get_debug_string (),
2789 comparison_strings[m_op],
2790 m_b->get_debug_string ());
2791}
2792
2793/* Implementation of pure virtual hook recording::memento::replay_into
2794 for recording::comparison. */
2795
2796void
2797recording::comparison::replay_into (replayer *r)
2798{
2799 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
2800 m_op,
2801 m_a->playback_rvalue (),
2802 m_b->playback_rvalue ()));
2803}
2804
2805/* Implementation of pure virtual hook recording::memento::replay_into
2806 for recording::cast. */
2807
2808void
2809recording::cast::replay_into (replayer *r)
2810{
2811 set_playback_obj (r->new_cast (playback_location (r, m_loc),
2812 m_rvalue->playback_rvalue (),
2813 get_type ()->playback_type ()));
2814}
2815
2816/* Implementation of recording::memento::make_debug_string for
2817 casts. */
2818
2819recording::string *
2820recording::cast::make_debug_string ()
2821{
2822 return string::from_printf (m_ctxt,
2823 "(%s)%s",
2824 get_type ()->get_debug_string (),
2825 m_rvalue->get_debug_string ());
2826}
2827
2828/* The implementation of class gcc::jit::recording::call. */
2829
2830/* The constructor for gcc::jit::recording::call. */
2831
2832recording::call::call (recording::context *ctxt,
2833 recording::location *loc,
2834 recording::function *func,
2835 int numargs,
2836 rvalue **args)
2837: rvalue (ctxt, loc, func->get_return_type ()),
2838 m_func (func),
2839 m_args ()
2840{
2841 for (int i = 0; i< numargs; i++)
2842 m_args.safe_push (args[i]);
2843}
2844
2845/* Implementation of pure virtual hook recording::memento::replay_into
2846 for recording::call. */
2847
2848void
2849recording::call::replay_into (replayer *r)
2850{
b957b2e0 2851 auto_vec<playback::rvalue *> playback_args;
35485da9
DM
2852 playback_args.create (m_args.length ());
2853 for (unsigned i = 0; i< m_args.length (); i++)
2854 playback_args.safe_push (m_args[i]->playback_rvalue ());
2855
2856 set_playback_obj (r->new_call (playback_location (r, m_loc),
2857 m_func->playback_function (),
b957b2e0 2858 &playback_args));
35485da9
DM
2859}
2860
2861/* Implementation of recording::memento::make_debug_string for
2862 function calls. */
2863
2864recording::string *
2865recording::call::make_debug_string ()
2866{
2867 /* First, build a buffer for the arguments. */
2868 /* Calculate length of said buffer. */
2869 size_t sz = 1; /* nil terminator */
2870 for (unsigned i = 0; i< m_args.length (); i++)
2871 {
2872 sz += strlen (m_args[i]->get_debug_string ());
2873 sz += 2; /* ", " separator */
2874 }
2875
2876 /* Now allocate and populate the buffer. */
2877 char *argbuf = new char[sz];
2878 size_t len = 0;
2879
2880 for (unsigned i = 0; i< m_args.length (); i++)
2881 {
2882 strcpy (argbuf + len, m_args[i]->get_debug_string ());
2883 len += strlen (m_args[i]->get_debug_string ());
2884 if (i + 1 < m_args.length ())
2885 {
2886 strcpy (argbuf + len, ", ");
2887 len += 2;
2888 }
2889 }
2890 argbuf[len] = '\0';
2891
2892 /* ...and use it to get the string for the call as a whole. */
2893 string *result = string::from_printf (m_ctxt,
2894 "%s (%s)",
2895 m_func->get_debug_string (),
2896 argbuf);
2897
2898 delete[] argbuf;
2899
2900 return result;
2901}
2902
2903/* The implementation of class gcc::jit::recording::call_through_ptr. */
2904
2905/* The constructor for recording::call_through_ptr. */
2906
2907recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
2908 recording::location *loc,
2909 recording::rvalue *fn_ptr,
2910 int numargs,
2911 rvalue **args)
2912: rvalue (ctxt, loc,
2913 fn_ptr->get_type ()->dereference ()
2914 ->as_a_function_type ()->get_return_type ()),
2915 m_fn_ptr (fn_ptr),
2916 m_args ()
2917{
2918 for (int i = 0; i< numargs; i++)
2919 m_args.safe_push (args[i]);
2920}
2921
2922/* Implementation of pure virtual hook recording::memento::replay_into
2923 for recording::call_through_ptr. */
2924
2925void
2926recording::call_through_ptr::replay_into (replayer *r)
2927{
b957b2e0 2928 auto_vec<playback::rvalue *> playback_args;
35485da9
DM
2929 playback_args.create (m_args.length ());
2930 for (unsigned i = 0; i< m_args.length (); i++)
2931 playback_args.safe_push (m_args[i]->playback_rvalue ());
2932
2933 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
2934 m_fn_ptr->playback_rvalue (),
b957b2e0 2935 &playback_args));
35485da9
DM
2936}
2937
2938/* Implementation of recording::memento::make_debug_string for
2939 calls through function ptrs. */
2940
2941recording::string *
2942recording::call_through_ptr::make_debug_string ()
2943{
2944 /* First, build a buffer for the arguments. */
2945 /* Calculate length of said buffer. */
2946 size_t sz = 1; /* nil terminator */
2947 for (unsigned i = 0; i< m_args.length (); i++)
2948 {
2949 sz += strlen (m_args[i]->get_debug_string ());
2950 sz += 2; /* ", " separator */
2951 }
2952
2953 /* Now allocate and populate the buffer. */
2954 char *argbuf = new char[sz];
2955 size_t len = 0;
2956
2957 for (unsigned i = 0; i< m_args.length (); i++)
2958 {
2959 strcpy (argbuf + len, m_args[i]->get_debug_string ());
2960 len += strlen (m_args[i]->get_debug_string ());
2961 if (i + 1 < m_args.length ())
2962 {
2963 strcpy (argbuf + len, ", ");
2964 len += 2;
2965 }
2966 }
2967 argbuf[len] = '\0';
2968
2969 /* ...and use it to get the string for the call as a whole. */
2970 string *result = string::from_printf (m_ctxt,
2971 "%s (%s)",
2972 m_fn_ptr->get_debug_string (),
2973 argbuf);
2974
2975 delete[] argbuf;
2976
2977 return result;
2978}
2979
2980/* The implementation of class gcc::jit::recording::array_access. */
2981
2982/* Implementation of pure virtual hook recording::memento::replay_into
2983 for recording::array_access. */
2984
2985void
2986recording::array_access::replay_into (replayer *r)
2987{
2988 set_playback_obj (
2989 r->new_array_access (playback_location (r, m_loc),
2990 m_ptr->playback_rvalue (),
2991 m_index->playback_rvalue ()));
2992}
2993
2994/* Implementation of recording::memento::make_debug_string for
2995 array accesses. */
2996
2997recording::string *
2998recording::array_access::make_debug_string ()
2999{
3000 return string::from_printf (m_ctxt,
3001 "%s[%s]",
3002 m_ptr->get_debug_string (),
3003 m_index->get_debug_string ());
3004}
3005
3006/* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
3007
3008/* Implementation of pure virtual hook recording::memento::replay_into
3009 for recording::access_field_of_lvalue. */
3010
3011void
3012recording::access_field_of_lvalue::replay_into (replayer *r)
3013{
3014 set_playback_obj (
3015 m_lvalue->playback_lvalue ()
3016 ->access_field (playback_location (r, m_loc),
3017 m_field->playback_field ()));
3018
3019}
3020
3021/* Implementation of recording::memento::make_debug_string for
3022 accessing a field of an lvalue. */
3023
3024recording::string *
3025recording::access_field_of_lvalue::make_debug_string ()
3026{
3027 return string::from_printf (m_ctxt,
3028 "%s.%s",
3029 m_lvalue->get_debug_string (),
3030 m_field->get_debug_string ());
3031}
3032
3033/* The implementation of class gcc::jit::recording::access_field_rvalue. */
3034
3035/* Implementation of pure virtual hook recording::memento::replay_into
3036 for recording::access_field_rvalue. */
3037
3038void
3039recording::access_field_rvalue::replay_into (replayer *r)
3040{
3041 set_playback_obj (
3042 m_rvalue->playback_rvalue ()
3043 ->access_field (playback_location (r, m_loc),
3044 m_field->playback_field ()));
3045}
3046
3047/* Implementation of recording::memento::make_debug_string for
3048 accessing a field of an rvalue. */
3049
3050recording::string *
3051recording::access_field_rvalue::make_debug_string ()
3052{
3053 return string::from_printf (m_ctxt,
3054 "%s.%s",
3055 m_rvalue->get_debug_string (),
3056 m_field->get_debug_string ());
3057}
3058
3059/* The implementation of class
3060 gcc::jit::recording::dereference_field_rvalue. */
3061
3062/* Implementation of pure virtual hook recording::memento::replay_into
3063 for recording::dereference_field_rvalue. */
3064
3065void
3066recording::dereference_field_rvalue::replay_into (replayer *r)
3067{
3068 set_playback_obj (
3069 m_rvalue->playback_rvalue ()->
3070 dereference_field (playback_location (r, m_loc),
3071 m_field->playback_field ()));
3072}
3073
3074/* Implementation of recording::memento::make_debug_string for
3075 dereferencing a field of an rvalue. */
3076
3077recording::string *
3078recording::dereference_field_rvalue::make_debug_string ()
3079{
3080 return string::from_printf (m_ctxt,
3081 "%s->%s",
3082 m_rvalue->get_debug_string (),
3083 m_field->get_debug_string ());
3084}
3085
3086/* The implementation of class gcc::jit::recording::dereference_rvalue. */
3087
3088/* Implementation of pure virtual hook recording::memento::replay_into
3089 for recording::dereference_rvalue. */
3090
3091void
3092recording::dereference_rvalue::replay_into (replayer *r)
3093{
3094 set_playback_obj (
3095 m_rvalue->playback_rvalue ()->
3096 dereference (playback_location (r, m_loc)));
3097}
3098
3099/* Implementation of recording::memento::make_debug_string for
3100 dereferencing an rvalue. */
3101
3102recording::string *
3103recording::dereference_rvalue::make_debug_string ()
3104{
3105 return string::from_printf (m_ctxt,
3106 "*%s",
3107 m_rvalue->get_debug_string ());
3108}
3109
3110/* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
3111
3112/* Implementation of pure virtual hook recording::memento::replay_into
3113 for recording::get_address_of_lvalue. */
3114
3115void
3116recording::get_address_of_lvalue::replay_into (replayer *r)
3117{
3118 set_playback_obj (
3119 m_lvalue->playback_lvalue ()->
3120 get_address (playback_location (r, m_loc)));
3121}
3122
3123/* Implementation of recording::memento::make_debug_string for
3124 getting the address of an lvalue. */
3125
3126recording::string *
3127recording::get_address_of_lvalue::make_debug_string ()
3128{
3129 return string::from_printf (m_ctxt,
3130 "&%s",
3131 m_lvalue->get_debug_string ());
3132}
3133
3134/* The implementation of class gcc::jit::recording::local. */
3135
3136/* Implementation of pure virtual hook recording::memento::replay_into
3137 for recording::local. */
3138
3139void
3140recording::local::replay_into (replayer *r)
3141{
3142 set_playback_obj (
3143 m_func->playback_function ()
3144 ->new_local (playback_location (r, m_loc),
3145 m_type->playback_type (),
3146 playback_string (m_name)));
3147}
3148
3149/* Override the default implementation of
3150 recording::memento::write_to_dump for locals by writing
3151 TYPE NAME;
3152 for use at the top of the function body as if it were a
3153 declaration. */
3154
3155void
3156recording::local::write_to_dump (dump &d)
3157{
3158 if (d.update_locations ())
3159 m_loc = d.make_location ();
3160 d.write(" %s %s;\n",
3161 m_type->get_debug_string (),
3162 get_debug_string ());
3163}
3164
3165/* The implementation of class gcc::jit::recording::statement. */
3166
3167/* We poison the default implementation of
3168 gcc::jit::recording::statement::get_successor_blocks
3169 since this vfunc must only ever be called on terminator
3170 statements. */
3171
3172int
3173recording::statement::get_successor_blocks (block **/*out_next1*/,
3174 block **/*out_next2*/) const
3175{
3176 /* The base class implementation is for non-terminating statements,
3177 and thus should never be called. */
3178 gcc_unreachable ();
3179 return 0;
3180}
3181
3182/* Extend the default implementation of
3183 recording::memento::write_to_dump for statements by (if requested)
3184 updating the location of the statement to the current location in
3185 the dumpfile. */
3186
3187void
3188recording::statement::write_to_dump (dump &d)
3189{
3190 memento::write_to_dump (d);
3191 if (d.update_locations ())
3192 m_loc = d.make_location ();
3193}
3194
3195/* The implementation of class gcc::jit::recording::eval. */
3196
3197/* Implementation of pure virtual hook recording::memento::replay_into
3198 for recording::eval. */
3199
3200void
3201recording::eval::replay_into (replayer *r)
3202{
3203 playback_block (get_block ())
3204 ->add_eval (playback_location (r),
3205 m_rvalue->playback_rvalue ());
3206}
3207
3208/* Implementation of recording::memento::make_debug_string for
3209 an eval statement. */
3210
3211recording::string *
3212recording::eval::make_debug_string ()
3213{
3214 return string::from_printf (m_ctxt,
3215 "(void)%s;",
3216 m_rvalue->get_debug_string ());
3217}
3218
3219/* The implementation of class gcc::jit::recording::assignment. */
3220
3221/* Implementation of pure virtual hook recording::memento::replay_into
3222 for recording::assignment. */
3223
3224void
3225recording::assignment::replay_into (replayer *r)
3226{
3227 playback_block (get_block ())
3228 ->add_assignment (playback_location (r),
3229 m_lvalue->playback_lvalue (),
3230 m_rvalue->playback_rvalue ());
3231}
3232
3233/* Implementation of recording::memento::make_debug_string for
3234 an assignment statement. */
3235
3236recording::string *
3237recording::assignment::make_debug_string ()
3238{
3239 return string::from_printf (m_ctxt,
3240 "%s = %s;",
3241 m_lvalue->get_debug_string (),
3242 m_rvalue->get_debug_string ());
3243}
3244
3245/* The implementation of class gcc::jit::recording::assignment_op. */
3246
3247/* Implementation of pure virtual hook recording::memento::replay_into
3248 for recording::assignment_op. */
3249
3250void
3251recording::assignment_op::replay_into (replayer *r)
3252{
3253 playback::type *result_type =
3254 m_lvalue->playback_lvalue ()->get_type ();
3255
3256 playback::rvalue *binary_op =
3257 r->new_binary_op (playback_location (r),
3258 m_op,
3259 result_type,
3260 m_lvalue->playback_rvalue (),
3261 m_rvalue->playback_rvalue ());
3262
3263 playback_block (get_block ())
3264 ->add_assignment (playback_location (r),
3265 m_lvalue->playback_lvalue (),
3266 binary_op);
3267}
3268
3269/* Implementation of recording::memento::make_debug_string for
3270 an assignment_op statement. */
3271
3272recording::string *
3273recording::assignment_op::make_debug_string ()
3274{
3275 return string::from_printf (m_ctxt,
3276 "%s %s= %s;",
3277 m_lvalue->get_debug_string (),
3278 binary_op_strings[m_op],
3279 m_rvalue->get_debug_string ());
3280}
3281
3282/* The implementation of class gcc::jit::recording::comment. */
3283
3284/* Implementation of pure virtual hook recording::memento::replay_into
3285 for recording::comment. */
3286
3287void
3288recording::comment::replay_into (replayer *r)
3289{
3290 playback_block (get_block ())
3291 ->add_comment (playback_location (r),
3292 m_text->c_str ());
3293}
3294
3295/* Implementation of recording::memento::make_debug_string for
3296 a comment "statement". */
3297
3298recording::string *
3299recording::comment::make_debug_string ()
3300{
3301 return string::from_printf (m_ctxt,
3302 "/* %s */",
3303 m_text->c_str ());
3304}
3305
3306/* The implementation of class gcc::jit::recording::conditional. */
3307
3308/* Implementation of pure virtual hook recording::memento::replay_into
3309 for recording::conditional. */
3310
3311void
3312recording::conditional::replay_into (replayer *r)
3313{
3314 playback_block (get_block ())
3315 ->add_conditional (playback_location (r),
3316 m_boolval->playback_rvalue (),
3317 playback_block (m_on_true),
3318 playback_block (m_on_false));
3319}
3320
3321/* Override the poisoned default implementation of
3322 gcc::jit::recording::statement::get_successor_blocks
3323
3324 A conditional jump has 2 successor blocks. */
3325
3326int
3327recording::conditional::get_successor_blocks (block **out_next1,
3328 block **out_next2) const
3329{
3330 *out_next1 = m_on_true;
3331 *out_next2 = m_on_false;
3332 return 2;
3333}
3334
3335/* Implementation of recording::memento::make_debug_string for
3336 a conditional jump statement. */
3337
3338recording::string *
3339recording::conditional::make_debug_string ()
3340{
3341 if (m_on_false)
3342 return string::from_printf (m_ctxt,
3343 "if (%s) goto %s; else goto %s;",
3344 m_boolval->get_debug_string (),
3345 m_on_true->get_debug_string (),
3346 m_on_false->get_debug_string ());
3347 else
3348 return string::from_printf (m_ctxt,
3349 "if (%s) goto %s;",
3350 m_boolval->get_debug_string (),
3351 m_on_true->get_debug_string ());
3352}
3353
3354/* The implementation of class gcc::jit::recording::jump. */
3355
3356/* Implementation of pure virtual hook recording::memento::replay_into
3357 for recording::jump. */
3358
3359void
3360recording::jump::replay_into (replayer *r)
3361{
3362 playback_block (get_block ())
3363 ->add_jump (playback_location (r),
3364 m_target->playback_block ());
3365}
3366
3367/* Override the poisoned default implementation of
3368 gcc::jit::recording::statement::get_successor_blocks
3369
3370 An unconditional jump has 1 successor block. */
3371
3372int
3373recording::jump::get_successor_blocks (block **out_next1,
3374 block **/*out_next2*/) const
3375{
3376 *out_next1 = m_target;
3377 return 1;
3378}
3379
3380/* Implementation of recording::memento::make_debug_string for
3381 a unconditional jump statement. */
3382
3383recording::string *
3384recording::jump::make_debug_string ()
3385{
3386 return string::from_printf (m_ctxt,
3387 "goto %s;",
3388 m_target->get_debug_string ());
3389}
3390
3391/* The implementation of class gcc::jit::recording::return_. */
3392
3393/* Implementation of pure virtual hook recording::memento::replay_into
3394 for recording::return_. */
3395
3396void
3397recording::return_::replay_into (replayer *r)
3398{
3399 playback_block (get_block ())
3400 ->add_return (playback_location (r),
3401 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
3402}
3403
3404/* Override the poisoned default implementation of
3405 gcc::jit::recording::statement::get_successor_blocks
3406
3407 A return statement has no successor block. */
3408
3409int
3410recording::return_::get_successor_blocks (block **/*out_next1*/,
3411 block **/*out_next2*/) const
3412{
3413 return 0;
3414}
3415
3416/* Implementation of recording::memento::make_debug_string for
3417 a return statement (covers both those with and without rvalues). */
3418
3419recording::string *
3420recording::return_::make_debug_string ()
3421{
3422 if (m_rvalue)
3423 return string::from_printf (m_ctxt,
3424 "return %s;",
3425 m_rvalue->get_debug_string ());
3426 else
3427 return string::from_printf (m_ctxt,
3428 "return;");
3429}
3430
3431} // namespace gcc::jit
3432
3433} // namespace gcc