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