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