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