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