]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/jit/jit-recording.c
toplev: gcc version information for jit
[thirdparty/gcc.git] / gcc / jit / jit-recording.c
CommitLineData
35485da9 1/* Internals of libgccjit: classes for recording calls made to the JIT API.
1e3b6a3d 2 Copyright (C) 2013-2015 Free Software Foundation, Inc.
35485da9
DM
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"
35485da9 25#include "pretty-print.h"
86d0ac88 26#include "hash-map.h"
53c04ec9 27#include "toplev.h"
35485da9
DM
28
29#include <pthread.h>
30
31#include "jit-common.h"
32#include "jit-builtins.h"
eb4c16eb 33#include "jit-logging.h"
35485da9
DM
34#include "jit-recording.h"
35#include "jit-playback.h"
36
37namespace gcc {
38namespace jit {
39
40// class dump
41
42dump::dump (recording::context &ctxt,
43 const char *filename,
44 bool update_locations)
45: m_ctxt (ctxt),
46 m_filename (filename),
47 m_update_locations (update_locations),
48 m_line (0),
49 m_column (0)
50{
51 m_file = fopen (filename, "w");
52 if (!m_file)
53 ctxt.add_error (NULL,
54 "error opening dump file %s for writing: %s",
55 filename,
56 xstrerror (errno));
57}
58
59dump::~dump ()
60{
61 if (m_file)
62 {
63 int err = fclose (m_file);
64 if (err)
65 m_ctxt.add_error (NULL,
66 "error closing dump file %s: %s",
67 m_filename,
68 xstrerror (errno));
69 }
70}
71
72/* Write the given message to the dump, using printf-formatting
73 conventions, updating the line/column within the dump.
74
75 Emit an error on the context if a failure occurs. */
76
77void
78dump::write (const char *fmt, ...)
79{
80 va_list ap;
81 char *buf = NULL;
82
83 /* If there was an error opening the file, we've already reported it.
84 Don't attempt further work. */
85 if (!m_file)
86 return;
87
88 va_start (ap, fmt);
89 vasprintf (&buf, fmt, ap);
90 va_end (ap);
91
92 if (!buf)
93 {
94 m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
95 m_filename);
96 return;
97 }
98
99 if (fwrite (buf, strlen (buf), 1, m_file) != 1)
100 m_ctxt.add_error (NULL, "error writing to dump file %s",
101 m_filename);
102
86d0ac88
DM
103 /* Flush after each line, to ease debugging crashes. */
104 fflush (m_file);
105
35485da9
DM
106 /* Update line/column: */
107 for (const char *ptr = buf; *ptr; ptr++)
108 {
109 if ('\n' == *ptr)
110 {
111 m_line++;
112 m_column = 0;
113 }
114 else
115 m_column++;
116 }
117
118 free (buf);
119}
120
121/* Construct a gcc::jit::recording::location instance for the current
122 location within the dump. */
123
124recording::location *
125dump::make_location () const
126{
86d0ac88
DM
127 return m_ctxt.new_location (m_filename, m_line, m_column,
128 /* We need to flag such locations as *not*
129 created by the user, so that
130 reproducer::get_identifier can cope with
131 them appearing *after* the memento that
132 refers to them. */
133 false);
134}
135
136/* A collection of allocations, all of which can be released together, to
137 avoid needing to track and release them individually. */
138
139class allocator
140{
141 public:
142 ~allocator ();
143
144 char *
145 xstrdup_printf (const char *, ...)
146 ATTRIBUTE_RETURNS_NONNULL
147 GNU_PRINTF(2, 3);
148
149 char *
150 xstrdup_printf_va (const char *, va_list ap)
151 ATTRIBUTE_RETURNS_NONNULL
152 GNU_PRINTF(2, 0);
153
154 private:
155 auto_vec <void *> m_buffers;
156};
157
158/* allocator's destructor. Call "free" on all of the allocations. */
159
160allocator::~allocator ()
161{
162 unsigned i;
163 void *buffer;
164 FOR_EACH_VEC_ELT (m_buffers, i, buffer)
165 free (buffer);
166}
167
168/* Formatted printing, allocating to a buffer (or exiting the process if
169 the allocation fails).
170
171 The buffer exists until the allocator is cleaned up, and is freed at
172 that point, so the caller doesn't need to track the result. */
173
174char *
175allocator::xstrdup_printf (const char *fmt, ...)
176{
177 char *result;
178 va_list ap;
179 va_start (ap, fmt);
180 result = xstrdup_printf_va (fmt, ap);
181 va_end (ap);
182 return result;
183}
184
185/* Formatted printing, allocating to a buffer (or exiting the process if
186 the allocation fails).
187
188 The buffer exists until the allocator is cleaned up, and is freed at
189 that point, so the caller doesn't need to track the result. */
190
191char *
192allocator::xstrdup_printf_va (const char *fmt, va_list ap)
193{
194 char *result = xvasprintf (fmt, ap);
195 m_buffers.safe_push (result);
196 return result;
197}
198
199/* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for
200 implementing gcc_jit_context_dump_reproducer_to_file. */
201
202class reproducer : public dump
203{
204 public:
205 reproducer (recording::context &ctxt,
206 const char *filename);
207
208 void
209 write_params (const vec <recording::context *> &contexts);
210
211 void
212 write_args (const vec <recording::context *> &contexts);
213
214 const char *
215 make_identifier (recording::memento *m, const char *prefix);
216
217 const char *
218 make_tmp_identifier (const char *prefix, recording::memento *m);
219
220 const char *
221 get_identifier (recording::context *ctxt);
222
223 const char *
224 get_identifier (recording::memento *m);
225
226 const char *
227 get_identifier_as_rvalue (recording::rvalue *m);
228
229 const char *
230 get_identifier_as_lvalue (recording::lvalue *m);
231
232 const char *
233 get_identifier_as_type (recording::type *m);
234
235 char *
236 xstrdup_printf (const char *, ...)
237 ATTRIBUTE_RETURNS_NONNULL
238 GNU_PRINTF(2, 3);
239
240 private:
241 hash_map<recording::memento *, const char *> m_identifiers;
242 allocator m_allocator;
243};
244
245/* gcc::jit::reproducer's constructor. */
246
247reproducer::reproducer (recording::context &ctxt,
248 const char *filename) :
249 dump (ctxt, filename, 0),
250 m_identifiers (),
251 m_allocator ()
252{
253}
254
255/* Write out a list of contexts as a set of parameters within a
256 C function declaration. */
257
258void
259reproducer::write_params (const vec <recording::context *> &contexts)
260{
261 unsigned i;
262 recording::context *ctxt;
263 FOR_EACH_VEC_ELT (contexts, i, ctxt)
264 {
265 write ("gcc_jit_context *%s",
266 get_identifier (ctxt));
267 if (i < contexts.length () - 1)
268 write (",\n"
269 " ");
270 }
271}
272
273/* Write out a list of contexts as a set of arguments within a call
274 to a C function. */
275
276void
277reproducer::write_args (const vec <recording::context *> &contexts)
278{
279 unsigned i;
280 recording::context *ctxt;
281 FOR_EACH_VEC_ELT (contexts, i, ctxt)
282 {
283 write ("%s",
284 get_identifier (ctxt));
285 if (i < contexts.length () - 1)
286 write (",\n"
287 " ");
288 }
289}
290
291/* Generate a C identifier for the given memento, associating the generated
292 buffer with the memento (for future calls to get_identifier et al).
293
294 The reproducer will eventually clean up the buffer in its dtor. */
295const char *
296reproducer::make_identifier (recording::memento *m, const char *prefix)
297{
298 char *result;
299 if (strlen (m->get_debug_string ()) < 100)
300 {
301 result = m_allocator.xstrdup_printf ("%s_%s_%p",
302 prefix,
303 m->get_debug_string (),
304 (void *) m);
305 for (char *p = result; *p; p++)
306 if (!ISALNUM (*p))
307 *p = '_';
308 }
309 else
310 result = m_allocator.xstrdup_printf ("%s_%p",
311 prefix, (void *) m);
312 m_identifiers.put (m, result);
313 return result;
314}
315
316/* Generate a C identifier for a temporary variable.
317 The reproducer will eventually clean up the buffer in its dtor. */
318
319const char *
320reproducer::make_tmp_identifier (const char *prefix, recording::memento *m)
321{
322 return m_allocator.xstrdup_printf ("%s_%s",
323 prefix, get_identifier (m));
324}
325
326/* Generate a C identifier for the given context.
327 The reproducer will eventually clean up the buffer in its dtor. */
328
329const char *
330reproducer::get_identifier (recording::context *ctxt)
331{
332 return m_allocator.xstrdup_printf ("ctxt_%p",
333 (void *)ctxt);
334}
335
336/* Locate the C identifier for the given memento, which is assumed to
337 have already been created via make_identifier. */
338
339const char *
340reproducer::get_identifier (recording::memento *m)
341{
342 if (!m)
343 return "NULL";
344
345 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations,
346 and hence these locations appear in the context's memento list
347 out-of-order: they appear in the context's memento list *after*
348 the memento that refers to them. For this case, it's simplest to
349 pretend that they're NULL when writing out the code to recreate the
350 memento that uses them. */
351 if (recording::location *loc = m->dyn_cast_location ())
352 if (!loc->created_by_user ())
353 return "NULL";
354
355 const char **slot = m_identifiers.get (m);
356 if (!slot)
357 {
358 get_context ().add_error (NULL,
359 "unable to find identifier for %p: %s",
360 (void *)m,
361 m->get_debug_string ());
362 gcc_unreachable ();
363 }
364 return *slot;
365}
366
367/* Locate the C identifier for the given rvalue, wrapping it within
368 a gcc_*_as_rvalue upcast if necessary. */
369
370const char *
371reproducer::get_identifier_as_rvalue (recording::rvalue *m)
372{
373 return m->access_as_rvalue (*this);
374}
375
376/* Locate the C identifier for the given lvalue, wrapping it within
377 a gcc_*_as_lvalue upcast if necessary. */
378
379const char *
380reproducer::get_identifier_as_lvalue (recording::lvalue *m)
381{
382 return m->access_as_lvalue (*this);
383}
384
385/* Locate the C identifier for the given type, wrapping it within
386 a gcc_*_as_type upcast if necessary. */
387
388const char *
389reproducer::get_identifier_as_type (recording::type *m)
390{
391 return m->access_as_type (*this);
392}
393
394/* Formatted printing, allocating to a buffer (or exiting the process if
395 the allocation fails).
396
397 The buffer exists until the allocator is cleaned up, and is freed at
398 that point, so the caller doesn't need to track the result.
399
400 Note that we can't use ggc_printf since we're not within the compiler
401 proper (when within gcc_jit_context_dump_reproducer_to_file). */
402
403char *
404reproducer::xstrdup_printf (const char *fmt, ...)
405{
406 char *result;
407 va_list ap;
408 va_start (ap, fmt);
409 result = m_allocator.xstrdup_printf_va (fmt, ap);
410 va_end (ap);
411 return result;
35485da9
DM
412}
413
414/**********************************************************************
415 Recording.
416 **********************************************************************/
417
418/* Get the playback::location for the given recording::location,
419 handling a NULL input with a NULL output. */
420
421playback::location *
422recording::playback_location (replayer *r, recording::location *loc)
423{
424 if (loc)
425 return loc->playback_location (r);
426 else
427 return NULL;
428}
429
430/* Get a const char * for the given recording::string
431 handling a NULL input with a NULL output. */
432
433const char *
434recording::playback_string (recording::string *str)
435{
436 if (str)
437 return str->c_str ();
438 else
439 return NULL;
440}
441
442/* Get the playback::block for the given recording::block,
443 handling a NULL input with a NULL output. */
444
445playback::block *
446recording::playback_block (recording::block *b)
447{
448 if (b)
449 return b->playback_block ();
450 else
451 return NULL;
452}
453
454/* Methods of cc::jit::recording::context. */
455
456/* The constructor for gcc::jit::recording::context, used by
457 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
458
459recording::context::context (context *parent_ctxt)
eb4c16eb
DM
460 : log_user (NULL),
461 m_parent_ctxt (parent_ctxt),
86d0ac88 462 m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this),
35485da9
DM
463 m_error_count (0),
464 m_first_error_str (NULL),
465 m_owns_first_error_str (false),
303e1d56
DM
466 m_last_error_str (NULL),
467 m_owns_last_error_str (false),
35485da9
DM
468 m_mementos (),
469 m_compound_types (),
791cfef8 470 m_globals (),
35485da9
DM
471 m_functions (),
472 m_FILE_type (NULL),
473 m_builtins_manager(NULL)
474{
475 if (parent_ctxt)
476 {
5afd44e3
DM
477 /* Inherit options from parent. */
478 for (unsigned i = 0;
479 i < sizeof (m_str_options) / sizeof (m_str_options[0]);
480 i++)
481 {
482 const char *parent_opt = parent_ctxt->m_str_options[i];
483 m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
484 }
35485da9 485 memcpy (m_int_options,
c168eab9
UD
486 parent_ctxt->m_int_options,
487 sizeof (m_int_options));
35485da9 488 memcpy (m_bool_options,
c168eab9
UD
489 parent_ctxt->m_bool_options,
490 sizeof (m_bool_options));
eb4c16eb 491 set_logger (parent_ctxt->get_logger ());
35485da9
DM
492 }
493 else
494 {
495 memset (m_str_options, 0, sizeof (m_str_options));
496 memset (m_int_options, 0, sizeof (m_int_options));
497 memset (m_bool_options, 0, sizeof (m_bool_options));
498 }
499
500 memset (m_basic_types, 0, sizeof (m_basic_types));
501}
502
503/* The destructor for gcc::jit::recording::context, implicitly used by
504 gcc_jit_context_release. */
505
506recording::context::~context ()
507{
eb4c16eb 508 JIT_LOG_SCOPE (get_logger ());
35485da9
DM
509 int i;
510 memento *m;
511 FOR_EACH_VEC_ELT (m_mementos, i, m)
512 {
513 delete m;
514 }
515
c168eab9
UD
516 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
517 free (m_str_options[i]);
518
35485da9
DM
519 if (m_builtins_manager)
520 delete m_builtins_manager;
521
522 if (m_owns_first_error_str)
523 free (m_first_error_str);
303e1d56
DM
524
525 if (m_owns_last_error_str)
526 if (m_last_error_str != m_first_error_str)
527 free (m_last_error_str);
35485da9
DM
528}
529
530/* Add the given mememto to the list of those tracked by this
531 gcc::jit::recording::context, so that e.g. it can be deleted
532 when this context is released. */
533
534void
535recording::context::record (memento *m)
536{
537 gcc_assert (m);
538
539 m_mementos.safe_push (m);
540}
541
542/* Replay this context (and any parents) into the given replayer. */
543
544void
545recording::context::replay_into (replayer *r)
546{
eb4c16eb 547 JIT_LOG_SCOPE (get_logger ());
35485da9
DM
548 int i;
549 memento *m;
550
551 /* If we have a parent context, we must replay it. This will
552 recursively walk backwards up the historical tree, then replay things
553 forwards "in historical order", starting with the ultimate parent
554 context, until we reach the "this" context.
555
556 Note that we fully replay the parent, then fully replay the child,
557 which means that inter-context references can only exist from child
558 to parent, not the other way around.
559
560 All of this replaying is suboptimal - it would be better to do the
561 work for the parent context *once*, rather than replaying the parent
562 every time we replay each child. However, fixing this requires deep
563 surgery to lifetime-management: we'd need every context family tree
564 to have its own GC heap, and to initialize the GCC code to use that
565 heap (with a mutex on such a heap). */
566 if (m_parent_ctxt)
567 m_parent_ctxt->replay_into (r);
568
569 if (r->errors_occurred ())
570 return;
571
572 /* Replay this context's saved operations into r. */
573 FOR_EACH_VEC_ELT (m_mementos, i, m)
574 {
575 /* Disabled low-level debugging, here if we need it: print what
576 we're replaying.
577 Note that the calls to get_debug_string might lead to more
578 mementos being created for the strings.
579 This can also be used to exercise the debug_string
580 machinery. */
581 if (0)
582 printf ("context %p replaying (%p): %s\n",
583 (void *)this, (void *)m, m->get_debug_string ());
584
585 m->replay_into (r);
586
587 if (r->errors_occurred ())
588 return;
589 }
590}
591
592/* During a playback, we associate objects from the recording with
593 their counterparts during this playback.
594
595 For simplicity, we store this within the recording objects.
596
597 The following method cleans away these associations, to ensure that
598 we never have out-of-date associations lingering on subsequent
599 playbacks (the objects pointed to are GC-managed, but the
600 recording objects don't own refs to them). */
601
602void
603recording::context::disassociate_from_playback ()
604{
eb4c16eb 605 JIT_LOG_SCOPE (get_logger ());
35485da9
DM
606 int i;
607 memento *m;
608
609 if (m_parent_ctxt)
610 m_parent_ctxt->disassociate_from_playback ();
611
612 FOR_EACH_VEC_ELT (m_mementos, i, m)
613 {
614 m->set_playback_obj (NULL);
615 }
616}
617
618/* Create a recording::string instance and add it to this context's list
619 of mementos.
620
621 This creates a fresh copy of the given 0-terminated buffer. */
622
623recording::string *
624recording::context::new_string (const char *text)
625{
626 if (!text)
627 return NULL;
628
629 recording::string *result = new string (this, text);
630 record (result);
631 return result;
632}
633
634/* Create a recording::location instance and add it to this context's
635 list of mementos.
636
637 Implements the post-error-checking part of
638 gcc_jit_context_new_location. */
639
640recording::location *
641recording::context::new_location (const char *filename,
86d0ac88
DM
642 int line,
643 int column,
644 bool created_by_user)
35485da9
DM
645{
646 recording::location *result =
647 new recording::location (this,
86d0ac88
DM
648 new_string (filename),
649 line, column,
650 created_by_user);
35485da9
DM
651 record (result);
652 return result;
653}
654
655/* If we haven't seen this enum value yet, create a recording::type
656 instance and add it to this context's list of mementos.
657
658 If we have seen it before, reuse our cached value, so that repeated
659 calls on the context give the same object.
660
661 If we have a parent context, the cache is within the ultimate
662 ancestor context.
663
664 Implements the post-error-checking part of
665 gcc_jit_context_get_type. */
666
667recording::type *
668recording::context::get_type (enum gcc_jit_types kind)
669{
670 if (!m_basic_types[kind])
671 {
672 if (m_parent_ctxt)
673 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
674 else
675 {
676 recording::type *result = new memento_of_get_type (this, kind);
677 record (result);
678 m_basic_types[kind] = result;
679 }
680 }
681
682 return m_basic_types[kind];
683}
684
685/* Get a recording::type instance for the given size and signedness.
686 This is implemented in terms of recording::context::get_type
687 above.
688
689 Implements the post-error-checking part of
690 gcc_jit_context_get_int_type. */
691
692recording::type *
693recording::context::get_int_type (int num_bytes, int is_signed)
694{
695 /* We can't use a switch here since some of the values are macros affected
696 by options; e.g. i386.h has
697 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
698 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
699 are in bits, rather than bytes.
700 */
701 const int num_bits = num_bytes * 8;
702 if (num_bits == INT_TYPE_SIZE)
703 return get_type (is_signed
704 ? GCC_JIT_TYPE_INT
705 : GCC_JIT_TYPE_UNSIGNED_INT);
706 if (num_bits == CHAR_TYPE_SIZE)
707 return get_type (is_signed
708 ? GCC_JIT_TYPE_SIGNED_CHAR
709 : GCC_JIT_TYPE_UNSIGNED_CHAR);
710 if (num_bits == SHORT_TYPE_SIZE)
711 return get_type (is_signed
712 ? GCC_JIT_TYPE_SHORT
713 : GCC_JIT_TYPE_UNSIGNED_SHORT);
714 if (num_bits == LONG_TYPE_SIZE)
715 return get_type (is_signed
716 ? GCC_JIT_TYPE_LONG
717 : GCC_JIT_TYPE_UNSIGNED_LONG);
718 if (num_bits == LONG_LONG_TYPE_SIZE)
719 return get_type (is_signed
720 ? GCC_JIT_TYPE_LONG_LONG
721 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
722
723 /* Some other size, not corresponding to the C int types. */
724 /* To be written: support arbitrary other sizes, sharing by
725 memoizing at the recording::context level? */
726 gcc_unreachable ();
727}
728
729/* Create a recording::type instance and add it to this context's list
730 of mementos.
731
732 Implements the post-error-checking part of
733 gcc_jit_context_new_array_type. */
734
735recording::type *
736recording::context::new_array_type (recording::location *loc,
737 recording::type *element_type,
738 int num_elements)
739{
740 if (struct_ *s = element_type->dyn_cast_struct ())
741 if (!s->get_fields ())
742 {
743 add_error (NULL,
744 "cannot create an array of type %s"
745 " until the fields have been set",
746 s->get_name ()->c_str ());
747 return NULL;
748 }
749 recording::type *result =
750 new recording::array_type (this, loc, element_type, num_elements);
751 record (result);
752 return result;
753}
754
755/* Create a recording::field instance and add it to this context's list
756 of mementos.
757
758 Implements the post-error-checking part of
759 gcc_jit_context_new_field. */
760
761recording::field *
762recording::context::new_field (recording::location *loc,
763 recording::type *type,
764 const char *name)
765{
766 recording::field *result =
767 new recording::field (this, loc, type, new_string (name));
768 record (result);
769 return result;
770}
771
772/* Create a recording::struct_ instance and add it to this context's
773 list of mementos and list of compound types.
774
775 Implements the post-error-checking part of
776 gcc_jit_context_new_struct_type. */
777
778recording::struct_ *
779recording::context::new_struct_type (recording::location *loc,
780 const char *name)
781{
782 recording::struct_ *result = new struct_ (this, loc, new_string (name));
783 record (result);
784 m_compound_types.safe_push (result);
785 return result;
786}
787
788/* Create a recording::union_ instance and add it to this context's
789 list of mementos and list of compound types.
790
791 Implements the first post-error-checking part of
792 gcc_jit_context_new_union_type. */
793
794recording::union_ *
795recording::context::new_union_type (recording::location *loc,
796 const char *name)
797{
798 recording::union_ *result = new union_ (this, loc, new_string (name));
799 record (result);
800 m_compound_types.safe_push (result);
801 return result;
802}
803
c8d19a69
DM
804/* Create a recording::function_type instance and add it to this context's
805 list of mementos.
806
807 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
808
809recording::function_type *
810recording::context::new_function_type (recording::type *return_type,
811 int num_params,
812 recording::type **param_types,
813 int is_variadic)
814{
815 recording::function_type *fn_type
816 = new function_type (this,
817 return_type,
818 num_params,
819 param_types,
820 is_variadic);
821 record (fn_type);
822 return fn_type;
823}
824
35485da9
DM
825/* Create a recording::type instance and add it to this context's list
826 of mementos.
827
828 Implements the post-error-checking part of
829 gcc_jit_context_new_function_ptr_type. */
830
831recording::type *
832recording::context::new_function_ptr_type (recording::location *, /* unused loc */
833 recording::type *return_type,
834 int num_params,
835 recording::type **param_types,
836 int is_variadic)
837{
c8d19a69
DM
838 recording::function_type *fn_type
839 = new_function_type (return_type,
840 num_params,
841 param_types,
842 is_variadic);
35485da9
DM
843
844 /* Return a pointer-type to the the function type. */
845 return fn_type->get_pointer ();
846}
847
848/* Create a recording::param instance and add it to this context's list
849 of mementos.
850
851 Implements the post-error-checking part of
852 gcc_jit_context_new_param. */
853
854recording::param *
855recording::context::new_param (recording::location *loc,
856 recording::type *type,
857 const char *name)
858{
859 recording::param *result = new recording::param (this, loc, type, new_string (name));
860 record (result);
861 return result;
862}
863
864/* Create a recording::function instance and add it to this context's list
865 of mementos and list of functions.
866
867 Implements the post-error-checking part of
868 gcc_jit_context_new_function. */
869
870recording::function *
871recording::context::new_function (recording::location *loc,
872 enum gcc_jit_function_kind kind,
873 recording::type *return_type,
874 const char *name,
875 int num_params,
876 recording::param **params,
877 int is_variadic,
878 enum built_in_function builtin_id)
879{
880 recording::function *result =
881 new recording::function (this,
882 loc, kind, return_type,
883 new_string (name),
884 num_params, params, is_variadic,
885 builtin_id);
886 record (result);
887 m_functions.safe_push (result);
888
889 return result;
890}
891
eeafb319
DM
892/* Locate the builtins_manager (if any) for this family of contexts,
893 creating it if it doesn't exist already.
894
895 All of the recording contexts in a family share one builtins_manager:
896 if we have a child context, follow the parent links to get the
897 ultimate ancestor context, and look for it/store it there. */
898
899builtins_manager *
900recording::context::get_builtins_manager ()
901{
902 if (m_parent_ctxt)
903 return m_parent_ctxt->get_builtins_manager ();
904
905 if (!m_builtins_manager)
906 m_builtins_manager = new builtins_manager (this);
907
908 return m_builtins_manager;
909}
910
35485da9
DM
911/* Get a recording::function instance, which is lazily-created and added
912 to the context's lists of mementos.
913
914 Implements the post-error-checking part of
915 gcc_jit_context_get_builtin_function. */
916
917recording::function *
918recording::context::get_builtin_function (const char *name)
919{
eeafb319
DM
920 builtins_manager *bm = get_builtins_manager ();
921 return bm->get_builtin_function (name);
35485da9
DM
922}
923
924/* Create a recording::global instance and add it to this context's list
925 of mementos.
926
927 Implements the post-error-checking part of
928 gcc_jit_context_new_global. */
929
930recording::lvalue *
931recording::context::new_global (recording::location *loc,
791cfef8 932 enum gcc_jit_global_kind kind,
35485da9
DM
933 recording::type *type,
934 const char *name)
935{
791cfef8
DM
936 recording::global *result =
937 new recording::global (this, loc, kind, type, new_string (name));
35485da9 938 record (result);
791cfef8
DM
939 m_globals.safe_push (result);
940
35485da9
DM
941 return result;
942}
943
35485da9
DM
944/* Create a recording::memento_of_new_string_literal instance and add it
945 to this context's list of mementos.
946
947 Implements the post-error-checking part of
948 gcc_jit_context_new_string_literal. */
949
950recording::rvalue *
951recording::context::new_string_literal (const char *value)
952{
953 recording::rvalue *result =
954 new memento_of_new_string_literal (this, NULL, new_string (value));
955 record (result);
956 return result;
957}
958
959/* Create a recording::unary_op instance and add it to this context's
960 list of mementos.
961
962 Implements the post-error-checking part of
963 gcc_jit_context_new_unary_op. */
964
965recording::rvalue *
966recording::context::new_unary_op (recording::location *loc,
967 enum gcc_jit_unary_op op,
968 recording::type *result_type,
969 recording::rvalue *a)
970{
971 recording::rvalue *result =
972 new unary_op (this, loc, op, result_type, a);
973 record (result);
974 return result;
975}
976
977/* Create a recording::binary_op instance and add it to this context's
978 list of mementos.
979
980 Implements the post-error-checking part of
981 gcc_jit_context_new_binary_op. */
982
983recording::rvalue *
984recording::context::new_binary_op (recording::location *loc,
985 enum gcc_jit_binary_op op,
986 recording::type *result_type,
987 recording::rvalue *a,
988 recording::rvalue *b)
989{
990 recording::rvalue *result =
991 new binary_op (this, loc, op, result_type, a, b);
992 record (result);
993 return result;
994}
995
996/* Create a recording::comparison instance and add it to this context's
997 list of mementos.
998
999 Implements the post-error-checking part of
1000 gcc_jit_context_new_comparison. */
1001
1002recording::rvalue *
1003recording::context::new_comparison (recording::location *loc,
1004 enum gcc_jit_comparison op,
1005 recording::rvalue *a,
1006 recording::rvalue *b)
1007{
1008 recording::rvalue *result = new comparison (this, loc, op, a, b);
1009 record (result);
1010 return result;
1011}
1012
1013/* Create a recording::cast instance and add it to this context's list
1014 of mementos.
1015
1016 Implements the post-error-checking part of
1017 gcc_jit_context_new_cast. */
1018
1019recording::rvalue *
1020recording::context::new_cast (recording::location *loc,
1021 recording::rvalue *expr,
1022 recording::type *type_)
1023{
1024 recording::rvalue *result = new cast (this, loc, expr, type_);
1025 record (result);
1026 return result;
1027}
1028
1029/* Create a recording::call instance and add it to this context's list
1030 of mementos.
1031
1032 Implements the post-error-checking part of
1033 gcc_jit_context_new_call. */
1034
1035recording::rvalue *
1036recording::context::new_call (recording::location *loc,
1037 function *func,
1038 int numargs , recording::rvalue **args)
1039{
1040 recording::rvalue *result = new call (this, loc, func, numargs, args);
1041 record (result);
1042 return result;
1043}
1044
1045/* Create a recording::call_through_ptr instance and add it to this
1046 context's list of mementos.
1047
1048 Implements the post-error-checking part of
1049 gcc_jit_context_new_call_through_ptr. */
1050
1051recording::rvalue *
1052recording::context::new_call_through_ptr (recording::location *loc,
1053 recording::rvalue *fn_ptr,
1054 int numargs,
1055 recording::rvalue **args)
1056 {
1057 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
1058 record (result);
1059 return result;
1060}
1061
1062/* Create a recording::array_access instance and add it to this context's list
1063 of mementos.
1064
1065 Implements the post-error-checking part of
1066 gcc_jit_context_new_array_access. */
1067
1068recording::lvalue *
1069recording::context::new_array_access (recording::location *loc,
1070 recording::rvalue *ptr,
1071 recording::rvalue *index)
1072{
1073 recording::lvalue *result = new array_access (this, loc, ptr, index);
1074 record (result);
1075 return result;
1076}
1077
1078/* Set the given string option for this context, or add an error if
1079 it's not recognized.
1080
1081 Implements the post-error-checking part of
1082 gcc_jit_context_set_str_option. */
1083
1084void
1085recording::context::set_str_option (enum gcc_jit_str_option opt,
1086 const char *value)
1087{
1088 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
1089 {
1090 add_error (NULL,
1091 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
1092 return;
1093 }
c168eab9 1094 free (m_str_options[opt]);
1f0858d7 1095 m_str_options[opt] = value ? xstrdup (value) : NULL;
35485da9
DM
1096}
1097
1098/* Set the given integer option for this context, or add an error if
1099 it's not recognized.
1100
1101 Implements the post-error-checking part of
1102 gcc_jit_context_set_int_option. */
1103
1104void
1105recording::context::set_int_option (enum gcc_jit_int_option opt,
1106 int value)
1107{
1108 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
1109 {
1110 add_error (NULL,
1111 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
1112 return;
1113 }
1114 m_int_options[opt] = value;
1115}
1116
1117/* Set the given boolean option for this context, or add an error if
1118 it's not recognized.
1119
1120 Implements the post-error-checking part of
1121 gcc_jit_context_set_bool_option. */
1122
1123void
1124recording::context::set_bool_option (enum gcc_jit_bool_option opt,
1125 int value)
1126{
1127 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
1128 {
1129 add_error (NULL,
1130 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
1131 return;
1132 }
1133 m_bool_options[opt] = value ? true : false;
1134}
1135
463366a0
DM
1136/* Add the given dumpname/out_ptr pair to this context's list of requested
1137 dumps.
1138
1139 Implements the post-error-checking part of
1140 gcc_jit_context_enable_dump. */
1141
1142void
1143recording::context::enable_dump (const char *dumpname,
1144 char **out_ptr)
1145{
1146 requested_dump d;
1147 gcc_assert (dumpname);
1148 gcc_assert (out_ptr);
1149
1150 d.m_dumpname = dumpname;
1151 d.m_out_ptr = out_ptr;
1152 *out_ptr = NULL;
1153 m_requested_dumps.safe_push (d);
1154}
1155
fdce7209
DM
1156/* Validate this context, and if it passes, compile it to memory
1157 (within a mutex).
35485da9
DM
1158
1159 Implements the post-error-checking part of
1160 gcc_jit_context_compile. */
1161
1162result *
1163recording::context::compile ()
1164{
eb4c16eb
DM
1165 JIT_LOG_SCOPE (get_logger ());
1166
35485da9
DM
1167 validate ();
1168
1169 if (errors_occurred ())
1170 return NULL;
1171
fdce7209
DM
1172 /* Set up a compile_to_memory playback context. */
1173 ::gcc::jit::playback::compile_to_memory replayer (this);
35485da9 1174
38771e4e 1175 /* Use it. */
fdce7209 1176 replayer.compile ();
35485da9 1177
fdce7209
DM
1178 /* Get the jit::result (or NULL) from the
1179 compile_to_memory playback context. */
1180 return replayer.get_result_obj ();
1181}
1182
1183/* Validate this context, and if it passes, compile it to a file
1184 (within a mutex).
1185
1186 Implements the post-error-checking part of
1187 gcc_jit_context_compile_to_file. */
1188
1189void
1190recording::context::compile_to_file (enum gcc_jit_output_kind output_kind,
1191 const char *output_path)
1192{
1193 JIT_LOG_SCOPE (get_logger ());
1194
1195 validate ();
1196
1197 if (errors_occurred ())
1198 return;
1199
1200 /* Set up a compile_to_file playback context. */
1201 ::gcc::jit::playback::compile_to_file replayer (this,
1202 output_kind,
1203 output_path);
1204
1205 /* Use it. */
1206 replayer.compile ();
35485da9
DM
1207}
1208
1209/* Format the given error using printf's conventions, print
1210 it to stderr, and add it to the context. */
1211
1212void
1213recording::context::add_error (location *loc, const char *fmt, ...)
1214{
1215 va_list ap;
1216 va_start (ap, fmt);
1217 add_error_va (loc, fmt, ap);
1218 va_end (ap);
1219}
1220
1221/* Format the given error using printf's conventions, print
1222 it to stderr, and add it to the context. */
1223
1224void
1225recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
1226{
1227 char *malloced_msg;
1228 const char *errmsg;
1229 bool has_ownership;
1230
eb4c16eb
DM
1231 JIT_LOG_SCOPE (get_logger ());
1232
35485da9
DM
1233 vasprintf (&malloced_msg, fmt, ap);
1234 if (malloced_msg)
1235 {
1236 errmsg = malloced_msg;
1237 has_ownership = true;
1238 }
1239 else
1240 {
1241 errmsg = "out of memory generating error message";
1242 has_ownership = false;
1243 }
eb4c16eb
DM
1244 if (get_logger ())
1245 get_logger ()->log ("error %i: %s", m_error_count, errmsg);
35485da9
DM
1246
1247 const char *ctxt_progname =
1248 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
1249 if (!ctxt_progname)
1250 ctxt_progname = "libgccjit.so";
1251
1252 if (loc)
1253 fprintf (stderr, "%s: %s: error: %s\n",
1254 ctxt_progname,
1255 loc->get_debug_string (),
1256 errmsg);
1257 else
1258 fprintf (stderr, "%s: error: %s\n",
1259 ctxt_progname,
1260 errmsg);
1261
1262 if (!m_error_count)
1263 {
1264 m_first_error_str = const_cast <char *> (errmsg);
1265 m_owns_first_error_str = has_ownership;
1266 }
303e1d56
DM
1267
1268 if (m_owns_last_error_str)
1269 if (m_last_error_str != m_first_error_str)
1270 free (m_last_error_str);
1271 m_last_error_str = const_cast <char *> (errmsg);
1272 m_owns_last_error_str = has_ownership;
35485da9
DM
1273
1274 m_error_count++;
1275}
1276
1277/* Get the message for the first error that occurred on this context, or
1278 NULL if no errors have occurred on it.
1279
1280 Implements the post-error-checking part of
1281 gcc_jit_context_get_first_error. */
1282
1283const char *
1284recording::context::get_first_error () const
1285{
1286 return m_first_error_str;
1287}
1288
303e1d56
DM
1289/* Get the message for the last error that occurred on this context, or
1290 NULL if no errors have occurred on it.
1291
1292 Implements the post-error-checking part of
1293 gcc_jit_context_get_last_error. */
1294
1295const char *
1296recording::context::get_last_error () const
1297{
1298 return m_last_error_str;
1299}
1300
35485da9
DM
1301/* Lazily generate and record a recording::type representing an opaque
1302 struct named "FILE".
1303
1304 For use if client code tries to dereference the result of
1305 get_type (GCC_JIT_TYPE_FILE_PTR). */
1306
1307recording::type *
1308recording::context::get_opaque_FILE_type ()
1309{
1310 if (!m_FILE_type)
1311 m_FILE_type = new_struct_type (NULL, "FILE");
1312 return m_FILE_type;
1313}
1314
1315/* Dump a C-like representation of the given context to the given path.
1316 If UPDATE_LOCATIONS is true, update the locations within the
1317 context's mementos to point to the dumpfile.
1318
1319 Implements the post-error-checking part of
1320 gcc_jit_context_dump_to_file. */
1321
1322void
1323recording::context::dump_to_file (const char *path, bool update_locations)
1324{
1325 int i;
1326 dump d (*this, path, update_locations);
1327
1328 /* Forward declaration of structs and unions. */
1329 compound_type *st;
1330 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1331 {
1332 d.write ("%s;\n\n", st->get_debug_string ());
1333 }
1334
1335 /* Content of structs, where set. */
1336 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1337 if (st->get_fields ())
1338 {
1339 st->get_fields ()->write_to_dump (d);
1340 d.write ("\n");
1341 }
1342
791cfef8
DM
1343 /* Globals. */
1344 global *g;
1345 FOR_EACH_VEC_ELT (m_globals, i, g)
1346 {
1347 g->write_to_dump (d);
1348 }
1349 if (!m_globals.is_empty ())
1350 d.write ("\n");
1351
35485da9
DM
1352 function *fn;
1353 FOR_EACH_VEC_ELT (m_functions, i, fn)
1354 {
1355 fn->write_to_dump (d);
1356 }
1357}
1358
86d0ac88
DM
1359static const char * const
1360 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = {
1361 "GCC_JIT_STR_OPTION_PROGNAME"
1362};
1363
1364static const char * const
1365 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = {
1366 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL"
1367};
1368
1369static const char * const
1370 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = {
1371 "GCC_JIT_BOOL_OPTION_DEBUGINFO",
1372 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE",
1373 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE",
1374 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE",
1375 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY",
1376 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING",
1377 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC",
1378 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES"
1379};
1380
1381/* Write C source code to PATH that attempts to replay the API
1382 calls made to this context (and its parents), for use in
1383 minimizing test cases for libgccjit.
1384
1385 Implements the post-error-checking part of
1386 gcc_jit_context_dump_reproducer_to_file. */
1387
1388void
1389recording::context::dump_reproducer_to_file (const char *path)
1390{
1391 JIT_LOG_SCOPE (get_logger ());
1392 reproducer r (*this, path);
1393
1394 /* Generate the "ancestry" of this context, as a list. */
1395 auto_vec <context *> ascending_contexts;
1396 for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt)
1397 ascending_contexts.safe_push (ctxt);
1398
1399 /* Reverse the list, giving a list of contexts from
1400 top-most parent context down through to youngest child context.
1401 We will use this list as the parameters of the functions in
1402 our generated file. */
1403 unsigned num_ctxts = ascending_contexts.length ();
1404 auto_vec <context *> contexts (num_ctxts);
1405 for (unsigned i = 0; i < num_ctxts; i++)
1406 contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]);
1407
1408 /* contexts[0] should be the top-level context. */
1409 gcc_assert (contexts[0]);
1410 gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]);
1411
1412 /* The final element in contexts should be "this". */
1413 gcc_assert (contexts[contexts.length () - 1] == this);
1414 gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt
1415 == contexts[0]);
1416
1417 r.write ("/* This code was autogenerated by"
53c04ec9
DM
1418 " gcc_jit_context_dump_reproducer_to_file.\n\n");
1419 print_version (r.get_file (), " ", false);
1420 r.write ("*/\n");
86d0ac88
DM
1421 r.write ("#include <libgccjit.h>\n\n");
1422 r.write ("static void\nset_options (");
1423 r.write_params (contexts);
1424 r.write (");\n\n");
1425 r.write ("static void\ncreate_code (");
1426 r.write_params (contexts);
1427 r.write (");\n\n");
1428 r.write ("int\nmain (int argc, const char **argv)\n");
1429 r.write ("{\n");
1430 for (unsigned i = 0; i < num_ctxts; i++)
1431 r.write (" gcc_jit_context *%s;\n",
1432 r.get_identifier (contexts[i]));
1433 r.write (" gcc_jit_result *result;\n"
1434 "\n");
1435
1436 /* Create the contexts.
1437 The top-level context is acquired from a clean slate, the others as
1438 children of the prior context. */
1439 r.write (" %s = gcc_jit_context_acquire ();\n",
1440 r.get_identifier (contexts[0]));
1441 for (unsigned i = 1; i < num_ctxts; i++)
1442 r.write (" %s = gcc_jit_context_new_child_context (%s);\n",
1443 r.get_identifier (contexts[i]),
1444 r.get_identifier (contexts[i - 1]));
1445 r.write (" set_options (");
1446 r.write_args (contexts);
1447 r.write (");\n");
1448 r.write (" create_code (");
1449 r.write_args (contexts);
1450 r.write (");\n");
1451
1452 r.write (" result = gcc_jit_context_compile (%s);\n",
1453 r.get_identifier (this));
1454
1455 for (unsigned i = num_ctxts; i > 0; i--)
1456 r.write (" gcc_jit_context_release (%s);\n",
1457 r.get_identifier (contexts[i - 1]));
1458
1459 r.write (" gcc_jit_result_release (result);\n"
1460 " return 0;\n"
1461 "}\n\n");
1462
1463 /* Define (char *) variables for use in calls to
1464 gcc_jit_context_enable_dump. */
1465 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1466 {
1467 if (m_requested_dumps.length ())
1468 {
1469 r.write ("/* Requested dumps for %s. */\n",
1470 r.get_identifier (contexts[ctxt_idx]));
1471 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1472 r.write ("static char *dump_%p;\n",
1473 (void *)&m_requested_dumps[i]);
1474 r.write ("\n");
1475 }
1476 }
1477
1478 /* Write out values of options. */
1479 r.write ("static void\nset_options (");
1480 r.write_params (contexts);
1481 r.write (")\n{\n");
1482 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1483 {
1484 if (ctxt_idx > 0)
1485 r.write ("\n");
1486
1487 r.write (" /* Set options for %s. */\n",
1488 r.get_identifier (contexts[ctxt_idx]));
1489
1490 r.write (" /* String options. */\n");
1491 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++)
1492 r.write (" gcc_jit_context_set_str_option (%s,\n"
1493 " %s,\n"
1494 " \"%s\");\n",
1495 r.get_identifier (contexts[ctxt_idx]),
1496 str_option_reproducer_strings[opt_idx],
1497 m_str_options[opt_idx] ? m_str_options[opt_idx] : "NULL");
1498 r.write (" /* Int options. */\n");
1499 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++)
1500 r.write (" gcc_jit_context_set_int_option (%s,\n"
1501 " %s,\n"
1502 " %i);\n",
1503 r.get_identifier (contexts[ctxt_idx]),
1504 int_option_reproducer_strings[opt_idx],
1505 m_int_options[opt_idx]);
1506 r.write (" /* Boolean options. */\n");
1507 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++)
1508 r.write (" gcc_jit_context_set_bool_option (%s,\n"
1509 " %s,\n"
1510 " %i);\n",
1511 r.get_identifier (contexts[ctxt_idx]),
1512 bool_option_reproducer_strings[opt_idx],
1513 m_bool_options[opt_idx]);
1514
1515 if (m_requested_dumps.length ())
1516 {
1517 r.write (" /* Requested dumps. */\n");
1518 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */
1519 for (unsigned i = 0; i < m_requested_dumps.length (); i++)
1520 {
1521 r.write (" gcc_jit_context_enable_dump (%s,\n"
1522 " \"%s\",\n"
1523 " &dump_%p);\n",
1524 r.get_identifier (contexts[ctxt_idx]),
1525 m_requested_dumps[i].m_dumpname,
1526 (void *)&m_requested_dumps[i]);
1527 }
1528 }
1529 }
1530 r.write ("}\n\n");
1531
1532 r.write ("static void\ncreate_code (");
1533 r.write_params (contexts);
1534 r.write (")\n"
1535 "{\n");
1536 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++)
1537 {
1538 memento *m;
1539 int i;
1540 if (ctxt_idx > 0)
1541 r.write ("\n\n");
1542
1543 r.write (" /* Replay of API calls for %s. */\n",
1544 r.get_identifier (contexts[ctxt_idx]));
1545 FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m)
1546 m->write_reproducer (r);
1547 }
1548 r.write ("}\n");
1549}
1550
463366a0
DM
1551/* Copy the requested dumps within this context and all ancestors into
1552 OUT. */
1553
1554void
1555recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
1556{
1557 if (m_parent_ctxt)
1558 m_parent_ctxt->get_all_requested_dumps (out);
1559
1560 out->reserve (m_requested_dumps.length ());
1561 out->splice (m_requested_dumps);
1562}
1563
35485da9
DM
1564/* This is a pre-compilation check for the context (and any parents).
1565
1566 Detect errors within the context, adding errors if any are found. */
1567
1568void
1569recording::context::validate ()
1570{
eb4c16eb
DM
1571 JIT_LOG_SCOPE (get_logger ());
1572
35485da9
DM
1573 if (m_parent_ctxt)
1574 m_parent_ctxt->validate ();
1575
1576 int i;
1577 function *fn;
1578 FOR_EACH_VEC_ELT (m_functions, i, fn)
1579 fn->validate ();
1580}
1581
1582/* The implementation of class gcc::jit::recording::memento. */
1583
1584/* Get a (const char *) debug description of the given memento, by
1585 calling the pure-virtual make_debug_string hook, caching the
1586 result.
1587
1588 It is intended that this should only be called in debugging and
1589 error-handling paths, so this doesn't need to be particularly
1590 optimized. */
1591
1592const char *
1593recording::memento::get_debug_string ()
1594{
1595 if (!m_debug_string)
1596 m_debug_string = make_debug_string ();
1597 return m_debug_string->c_str ();
1598}
1599
1600/* Default implementation of recording::memento::write_to_dump, writing
1601 an indented form of the memento's debug string to the dump. */
1602
1603void
1604recording::memento::write_to_dump (dump &d)
1605{
1606 d.write(" %s\n", get_debug_string ());
1607}
1608
1609/* The implementation of class gcc::jit::recording::string. */
1610
1611/* Constructor for gcc::jit::recording::string::string, allocating a
1612 copy of the given text using new char[]. */
1613
1614recording::string::string (context *ctxt, const char *text)
1615 : memento (ctxt)
1616{
1617 m_len = strlen (text);
1618 m_buffer = new char[m_len + 1];
1619 strcpy (m_buffer, text);
1620}
1621
1622/* Destructor for gcc::jit::recording::string::string. */
1623
1624recording::string::~string ()
1625{
1626 delete[] m_buffer;
1627}
1628
1629/* Function for making gcc::jit::recording::string instances on a
1630 context via printf-style formatting.
1631
1632 It is intended that this should only be called in debugging and
1633 error-handling paths, so this doesn't need to be particularly
1634 optimized, hence the double-copy of the string is acceptable. */
1635
1636recording::string *
1637recording::string::from_printf (context *ctxt, const char *fmt, ...)
1638{
1639 va_list ap;
1640 char *buf = NULL;
1641 recording::string *result;
1642
1643 va_start (ap, fmt);
1644 vasprintf (&buf, fmt, ap);
1645 va_end (ap);
1646
1647 if (!buf)
1648 {
1649 ctxt->add_error (NULL, "malloc failure");
1650 return NULL;
1651 }
1652
1653 result = ctxt->new_string (buf);
1654 free (buf);
1655 return result;
1656}
1657
1658/* Implementation of recording::memento::make_debug_string for strings,
1659 wrapping the given string in quotes and escaping as necessary. */
1660
1661recording::string *
1662recording::string::make_debug_string ()
1663{
1664 /* Hack to avoid infinite recursion into strings when logging all
1665 mementos: don't re-escape strings: */
1666 if (m_buffer[0] == '"')
1667 return this;
1668
1669 /* Wrap in quotes and do escaping etc */
1670
1671 size_t sz = (1 /* opening quote */
1672 + (m_len * 2) /* each char might get escaped */
1673 + 1 /* closing quote */
1674 + 1); /* nil termintator */
1675 char *tmp = new char[sz];
1676 size_t len = 0;
1677
1678#define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1679 APPEND('"'); /* opening quote */
1680 for (size_t i = 0; i < m_len ; i++)
1681 {
1682 char ch = m_buffer[i];
1683 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
1684 APPEND('\\');
1685 APPEND(ch);
1686 }
1687 APPEND('"'); /* closing quote */
1688#undef APPEND
1689 tmp[len] = '\0'; /* nil termintator */
1690
1691 string *result = m_ctxt->new_string (tmp);
1692
1693 delete[] tmp;
1694 return result;
1695}
1696
86d0ac88
DM
1697/* Implementation of recording::memento::write_reproducer for strings. */
1698
1699void
1700recording::string::write_reproducer (reproducer &)
1701{
1702 /* Empty. */
1703}
1704
35485da9
DM
1705/* The implementation of class gcc::jit::recording::location. */
1706
1707/* Implementation of recording::memento::replay_into for locations.
1708
1709 Create a new playback::location and store it into the
1710 recording::location's m_playback_obj field. */
1711
1712void
1713recording::location::replay_into (replayer *r)
1714{
1715 m_playback_obj = r->new_location (this,
1716 m_filename->c_str (),
1717 m_line,
1718 m_column);
1719}
1720
1721/* Implementation of recording::memento::make_debug_string for locations,
1722 turning them into the usual form:
1723 FILENAME:LINE:COLUMN
1724 like we do when emitting diagnostics. */
1725
1726recording::string *
1727recording::location::make_debug_string ()
1728{
1729 return string::from_printf (m_ctxt,
1730 "%s:%i:%i",
1731 m_filename->c_str (), m_line, m_column);
1732}
1733
86d0ac88
DM
1734/* Implementation of recording::memento::write_reproducer for locations. */
1735
1736void
1737recording::location::write_reproducer (reproducer &r)
1738{
1739 const char *id = r.make_identifier (this, "loc");
1740 r.write (" gcc_jit_location *%s =\n"
1741 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n"
1742 " %s, /* const char *filename */\n"
1743 " %i, /* int line */\n"
1744 " %i);/* int column */\n",
1745 id,
1746 r.get_identifier (get_context ()),
1747 m_filename->get_debug_string (),
1748 m_line, m_column);
1749}
1750
35485da9
DM
1751/* The implementation of class gcc::jit::recording::type. */
1752
1753/* Given a type T, get the type T*.
1754
1755 If this doesn't already exist, generate a new memento_of_get_pointer
1756 instance and add it to this type's context's list of mementos.
1757
1758 Otherwise, use the cached type.
1759
1760 Implements the post-error-checking part of
1761 gcc_jit_type_get_pointer. */
1762
1763recording::type *
1764recording::type::get_pointer ()
1765{
1766 if (!m_pointer_to_this_type)
1767 {
1768 m_pointer_to_this_type = new memento_of_get_pointer (this);
1769 m_ctxt->record (m_pointer_to_this_type);
1770 }
1771 return m_pointer_to_this_type;
1772}
1773
1774/* Given a type T, get the type const T.
1775
1776 Implements the post-error-checking part of
1777 gcc_jit_type_get_const. */
1778
1779recording::type *
1780recording::type::get_const ()
1781{
1782 recording::type *result = new memento_of_get_const (this);
1783 m_ctxt->record (result);
1784 return result;
1785}
1786
1787/* Given a type T, get the type volatile T.
1788
1789 Implements the post-error-checking part of
1790 gcc_jit_type_get_volatile. */
1791
1792recording::type *
1793recording::type::get_volatile ()
1794{
1795 recording::type *result = new memento_of_get_volatile (this);
1796 m_ctxt->record (result);
1797 return result;
1798}
1799
86d0ac88
DM
1800const char *
1801recording::type::access_as_type (reproducer &r)
1802{
1803 return r.get_identifier (this);
1804}
1805
35485da9
DM
1806/* Implementation of pure virtual hook recording::type::dereference for
1807 recording::memento_of_get_type. */
1808
1809recording::type *
1810recording::memento_of_get_type::dereference ()
1811{
1812 switch (m_kind)
1813 {
1814 default: gcc_unreachable ();
1815
1816 case GCC_JIT_TYPE_VOID:
1817 return NULL;
1818
1819 case GCC_JIT_TYPE_VOID_PTR:
1820 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
1821
1822 case GCC_JIT_TYPE_BOOL:
1823 case GCC_JIT_TYPE_CHAR:
1824 case GCC_JIT_TYPE_SIGNED_CHAR:
1825 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1826 case GCC_JIT_TYPE_SHORT:
1827 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1828 case GCC_JIT_TYPE_INT:
1829 case GCC_JIT_TYPE_UNSIGNED_INT:
1830 case GCC_JIT_TYPE_LONG:
1831 case GCC_JIT_TYPE_UNSIGNED_LONG:
1832 case GCC_JIT_TYPE_LONG_LONG:
1833 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1834 case GCC_JIT_TYPE_FLOAT:
1835 case GCC_JIT_TYPE_DOUBLE:
1836 case GCC_JIT_TYPE_LONG_DOUBLE:
eeafb319
DM
1837 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1838 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1839 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
35485da9
DM
1840 /* Not a pointer: */
1841 return NULL;
1842
1843 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1844 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
1845
1846 case GCC_JIT_TYPE_SIZE_T:
1847 /* Not a pointer: */
1848 return NULL;
1849
1850 case GCC_JIT_TYPE_FILE_PTR:
1851 /* Give the client code back an opaque "struct FILE". */
1852 return m_ctxt->get_opaque_FILE_type ();
1853 }
1854}
1855
1856/* Implementation of pure virtual hook recording::type::is_int for
1857 recording::memento_of_get_type. */
1858
1859bool
1860recording::memento_of_get_type::is_int () const
1861{
1862 switch (m_kind)
1863 {
1864 default: gcc_unreachable ();
1865
1866 case GCC_JIT_TYPE_VOID:
1867 return false;
1868
1869 case GCC_JIT_TYPE_VOID_PTR:
1870 return false;
1871
1872 case GCC_JIT_TYPE_BOOL:
1873 return false;
1874
1875 case GCC_JIT_TYPE_CHAR:
1876 case GCC_JIT_TYPE_SIGNED_CHAR:
1877 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1878 case GCC_JIT_TYPE_SHORT:
1879 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1880 case GCC_JIT_TYPE_INT:
1881 case GCC_JIT_TYPE_UNSIGNED_INT:
1882 case GCC_JIT_TYPE_LONG:
1883 case GCC_JIT_TYPE_UNSIGNED_LONG:
1884 case GCC_JIT_TYPE_LONG_LONG:
1885 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1886 return true;
1887
1888 case GCC_JIT_TYPE_FLOAT:
1889 case GCC_JIT_TYPE_DOUBLE:
1890 case GCC_JIT_TYPE_LONG_DOUBLE:
1891 return false;
1892
1893 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1894 return false;
1895
1896 case GCC_JIT_TYPE_SIZE_T:
1897 return true;
1898
1899 case GCC_JIT_TYPE_FILE_PTR:
1900 return false;
eeafb319
DM
1901
1902 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1903 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1904 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
1905 return false;
35485da9
DM
1906 }
1907}
1908
1909/* Implementation of pure virtual hook recording::type::is_float for
1910 recording::memento_of_get_type. */
1911
1912bool
1913recording::memento_of_get_type::is_float () const
1914{
1915 switch (m_kind)
1916 {
1917 default: gcc_unreachable ();
1918
1919 case GCC_JIT_TYPE_VOID:
1920 return false;
1921
1922 case GCC_JIT_TYPE_VOID_PTR:
1923 return false;
1924
1925 case GCC_JIT_TYPE_BOOL:
1926 return false;
1927
1928 case GCC_JIT_TYPE_CHAR:
1929 case GCC_JIT_TYPE_SIGNED_CHAR:
1930 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1931 case GCC_JIT_TYPE_SHORT:
1932 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1933 case GCC_JIT_TYPE_INT:
1934 case GCC_JIT_TYPE_UNSIGNED_INT:
1935 case GCC_JIT_TYPE_LONG:
1936 case GCC_JIT_TYPE_UNSIGNED_LONG:
1937 case GCC_JIT_TYPE_LONG_LONG:
1938 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1939 return false;
1940
1941 case GCC_JIT_TYPE_FLOAT:
1942 case GCC_JIT_TYPE_DOUBLE:
1943 case GCC_JIT_TYPE_LONG_DOUBLE:
1944 return true;
1945
1946 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1947 return false;
1948
1949 case GCC_JIT_TYPE_SIZE_T:
1950 return false;
1951
1952 case GCC_JIT_TYPE_FILE_PTR:
1953 return false;
eeafb319
DM
1954
1955 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1956 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1957 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
1958 return true;
35485da9
DM
1959 }
1960}
1961
1962/* Implementation of pure virtual hook recording::type::is_bool for
1963 recording::memento_of_get_type. */
1964
1965bool
1966recording::memento_of_get_type::is_bool () const
1967{
1968 switch (m_kind)
1969 {
1970 default: gcc_unreachable ();
1971
1972 case GCC_JIT_TYPE_VOID:
1973 return false;
1974
1975 case GCC_JIT_TYPE_VOID_PTR:
1976 return false;
1977
1978 case GCC_JIT_TYPE_BOOL:
1979 return true;
1980
1981 case GCC_JIT_TYPE_CHAR:
1982 case GCC_JIT_TYPE_SIGNED_CHAR:
1983 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1984 case GCC_JIT_TYPE_SHORT:
1985 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1986 case GCC_JIT_TYPE_INT:
1987 case GCC_JIT_TYPE_UNSIGNED_INT:
1988 case GCC_JIT_TYPE_LONG:
1989 case GCC_JIT_TYPE_UNSIGNED_LONG:
1990 case GCC_JIT_TYPE_LONG_LONG:
1991 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1992 return false;
1993
1994 case GCC_JIT_TYPE_FLOAT:
1995 case GCC_JIT_TYPE_DOUBLE:
1996 case GCC_JIT_TYPE_LONG_DOUBLE:
1997 return false;
1998
1999 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2000 return false;
2001
2002 case GCC_JIT_TYPE_SIZE_T:
2003 return false;
2004
2005 case GCC_JIT_TYPE_FILE_PTR:
2006 return false;
eeafb319
DM
2007
2008 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2009 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2010 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2011 return false;
35485da9
DM
2012 }
2013}
2014
2015/* Implementation of pure virtual hook recording::memento::replay_into
2016 for recording::memento_of_get_type. */
2017
2018void
2019recording::memento_of_get_type::replay_into (replayer *r)
2020{
2021 set_playback_obj (r->get_type (m_kind));
2022}
2023
2024/* The implementation of class gcc::jit::recording::memento_of_get_type. */
2025
2026/* Descriptive strings for each of enum gcc_jit_types. */
2027
2028static const char * const get_type_strings[] = {
2029 "void", /* GCC_JIT_TYPE_VOID */
2030 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2031
2032 "bool", /* GCC_JIT_TYPE_BOOL */
2033
2034 "char", /* GCC_JIT_TYPE_CHAR */
2035 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2036 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2037
2038 "short", /* GCC_JIT_TYPE_SHORT */
2039 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2040
2041 "int", /* GCC_JIT_TYPE_INT */
2042 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2043
2044 "long", /* GCC_JIT_TYPE_LONG */
2045 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2046
2047 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2048 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2049
2050 "float", /* GCC_JIT_TYPE_FLOAT */
2051 "double", /* GCC_JIT_TYPE_DOUBLE */
2052 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2053
2054 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2055
2056 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2057
eeafb319
DM
2058 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2059
2060 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2061 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2062 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
35485da9
DM
2063
2064};
2065
2066/* Implementation of recording::memento::make_debug_string for
2067 results of get_type, using a simple table of type names. */
2068
2069recording::string *
2070recording::memento_of_get_type::make_debug_string ()
2071{
2072 return m_ctxt->new_string (get_type_strings[m_kind]);
2073}
2074
86d0ac88
DM
2075static const char * const get_type_enum_strings[] = {
2076 "GCC_JIT_TYPE_VOID",
2077 "GCC_JIT_TYPE_VOID_PTR",
2078 "GCC_JIT_TYPE_BOOL",
2079 "GCC_JIT_TYPE_CHAR",
2080 "GCC_JIT_TYPE_SIGNED_CHAR",
2081 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2082 "GCC_JIT_TYPE_SHORT",
2083 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2084 "GCC_JIT_TYPE_INT",
2085 "GCC_JIT_TYPE_UNSIGNED_INT",
2086 "GCC_JIT_TYPE_LONG",
2087 "GCC_JIT_TYPE_UNSIGNED_LONG",
2088 "GCC_JIT_TYPE_LONG_LONG",
2089 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2090 "GCC_JIT_TYPE_FLOAT",
2091 "GCC_JIT_TYPE_DOUBLE",
2092 "GCC_JIT_TYPE_LONG_DOUBLE",
2093 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2094 "GCC_JIT_TYPE_SIZE_T",
2095 "GCC_JIT_TYPE_FILE_PTR",
2096 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2097 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2098 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2099};
2100
2101void
2102recording::memento_of_get_type::write_reproducer (reproducer &r)
2103{
2104 const char *id = r.make_identifier (this, "type");
2105 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2106 id,
2107 r.get_identifier (get_context ()),
2108 get_type_enum_strings[m_kind]);
2109}
2110
35485da9
DM
2111/* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2112
2113/* Override of default implementation of
2114 recording::type::accepts_writes_from for get_pointer.
2115
2116 Require a pointer type, and allowing writes to
2117 (const T *) from a (T*), but not the other way around. */
2118
2119bool
2120recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2121{
2122 /* Must be a pointer type: */
2123 type *rtype_points_to = rtype->is_pointer ();
2124 if (!rtype_points_to)
2125 return false;
2126
2127 /* It's OK to assign to a (const T *) from a (T *). */
2128 return m_other_type->unqualified ()
2129 ->accepts_writes_from (rtype_points_to);
2130}
2131
2132/* Implementation of pure virtual hook recording::memento::replay_into
2133 for recording::memento_of_get_pointer. */
2134
2135void
2136recording::memento_of_get_pointer::replay_into (replayer *)
2137{
2138 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2139}
2140
2141/* Implementation of recording::memento::make_debug_string for
2142 results of get_pointer, adding " *" to the underlying type,
2143 with special-casing to handle function pointer types. */
2144
2145recording::string *
2146recording::memento_of_get_pointer::make_debug_string ()
2147{
2148 /* Special-case function pointer types, to put the "*" in parens between
2149 the return type and the params (for one level of dereferencing, at
2150 least). */
2151 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2152 return fn_type->make_debug_string_with_ptr ();
2153
2154 return string::from_printf (m_ctxt,
2155 "%s *", m_other_type->get_debug_string ());
2156}
2157
86d0ac88
DM
2158/* Implementation of recording::memento::write_reproducer for get_pointer. */
2159
2160void
2161recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2162{
2163 /* We need to special-case function pointer types; see the notes in
2164 recording::function_type::write_deferred_reproducer. */
2165 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2166 {
2167 fn_type->write_deferred_reproducer (r, this);
2168 return;
2169 }
2170
2171 const char *id = r.make_identifier (this, "type");
2172 r.write (" gcc_jit_type *%s =\n"
2173 " gcc_jit_type_get_pointer (%s);\n",
2174 id,
2175 r.get_identifier_as_type (m_other_type));
2176}
2177
35485da9
DM
2178/* The implementation of class gcc::jit::recording::memento_of_get_const. */
2179
2180/* Implementation of pure virtual hook recording::memento::replay_into
2181 for recording::memento_of_get_const. */
2182
2183void
2184recording::memento_of_get_const::replay_into (replayer *)
2185{
2186 set_playback_obj (m_other_type->playback_type ()->get_const ());
2187}
2188
2189/* Implementation of recording::memento::make_debug_string for
2190 results of get_const, prepending "const ". */
2191
2192recording::string *
2193recording::memento_of_get_const::make_debug_string ()
2194{
2195 return string::from_printf (m_ctxt,
2196 "const %s", m_other_type->get_debug_string ());
2197}
2198
86d0ac88
DM
2199/* Implementation of recording::memento::write_reproducer for const types. */
2200
2201void
2202recording::memento_of_get_const::write_reproducer (reproducer &r)
2203{
2204 const char *id = r.make_identifier (this, "type");
2205 r.write (" gcc_jit_type *%s =\n"
2206 " gcc_jit_type_get_const (%s);\n",
2207 id,
2208 r.get_identifier_as_type (m_other_type));
2209}
2210
35485da9
DM
2211/* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2212
2213/* Implementation of pure virtual hook recording::memento::replay_into
2214 for recording::memento_of_get_volatile. */
2215
2216void
2217recording::memento_of_get_volatile::replay_into (replayer *)
2218{
2219 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2220}
2221
2222/* Implementation of recording::memento::make_debug_string for
2223 results of get_volatile, prepending "volatile ". */
2224
2225recording::string *
2226recording::memento_of_get_volatile::make_debug_string ()
2227{
2228 return string::from_printf (m_ctxt,
2229 "volatile %s", m_other_type->get_debug_string ());
2230}
2231
86d0ac88
DM
2232/* Implementation of recording::memento::write_reproducer for volatile
2233 types. */
2234
2235void
2236recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2237{
2238 const char *id = r.make_identifier (this, "type");
2239 r.write (" gcc_jit_type *%s =\n"
2240 " gcc_jit_type_get_volatile (%s);\n",
2241 id,
2242 r.get_identifier_as_type (m_other_type));
2243}
2244
35485da9
DM
2245/* The implementation of class gcc::jit::recording::array_type */
2246
2247/* Implementation of pure virtual hook recording::type::dereference for
2248 recording::array_type. */
2249
2250recording::type *
2251recording::array_type::dereference ()
2252{
2253 return m_element_type;
2254}
2255
2256/* Implementation of pure virtual hook recording::memento::replay_into
2257 for recording::array_type. */
2258
2259void
2260recording::array_type::replay_into (replayer *r)
2261{
2262 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
2263 m_element_type->playback_type (),
2264 m_num_elements));
2265}
2266
2267/* Implementation of recording::memento::make_debug_string for
2268 results of new_array_type. */
2269
2270recording::string *
2271recording::array_type::make_debug_string ()
2272{
2273 return string::from_printf (m_ctxt,
2274 "%s[%d]",
2275 m_element_type->get_debug_string (),
2276 m_num_elements);
2277}
2278
86d0ac88
DM
2279/* Implementation of recording::memento::write_reproducer for array
2280 types. */
2281
2282void
2283recording::array_type::write_reproducer (reproducer &r)
2284{
2285 const char *id = r.make_identifier (this, "array_type");
2286 r.write (" gcc_jit_type *%s =\n"
2287 " gcc_jit_context_new_array_type (%s,\n"
2288 " %s, /* gcc_jit_location *loc */\n"
2289 " %s, /* gcc_jit_type *element_type */\n"
2290 " %i); /* int num_elements */\n",
2291 id,
2292 r.get_identifier (get_context ()),
2293 r.get_identifier (m_loc),
2294 r.get_identifier_as_type (m_element_type),
2295 m_num_elements);
2296}
2297
35485da9
DM
2298/* The implementation of class gcc::jit::recording::function_type */
2299
2300/* Constructor for gcc::jit::recording::function_type. */
2301
2302recording::function_type::function_type (context *ctxt,
2303 type *return_type,
2304 int num_params,
2305 type **param_types,
2306 int is_variadic)
2307: type (ctxt),
2308 m_return_type (return_type),
2309 m_param_types (),
2310 m_is_variadic (is_variadic)
2311{
2312 for (int i = 0; i< num_params; i++)
2313 m_param_types.safe_push (param_types[i]);
2314}
2315
2316/* Implementation of pure virtual hook recording::type::dereference for
2317 recording::function_type. */
2318
2319recording::type *
2320recording::function_type::dereference ()
2321{
2322 return NULL;
2323}
2324
2325/* Implementation of pure virtual hook recording::memento::replay_into
2326 for recording::function_type. */
2327
2328void
2329recording::function_type::replay_into (replayer *r)
2330{
2331 /* Convert m_param_types to a vec of playback type. */
b957b2e0 2332 auto_vec <playback::type *> param_types;
35485da9
DM
2333 int i;
2334 recording::type *type;
2335 param_types.create (m_param_types.length ());
2336 FOR_EACH_VEC_ELT (m_param_types, i, type)
2337 param_types.safe_push (type->playback_type ());
2338
2339 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
2340 &param_types,
2341 m_is_variadic));
2342}
2343
2344/* Special-casing for make_debug_string for get_pointer results for
2345 handling (one level) of pointers to functions. */
2346
2347recording::string *
2348recording::function_type::make_debug_string_with_ptr ()
2349{
2350 return make_debug_string_with ("(*) ");
2351}
2352
2353/* Implementation of recording::memento::make_debug_string for
2354 results of new_function_type. */
2355
2356recording::string *
2357recording::function_type::make_debug_string ()
2358{
2359 return make_debug_string_with ("");
2360}
2361
2362/* Build a debug string representation of the form:
2363
2364 RESULT_TYPE INSERT (PARAM_TYPES)
2365
2366 for use when handling 0 and 1 level of indirection to this
2367 function type. */
2368
2369recording::string *
2370recording::function_type::make_debug_string_with (const char *insert)
2371{
2372 /* First, build a buffer for the arguments. */
2373 /* Calculate length of said buffer. */
2374 size_t sz = 1; /* nil terminator */
2375 for (unsigned i = 0; i< m_param_types.length (); i++)
2376 {
2377 sz += strlen (m_param_types[i]->get_debug_string ());
2378 sz += 2; /* ", " separator */
2379 }
2380 if (m_is_variadic)
2381 sz += 5; /* ", ..." separator and ellipsis */
2382
2383 /* Now allocate and populate the buffer. */
2384 char *argbuf = new char[sz];
2385 size_t len = 0;
2386
2387 for (unsigned i = 0; i< m_param_types.length (); i++)
2388 {
2389 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
2390 len += strlen (m_param_types[i]->get_debug_string ());
2391 if (i + 1 < m_param_types.length ())
2392 {
2393 strcpy (argbuf + len, ", ");
2394 len += 2;
2395 }
2396 }
2397 if (m_is_variadic)
2398 {
2399 if (m_param_types.length ())
2400 {
2401 strcpy (argbuf + len, ", ");
2402 len += 2;
2403 }
2404 strcpy (argbuf + len, "...");
2405 len += 3;
2406 }
2407 argbuf[len] = '\0';
2408
2409 /* ...and use it to get the string for the call as a whole. */
2410 string *result = string::from_printf (m_ctxt,
2411 "%s %s(%s)",
2412 m_return_type->get_debug_string (),
2413 insert,
2414 argbuf);
2415
2416 delete[] argbuf;
2417
2418 return result;
2419}
2420
86d0ac88
DM
2421/* Implementation of recording::memento::write_reproducer for function
2422 types. */
2423
2424void
2425recording::function_type::write_reproducer (reproducer &)
2426{
2427 /* see notes below. */
2428}
2429
2430/* There's a get_pointer within context::new_function_ptr_type:
2431 the type received by client code isn't the memento for the
2432 function_type, but instead the result of get_pointer on it.
2433
2434 Hence we can't directly write a reproducer that gives function_type.
2435 Instead we special-case things within get_pointer, detecting this
2436 case, calling the following function. */
2437
2438void
2439recording::function_type::write_deferred_reproducer (reproducer &r,
2440 memento *ptr_type)
2441{
2442 gcc_assert (ptr_type);
2443 r.make_identifier (this, "function_type");
2444 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
2445 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
2446 r.write (" gcc_jit_type *%s[%i] = {\n",
2447 param_types_id,
2448 m_param_types.length ());
2449 int i;
2450 type *param_type;
2451 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2452 r.write (" %s,\n", r.get_identifier_as_type (param_type));
2453 r.write (" };\n");
2454 r.write (" gcc_jit_type *%s =\n"
2455 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2456 " %s, /* gcc_jit_location *loc */\n"
2457 " %s, /* gcc_jit_type *return_type */\n"
2458 " %i, /* int num_params */\n"
2459 " %s, /* gcc_jit_type **param_types */\n"
2460 " %i); /* int is_variadic */\n",
2461 ptr_id,
2462 r.get_identifier (get_context ()),
2463 "NULL", /* location is not stored */
2464 r.get_identifier_as_type (m_return_type),
2465 m_param_types.length (),
2466 param_types_id,
2467 m_is_variadic);
2468}
2469
35485da9
DM
2470/* The implementation of class gcc::jit::recording::field. */
2471
2472/* Implementation of pure virtual hook recording::memento::replay_into
2473 for recording::field. */
2474
2475void
2476recording::field::replay_into (replayer *r)
2477{
2478 set_playback_obj (r->new_field (playback_location (r, m_loc),
2479 m_type->playback_type (),
2480 playback_string (m_name)));
2481}
2482
2483/* Override the default implementation of
2484 recording::memento::write_to_dump. Dump each field
2485 by dumping a line of the form:
2486 TYPE NAME;
2487 so that we can build up a struct/union field-byfield. */
2488
2489void
2490recording::field::write_to_dump (dump &d)
2491{
2492 d.write (" %s %s;\n",
2493 m_type->get_debug_string (),
2494 m_name->c_str ());
2495}
2496
2497/* Implementation of recording::memento::make_debug_string for
2498 results of new_field. */
2499
2500recording::string *
2501recording::field::make_debug_string ()
2502{
2503 return m_name;
2504}
2505
86d0ac88
DM
2506/* Implementation of recording::memento::write_reproducer for fields. */
2507
2508void
2509recording::field::write_reproducer (reproducer &r)
2510{
2511 const char *id = r.make_identifier (this, "field");
2512 r.write(" gcc_jit_field *%s =\n"
2513 " gcc_jit_context_new_field (%s,\n"
2514 " %s, /* gcc_jit_location *loc */\n"
2515 " %s, /* gcc_jit_type *type, */\n"
2516 " %s); /* const char *name */\n",
2517 id,
2518 r.get_identifier (get_context ()),
2519 r.get_identifier (m_loc),
2520 r.get_identifier_as_type (m_type),
2521 m_name->get_debug_string ());
2522}
2523
35485da9
DM
2524/* The implementation of class gcc::jit::recording::compound_type */
2525
2526/* The constructor for gcc::jit::recording::compound_type. */
2527
2528recording::compound_type::compound_type (context *ctxt,
2529 location *loc,
2530 string *name)
2531: type (ctxt),
2532 m_loc (loc),
2533 m_name (name),
2534 m_fields (NULL)
2535{
2536}
2537
2538/* Set the fields of a compound type.
2539
2540 Implements the post-error-checking part of
2541 gcc_jit_struct_set_fields, and is also used by
2542 gcc_jit_context_new_union_type. */
2543
2544void
2545recording::compound_type::set_fields (location *loc,
2546 int num_fields,
2547 field **field_array)
2548{
2549 m_loc = loc;
2550 gcc_assert (NULL == m_fields);
2551
2552 m_fields = new fields (this, num_fields, field_array);
2553 m_ctxt->record (m_fields);
2554}
2555
2556/* Implementation of pure virtual hook recording::type::dereference for
2557 recording::compound_type. */
2558
2559recording::type *
2560recording::compound_type::dereference ()
2561{
2562 return NULL; /* not a pointer */
2563}
2564
2565/* The implementation of class gcc::jit::recording::struct_. */
2566
2567/* The constructor for gcc::jit::recording::struct_. */
2568
2569recording::struct_::struct_ (context *ctxt,
2570 location *loc,
2571 string *name)
2572: compound_type (ctxt, loc, name)
2573{
2574}
2575
2576/* Implementation of pure virtual hook recording::memento::replay_into
2577 for recording::struct_. */
2578
2579void
2580recording::struct_::replay_into (replayer *r)
2581{
2582 set_playback_obj (
2583 r->new_compound_type (playback_location (r, get_loc ()),
2584 get_name ()->c_str (),
2585 true /* is_struct */));
2586}
2587
86d0ac88
DM
2588const char *
2589recording::struct_::access_as_type (reproducer &r)
2590{
2591 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2592 r.get_identifier (this));
2593}
2594
35485da9
DM
2595/* Implementation of recording::memento::make_debug_string for
2596 structs. */
2597
2598recording::string *
2599recording::struct_::make_debug_string ()
2600{
2601 return string::from_printf (m_ctxt,
2602 "struct %s", get_name ()->c_str ());
2603}
2604
86d0ac88
DM
2605void
2606recording::struct_::write_reproducer (reproducer &r)
2607{
2608 const char *id = r.make_identifier (this, "struct");
2609 r.write (" gcc_jit_struct *%s =\n"
2610 " gcc_jit_context_new_opaque_struct (%s,\n"
2611 " %s, /* gcc_jit_location *loc */\n"
2612 " %s); /* const char *name */\n",
2613 id,
2614 r.get_identifier (get_context ()),
2615 r.get_identifier (get_loc ()),
2616 get_name ()->get_debug_string ());
2617}
2618
35485da9
DM
2619/* The implementation of class gcc::jit::recording::union_. */
2620
2621/* The constructor for gcc::jit::recording::union_. */
2622
2623recording::union_::union_ (context *ctxt,
2624 location *loc,
2625 string *name)
2626: compound_type (ctxt, loc, name)
2627{
2628}
2629
2630/* Implementation of pure virtual hook recording::memento::replay_into
2631 for recording::union_. */
2632
2633void
2634recording::union_::replay_into (replayer *r)
2635{
2636 set_playback_obj (
2637 r->new_compound_type (playback_location (r, get_loc ()),
2638 get_name ()->c_str (),
2639 false /* is_struct */));
2640}
2641
2642/* Implementation of recording::memento::make_debug_string for
2643 unions. */
2644
2645recording::string *
2646recording::union_::make_debug_string ()
2647{
2648 return string::from_printf (m_ctxt,
2649 "union %s", get_name ()->c_str ());
2650}
2651
86d0ac88
DM
2652/* Implementation of recording::memento::write_reproducer for unions. */
2653
2654void
2655recording::union_::write_reproducer (reproducer &r)
2656{
2657 const char *id = r.make_identifier (this, "union");
2658
2659 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
2660 r.write (" gcc_jit_field *%s[%i] = {\n",
2661 fields_id,
2662 get_fields ()->length ());
2663 for (int i = 0; i < get_fields ()->length (); i++)
2664 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
2665 r.write (" };\n");
2666
2667 r.write (" gcc_jit_type *%s =\n"
2668 " gcc_jit_context_new_union_type (%s,\n"
2669 " %s, /* gcc_jit_location *loc */\n"
2670 " %s, /* const char *name */\n"
2671 " %i, /* int num_fields */\n"
2672 " %s); /* gcc_jit_field **fields */\n",
2673 id,
2674 r.get_identifier (get_context ()),
2675 r.get_identifier (get_loc ()),
2676 get_name ()->get_debug_string (),
2677 get_fields ()->length (),
2678 fields_id);
2679}
2680
35485da9
DM
2681/* The implementation of class gcc::jit::recording::fields. */
2682
2683/* The constructor for gcc::jit::recording::fields. */
2684
2685recording::fields::fields (compound_type *struct_or_union,
2686 int num_fields,
2687 field **fields)
2688: memento (struct_or_union->m_ctxt),
2689 m_struct_or_union (struct_or_union),
2690 m_fields ()
2691{
2692 for (int i = 0; i < num_fields; i++)
2693 {
2694 gcc_assert (fields[i]->get_container () == NULL);
2695 fields[i]->set_container (m_struct_or_union);
2696 m_fields.safe_push (fields[i]);
2697 }
2698}
2699
2700/* Implementation of pure virtual hook recording::memento::replay_into
2701 for recording::fields. */
2702
2703void
2704recording::fields::replay_into (replayer *)
2705{
b957b2e0 2706 auto_vec<playback::field *> playback_fields;
35485da9
DM
2707 playback_fields.create (m_fields.length ());
2708 for (unsigned i = 0; i < m_fields.length (); i++)
2709 playback_fields.safe_push (m_fields[i]->playback_field ());
b957b2e0 2710 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
35485da9
DM
2711}
2712
2713/* Override the default implementation of
2714 recording::memento::write_to_dump by writing a union/struct
2715 declaration of this form:
2716
2717 struct/union NAME {
c168eab9
UD
2718 TYPE_1 NAME_1;
2719 TYPE_2 NAME_2;
35485da9 2720 ....
c168eab9 2721 TYPE_N NAME_N;
35485da9
DM
2722 };
2723
2724 to the dump. */
2725
2726void
2727recording::fields::write_to_dump (dump &d)
2728{
2729 int i;
2730 field *f;
2731
2732 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
2733 FOR_EACH_VEC_ELT (m_fields, i, f)
2734 f->write_to_dump (d);
2735 d.write ("};\n");
2736}
2737
86d0ac88
DM
2738/* Implementation of recording::memento::write_reproducer for the fields
2739 subclass. */
2740
2741void
2742recording::fields::write_reproducer (reproducer &r)
2743{
2744 if (m_struct_or_union)
2745 if (NULL == m_struct_or_union->dyn_cast_struct ())
2746 /* We have a union; the fields have already been written by
2747 union::write_reproducer. */
2748 return;
2749
2750 const char *fields_id = r.make_identifier (this, "fields");
2751 r.write (" gcc_jit_field *%s[%i] = {\n",
2752 fields_id,
2753 m_fields.length ());
2754 int i;
2755 field *field;
2756 FOR_EACH_VEC_ELT (m_fields, i, field)
2757 r.write (" %s,\n", r.get_identifier (field));
2758 r.write (" };\n");
2759
2760 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
2761 " %s, /* gcc_jit_location *loc */\n"
2762 " %i, /* int num_fields */\n"
2763 " %s); /* gcc_jit_field **fields */\n",
2764 r.get_identifier (m_struct_or_union),
2765 r.get_identifier ((memento *)NULL),
2766 m_fields.length (),
2767 fields_id);
2768}
2769
35485da9
DM
2770/* Implementation of recording::memento::make_debug_string for
2771 field tables. */
2772
2773recording::string *
2774recording::fields::make_debug_string ()
2775{
2776 return string::from_printf (m_ctxt,
2777 "fields");
2778}
2779
2780/* The implementation of class gcc::jit::recording::rvalue. */
2781
2782/* Create a recording::access_field_rvalue instance and add it to
2783 the rvalue's context's list of mementos.
2784
2785 Implements the post-error-checking part of
2786 gcc_jit_rvalue_access_field. */
2787
2788recording::rvalue *
2789recording::rvalue::access_field (recording::location *loc,
2790 field *field)
2791{
2792 recording::rvalue *result =
2793 new access_field_rvalue (m_ctxt, loc, this, field);
2794 m_ctxt->record (result);
2795 return result;
2796}
2797
2798/* Create a recording::dereference_field_rvalue instance and add it to
2799 the rvalue's context's list of mementos.
2800
2801 Implements the post-error-checking part of
2802 gcc_jit_rvalue_dereference_field. */
2803
2804recording::lvalue *
2805recording::rvalue::dereference_field (recording::location *loc,
2806 field *field)
2807{
2808 recording::lvalue *result =
2809 new dereference_field_rvalue (m_ctxt, loc, this, field);
2810 m_ctxt->record (result);
2811 return result;
2812}
2813
2814/* Create a recording::dereference_rvalue instance and add it to the
2815 rvalue's context's list of mementos.
2816
2817 Implements the post-error-checking part of
2818 gcc_jit_rvalue_dereference. */
2819
2820recording::lvalue *
2821recording::rvalue::dereference (recording::location *loc)
2822{
2823 recording::lvalue *result =
2824 new dereference_rvalue (m_ctxt, loc, this);
2825 m_ctxt->record (result);
2826 return result;
2827}
2828
f6f2b019
DM
2829/* An rvalue visitor, for validating that every rvalue within an expression
2830 trees within "STMT" has the correct scope (e.g. no access to locals
2831 of a different function). */
2832
2833class rvalue_usage_validator : public recording::rvalue_visitor
2834{
2835 public:
2836 rvalue_usage_validator (const char *api_funcname,
2837 recording::context *ctxt,
2838 recording::statement *stmt);
2839
2840 void
2841 visit (recording::rvalue *rvalue);
2842
2843 private:
2844 const char *m_api_funcname;
2845 recording::context *m_ctxt;
2846 recording::statement *m_stmt;
2847};
2848
2849/* The trivial constructor for rvalue_usage_validator. */
2850
2851rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
2852 recording::context *ctxt,
2853 recording::statement *stmt)
2854 : m_api_funcname (api_funcname),
2855 m_ctxt (ctxt),
2856 m_stmt (stmt)
2857{
2858}
2859
2860/* Verify that the given rvalue is in the correct scope. */
2861
2862void
2863rvalue_usage_validator::visit (recording::rvalue *rvalue)
2864{
2865 gcc_assert (m_stmt->get_block ());
2866 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
2867
2868 /* Most rvalues don't have a scope (only locals and params). */
2869 if (rvalue->get_scope ())
2870 {
2871 if (rvalue->get_scope () != stmt_scope)
2872 m_ctxt->add_error
2873 (rvalue->get_loc (),
2874 "%s:"
2875 " rvalue %s (type: %s)"
2876 " has scope limited to function %s"
2877 " but was used within function %s"
2878 " (in statement: %s)",
2879 m_api_funcname,
2880 rvalue->get_debug_string (),
2881 rvalue->get_type ()->get_debug_string (),
2882 rvalue->get_scope ()->get_debug_string (),
2883 stmt_scope->get_debug_string (),
2884 m_stmt->get_debug_string ());
2885 }
2886 else
2887 {
2888 if (rvalue->dyn_cast_param ())
2889 m_ctxt->add_error
2890 (rvalue->get_loc (),
2891 "%s:"
2892 " param %s (type: %s)"
2893 " was used within function %s"
2894 " (in statement: %s)"
2895 " but is not associated with any function",
2896 m_api_funcname,
2897 rvalue->get_debug_string (),
2898 rvalue->get_type ()->get_debug_string (),
2899 stmt_scope->get_debug_string (),
2900 m_stmt->get_debug_string ());
2901 }
2902}
2903
2904/* Verify that it's valid to use this rvalue (and all expressions
2905 in the tree below it) within the given statement.
2906
2907 For example, we must reject attempts to use a local from one
2908 function within a different function here, or we'll get
2909 an ICE deep inside toplev::main. */
2910
2911void
2912recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
2913{
2914 rvalue_usage_validator v (api_funcname,
2915 s->get_context (),
2916 s);
2917
2918 /* Verify that it's OK to use this rvalue within s. */
2919 v.visit (this);
2920
2921 /* Traverse the expression tree below "this", verifying all rvalues
2922 within it. */
2923 visit_children (&v);
2924}
2925
2926/* Set the scope of this rvalue to be the given function. This can only
2927 be done once on a given rvalue. */
2928
2929void
2930recording::rvalue::set_scope (function *scope)
2931{
2932 gcc_assert (scope);
2933 gcc_assert (NULL == m_scope);
2934 m_scope = scope;
2935}
2936
2937
86d0ac88
DM
2938/* Implementation of recording::rvalue::access_as_rvalue for rvalues
2939 themselves.
2940 Instances of rvalue don't need an upcast call. */
2941
2942const char *
2943recording::rvalue::access_as_rvalue (reproducer &r)
2944{
2945 return r.get_identifier (this);
2946}
2947
2948
35485da9
DM
2949/* The implementation of class gcc::jit::recording::lvalue. */
2950
2951/* Create a recording::new_access_field_of_lvalue instance and add it to
2952 the lvalue's context's list of mementos.
2953
2954 Implements the post-error-checking part of
2955 gcc_jit_lvalue_access_field. */
2956
2957recording::lvalue *
2958recording::lvalue::access_field (recording::location *loc,
2959 field *field)
2960{
2961 recording::lvalue *result =
2962 new access_field_of_lvalue (m_ctxt, loc, this, field);
2963 m_ctxt->record (result);
2964 return result;
2965}
2966
86d0ac88
DM
2967/* Implementation of recording::rvalue::access_as_rvalue for lvalues.
2968 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
2969 upcast call. */
2970
2971const char *
2972recording::lvalue::access_as_rvalue (reproducer &r)
2973{
2974 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
2975 r.get_identifier (this));
2976}
2977
2978/* Implementation of recording::lvalue::access_as_lvalue for lvalues.
2979 Instances of lvalue don't need to be upcast. */
2980
2981const char *
2982recording::lvalue::access_as_lvalue (reproducer &r)
2983{
2984 return r.get_identifier (this);
2985}
2986
35485da9
DM
2987/* Create a recording::get_address_of_lvalue instance and add it to
2988 the lvalue's context's list of mementos.
2989
2990 Implements the post-error-checking part of
2991 gcc_jit_lvalue_get_address. */
2992
2993recording::rvalue *
2994recording::lvalue::get_address (recording::location *loc)
2995{
2996 recording::rvalue *result =
2997 new get_address_of_lvalue (m_ctxt, loc, this);
2998 m_ctxt->record (result);
2999 return result;
3000}
3001
3002/* The implementation of class gcc::jit::recording::param. */
3003
3004/* Implementation of pure virtual hook recording::memento::replay_into
3005 for recording::param. */
3006
3007void
3008recording::param::replay_into (replayer *r)
3009{
3010 set_playback_obj (r->new_param (playback_location (r, m_loc),
3011 m_type->playback_type (),
3012 m_name->c_str ()));
3013}
3014
86d0ac88
DM
3015/* Implementation of recording::rvalue::access_as_rvalue for params.
3016 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3017 upcast call. */
3018
3019const char *
3020recording::param::access_as_rvalue (reproducer &r)
3021{
3022 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3023 r.get_identifier (this));
3024}
3025
3026/* Implementation of recording::lvalue::access_as_lvalue for params.
3027 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3028 upcast call. */
3029
3030const char *
3031recording::param::access_as_lvalue (reproducer &r)
3032{
3033 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3034 r.get_identifier (this));
3035}
3036
3037/* Implementation of recording::memento::write_reproducer for params. */
3038
3039void
3040recording::param::write_reproducer (reproducer &r)
3041{
3042 const char *id = r.make_identifier (this, "param");
3043 r.write (" gcc_jit_param *%s =\n"
3044 " gcc_jit_context_new_param (%s,\n"
3045 " %s, /* gcc_jit_location *loc */\n"
3046 " %s, /*gcc_jit_type *type */\n"
3047 " %s); /* const char *name */\n",
3048 id,
3049 r.get_identifier (get_context ()),
3050 r.get_identifier (m_loc),
3051 r.get_identifier_as_type (m_type),
3052 m_name->get_debug_string ());
3053}
35485da9
DM
3054
3055/* The implementation of class gcc::jit::recording::function. */
3056
3057/* gcc::jit::recording::function's constructor. */
3058
3059recording::function::function (context *ctxt,
3060 recording::location *loc,
3061 enum gcc_jit_function_kind kind,
3062 type *return_type,
3063 recording::string *name,
3064 int num_params,
3065 recording::param **params,
3066 int is_variadic,
3067 enum built_in_function builtin_id)
3068: memento (ctxt),
3069 m_loc (loc),
3070 m_kind (kind),
3071 m_return_type (return_type),
3072 m_name (name),
3073 m_params (),
3074 m_is_variadic (is_variadic),
3075 m_builtin_id (builtin_id),
3076 m_locals (),
3077 m_blocks ()
3078{
3079 for (int i = 0; i< num_params; i++)
f6f2b019
DM
3080 {
3081 param *param = params[i];
3082 gcc_assert (param);
3083
3084 /* Associate each param with this function.
3085
3086 Verify that the param doesn't already have a function. */
3087 if (param->get_scope ())
3088 {
3089 /* We've already rejected attempts to reuse a param between
3090 different functions (within gcc_jit_context_new_function), so
3091 if the param *does* already have a function, it must be being
3092 reused within the params array for this function. We must
3093 produce an error for this reuse (blocking the compile), since
3094 otherwise we'd have an ICE later on. */
3095 gcc_assert (this == param->get_scope ());
3096 ctxt->add_error
3097 (loc,
3098 "gcc_jit_context_new_function:"
3099 " parameter %s (type: %s)"
3100 " is used more than once when creating function %s",
3101 param->get_debug_string (),
3102 param->get_type ()->get_debug_string (),
3103 name->c_str ());
3104 }
3105 else
3106 {
3107 /* The normal, non-error case: associate this function with the
3108 param. */
3109 param->set_scope (this);
3110 }
3111
3112 m_params.safe_push (param);
3113 }
35485da9
DM
3114}
3115
3116/* Implementation of pure virtual hook recording::memento::replay_into
3117 for recording::function. */
3118
3119void
3120recording::function::replay_into (replayer *r)
3121{
3122 /* Convert m_params to a vec of playback param. */
b957b2e0 3123 auto_vec <playback::param *> params;
35485da9
DM
3124 int i;
3125 recording::param *param;
3126 params.create (m_params.length ());
3127 FOR_EACH_VEC_ELT (m_params, i, param)
3128 params.safe_push (param->playback_param ());
3129
3130 set_playback_obj (r->new_function (playback_location (r, m_loc),
3131 m_kind,
3132 m_return_type->playback_type (),
3133 m_name->c_str (),
3134 &params,
3135 m_is_variadic,
3136 m_builtin_id));
3137}
3138
3139/* Create a recording::local instance and add it to
3140 the functions's context's list of mementos, and to the function's
3141 list of locals.
3142
3143 Implements the post-error-checking part of
3144 gcc_jit_function_new_local. */
3145
3146recording::lvalue *
3147recording::function::new_local (recording::location *loc,
3148 type *type,
3149 const char *name)
3150{
3151 local *result = new local (this, loc, type, new_string (name));
3152 m_ctxt->record (result);
3153 m_locals.safe_push (result);
3154 return result;
3155}
3156
3157/* Create a recording::block instance and add it to
3158 the functions's context's list of mementos, and to the function's
3159 list of blocks.
3160
3161 Implements the post-error-checking part of
3162 gcc_jit_function_new_block. */
3163
3164recording::block*
3165recording::function::new_block (const char *name)
3166{
3167 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
3168
3169 recording::block *result =
3170 new recording::block (this, m_blocks.length (), new_string (name));
3171 m_ctxt->record (result);
3172 m_blocks.safe_push (result);
3173 return result;
3174}
3175
3176/* Override the default implementation of
3177 recording::memento::write_to_dump by dumping a C-like
3178 representation of the function; either like a prototype
3179 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3180 all other kinds of function. */
3181
3182void
3183recording::function::write_to_dump (dump &d)
3184{
3185 switch (m_kind)
3186 {
3187 default: gcc_unreachable ();
3188 case GCC_JIT_FUNCTION_EXPORTED:
3189 case GCC_JIT_FUNCTION_IMPORTED:
3190 d.write ("extern ");
3191 break;
3192 case GCC_JIT_FUNCTION_INTERNAL:
3193 d.write ("static ");
3194 break;
3195 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
3196 d.write ("static inline ");
3197 break;
3198 }
3199 d.write ("%s\n", m_return_type->get_debug_string ());
3200
3201 if (d.update_locations ())
3202 m_loc = d.make_location ();
3203
3204 d.write ("%s (", get_debug_string ());
3205
3206 int i;
3207 recording::param *param;
3208 FOR_EACH_VEC_ELT (m_params, i, param)
3209 {
3210 if (i > 0)
3211 d.write (", ");
3212 d.write ("%s %s",
3213 param->get_type ()->get_debug_string (),
3214 param->get_debug_string ());
3215 }
3216 d.write (")");
3217 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
3218 {
3219 d.write ("; /* (imported) */\n\n");
3220 }
3221 else
3222 {
3223 int i;
3224 local *var = NULL;
3225 block *b;
3226 d.write ("\n{\n");
3227
3228 /* Write locals: */
3229 FOR_EACH_VEC_ELT (m_locals, i, var)
3230 var->write_to_dump (d);
3231 if (m_locals.length ())
3232 d.write ("\n");
3233
3234 /* Write each block: */
3235 FOR_EACH_VEC_ELT (m_blocks, i, b)
3236 {
3237 if (i > 0)
3238 d.write ("\n");
3239 b->write_to_dump (d);
3240 }
3241
3242 d.write ("}\n\n");
3243 }
3244}
3245
3246/* Pre-compilation validation of a function, for those things we can't
3247 check until the context is (supposedly) fully-populated. */
3248
3249void
3250recording::function::validate ()
3251{
3252 /* Complain about empty functions with non-void return type. */
3253 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
3254 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
3255 if (0 == m_blocks.length ())
3256 m_ctxt->add_error (m_loc,
3257 "function %s returns non-void (type: %s)"
3258 " but has no blocks",
3259 get_debug_string (),
3260 m_return_type->get_debug_string ());
3261
3262 /* Check that all blocks are terminated. */
3263 int num_invalid_blocks = 0;
3264 {
3265 int i;
3266 block *b;
3267
3268 FOR_EACH_VEC_ELT (m_blocks, i, b)
3269 if (!b->validate ())
3270 num_invalid_blocks++;
3271 }
3272
3273 /* Check that all blocks are reachable. */
3274 if (m_blocks.length () > 0 && 0 == num_invalid_blocks)
3275 {
3276 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3277 flag, starting at the initial block. */
79cafc7a 3278 auto_vec<block *> worklist (m_blocks.length ());
35485da9
DM
3279 worklist.safe_push (m_blocks[0]);
3280 while (worklist.length () > 0)
3281 {
3282 block *b = worklist.pop ();
3283 b->m_is_reachable = true;
3284
3285 /* Add successor blocks that aren't yet marked to the worklist. */
3286 /* We checked that each block has a terminating statement above . */
3287 block *next1, *next2;
3288 int n = b->get_successor_blocks (&next1, &next2);
3289 switch (n)
3290 {
3291 default:
3292 gcc_unreachable ();
3293 case 2:
3294 if (!next2->m_is_reachable)
3295 worklist.safe_push (next2);
3296 /* fallthrough */
3297 case 1:
3298 if (!next1->m_is_reachable)
3299 worklist.safe_push (next1);
3300 break;
3301 case 0:
3302 break;
3303 }
3304 }
3305
3306 /* Now complain about any blocks that haven't been marked. */
3307 {
3308 int i;
3309 block *b;
3310 FOR_EACH_VEC_ELT (m_blocks, i, b)
3311 if (!b->m_is_reachable)
3312 m_ctxt->add_error (b->get_loc (),
3313 "unreachable block: %s",
3314 b->get_debug_string ());
3315 }
3316 }
3317}
3318
3319/* Implements the post-error-checking part of
3320 gcc_jit_function_dump_to_dot. */
3321
3322void
3323recording::function::dump_to_dot (const char *path)
3324{
3325 FILE *fp = fopen (path, "w");
3326 if (!fp)
3327 return;
3328
3329 pretty_printer the_pp;
3330 the_pp.buffer->stream = fp;
3331
3332 pretty_printer *pp = &the_pp;
3333
3334 pp_printf (pp,
3335 "digraph %s {\n", get_debug_string ());
3336
3337 /* Blocks: */
3338 {
3339 int i;
3340 block *b;
3341 FOR_EACH_VEC_ELT (m_blocks, i, b)
3342 b->dump_to_dot (pp);
3343 }
3344
3345 /* Edges: */
3346 {
3347 int i;
3348 block *b;
3349 FOR_EACH_VEC_ELT (m_blocks, i, b)
3350 b->dump_edges_to_dot (pp);
3351 }
3352
3353 pp_printf (pp, "}\n");
3354 pp_flush (pp);
3355 fclose (fp);
3356}
3357
3358/* Implementation of recording::memento::make_debug_string for
3359 functions. */
3360
3361recording::string *
3362recording::function::make_debug_string ()
3363{
3364 return m_name;
3365}
3366
86d0ac88
DM
3367/* A table of enum gcc_jit_function_kind values expressed in string
3368 form. */
3369
3370static const char * const names_of_function_kinds[] = {
3371 "GCC_JIT_FUNCTION_EXPORTED",
3372 "GCC_JIT_FUNCTION_INTERNAL",
3373 "GCC_JIT_FUNCTION_IMPORTED",
3374 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3375};
3376
3377/* Implementation of recording::memento::write_reproducer for functions. */
3378
3379void
3380recording::function::write_reproducer (reproducer &r)
3381{
3382 const char *id = r.make_identifier (this, "func");
3383
3384 if (m_builtin_id)
3385 {
3386 r.write (" gcc_jit_function *%s =\n"
3387 " gcc_jit_context_get_builtin_function (%s,\n"
3388 " %s);\n",
3389 id,
3390 r.get_identifier (get_context ()),
3391 m_name->get_debug_string ());
3392 return;
3393 }
3394 const char *params_id = r.make_tmp_identifier ("params_for", this);
3395 r.write (" gcc_jit_param *%s[%i] = {\n",
3396 params_id,
3397 m_params.length ());
3398 int i;
3399 param *param;
3400 FOR_EACH_VEC_ELT (m_params, i, param)
3401 r.write (" %s,\n", r.get_identifier (param));
3402 r.write (" };\n");
3403 r.write (" gcc_jit_function *%s =\n"
3404 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3405 " %s, /* gcc_jit_location *loc */\n"
3406 " %s, /* enum gcc_jit_function_kind kind */\n"
3407 " %s, /* gcc_jit_type *return_type */\n"
3408 " %s, /* const char *name */\n"
3409 " %i, /* int num_params */\n"
3410 " %s, /* gcc_jit_param **params */\n"
3411 " %i); /* int is_variadic */\n",
3412 id,
3413 r.get_identifier (get_context ()),
3414 r.get_identifier (m_loc),
3415 names_of_function_kinds[m_kind],
3416 r.get_identifier_as_type (m_return_type),
3417 m_name->get_debug_string (),
3418 m_params.length (),
3419 params_id,
3420 m_is_variadic);
3421}
3422
3423
35485da9
DM
3424/* The implementation of class gcc::jit::recording::block. */
3425
3426/* Create a recording::eval instance and add it to
3427 the block's context's list of mementos, and to the block's
3428 list of statements.
3429
f6f2b019 3430 Implements the heart of gcc_jit_block_add_eval. */
35485da9 3431
f6f2b019 3432recording::statement *
35485da9
DM
3433recording::block::add_eval (recording::location *loc,
3434 recording::rvalue *rvalue)
3435{
3436 statement *result = new eval (this, loc, rvalue);
3437 m_ctxt->record (result);
3438 m_statements.safe_push (result);
f6f2b019 3439 return result;
35485da9
DM
3440}
3441
3442/* Create a recording::assignment instance and add it to
3443 the block's context's list of mementos, and to the block's
3444 list of statements.
3445
f6f2b019 3446 Implements the heart of gcc_jit_block_add_assignment. */
35485da9 3447
f6f2b019 3448recording::statement *
35485da9
DM
3449recording::block::add_assignment (recording::location *loc,
3450 recording::lvalue *lvalue,
3451 recording::rvalue *rvalue)
3452{
3453 statement *result = new assignment (this, loc, lvalue, rvalue);
3454 m_ctxt->record (result);
3455 m_statements.safe_push (result);
f6f2b019 3456 return result;
35485da9
DM
3457}
3458
3459/* Create a recording::assignment_op instance and add it to
3460 the block's context's list of mementos, and to the block's
3461 list of statements.
3462
f6f2b019 3463 Implements the heart of gcc_jit_block_add_assignment_op. */
35485da9 3464
f6f2b019 3465recording::statement *
35485da9
DM
3466recording::block::add_assignment_op (recording::location *loc,
3467 recording::lvalue *lvalue,
3468 enum gcc_jit_binary_op op,
3469 recording::rvalue *rvalue)
3470{
3471 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
3472 m_ctxt->record (result);
3473 m_statements.safe_push (result);
f6f2b019 3474 return result;
35485da9
DM
3475}
3476
3477/* Create a recording::comment instance and add it to
3478 the block's context's list of mementos, and to the block's
3479 list of statements.
3480
f6f2b019 3481 Implements the heart of gcc_jit_block_add_comment. */
35485da9 3482
f6f2b019 3483recording::statement *
35485da9
DM
3484recording::block::add_comment (recording::location *loc,
3485 const char *text)
3486{
3487 statement *result = new comment (this, loc, new_string (text));
3488 m_ctxt->record (result);
3489 m_statements.safe_push (result);
f6f2b019 3490 return result;
35485da9
DM
3491}
3492
3493/* Create a recording::end_with_conditional instance and add it to
3494 the block's context's list of mementos, and to the block's
3495 list of statements.
3496
f6f2b019 3497 Implements the heart of gcc_jit_block_end_with_conditional. */
35485da9 3498
f6f2b019 3499recording::statement *
35485da9
DM
3500recording::block::end_with_conditional (recording::location *loc,
3501 recording::rvalue *boolval,
3502 recording::block *on_true,
3503 recording::block *on_false)
3504{
3505 statement *result = new conditional (this, loc, boolval, on_true, on_false);
3506 m_ctxt->record (result);
3507 m_statements.safe_push (result);
3508 m_has_been_terminated = true;
f6f2b019 3509 return result;
35485da9
DM
3510}
3511
3512/* Create a recording::end_with_jump instance and add it to
3513 the block's context's list of mementos, and to the block's
3514 list of statements.
3515
f6f2b019 3516 Implements the heart of gcc_jit_block_end_with_jump. */
35485da9 3517
f6f2b019 3518recording::statement *
35485da9
DM
3519recording::block::end_with_jump (recording::location *loc,
3520 recording::block *target)
3521{
3522 statement *result = new jump (this, loc, target);
3523 m_ctxt->record (result);
3524 m_statements.safe_push (result);
3525 m_has_been_terminated = true;
f6f2b019 3526 return result;
35485da9
DM
3527}
3528
3529/* Create a recording::end_with_return instance and add it to
3530 the block's context's list of mementos, and to the block's
3531 list of statements.
3532
3533 Implements the post-error-checking parts of
3534 gcc_jit_block_end_with_return and
3535 gcc_jit_block_end_with_void_return. */
3536
f6f2b019 3537recording::statement *
35485da9
DM
3538recording::block::end_with_return (recording::location *loc,
3539 recording::rvalue *rvalue)
3540{
3541 /* This is used by both gcc_jit_function_add_return and
3542 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3543 the former and NULL for the latter. */
3544 statement *result = new return_ (this, loc, rvalue);
3545 m_ctxt->record (result);
3546 m_statements.safe_push (result);
3547 m_has_been_terminated = true;
f6f2b019 3548 return result;
35485da9
DM
3549}
3550
3551/* Override the default implementation of
3552 recording::memento::write_to_dump for blocks by writing
3553 an unindented block name as a label, followed by the indented
3554 statements:
3555
3556 BLOCK_NAME:
3557 STATEMENT_1;
3558 STATEMENT_2;
3559 ...
3560 STATEMENT_N; */
3561
3562void
3563recording::block::write_to_dump (dump &d)
3564{
3565 d.write ("%s:\n", get_debug_string ());
3566
3567 int i;
3568 statement *s;
3569 FOR_EACH_VEC_ELT (m_statements, i, s)
3570 s->write_to_dump (d);
3571}
3572
3573/* Validate a block by ensuring that it has been terminated. */
3574
3575bool
3576recording::block::validate ()
3577{
f6f2b019 3578 /* Check for termination. */
35485da9
DM
3579 if (!has_been_terminated ())
3580 {
3581 statement *stmt = get_last_statement ();
3582 location *loc = stmt ? stmt->get_loc () : NULL;
3583 m_func->get_context ()->add_error (loc,
3584 "unterminated block in %s: %s",
3585 m_func->get_debug_string (),
3586 get_debug_string ());
3587 return false;
3588 }
3589
3590 return true;
3591}
3592
3593/* Get the source-location of a block by using that of the first
3594 statement within it, if any. */
3595
3596recording::location *
3597recording::block::get_loc () const
3598{
3599 recording::statement *stmt = get_first_statement ();
3600 if (stmt)
3601 return stmt->get_loc ();
3602 else
3603 return NULL;
3604}
3605
3606/* Get the first statement within a block, if any. */
3607
3608recording::statement *
3609recording::block::get_first_statement () const
3610{
3611 if (m_statements.length ())
3612 return m_statements[0];
3613 else
3614 return NULL;
3615}
3616
3617/* Get the last statement within a block, if any. */
3618
3619recording::statement *
3620recording::block::get_last_statement () const
3621{
3622 if (m_statements.length ())
3623 return m_statements[m_statements.length () - 1];
3624 else
3625 return NULL;
3626}
3627
3628/* Assuming that this block has been terminated, get the number of
3629 successor blocks, which will be 0, 1 or 2, for return, unconditional
3630 jump, and conditional jump respectively.
3631 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
3632 is written to NEXT1, and the second (if any) to NEXT2.
3633
3634 Used when validating functions, and when dumping dot representations
3635 of them. */
3636
3637int
3638recording::block::get_successor_blocks (block **next1, block **next2) const
3639{
3640 gcc_assert (m_has_been_terminated);
3641 gcc_assert (next1);
3642 gcc_assert (next2);
3643 statement *last_statement = get_last_statement ();
3644 gcc_assert (last_statement);
3645 return last_statement->get_successor_blocks (next1, next2);
3646}
3647
3648/* Implementation of pure virtual hook recording::memento::replay_into
3649 for recording::block. */
3650
3651void
3652recording::block::replay_into (replayer *)
3653{
3654 set_playback_obj (m_func->playback_function ()
3655 ->new_block (playback_string (m_name)));
3656}
3657
3658/* Implementation of recording::memento::make_debug_string for
3659 blocks. */
3660
3661recording::string *
3662recording::block::make_debug_string ()
3663{
3664 if (m_name)
3665 return m_name;
3666 else
3667 return string::from_printf (m_ctxt,
3668 "<UNNAMED BLOCK %p>",
3669 (void *)this);
3670}
3671
86d0ac88
DM
3672/* Implementation of recording::memento::write_reproducer for blocks. */
3673
3674void
3675recording::block::write_reproducer (reproducer &r)
3676{
3677 const char *id = r.make_identifier (this, "block");
3678 r.write (" gcc_jit_block *%s =\n"
3679 " gcc_jit_function_new_block (%s, %s);\n",
3680 id,
3681 r.get_identifier (m_func),
3682 m_name ? m_name->get_debug_string () : "NULL");
3683}
3684
35485da9
DM
3685/* Dump a block in graphviz form into PP, capturing the block name (if
3686 any) and the statements. */
3687
3688void
3689recording::block::dump_to_dot (pretty_printer *pp)
3690{
3691 pp_printf (pp,
3692 ("\tblock_%d "
3693 "[shape=record,style=filled,fillcolor=white,label=\"{"),
3694 m_index);
3695 pp_write_text_to_stream (pp);
3696 if (m_name)
3697 {
3698 pp_string (pp, m_name->c_str ());
3699 pp_string (pp, ":");
3700 pp_newline (pp);
3701 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3702 }
3703
3704 int i;
3705 statement *s;
3706 FOR_EACH_VEC_ELT (m_statements, i, s)
3707 {
3708 pp_string (pp, s->get_debug_string ());
3709 pp_newline (pp);
3710 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
3711 }
3712
3713 pp_printf (pp,
3714 "}\"];\n\n");
3715 pp_flush (pp);
3716}
3717
3718/* Dump the out-edges of the block in graphviz form into PP. */
3719
3720void
3721recording::block::dump_edges_to_dot (pretty_printer *pp)
3722{
3723 block *next[2];
3724 int num_succs = get_successor_blocks (&next[0], &next[1]);
3725 for (int i = 0; i < num_succs; i++)
3726 pp_printf (pp,
3727 "\tblock_%d:s -> block_%d:n;\n",
3728 m_index, next[i]->m_index);
3729}
3730
3731/* The implementation of class gcc::jit::recording::global. */
3732
3733/* Implementation of pure virtual hook recording::memento::replay_into
3734 for recording::global. */
3735
3736void
3737recording::global::replay_into (replayer *r)
3738{
3739 set_playback_obj (r->new_global (playback_location (r, m_loc),
791cfef8 3740 m_kind,
35485da9
DM
3741 m_type->playback_type (),
3742 playback_string (m_name)));
3743}
3744
791cfef8
DM
3745/* Override the default implementation of
3746 recording::memento::write_to_dump for globals.
3747 This will be of the form:
3748
3749 GCC_JIT_GLOBAL_EXPORTED:
3750 "TYPE NAME;"
3751 e.g. "int foo;"
3752
3753 GCC_JIT_GLOBAL_INTERNAL:
3754 "static TYPE NAME;"
3755 e.g. "static int foo;"
3756
3757 GCC_JIT_GLOBAL_IMPORTED:
3758 "extern TYPE NAME;"
3759 e.g. "extern int foo;"
3760
3761 These are written to the top of the dump by
3762 recording::context::dump_to_file. */
3763
3764void
3765recording::global::write_to_dump (dump &d)
3766{
3767 if (d.update_locations ())
3768 m_loc = d.make_location ();
3769
3770 switch (m_kind)
3771 {
3772 default:
3773 gcc_unreachable ();
3774
3775 case GCC_JIT_GLOBAL_EXPORTED:
3776 break;
3777
3778 case GCC_JIT_GLOBAL_INTERNAL:
3779 d.write ("static ");
3780 break;
3781
3782 case GCC_JIT_GLOBAL_IMPORTED:
3783 d.write ("extern ");
3784 break;
3785 }
3786 d.write ("%s %s;\n",
3787 m_type->get_debug_string (),
3788 get_debug_string ());
3789}
3790
86d0ac88
DM
3791/* A table of enum gcc_jit_global_kind values expressed in string
3792 form. */
3793
3794static const char * const global_kind_reproducer_strings[] = {
3795 "GCC_JIT_GLOBAL_EXPORTED",
3796 "GCC_JIT_GLOBAL_INTERNAL",
3797 "GCC_JIT_GLOBAL_IMPORTED"
3798};
3799
3800/* Implementation of recording::memento::write_reproducer for globals. */
3801
3802void
3803recording::global::write_reproducer (reproducer &r)
3804{
3805 const char *id = r.make_identifier (this, "block");
3806 r.write (" gcc_jit_lvalue *%s =\n"
3807 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
3808 " %s, /* gcc_jit_location *loc */\n"
3809 " %s, /* enum gcc_jit_global_kind kind */\n"
3810 " %s, /* gcc_jit_type *type */\n"
3811 " %s); /* const char *name */\n",
3812 id,
3813 r.get_identifier (get_context ()),
3814 r.get_identifier (m_loc),
3815 global_kind_reproducer_strings[m_kind],
3816 r.get_identifier_as_type (get_type ()),
3817 m_name->get_debug_string ());
3818}
3819
ccce3b2a
DM
3820/* The implementation of the various const-handling classes:
3821 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
35485da9 3822
ccce3b2a
DM
3823/* Explicit specialization of the various mementos we're interested in. */
3824template class recording::memento_of_new_rvalue_from_const <int>;
3825template class recording::memento_of_new_rvalue_from_const <long>;
3826template class recording::memento_of_new_rvalue_from_const <double>;
3827template class recording::memento_of_new_rvalue_from_const <void *>;
3828
3829/* Implementation of the pure virtual hook recording::memento::replay_into
3830 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
35485da9 3831
ccce3b2a 3832template <typename HOST_TYPE>
35485da9 3833void
ccce3b2a
DM
3834recording::
3835memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
35485da9 3836{
ccce3b2a
DM
3837 set_playback_obj
3838 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
3839 m_value));
35485da9
DM
3840}
3841
86d0ac88
DM
3842/* The make_debug_string and write_reproducer methods vary between the
3843 various
3844 memento_of_new_rvalue_from_const <HOST_TYPE>
3845 classes, so we explicitly write specializations of them.
ccce3b2a
DM
3846
3847 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
3848 namespaces are written out explicitly, which is why most of this file
3849 doesn't abbreviate things by entering the "recording" namespace.
3850
3851 However, these specializations are required to be in the same namespace
3852 as the template, hence we now have to enter the gcc::jit::recording
3853 namespace. */
3854
3855namespace recording
3856{
3857
3858/* The make_debug_string specialization for <int>, which renders it as
3859 (TARGET_TYPE)LITERAL
35485da9
DM
3860 e.g.
3861 "(int)42". */
3862
ccce3b2a
DM
3863template <>
3864string *
3865memento_of_new_rvalue_from_const <int>::make_debug_string ()
35485da9
DM
3866{
3867 return string::from_printf (m_ctxt,
3868 "(%s)%i",
3869 m_type->get_debug_string (),
3870 m_value);
3871}
3872
86d0ac88
DM
3873/* The write_reproducer specialization for <int>. */
3874
3875template <>
3876void
3877memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
3878{
3879 const char *id = r.make_identifier (this, "rvalue");
3880 r.write (" gcc_jit_rvalue *%s =\n"
3881 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
3882 " %s, /* gcc_jit_type *numeric_type */\n"
3883 " %i); /* int value */\n",
3884 id,
3885 r.get_identifier (get_context ()),
3886 r.get_identifier_as_type (m_type),
3887 m_value);
3888}
3889
ccce3b2a
DM
3890/* The make_debug_string specialization for <long>, rendering it as
3891 (TARGET_TYPE)LITERAL
3892 e.g.
3893 "(long)42". */
35485da9 3894
ccce3b2a
DM
3895template <>
3896string *
3897memento_of_new_rvalue_from_const <long>::make_debug_string ()
35485da9 3898{
ccce3b2a
DM
3899 return string::from_printf (m_ctxt,
3900 "(%s)%li",
3901 m_type->get_debug_string (),
3902 m_value);
35485da9
DM
3903}
3904
86d0ac88
DM
3905/* The write_reproducer specialization for <long>. */
3906
3907template <>
3908void
3909recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
3910{
3911 const char *id = r.make_identifier (this, "rvalue");
3912
3913 /* We have to special-case LONG_MIN, since e.g.
3914 -9223372036854775808L
3915 is parsed as
3916 -(9223372036854775808L)
3917 and hence we'd get:
3918 error: integer constant is so large that it is unsigned [-Werror]
3919 Workaround this by writing (LONG_MIN + 1) - 1. */
3920 if (m_value == LONG_MIN)
3921 {
3922 r.write (" gcc_jit_rvalue *%s =\n"
3923 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
3924 " %s, /* gcc_jit_type *numeric_type */\n"
3925 " %ldL - 1); /* long value */\n",
3926 id,
3927 r.get_identifier (get_context ()),
3928 r.get_identifier_as_type (m_type),
3929 m_value + 1);;
3930 return;
3931 }
3932
3933 r.write (" gcc_jit_rvalue *%s =\n"
3934 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
3935 " %s, /* gcc_jit_type *numeric_type */\n"
3936 " %ldL); /* long value */\n",
3937 id,
3938 r.get_identifier (get_context ()),
3939 r.get_identifier_as_type (m_type),
3940 m_value);
3941 }
3942
ccce3b2a
DM
3943/* The make_debug_string specialization for <double>, rendering it as
3944 (TARGET_TYPE)LITERAL
35485da9
DM
3945 e.g.
3946 "(float)42.0". */
3947
ccce3b2a
DM
3948template <>
3949string *
3950memento_of_new_rvalue_from_const <double>::make_debug_string ()
35485da9
DM
3951{
3952 return string::from_printf (m_ctxt,
3953 "(%s)%f",
3954 m_type->get_debug_string (),
3955 m_value);
3956}
3957
86d0ac88
DM
3958/* The write_reproducer specialization for <double>. */
3959
3960template <>
3961void
3962recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
3963{
3964 const char *id = r.make_identifier (this, "rvalue");
3965 r.write (" gcc_jit_rvalue *%s =\n"
3966 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
3967 " %s, /* gcc_jit_type *numeric_type */\n"
3968 " %f); /* double value */\n",
3969 id,
3970 r.get_identifier (get_context ()),
3971 r.get_identifier_as_type (m_type),
3972 m_value);
3973}
3974
ccce3b2a
DM
3975/* The make_debug_string specialization for <void *>, rendering it as
3976 (TARGET_TYPE)HEX
35485da9
DM
3977 e.g.
3978 "(int *)0xdeadbeef"
3979
3980 Zero is rendered as NULL e.g.
3981 "(int *)NULL". */
3982
ccce3b2a
DM
3983template <>
3984string *
3985memento_of_new_rvalue_from_const <void *>::make_debug_string ()
35485da9
DM
3986{
3987 if (m_value != NULL)
3988 return string::from_printf (m_ctxt,
3989 "(%s)%p",
3990 m_type->get_debug_string (), m_value);
3991 else
3992 return string::from_printf (m_ctxt,
3993 "(%s)NULL",
3994 m_type->get_debug_string ());
3995}
3996
86d0ac88
DM
3997/* Implementation of recording::memento::write_reproducer for <void *>
3998 values. */
3999
4000template <>
4001void
4002memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
4003{
4004 const char *id = r.make_identifier (this, "rvalue");
4005 if (m_value)
4006 r.write (" gcc_jit_rvalue *%s =\n"
4007 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4008 " %s, /* gcc_jit_type *pointer_type */\n"
4009 " (void *)%p); /* void *value */\n",
4010 id,
4011 r.get_identifier (get_context ()),
4012 r.get_identifier_as_type (m_type),
4013 m_value);
4014 else
4015 r.write (" gcc_jit_rvalue *%s =\n"
4016 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4017 " %s); /* gcc_jit_type *pointer_type */\n",
4018 id,
4019 r.get_identifier (get_context ()),
4020 r.get_identifier_as_type (m_type));
4021}
4022
4023/* We're done specializing make_debug_string and write_reproducer, so we
4024 can exit the gcc::jit::recording namespace. */
ccce3b2a
DM
4025
4026} // namespace recording
4027
35485da9
DM
4028/* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4029
4030/* Implementation of pure virtual hook recording::memento::replay_into
4031 for recording::memento_of_new_string_literal. */
4032
4033void
4034recording::memento_of_new_string_literal::replay_into (replayer *r)
4035{
4036 set_playback_obj (r->new_string_literal (m_value->c_str ()));
4037}
4038
4039/* Implementation of recording::memento::make_debug_string for
4040 string literals. */
4041
4042recording::string *
4043recording::memento_of_new_string_literal::make_debug_string ()
4044{
4045 return string::from_printf (m_ctxt,
450e225b 4046 "%s",
35485da9
DM
4047 m_value->get_debug_string ());
4048}
4049
86d0ac88
DM
4050/* Implementation of recording::memento::write_reproducer for string literal
4051 values. */
4052
4053void
4054recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
4055{
4056 const char *id = r.make_identifier (this, "rvalue");
4057 r.write (" gcc_jit_rvalue *%s =\n"
4058 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4059 " %s); /* const char *value */\n",
4060 id,
4061 r.get_identifier (get_context ()),
4062 m_value->get_debug_string ());
4063}
4064
35485da9
DM
4065/* The implementation of class gcc::jit::recording::unary_op. */
4066
4067/* Implementation of pure virtual hook recording::memento::replay_into
4068 for recording::unary_op. */
4069
4070void
4071recording::unary_op::replay_into (replayer *r)
4072{
4073 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
4074 m_op,
4075 get_type ()->playback_type (),
4076 m_a->playback_rvalue ()));
4077}
4078
f6f2b019
DM
4079/* Implementation of pure virtual hook recording::rvalue::visit_children
4080 for recording::unary_op. */
4081void
4082recording::unary_op::visit_children (rvalue_visitor *v)
4083{
4084 v->visit (m_a);
4085}
4086
35485da9
DM
4087/* Implementation of recording::memento::make_debug_string for
4088 unary ops. */
4089
4090static const char * const unary_op_strings[] = {
4091 "-", /* GCC_JIT_UNARY_OP_MINUS */
4092 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4093 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
18146f45 4094 "abs ", /* GCC_JIT_UNARY_OP_ABS */
35485da9
DM
4095};
4096
4097recording::string *
4098recording::unary_op::make_debug_string ()
4099{
4100 return string::from_printf (m_ctxt,
4101 "%s(%s)",
4102 unary_op_strings[m_op],
4103 m_a->get_debug_string ());
4104}
4105
86d0ac88
DM
4106static const char * const unary_op_reproducer_strings[] = {
4107 "GCC_JIT_UNARY_OP_MINUS",
4108 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4109 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4110 "GCC_JIT_UNARY_OP_ABS"
4111};
4112
4113/* Implementation of recording::memento::write_reproducer for unary ops. */
4114
4115void
4116recording::unary_op::write_reproducer (reproducer &r)
4117{
4118 const char *id = r.make_identifier (this, "rvalue");
4119 r.write (" gcc_jit_rvalue *%s =\n"
4120 " gcc_jit_context_new_unary_op (%s,\n"
4121 " %s, /* gcc_jit_location *loc */\n"
4122 " %s, /* enum gcc_jit_unary_op op */\n"
4123 " %s, /* gcc_jit_type *result_type */\n"
4124 " %s); /* gcc_jit_rvalue *a */\n",
4125 id,
4126 r.get_identifier (get_context ()),
4127 r.get_identifier (m_loc),
4128 unary_op_reproducer_strings[m_op],
4129 r.get_identifier_as_type (get_type ()),
4130 r.get_identifier_as_rvalue (m_a));
4131}
4132
35485da9
DM
4133/* The implementation of class gcc::jit::recording::binary_op. */
4134
4135/* Implementation of pure virtual hook recording::memento::replay_into
4136 for recording::binary_op. */
4137
4138void
4139recording::binary_op::replay_into (replayer *r)
4140{
4141 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
4142 m_op,
4143 get_type ()->playback_type (),
4144 m_a->playback_rvalue (),
4145 m_b->playback_rvalue ()));
4146}
4147
f6f2b019
DM
4148/* Implementation of pure virtual hook recording::rvalue::visit_children
4149 for recording::binary_op. */
4150void
4151recording::binary_op::visit_children (rvalue_visitor *v)
4152{
4153 v->visit (m_a);
4154 v->visit (m_b);
4155}
4156
35485da9
DM
4157/* Implementation of recording::memento::make_debug_string for
4158 binary ops. */
4159
4160static const char * const binary_op_strings[] = {
4161 "+", /* GCC_JIT_BINARY_OP_PLUS */
4162 "-", /* GCC_JIT_BINARY_OP_MINUS */
4163 "*", /* GCC_JIT_BINARY_OP_MULT */
4164 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4165 "%", /* GCC_JIT_BINARY_OP_MODULO */
4166 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4167 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4168 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4169 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4170 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4171 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4172 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4173};
4174
4175recording::string *
4176recording::binary_op::make_debug_string ()
4177{
4178 return string::from_printf (m_ctxt,
4179 "%s %s %s",
4180 m_a->get_debug_string (),
4181 binary_op_strings[m_op],
4182 m_b->get_debug_string ());
4183}
4184
86d0ac88
DM
4185static const char * const binary_op_reproducer_strings[] = {
4186 "GCC_JIT_BINARY_OP_PLUS",
4187 "GCC_JIT_BINARY_OP_MINUS",
4188 "GCC_JIT_BINARY_OP_MULT",
4189 "GCC_JIT_BINARY_OP_DIVIDE",
4190 "GCC_JIT_BINARY_OP_MODULO",
4191 "GCC_JIT_BINARY_OP_BITWISE_AND",
4192 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4193 "GCC_JIT_BINARY_OP_BITWISE_OR",
4194 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4195 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4196 "GCC_JIT_BINARY_OP_LSHIFT",
4197 "GCC_JIT_BINARY_OP_RSHIFT"
4198};
4199
4200/* Implementation of recording::memento::write_reproducer for binary ops. */
4201
4202void
4203recording::binary_op::write_reproducer (reproducer &r)
4204{
4205 const char *id = r.make_identifier (this, "rvalue");
4206 r.write (" gcc_jit_rvalue *%s =\n"
4207 " gcc_jit_context_new_binary_op (%s,\n"
4208 " %s, /* gcc_jit_location *loc */\n"
4209 " %s, /* enum gcc_jit_binary_op op */\n"
4210 " %s, /* gcc_jit_type *result_type */\n"
4211 " %s, /* gcc_jit_rvalue *a */\n"
4212 " %s); /* gcc_jit_rvalue *b */\n",
4213 id,
4214 r.get_identifier (get_context ()),
4215 r.get_identifier (m_loc),
4216 binary_op_reproducer_strings[m_op],
4217 r.get_identifier_as_type (get_type ()),
4218 r.get_identifier_as_rvalue (m_a),
4219 r.get_identifier_as_rvalue (m_b));
4220}
4221
35485da9
DM
4222/* The implementation of class gcc::jit::recording::comparison. */
4223
4224/* Implementation of recording::memento::make_debug_string for
4225 comparisons. */
4226
4227static const char * const comparison_strings[] =
4228{
4229 "==", /* GCC_JIT_COMPARISON_EQ */
4230 "!=", /* GCC_JIT_COMPARISON_NE */
4231 "<", /* GCC_JIT_COMPARISON_LT */
4232 "<=", /* GCC_JIT_COMPARISON_LE */
4233 ">", /* GCC_JIT_COMPARISON_GT */
4234 ">=", /* GCC_JIT_COMPARISON_GE */
4235};
4236
4237recording::string *
4238recording::comparison::make_debug_string ()
4239{
4240 return string::from_printf (m_ctxt,
4241 "%s %s %s",
4242 m_a->get_debug_string (),
4243 comparison_strings[m_op],
4244 m_b->get_debug_string ());
4245}
4246
86d0ac88
DM
4247/* A table of enum gcc_jit_comparison values expressed in string
4248 form. */
4249
4250static const char * const comparison_reproducer_strings[] =
4251{
4252 "GCC_JIT_COMPARISON_EQ",
4253 "GCC_JIT_COMPARISON_NE",
4254 "GCC_JIT_COMPARISON_LT",
4255 "GCC_JIT_COMPARISON_LE",
4256 "GCC_JIT_COMPARISON_GT",
4257 "GCC_JIT_COMPARISON_GE"
4258};
4259
4260/* Implementation of recording::memento::write_reproducer for comparisons. */
4261
4262void
4263recording::comparison::write_reproducer (reproducer &r)
4264{
4265 const char *id = r.make_identifier (this, "rvalue");
4266 r.write (" gcc_jit_rvalue *%s =\n"
4267 " gcc_jit_context_new_comparison (%s,\n"
4268 " %s, /* gcc_jit_location *loc */\n"
4269 " %s, /* enum gcc_jit_comparison op */\n"
4270 " %s, /* gcc_jit_rvalue *a */\n"
4271 " %s); /* gcc_jit_rvalue *b */\n",
4272 id,
4273 r.get_identifier (get_context ()),
4274 r.get_identifier (m_loc),
4275 comparison_reproducer_strings[m_op],
4276 r.get_identifier_as_rvalue (m_a),
4277 r.get_identifier_as_rvalue (m_b));
4278}
4279
35485da9
DM
4280/* Implementation of pure virtual hook recording::memento::replay_into
4281 for recording::comparison. */
4282
4283void
4284recording::comparison::replay_into (replayer *r)
4285{
4286 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
4287 m_op,
4288 m_a->playback_rvalue (),
4289 m_b->playback_rvalue ()));
4290}
4291
f6f2b019
DM
4292/* Implementation of pure virtual hook recording::rvalue::visit_children
4293 for recording::comparison. */
4294
4295void
4296recording::comparison::visit_children (rvalue_visitor *v)
4297{
4298 v->visit (m_a);
4299 v->visit (m_b);
4300}
4301
35485da9
DM
4302/* Implementation of pure virtual hook recording::memento::replay_into
4303 for recording::cast. */
4304
4305void
4306recording::cast::replay_into (replayer *r)
4307{
4308 set_playback_obj (r->new_cast (playback_location (r, m_loc),
4309 m_rvalue->playback_rvalue (),
4310 get_type ()->playback_type ()));
4311}
4312
f6f2b019
DM
4313/* Implementation of pure virtual hook recording::rvalue::visit_children
4314 for recording::cast. */
4315void
4316recording::cast::visit_children (rvalue_visitor *v)
4317{
4318 v->visit (m_rvalue);
4319}
4320
35485da9
DM
4321/* Implementation of recording::memento::make_debug_string for
4322 casts. */
4323
4324recording::string *
4325recording::cast::make_debug_string ()
4326{
4327 return string::from_printf (m_ctxt,
4328 "(%s)%s",
4329 get_type ()->get_debug_string (),
4330 m_rvalue->get_debug_string ());
4331}
4332
86d0ac88
DM
4333/* Implementation of recording::memento::write_reproducer for casts. */
4334
4335void
4336recording::cast::write_reproducer (reproducer &r)
4337{
4338 const char *id = r.make_identifier (this, "rvalue");
4339 r.write (" gcc_jit_rvalue *%s =\n"
4340 " gcc_jit_context_new_cast (%s,\n"
4341 " %s, /* gcc_jit_location *loc */\n"
4342 " %s, /* gcc_jit_rvalue *rvalue */\n"
4343 " %s); /* gcc_jit_type *type */\n",
4344 id,
4345 r.get_identifier (get_context ()),
4346 r.get_identifier (m_loc),
4347 r.get_identifier_as_rvalue (m_rvalue),
4348 r.get_identifier_as_type (get_type ()));
4349}
4350
35485da9
DM
4351/* The implementation of class gcc::jit::recording::call. */
4352
4353/* The constructor for gcc::jit::recording::call. */
4354
4355recording::call::call (recording::context *ctxt,
4356 recording::location *loc,
4357 recording::function *func,
4358 int numargs,
4359 rvalue **args)
4360: rvalue (ctxt, loc, func->get_return_type ()),
4361 m_func (func),
4362 m_args ()
4363{
4364 for (int i = 0; i< numargs; i++)
4365 m_args.safe_push (args[i]);
4366}
4367
4368/* Implementation of pure virtual hook recording::memento::replay_into
4369 for recording::call. */
4370
4371void
4372recording::call::replay_into (replayer *r)
4373{
b957b2e0 4374 auto_vec<playback::rvalue *> playback_args;
35485da9
DM
4375 playback_args.create (m_args.length ());
4376 for (unsigned i = 0; i< m_args.length (); i++)
4377 playback_args.safe_push (m_args[i]->playback_rvalue ());
4378
4379 set_playback_obj (r->new_call (playback_location (r, m_loc),
4380 m_func->playback_function (),
b957b2e0 4381 &playback_args));
35485da9
DM
4382}
4383
f6f2b019
DM
4384/* Implementation of pure virtual hook recording::rvalue::visit_children
4385 for recording::call. */
4386
4387void
4388recording::call::visit_children (rvalue_visitor *v)
4389{
4390 for (unsigned i = 0; i< m_args.length (); i++)
4391 v->visit (m_args[i]);
4392}
4393
35485da9
DM
4394/* Implementation of recording::memento::make_debug_string for
4395 function calls. */
4396
4397recording::string *
4398recording::call::make_debug_string ()
4399{
4400 /* First, build a buffer for the arguments. */
4401 /* Calculate length of said buffer. */
4402 size_t sz = 1; /* nil terminator */
4403 for (unsigned i = 0; i< m_args.length (); i++)
4404 {
4405 sz += strlen (m_args[i]->get_debug_string ());
4406 sz += 2; /* ", " separator */
4407 }
4408
4409 /* Now allocate and populate the buffer. */
4410 char *argbuf = new char[sz];
4411 size_t len = 0;
4412
4413 for (unsigned i = 0; i< m_args.length (); i++)
4414 {
4415 strcpy (argbuf + len, m_args[i]->get_debug_string ());
4416 len += strlen (m_args[i]->get_debug_string ());
4417 if (i + 1 < m_args.length ())
4418 {
4419 strcpy (argbuf + len, ", ");
4420 len += 2;
4421 }
4422 }
4423 argbuf[len] = '\0';
4424
4425 /* ...and use it to get the string for the call as a whole. */
4426 string *result = string::from_printf (m_ctxt,
4427 "%s (%s)",
4428 m_func->get_debug_string (),
4429 argbuf);
4430
4431 delete[] argbuf;
4432
4433 return result;
4434}
4435
86d0ac88
DM
4436void
4437recording::call::write_reproducer (reproducer &r)
4438{
4439 const char *id = r.make_identifier (this, "call");
4440 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4441 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4442 args_id,
4443 m_args.length ());
4444 for (unsigned i = 0; i< m_args.length (); i++)
4445 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4446 r.write (" };\n");
4447 r.write (" gcc_jit_rvalue *%s =\n"
4448 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4449 " %s, /* gcc_jit_location *loc */\n"
4450 " %s, /* gcc_jit_function *func */\n"
4451 " %i, /* int numargs */ \n"
4452 " %s); /* gcc_jit_rvalue **args*/\n",
4453 id,
4454 r.get_identifier (get_context ()),
4455 r.get_identifier (m_loc),
4456 r.get_identifier (m_func),
4457 m_args.length (),
4458 args_id);
4459}
4460
35485da9
DM
4461/* The implementation of class gcc::jit::recording::call_through_ptr. */
4462
4463/* The constructor for recording::call_through_ptr. */
4464
4465recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
4466 recording::location *loc,
4467 recording::rvalue *fn_ptr,
4468 int numargs,
4469 rvalue **args)
4470: rvalue (ctxt, loc,
4471 fn_ptr->get_type ()->dereference ()
4472 ->as_a_function_type ()->get_return_type ()),
4473 m_fn_ptr (fn_ptr),
4474 m_args ()
4475{
4476 for (int i = 0; i< numargs; i++)
4477 m_args.safe_push (args[i]);
4478}
4479
4480/* Implementation of pure virtual hook recording::memento::replay_into
4481 for recording::call_through_ptr. */
4482
4483void
4484recording::call_through_ptr::replay_into (replayer *r)
4485{
b957b2e0 4486 auto_vec<playback::rvalue *> playback_args;
35485da9
DM
4487 playback_args.create (m_args.length ());
4488 for (unsigned i = 0; i< m_args.length (); i++)
4489 playback_args.safe_push (m_args[i]->playback_rvalue ());
4490
4491 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
4492 m_fn_ptr->playback_rvalue (),
b957b2e0 4493 &playback_args));
35485da9
DM
4494}
4495
f6f2b019
DM
4496/* Implementation of pure virtual hook recording::rvalue::visit_children
4497 for recording::call_through_ptr. */
4498
4499void
4500recording::call_through_ptr::visit_children (rvalue_visitor *v)
4501{
4502 v->visit (m_fn_ptr);
4503 for (unsigned i = 0; i< m_args.length (); i++)
4504 v->visit (m_args[i]);
4505}
4506
35485da9
DM
4507/* Implementation of recording::memento::make_debug_string for
4508 calls through function ptrs. */
4509
4510recording::string *
4511recording::call_through_ptr::make_debug_string ()
4512{
4513 /* First, build a buffer for the arguments. */
4514 /* Calculate length of said buffer. */
4515 size_t sz = 1; /* nil terminator */
4516 for (unsigned i = 0; i< m_args.length (); i++)
4517 {
4518 sz += strlen (m_args[i]->get_debug_string ());
4519 sz += 2; /* ", " separator */
4520 }
4521
4522 /* Now allocate and populate the buffer. */
4523 char *argbuf = new char[sz];
4524 size_t len = 0;
4525
4526 for (unsigned i = 0; i< m_args.length (); i++)
4527 {
4528 strcpy (argbuf + len, m_args[i]->get_debug_string ());
4529 len += strlen (m_args[i]->get_debug_string ());
4530 if (i + 1 < m_args.length ())
4531 {
4532 strcpy (argbuf + len, ", ");
4533 len += 2;
4534 }
4535 }
4536 argbuf[len] = '\0';
4537
4538 /* ...and use it to get the string for the call as a whole. */
4539 string *result = string::from_printf (m_ctxt,
4540 "%s (%s)",
4541 m_fn_ptr->get_debug_string (),
4542 argbuf);
4543
4544 delete[] argbuf;
4545
4546 return result;
4547}
4548
86d0ac88
DM
4549/* Implementation of recording::memento::write_reproducer for
4550 call_through_ptr. */
4551
4552void
4553recording::call_through_ptr::write_reproducer (reproducer &r)
4554{
4555 const char *id = r.make_identifier (this, "call");
4556 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4557 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4558 args_id,
4559 m_args.length ());
4560 for (unsigned i = 0; i< m_args.length (); i++)
4561 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4562 r.write (" };\n");
4563 r.write (" gcc_jit_rvalue *%s =\n"
4564 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
4565 " %s, /* gcc_jit_location *loc */\n"
4566 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
4567 " %i, /* int numargs */ \n"
4568 " %s); /* gcc_jit_rvalue **args*/\n",
4569 id,
4570 r.get_identifier (get_context ()),
4571 r.get_identifier (m_loc),
4572 r.get_identifier_as_rvalue (m_fn_ptr),
4573 m_args.length (),
4574 args_id);
4575}
4576
35485da9
DM
4577/* The implementation of class gcc::jit::recording::array_access. */
4578
4579/* Implementation of pure virtual hook recording::memento::replay_into
4580 for recording::array_access. */
4581
4582void
4583recording::array_access::replay_into (replayer *r)
4584{
4585 set_playback_obj (
4586 r->new_array_access (playback_location (r, m_loc),
4587 m_ptr->playback_rvalue (),
4588 m_index->playback_rvalue ()));
4589}
4590
f6f2b019
DM
4591/* Implementation of pure virtual hook recording::rvalue::visit_children
4592 for recording::array_access. */
4593
4594void
4595recording::array_access::visit_children (rvalue_visitor *v)
4596{
4597 v->visit (m_ptr);
4598 v->visit (m_index);
4599}
4600
35485da9
DM
4601/* Implementation of recording::memento::make_debug_string for
4602 array accesses. */
4603
4604recording::string *
4605recording::array_access::make_debug_string ()
4606{
4607 return string::from_printf (m_ctxt,
4608 "%s[%s]",
4609 m_ptr->get_debug_string (),
4610 m_index->get_debug_string ());
4611}
4612
86d0ac88
DM
4613/* Implementation of recording::memento::write_reproducer for
4614 array_access. */
4615
4616void
4617recording::array_access::write_reproducer (reproducer &r)
4618{
4619 const char *id = r.make_identifier (this, "lvalue");
4620 r.write (" gcc_jit_lvalue *%s = \n"
4621 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
4622 " %s, /*gcc_jit_location *loc */\n"
4623 " %s, /* gcc_jit_rvalue *ptr */\n"
4624 " %s); /* gcc_jit_rvalue *index */\n",
4625 id,
4626 r.get_identifier (get_context ()),
4627 r.get_identifier (m_loc),
4628 r.get_identifier_as_rvalue (m_ptr),
4629 r.get_identifier_as_rvalue (m_index));
4630}
4631
35485da9
DM
4632/* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
4633
4634/* Implementation of pure virtual hook recording::memento::replay_into
4635 for recording::access_field_of_lvalue. */
4636
4637void
4638recording::access_field_of_lvalue::replay_into (replayer *r)
4639{
4640 set_playback_obj (
4641 m_lvalue->playback_lvalue ()
4642 ->access_field (playback_location (r, m_loc),
4643 m_field->playback_field ()));
4644
4645}
4646
f6f2b019
DM
4647/* Implementation of pure virtual hook recording::rvalue::visit_children
4648 for recording::access_field_of_lvalue. */
4649
4650void
4651recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
4652{
4653 v->visit (m_lvalue);
4654}
4655
35485da9
DM
4656/* Implementation of recording::memento::make_debug_string for
4657 accessing a field of an lvalue. */
4658
4659recording::string *
4660recording::access_field_of_lvalue::make_debug_string ()
4661{
4662 return string::from_printf (m_ctxt,
4663 "%s.%s",
4664 m_lvalue->get_debug_string (),
4665 m_field->get_debug_string ());
4666}
4667
86d0ac88
DM
4668/* Implementation of recording::memento::write_reproducer for
4669 access_field_of_lvalue. */
4670
4671void
4672recording::access_field_of_lvalue::write_reproducer (reproducer &r)
4673{
4674 const char *id = r.make_identifier (this, "lvalue");
4675 r.write (" gcc_jit_lvalue *%s = \n"
4676 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
4677 " %s, /*gcc_jit_location *loc */\n"
4678 " %s);\n",
4679 id,
4680 r.get_identifier_as_lvalue (m_lvalue),
4681 r.get_identifier (m_loc),
4682 r.get_identifier (m_field));
4683}
4684
35485da9
DM
4685/* The implementation of class gcc::jit::recording::access_field_rvalue. */
4686
4687/* Implementation of pure virtual hook recording::memento::replay_into
4688 for recording::access_field_rvalue. */
4689
4690void
4691recording::access_field_rvalue::replay_into (replayer *r)
4692{
4693 set_playback_obj (
4694 m_rvalue->playback_rvalue ()
4695 ->access_field (playback_location (r, m_loc),
4696 m_field->playback_field ()));
4697}
4698
f6f2b019
DM
4699/* Implementation of pure virtual hook recording::rvalue::visit_children
4700 for recording::access_field_rvalue. */
4701
4702void
4703recording::access_field_rvalue::visit_children (rvalue_visitor *v)
4704{
4705 v->visit (m_rvalue);
4706}
4707
35485da9
DM
4708/* Implementation of recording::memento::make_debug_string for
4709 accessing a field of an rvalue. */
4710
4711recording::string *
4712recording::access_field_rvalue::make_debug_string ()
4713{
4714 return string::from_printf (m_ctxt,
4715 "%s.%s",
4716 m_rvalue->get_debug_string (),
4717 m_field->get_debug_string ());
4718}
4719
86d0ac88
DM
4720/* Implementation of recording::memento::write_reproducer for
4721 access_field_rvalue. */
4722
4723void
4724recording::access_field_rvalue::write_reproducer (reproducer &r)
4725{
4726 const char *id = r.make_identifier (this, "rvalue");
4727 r.write (" gcc_jit_rvalue *%s = \n"
4728 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
4729 " %s, /*gcc_jit_location *loc */\n"
4730 " %s);\n",
4731 id,
4732 r.get_identifier_as_rvalue (m_rvalue),
4733 r.get_identifier (m_loc),
4734 r.get_identifier (m_field));
4735}
4736
35485da9
DM
4737/* The implementation of class
4738 gcc::jit::recording::dereference_field_rvalue. */
4739
4740/* Implementation of pure virtual hook recording::memento::replay_into
4741 for recording::dereference_field_rvalue. */
4742
4743void
4744recording::dereference_field_rvalue::replay_into (replayer *r)
4745{
4746 set_playback_obj (
4747 m_rvalue->playback_rvalue ()->
4748 dereference_field (playback_location (r, m_loc),
4749 m_field->playback_field ()));
4750}
4751
f6f2b019
DM
4752/* Implementation of pure virtual hook recording::rvalue::visit_children
4753 for recording::dereference_field_rvalue. */
4754
4755void
4756recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
4757{
4758 v->visit (m_rvalue);
4759}
4760
35485da9
DM
4761/* Implementation of recording::memento::make_debug_string for
4762 dereferencing a field of an rvalue. */
4763
4764recording::string *
4765recording::dereference_field_rvalue::make_debug_string ()
4766{
4767 return string::from_printf (m_ctxt,
4768 "%s->%s",
4769 m_rvalue->get_debug_string (),
4770 m_field->get_debug_string ());
4771}
4772
86d0ac88
DM
4773/* Implementation of recording::memento::write_reproducer for
4774 dereference_field_rvalue. */
4775
4776void
4777recording::dereference_field_rvalue::write_reproducer (reproducer &r)
4778{
4779 const char *id = r.make_identifier (this, "lvalue");
4780 r.write (" gcc_jit_lvalue *%s=\n"
4781 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
4782 " %s, /* gcc_jit_location *loc */\n"
4783 " %s); /* gcc_jit_field *field */\n",
4784 id,
4785 r.get_identifier_as_rvalue (m_rvalue),
4786 r.get_identifier (m_loc),
4787 r.get_identifier (m_field));
4788}
4789
35485da9
DM
4790/* The implementation of class gcc::jit::recording::dereference_rvalue. */
4791
4792/* Implementation of pure virtual hook recording::memento::replay_into
4793 for recording::dereference_rvalue. */
4794
4795void
4796recording::dereference_rvalue::replay_into (replayer *r)
4797{
4798 set_playback_obj (
4799 m_rvalue->playback_rvalue ()->
4800 dereference (playback_location (r, m_loc)));
4801}
4802
f6f2b019
DM
4803/* Implementation of pure virtual hook recording::rvalue::visit_children
4804 for recording::dereference_rvalue. */
4805
4806void
4807recording::dereference_rvalue::visit_children (rvalue_visitor *v)
4808{
4809 v->visit (m_rvalue);
4810}
4811
35485da9
DM
4812/* Implementation of recording::memento::make_debug_string for
4813 dereferencing an rvalue. */
4814
4815recording::string *
4816recording::dereference_rvalue::make_debug_string ()
4817{
4818 return string::from_printf (m_ctxt,
4819 "*%s",
4820 m_rvalue->get_debug_string ());
4821}
4822
86d0ac88
DM
4823/* Implementation of recording::memento::write_reproducer for
4824 dereference_rvalue. */
4825
4826void
4827recording::dereference_rvalue::write_reproducer (reproducer &r)
4828{
4829 const char *id = r.make_identifier (this, "dereference");
4830 r.write (" gcc_jit_lvalue *%s =\n"
4831 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
4832 " %s); /* gcc_jit_location *loc */\n",
4833 id,
4834 r.get_identifier_as_rvalue (m_rvalue),
4835 r.get_identifier (m_loc));
4836}
4837
35485da9
DM
4838/* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
4839
4840/* Implementation of pure virtual hook recording::memento::replay_into
4841 for recording::get_address_of_lvalue. */
4842
4843void
4844recording::get_address_of_lvalue::replay_into (replayer *r)
4845{
4846 set_playback_obj (
4847 m_lvalue->playback_lvalue ()->
4848 get_address (playback_location (r, m_loc)));
4849}
4850
f6f2b019
DM
4851/* Implementation of pure virtual hook recording::rvalue::visit_children
4852 for recording::get_address_of_lvalue. */
4853
4854void
4855recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
4856{
4857 v->visit (m_lvalue);
4858}
4859
35485da9
DM
4860/* Implementation of recording::memento::make_debug_string for
4861 getting the address of an lvalue. */
4862
4863recording::string *
4864recording::get_address_of_lvalue::make_debug_string ()
4865{
4866 return string::from_printf (m_ctxt,
4867 "&%s",
4868 m_lvalue->get_debug_string ());
4869}
4870
86d0ac88
DM
4871/* Implementation of recording::memento::write_reproducer for
4872 get_address_of_lvalue. */
4873
4874void
4875recording::get_address_of_lvalue::write_reproducer (reproducer &r)
4876{
4877 const char *id = r.make_identifier (this, "address_of");
4878 r.write (" gcc_jit_rvalue *%s =\n"
4879 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
4880 " %s); /* gcc_jit_location *loc */\n",
4881 id,
4882 r.get_identifier_as_lvalue (m_lvalue),
4883 r.get_identifier (m_loc));
4884}
4885
35485da9
DM
4886/* The implementation of class gcc::jit::recording::local. */
4887
4888/* Implementation of pure virtual hook recording::memento::replay_into
4889 for recording::local. */
4890
4891void
4892recording::local::replay_into (replayer *r)
4893{
4894 set_playback_obj (
4895 m_func->playback_function ()
4896 ->new_local (playback_location (r, m_loc),
4897 m_type->playback_type (),
4898 playback_string (m_name)));
4899}
4900
4901/* Override the default implementation of
4902 recording::memento::write_to_dump for locals by writing
4903 TYPE NAME;
4904 for use at the top of the function body as if it were a
4905 declaration. */
4906
4907void
4908recording::local::write_to_dump (dump &d)
4909{
4910 if (d.update_locations ())
4911 m_loc = d.make_location ();
4912 d.write(" %s %s;\n",
4913 m_type->get_debug_string (),
4914 get_debug_string ());
4915}
4916
86d0ac88
DM
4917void
4918recording::local::write_reproducer (reproducer &r)
4919{
4920 const char *id = r.make_identifier (this, "local");
4921 r.write (" gcc_jit_lvalue *%s =\n"
4922 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
4923 " %s, /* gcc_jit_location *loc */\n"
4924 " %s, /* gcc_jit_type *type */\n"
4925 " %s); /* const char *name */\n",
4926 id,
4927 r.get_identifier (m_func),
4928 r.get_identifier (m_loc),
4929 r.get_identifier_as_type (m_type),
4930 m_name->get_debug_string ());
4931}
4932
35485da9
DM
4933/* The implementation of class gcc::jit::recording::statement. */
4934
4935/* We poison the default implementation of
4936 gcc::jit::recording::statement::get_successor_blocks
4937 since this vfunc must only ever be called on terminator
4938 statements. */
4939
4940int
4941recording::statement::get_successor_blocks (block **/*out_next1*/,
4942 block **/*out_next2*/) const
4943{
4944 /* The base class implementation is for non-terminating statements,
4945 and thus should never be called. */
4946 gcc_unreachable ();
4947 return 0;
4948}
4949
4950/* Extend the default implementation of
4951 recording::memento::write_to_dump for statements by (if requested)
4952 updating the location of the statement to the current location in
4953 the dumpfile. */
4954
4955void
4956recording::statement::write_to_dump (dump &d)
4957{
4958 memento::write_to_dump (d);
4959 if (d.update_locations ())
4960 m_loc = d.make_location ();
4961}
4962
4963/* The implementation of class gcc::jit::recording::eval. */
4964
4965/* Implementation of pure virtual hook recording::memento::replay_into
4966 for recording::eval. */
4967
4968void
4969recording::eval::replay_into (replayer *r)
4970{
4971 playback_block (get_block ())
4972 ->add_eval (playback_location (r),
4973 m_rvalue->playback_rvalue ());
4974}
4975
4976/* Implementation of recording::memento::make_debug_string for
4977 an eval statement. */
4978
4979recording::string *
4980recording::eval::make_debug_string ()
4981{
4982 return string::from_printf (m_ctxt,
4983 "(void)%s;",
4984 m_rvalue->get_debug_string ());
4985}
4986
86d0ac88
DM
4987/* Implementation of recording::memento::write_reproducer for
4988 eval statements. */
4989
4990void
4991recording::eval::write_reproducer (reproducer &r)
4992{
4993 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
4994 " %s, /* gcc_jit_location *loc */\n"
4995 " %s); /* gcc_jit_rvalue *rvalue */\n",
4996 r.get_identifier (get_block ()),
4997 r.get_identifier (get_loc ()),
4998 r.get_identifier_as_rvalue (m_rvalue));
4999}
5000
35485da9
DM
5001/* The implementation of class gcc::jit::recording::assignment. */
5002
5003/* Implementation of pure virtual hook recording::memento::replay_into
5004 for recording::assignment. */
5005
5006void
5007recording::assignment::replay_into (replayer *r)
5008{
5009 playback_block (get_block ())
5010 ->add_assignment (playback_location (r),
5011 m_lvalue->playback_lvalue (),
5012 m_rvalue->playback_rvalue ());
5013}
5014
5015/* Implementation of recording::memento::make_debug_string for
5016 an assignment statement. */
5017
5018recording::string *
5019recording::assignment::make_debug_string ()
5020{
5021 return string::from_printf (m_ctxt,
5022 "%s = %s;",
5023 m_lvalue->get_debug_string (),
5024 m_rvalue->get_debug_string ());
5025}
5026
86d0ac88
DM
5027/* Implementation of recording::memento::write_reproducer for
5028 assignment statements. */
5029
5030void
5031recording::assignment::write_reproducer (reproducer &r)
5032{
5033 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5034 " %s, /* gcc_jit_location *loc */\n"
5035 " %s, /* gcc_jit_lvalue *lvalue */\n"
5036 " %s); /* gcc_jit_rvalue *rvalue */\n",
5037 r.get_identifier (get_block ()),
5038 r.get_identifier (get_loc ()),
5039 r.get_identifier_as_lvalue (m_lvalue),
5040 r.get_identifier_as_rvalue (m_rvalue));
5041}
5042
35485da9
DM
5043/* The implementation of class gcc::jit::recording::assignment_op. */
5044
5045/* Implementation of pure virtual hook recording::memento::replay_into
5046 for recording::assignment_op. */
5047
5048void
5049recording::assignment_op::replay_into (replayer *r)
5050{
5051 playback::type *result_type =
5052 m_lvalue->playback_lvalue ()->get_type ();
5053
5054 playback::rvalue *binary_op =
5055 r->new_binary_op (playback_location (r),
5056 m_op,
5057 result_type,
5058 m_lvalue->playback_rvalue (),
5059 m_rvalue->playback_rvalue ());
5060
5061 playback_block (get_block ())
5062 ->add_assignment (playback_location (r),
5063 m_lvalue->playback_lvalue (),
5064 binary_op);
5065}
5066
5067/* Implementation of recording::memento::make_debug_string for
5068 an assignment_op statement. */
5069
5070recording::string *
5071recording::assignment_op::make_debug_string ()
5072{
5073 return string::from_printf (m_ctxt,
5074 "%s %s= %s;",
5075 m_lvalue->get_debug_string (),
5076 binary_op_strings[m_op],
5077 m_rvalue->get_debug_string ());
5078}
5079
86d0ac88
DM
5080/* Implementation of recording::memento::write_reproducer for
5081 assignment_op statements. */
5082
5083void
5084recording::assignment_op::write_reproducer (reproducer &r)
5085{
5086 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5087 " %s, /* gcc_jit_location *loc */\n"
5088 " %s, /* gcc_jit_lvalue *lvalue */\n"
5089 " %s, /* enum gcc_jit_binary_op op */\n"
5090 " %s); /* gcc_jit_rvalue *rvalue */\n",
5091 r.get_identifier (get_block ()),
5092 r.get_identifier (get_loc ()),
5093 r.get_identifier_as_lvalue (m_lvalue),
5094 binary_op_reproducer_strings[m_op],
5095 r.get_identifier_as_rvalue (m_rvalue));
5096}
5097
35485da9
DM
5098/* The implementation of class gcc::jit::recording::comment. */
5099
5100/* Implementation of pure virtual hook recording::memento::replay_into
5101 for recording::comment. */
5102
5103void
5104recording::comment::replay_into (replayer *r)
5105{
5106 playback_block (get_block ())
5107 ->add_comment (playback_location (r),
5108 m_text->c_str ());
5109}
5110
5111/* Implementation of recording::memento::make_debug_string for
5112 a comment "statement". */
5113
5114recording::string *
5115recording::comment::make_debug_string ()
5116{
5117 return string::from_printf (m_ctxt,
5118 "/* %s */",
5119 m_text->c_str ());
5120}
5121
86d0ac88
DM
5122/* Implementation of recording::memento::write_reproducer for
5123 comments. */
5124
5125void
5126recording::comment::write_reproducer (reproducer &r)
5127{
5128 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5129 " %s, /* gcc_jit_location *loc */\n"
5130 " %s); /* const char *text */\n",
5131 r.get_identifier (get_block ()),
5132 r.get_identifier (get_loc ()),
5133 m_text->get_debug_string ());
5134}
5135
35485da9
DM
5136/* The implementation of class gcc::jit::recording::conditional. */
5137
5138/* Implementation of pure virtual hook recording::memento::replay_into
5139 for recording::conditional. */
5140
5141void
5142recording::conditional::replay_into (replayer *r)
5143{
5144 playback_block (get_block ())
5145 ->add_conditional (playback_location (r),
5146 m_boolval->playback_rvalue (),
5147 playback_block (m_on_true),
5148 playback_block (m_on_false));
5149}
5150
5151/* Override the poisoned default implementation of
5152 gcc::jit::recording::statement::get_successor_blocks
5153
5154 A conditional jump has 2 successor blocks. */
5155
5156int
5157recording::conditional::get_successor_blocks (block **out_next1,
5158 block **out_next2) const
5159{
5160 *out_next1 = m_on_true;
5161 *out_next2 = m_on_false;
5162 return 2;
5163}
5164
5165/* Implementation of recording::memento::make_debug_string for
5166 a conditional jump statement. */
5167
5168recording::string *
5169recording::conditional::make_debug_string ()
5170{
5171 if (m_on_false)
5172 return string::from_printf (m_ctxt,
5173 "if (%s) goto %s; else goto %s;",
5174 m_boolval->get_debug_string (),
5175 m_on_true->get_debug_string (),
5176 m_on_false->get_debug_string ());
5177 else
5178 return string::from_printf (m_ctxt,
5179 "if (%s) goto %s;",
5180 m_boolval->get_debug_string (),
5181 m_on_true->get_debug_string ());
5182}
5183
86d0ac88
DM
5184/* Implementation of recording::memento::write_reproducer for
5185 conditional statements. */
5186
5187void
5188recording::conditional::write_reproducer (reproducer &r)
5189{
5190 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5191 " %s, /* gcc_jit_location *loc */\n"
5192 " %s, /* gcc_jit_rvalue *boolval */\n"
5193 " %s, /* gcc_jit_block *on_true */\n"
5194 " %s); /* gcc_jit_block *on_false */\n",
5195 r.get_identifier (get_block ()),
5196 r.get_identifier (get_loc ()),
5197 r.get_identifier_as_rvalue (m_boolval),
5198 r.get_identifier (m_on_true),
5199 r.get_identifier (m_on_false));
5200}
5201
35485da9
DM
5202/* The implementation of class gcc::jit::recording::jump. */
5203
5204/* Implementation of pure virtual hook recording::memento::replay_into
5205 for recording::jump. */
5206
5207void
5208recording::jump::replay_into (replayer *r)
5209{
5210 playback_block (get_block ())
5211 ->add_jump (playback_location (r),
5212 m_target->playback_block ());
5213}
5214
5215/* Override the poisoned default implementation of
5216 gcc::jit::recording::statement::get_successor_blocks
5217
5218 An unconditional jump has 1 successor block. */
5219
5220int
5221recording::jump::get_successor_blocks (block **out_next1,
5222 block **/*out_next2*/) const
5223{
5224 *out_next1 = m_target;
5225 return 1;
5226}
5227
5228/* Implementation of recording::memento::make_debug_string for
5229 a unconditional jump statement. */
5230
5231recording::string *
5232recording::jump::make_debug_string ()
5233{
5234 return string::from_printf (m_ctxt,
5235 "goto %s;",
5236 m_target->get_debug_string ());
5237}
5238
86d0ac88
DM
5239/* Implementation of recording::memento::write_reproducer for
5240 jump statements. */
5241
5242void
5243recording::jump::write_reproducer (reproducer &r)
5244{
5245 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5246 " %s, /* gcc_jit_location *loc */\n"
5247 " %s); /* gcc_jit_block *target */\n",
5248 r.get_identifier (get_block ()),
5249 r.get_identifier (get_loc ()),
5250 r.get_identifier (m_target));
5251}
5252
35485da9
DM
5253/* The implementation of class gcc::jit::recording::return_. */
5254
5255/* Implementation of pure virtual hook recording::memento::replay_into
5256 for recording::return_. */
5257
5258void
5259recording::return_::replay_into (replayer *r)
5260{
5261 playback_block (get_block ())
5262 ->add_return (playback_location (r),
5263 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
5264}
5265
5266/* Override the poisoned default implementation of
5267 gcc::jit::recording::statement::get_successor_blocks
5268
5269 A return statement has no successor block. */
5270
5271int
5272recording::return_::get_successor_blocks (block **/*out_next1*/,
5273 block **/*out_next2*/) const
5274{
5275 return 0;
5276}
5277
5278/* Implementation of recording::memento::make_debug_string for
5279 a return statement (covers both those with and without rvalues). */
5280
5281recording::string *
5282recording::return_::make_debug_string ()
5283{
5284 if (m_rvalue)
5285 return string::from_printf (m_ctxt,
5286 "return %s;",
5287 m_rvalue->get_debug_string ());
5288 else
5289 return string::from_printf (m_ctxt,
5290 "return;");
5291}
5292
86d0ac88
DM
5293/* Implementation of recording::memento::write_reproducer for
5294 return statements. */
5295
5296void
5297recording::return_::write_reproducer (reproducer &r)
5298{
5299 if (m_rvalue)
5300 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5301 " %s, /* gcc_jit_location *loc */\n"
5302 " %s); /* gcc_jit_rvalue *rvalue */\n",
5303 r.get_identifier (get_block ()),
5304 r.get_identifier (get_loc ()),
5305 r.get_identifier_as_rvalue (m_rvalue));
5306 else
5307 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5308 " %s); /* gcc_jit_location *loc */\n",
5309 r.get_identifier (get_block ()),
5310 r.get_identifier (get_loc ()));
5311}
5312
35485da9
DM
5313} // namespace gcc::jit
5314
5315} // namespace gcc