]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/jit/jit-recording.c
re PR target/80210 (ICE in in extract_insn, at recog.c:2311 on ppc64 for with __built...
[thirdparty/gcc.git] / gcc / jit / jit-recording.c
CommitLineData
35485da9 1/* Internals of libgccjit: classes for recording calls made to the JIT API.
cbe34bb5 2 Copyright (C) 2013-2017 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
0ebd1f00
DM
1977/* Given a type, get an aligned version of the type.
1978
1979 Implements the post-error-checking part of
1980 gcc_jit_type_get_aligned. */
1981
1982recording::type *
1983recording::type::get_aligned (size_t alignment_in_bytes)
1984{
1985 recording::type *result
1986 = new memento_of_get_aligned (this, alignment_in_bytes);
1987 m_ctxt->record (result);
1988 return result;
1989}
1990
47ee1b7c
DM
1991/* Given a type, get a vector version of the type.
1992
1993 Implements the post-error-checking part of
1994 gcc_jit_type_get_vector. */
1995
1996recording::type *
1997recording::type::get_vector (size_t num_units)
1998{
1999 recording::type *result
2000 = new memento_of_get_vector (this, num_units);
2001 m_ctxt->record (result);
2002 return result;
2003}
2004
86d0ac88
DM
2005const char *
2006recording::type::access_as_type (reproducer &r)
2007{
2008 return r.get_identifier (this);
2009}
2010
35485da9
DM
2011/* Implementation of pure virtual hook recording::type::dereference for
2012 recording::memento_of_get_type. */
2013
2014recording::type *
2015recording::memento_of_get_type::dereference ()
2016{
2017 switch (m_kind)
2018 {
2019 default: gcc_unreachable ();
2020
2021 case GCC_JIT_TYPE_VOID:
2022 return NULL;
2023
2024 case GCC_JIT_TYPE_VOID_PTR:
2025 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
2026
2027 case GCC_JIT_TYPE_BOOL:
2028 case GCC_JIT_TYPE_CHAR:
2029 case GCC_JIT_TYPE_SIGNED_CHAR:
2030 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2031 case GCC_JIT_TYPE_SHORT:
2032 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2033 case GCC_JIT_TYPE_INT:
2034 case GCC_JIT_TYPE_UNSIGNED_INT:
2035 case GCC_JIT_TYPE_LONG:
2036 case GCC_JIT_TYPE_UNSIGNED_LONG:
2037 case GCC_JIT_TYPE_LONG_LONG:
2038 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2039 case GCC_JIT_TYPE_FLOAT:
2040 case GCC_JIT_TYPE_DOUBLE:
2041 case GCC_JIT_TYPE_LONG_DOUBLE:
eeafb319
DM
2042 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2043 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2044 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
35485da9
DM
2045 /* Not a pointer: */
2046 return NULL;
2047
2048 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2049 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
2050
2051 case GCC_JIT_TYPE_SIZE_T:
2052 /* Not a pointer: */
2053 return NULL;
2054
2055 case GCC_JIT_TYPE_FILE_PTR:
2056 /* Give the client code back an opaque "struct FILE". */
2057 return m_ctxt->get_opaque_FILE_type ();
2058 }
2059}
2060
2061/* Implementation of pure virtual hook recording::type::is_int for
2062 recording::memento_of_get_type. */
2063
2064bool
2065recording::memento_of_get_type::is_int () const
2066{
2067 switch (m_kind)
2068 {
2069 default: gcc_unreachable ();
2070
2071 case GCC_JIT_TYPE_VOID:
2072 return false;
2073
2074 case GCC_JIT_TYPE_VOID_PTR:
2075 return false;
2076
2077 case GCC_JIT_TYPE_BOOL:
2078 return false;
2079
2080 case GCC_JIT_TYPE_CHAR:
2081 case GCC_JIT_TYPE_SIGNED_CHAR:
2082 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2083 case GCC_JIT_TYPE_SHORT:
2084 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2085 case GCC_JIT_TYPE_INT:
2086 case GCC_JIT_TYPE_UNSIGNED_INT:
2087 case GCC_JIT_TYPE_LONG:
2088 case GCC_JIT_TYPE_UNSIGNED_LONG:
2089 case GCC_JIT_TYPE_LONG_LONG:
2090 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2091 return true;
2092
2093 case GCC_JIT_TYPE_FLOAT:
2094 case GCC_JIT_TYPE_DOUBLE:
2095 case GCC_JIT_TYPE_LONG_DOUBLE:
2096 return false;
2097
2098 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2099 return false;
2100
2101 case GCC_JIT_TYPE_SIZE_T:
2102 return true;
2103
2104 case GCC_JIT_TYPE_FILE_PTR:
2105 return false;
eeafb319
DM
2106
2107 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2108 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2109 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2110 return false;
35485da9
DM
2111 }
2112}
2113
2114/* Implementation of pure virtual hook recording::type::is_float for
2115 recording::memento_of_get_type. */
2116
2117bool
2118recording::memento_of_get_type::is_float () const
2119{
2120 switch (m_kind)
2121 {
2122 default: gcc_unreachable ();
2123
2124 case GCC_JIT_TYPE_VOID:
2125 return false;
2126
2127 case GCC_JIT_TYPE_VOID_PTR:
2128 return false;
2129
2130 case GCC_JIT_TYPE_BOOL:
2131 return false;
2132
2133 case GCC_JIT_TYPE_CHAR:
2134 case GCC_JIT_TYPE_SIGNED_CHAR:
2135 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2136 case GCC_JIT_TYPE_SHORT:
2137 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2138 case GCC_JIT_TYPE_INT:
2139 case GCC_JIT_TYPE_UNSIGNED_INT:
2140 case GCC_JIT_TYPE_LONG:
2141 case GCC_JIT_TYPE_UNSIGNED_LONG:
2142 case GCC_JIT_TYPE_LONG_LONG:
2143 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2144 return false;
2145
2146 case GCC_JIT_TYPE_FLOAT:
2147 case GCC_JIT_TYPE_DOUBLE:
2148 case GCC_JIT_TYPE_LONG_DOUBLE:
2149 return true;
2150
2151 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2152 return false;
2153
2154 case GCC_JIT_TYPE_SIZE_T:
2155 return false;
2156
2157 case GCC_JIT_TYPE_FILE_PTR:
2158 return false;
eeafb319
DM
2159
2160 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2161 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2162 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2163 return true;
35485da9
DM
2164 }
2165}
2166
2167/* Implementation of pure virtual hook recording::type::is_bool for
2168 recording::memento_of_get_type. */
2169
2170bool
2171recording::memento_of_get_type::is_bool () const
2172{
2173 switch (m_kind)
2174 {
2175 default: gcc_unreachable ();
2176
2177 case GCC_JIT_TYPE_VOID:
2178 return false;
2179
2180 case GCC_JIT_TYPE_VOID_PTR:
2181 return false;
2182
2183 case GCC_JIT_TYPE_BOOL:
2184 return true;
2185
2186 case GCC_JIT_TYPE_CHAR:
2187 case GCC_JIT_TYPE_SIGNED_CHAR:
2188 case GCC_JIT_TYPE_UNSIGNED_CHAR:
2189 case GCC_JIT_TYPE_SHORT:
2190 case GCC_JIT_TYPE_UNSIGNED_SHORT:
2191 case GCC_JIT_TYPE_INT:
2192 case GCC_JIT_TYPE_UNSIGNED_INT:
2193 case GCC_JIT_TYPE_LONG:
2194 case GCC_JIT_TYPE_UNSIGNED_LONG:
2195 case GCC_JIT_TYPE_LONG_LONG:
2196 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
2197 return false;
2198
2199 case GCC_JIT_TYPE_FLOAT:
2200 case GCC_JIT_TYPE_DOUBLE:
2201 case GCC_JIT_TYPE_LONG_DOUBLE:
2202 return false;
2203
2204 case GCC_JIT_TYPE_CONST_CHAR_PTR:
2205 return false;
2206
2207 case GCC_JIT_TYPE_SIZE_T:
2208 return false;
2209
2210 case GCC_JIT_TYPE_FILE_PTR:
2211 return false;
eeafb319
DM
2212
2213 case GCC_JIT_TYPE_COMPLEX_FLOAT:
2214 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
2215 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
2216 return false;
35485da9
DM
2217 }
2218}
2219
2220/* Implementation of pure virtual hook recording::memento::replay_into
2221 for recording::memento_of_get_type. */
2222
2223void
2224recording::memento_of_get_type::replay_into (replayer *r)
2225{
2226 set_playback_obj (r->get_type (m_kind));
2227}
2228
2229/* The implementation of class gcc::jit::recording::memento_of_get_type. */
2230
2231/* Descriptive strings for each of enum gcc_jit_types. */
2232
2233static const char * const get_type_strings[] = {
2234 "void", /* GCC_JIT_TYPE_VOID */
2235 "void *", /* GCC_JIT_TYPE_VOID_PTR */
2236
2237 "bool", /* GCC_JIT_TYPE_BOOL */
2238
2239 "char", /* GCC_JIT_TYPE_CHAR */
2240 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
2241 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
2242
2243 "short", /* GCC_JIT_TYPE_SHORT */
2244 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
2245
2246 "int", /* GCC_JIT_TYPE_INT */
2247 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
2248
2249 "long", /* GCC_JIT_TYPE_LONG */
2250 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
2251
2252 "long long", /* GCC_JIT_TYPE_LONG_LONG */
2253 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
2254
2255 "float", /* GCC_JIT_TYPE_FLOAT */
2256 "double", /* GCC_JIT_TYPE_DOUBLE */
2257 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
2258
2259 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
2260
2261 "size_t", /* GCC_JIT_TYPE_SIZE_T */
2262
eeafb319
DM
2263 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
2264
2265 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
2266 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
2267 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
35485da9
DM
2268
2269};
2270
2271/* Implementation of recording::memento::make_debug_string for
2272 results of get_type, using a simple table of type names. */
2273
2274recording::string *
2275recording::memento_of_get_type::make_debug_string ()
2276{
2277 return m_ctxt->new_string (get_type_strings[m_kind]);
2278}
2279
86d0ac88
DM
2280static const char * const get_type_enum_strings[] = {
2281 "GCC_JIT_TYPE_VOID",
2282 "GCC_JIT_TYPE_VOID_PTR",
2283 "GCC_JIT_TYPE_BOOL",
2284 "GCC_JIT_TYPE_CHAR",
2285 "GCC_JIT_TYPE_SIGNED_CHAR",
2286 "GCC_JIT_TYPE_UNSIGNED_CHAR",
2287 "GCC_JIT_TYPE_SHORT",
2288 "GCC_JIT_TYPE_UNSIGNED_SHORT",
2289 "GCC_JIT_TYPE_INT",
2290 "GCC_JIT_TYPE_UNSIGNED_INT",
2291 "GCC_JIT_TYPE_LONG",
2292 "GCC_JIT_TYPE_UNSIGNED_LONG",
2293 "GCC_JIT_TYPE_LONG_LONG",
2294 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG",
2295 "GCC_JIT_TYPE_FLOAT",
2296 "GCC_JIT_TYPE_DOUBLE",
2297 "GCC_JIT_TYPE_LONG_DOUBLE",
2298 "GCC_JIT_TYPE_CONST_CHAR_PTR",
2299 "GCC_JIT_TYPE_SIZE_T",
2300 "GCC_JIT_TYPE_FILE_PTR",
2301 "GCC_JIT_TYPE_COMPLEX_FLOAT",
2302 "GCC_JIT_TYPE_COMPLEX_DOUBLE",
2303 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE"
2304};
2305
2306void
2307recording::memento_of_get_type::write_reproducer (reproducer &r)
2308{
2309 const char *id = r.make_identifier (this, "type");
2310 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n",
2311 id,
2312 r.get_identifier (get_context ()),
2313 get_type_enum_strings[m_kind]);
2314}
2315
35485da9
DM
2316/* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
2317
2318/* Override of default implementation of
2319 recording::type::accepts_writes_from for get_pointer.
2320
2321 Require a pointer type, and allowing writes to
2322 (const T *) from a (T*), but not the other way around. */
2323
2324bool
2325recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
2326{
2327 /* Must be a pointer type: */
2328 type *rtype_points_to = rtype->is_pointer ();
2329 if (!rtype_points_to)
2330 return false;
2331
2332 /* It's OK to assign to a (const T *) from a (T *). */
2333 return m_other_type->unqualified ()
2334 ->accepts_writes_from (rtype_points_to);
2335}
2336
2337/* Implementation of pure virtual hook recording::memento::replay_into
2338 for recording::memento_of_get_pointer. */
2339
2340void
2341recording::memento_of_get_pointer::replay_into (replayer *)
2342{
2343 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
2344}
2345
2346/* Implementation of recording::memento::make_debug_string for
2347 results of get_pointer, adding " *" to the underlying type,
2348 with special-casing to handle function pointer types. */
2349
2350recording::string *
2351recording::memento_of_get_pointer::make_debug_string ()
2352{
2353 /* Special-case function pointer types, to put the "*" in parens between
2354 the return type and the params (for one level of dereferencing, at
2355 least). */
2356 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2357 return fn_type->make_debug_string_with_ptr ();
2358
2359 return string::from_printf (m_ctxt,
2360 "%s *", m_other_type->get_debug_string ());
2361}
2362
86d0ac88
DM
2363/* Implementation of recording::memento::write_reproducer for get_pointer. */
2364
2365void
2366recording::memento_of_get_pointer::write_reproducer (reproducer &r)
2367{
2368 /* We need to special-case function pointer types; see the notes in
2369 recording::function_type::write_deferred_reproducer. */
2370 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
2371 {
2372 fn_type->write_deferred_reproducer (r, this);
2373 return;
2374 }
2375
2376 const char *id = r.make_identifier (this, "type");
2377 r.write (" gcc_jit_type *%s =\n"
2378 " gcc_jit_type_get_pointer (%s);\n",
2379 id,
2380 r.get_identifier_as_type (m_other_type));
2381}
2382
35485da9
DM
2383/* The implementation of class gcc::jit::recording::memento_of_get_const. */
2384
2385/* Implementation of pure virtual hook recording::memento::replay_into
2386 for recording::memento_of_get_const. */
2387
2388void
2389recording::memento_of_get_const::replay_into (replayer *)
2390{
2391 set_playback_obj (m_other_type->playback_type ()->get_const ());
2392}
2393
2394/* Implementation of recording::memento::make_debug_string for
2395 results of get_const, prepending "const ". */
2396
2397recording::string *
2398recording::memento_of_get_const::make_debug_string ()
2399{
2400 return string::from_printf (m_ctxt,
2401 "const %s", m_other_type->get_debug_string ());
2402}
2403
86d0ac88
DM
2404/* Implementation of recording::memento::write_reproducer for const types. */
2405
2406void
2407recording::memento_of_get_const::write_reproducer (reproducer &r)
2408{
2409 const char *id = r.make_identifier (this, "type");
2410 r.write (" gcc_jit_type *%s =\n"
2411 " gcc_jit_type_get_const (%s);\n",
2412 id,
2413 r.get_identifier_as_type (m_other_type));
2414}
2415
35485da9
DM
2416/* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
2417
2418/* Implementation of pure virtual hook recording::memento::replay_into
2419 for recording::memento_of_get_volatile. */
2420
2421void
2422recording::memento_of_get_volatile::replay_into (replayer *)
2423{
2424 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
2425}
2426
2427/* Implementation of recording::memento::make_debug_string for
2428 results of get_volatile, prepending "volatile ". */
2429
2430recording::string *
2431recording::memento_of_get_volatile::make_debug_string ()
2432{
2433 return string::from_printf (m_ctxt,
2434 "volatile %s", m_other_type->get_debug_string ());
2435}
2436
86d0ac88
DM
2437/* Implementation of recording::memento::write_reproducer for volatile
2438 types. */
2439
2440void
2441recording::memento_of_get_volatile::write_reproducer (reproducer &r)
2442{
2443 const char *id = r.make_identifier (this, "type");
2444 r.write (" gcc_jit_type *%s =\n"
2445 " gcc_jit_type_get_volatile (%s);\n",
2446 id,
2447 r.get_identifier_as_type (m_other_type));
2448}
2449
0ebd1f00
DM
2450/* The implementation of class gcc::jit::recording::memento_of_get_aligned. */
2451
2452/* Implementation of pure virtual hook recording::memento::replay_into
2453 for recording::memento_of_get_aligned. */
2454
2455void
2456recording::memento_of_get_aligned::replay_into (replayer *)
2457{
2458 set_playback_obj
2459 (m_other_type->playback_type ()->get_aligned (m_alignment_in_bytes));
2460}
2461
2462/* Implementation of recording::memento::make_debug_string for
2463 results of get_aligned. */
2464
2465recording::string *
2466recording::memento_of_get_aligned::make_debug_string ()
2467{
2468 return string::from_printf (m_ctxt,
2469 "%s __attribute__((aligned(%zi)))",
2470 m_other_type->get_debug_string (),
2471 m_alignment_in_bytes);
2472}
2473
47ee1b7c 2474/* Implementation of recording::memento::write_reproducer for aligned
0ebd1f00
DM
2475 types. */
2476
2477void
2478recording::memento_of_get_aligned::write_reproducer (reproducer &r)
2479{
2480 const char *id = r.make_identifier (this, "type");
2481 r.write (" gcc_jit_type *%s =\n"
2482 " gcc_jit_type_get_aligned (%s, %zi);\n",
2483 id,
2484 r.get_identifier_as_type (m_other_type),
2485 m_alignment_in_bytes);
2486}
2487
47ee1b7c
DM
2488/* The implementation of class gcc::jit::recording::memento_of_get_vector. */
2489
2490/* Implementation of pure virtual hook recording::memento::replay_into
2491 for recording::memento_of_get_vector. */
2492
2493void
2494recording::memento_of_get_vector::replay_into (replayer *)
2495{
2496 set_playback_obj
2497 (m_other_type->playback_type ()->get_vector (m_num_units));
2498}
2499
2500/* Implementation of recording::memento::make_debug_string for
2501 results of get_vector. */
2502
2503recording::string *
2504recording::memento_of_get_vector::make_debug_string ()
2505{
2506 return string::from_printf
2507 (m_ctxt,
2508 "%s __attribute__((vector_size(sizeof (%s) * %zi)))",
2509 m_other_type->get_debug_string (),
2510 m_other_type->get_debug_string (),
2511 m_num_units);
2512}
2513
2514/* Implementation of recording::memento::write_reproducer for volatile
2515 types. */
2516
2517void
2518recording::memento_of_get_vector::write_reproducer (reproducer &r)
2519{
2520 const char *id = r.make_identifier (this, "type");
2521 r.write (" gcc_jit_type *%s =\n"
2522 " gcc_jit_type_get_vector (%s, %zi);\n",
2523 id,
2524 r.get_identifier_as_type (m_other_type),
2525 m_num_units);
2526}
2527
35485da9
DM
2528/* The implementation of class gcc::jit::recording::array_type */
2529
2530/* Implementation of pure virtual hook recording::type::dereference for
2531 recording::array_type. */
2532
2533recording::type *
2534recording::array_type::dereference ()
2535{
2536 return m_element_type;
2537}
2538
2539/* Implementation of pure virtual hook recording::memento::replay_into
2540 for recording::array_type. */
2541
2542void
2543recording::array_type::replay_into (replayer *r)
2544{
2545 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
2546 m_element_type->playback_type (),
2547 m_num_elements));
2548}
2549
2550/* Implementation of recording::memento::make_debug_string for
2551 results of new_array_type. */
2552
2553recording::string *
2554recording::array_type::make_debug_string ()
2555{
2556 return string::from_printf (m_ctxt,
2557 "%s[%d]",
2558 m_element_type->get_debug_string (),
2559 m_num_elements);
2560}
2561
86d0ac88
DM
2562/* Implementation of recording::memento::write_reproducer for array
2563 types. */
2564
2565void
2566recording::array_type::write_reproducer (reproducer &r)
2567{
2568 const char *id = r.make_identifier (this, "array_type");
2569 r.write (" gcc_jit_type *%s =\n"
2570 " gcc_jit_context_new_array_type (%s,\n"
2571 " %s, /* gcc_jit_location *loc */\n"
2572 " %s, /* gcc_jit_type *element_type */\n"
2573 " %i); /* int num_elements */\n",
2574 id,
2575 r.get_identifier (get_context ()),
2576 r.get_identifier (m_loc),
2577 r.get_identifier_as_type (m_element_type),
2578 m_num_elements);
2579}
2580
35485da9
DM
2581/* The implementation of class gcc::jit::recording::function_type */
2582
2583/* Constructor for gcc::jit::recording::function_type. */
2584
2585recording::function_type::function_type (context *ctxt,
2586 type *return_type,
2587 int num_params,
2588 type **param_types,
2589 int is_variadic)
2590: type (ctxt),
2591 m_return_type (return_type),
2592 m_param_types (),
2593 m_is_variadic (is_variadic)
2594{
2595 for (int i = 0; i< num_params; i++)
2596 m_param_types.safe_push (param_types[i]);
2597}
2598
2599/* Implementation of pure virtual hook recording::type::dereference for
2600 recording::function_type. */
2601
2602recording::type *
2603recording::function_type::dereference ()
2604{
2605 return NULL;
2606}
2607
2608/* Implementation of pure virtual hook recording::memento::replay_into
2609 for recording::function_type. */
2610
2611void
2612recording::function_type::replay_into (replayer *r)
2613{
2614 /* Convert m_param_types to a vec of playback type. */
b957b2e0 2615 auto_vec <playback::type *> param_types;
35485da9
DM
2616 int i;
2617 recording::type *type;
2618 param_types.create (m_param_types.length ());
2619 FOR_EACH_VEC_ELT (m_param_types, i, type)
2620 param_types.safe_push (type->playback_type ());
2621
2622 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
2623 &param_types,
2624 m_is_variadic));
2625}
2626
2627/* Special-casing for make_debug_string for get_pointer results for
2628 handling (one level) of pointers to functions. */
2629
2630recording::string *
2631recording::function_type::make_debug_string_with_ptr ()
2632{
2633 return make_debug_string_with ("(*) ");
2634}
2635
2636/* Implementation of recording::memento::make_debug_string for
2637 results of new_function_type. */
2638
2639recording::string *
2640recording::function_type::make_debug_string ()
2641{
2642 return make_debug_string_with ("");
2643}
2644
2645/* Build a debug string representation of the form:
2646
2647 RESULT_TYPE INSERT (PARAM_TYPES)
2648
2649 for use when handling 0 and 1 level of indirection to this
2650 function type. */
2651
2652recording::string *
2653recording::function_type::make_debug_string_with (const char *insert)
2654{
2655 /* First, build a buffer for the arguments. */
2656 /* Calculate length of said buffer. */
2657 size_t sz = 1; /* nil terminator */
2658 for (unsigned i = 0; i< m_param_types.length (); i++)
2659 {
2660 sz += strlen (m_param_types[i]->get_debug_string ());
2661 sz += 2; /* ", " separator */
2662 }
2663 if (m_is_variadic)
2664 sz += 5; /* ", ..." separator and ellipsis */
2665
2666 /* Now allocate and populate the buffer. */
2667 char *argbuf = new char[sz];
2668 size_t len = 0;
2669
2670 for (unsigned i = 0; i< m_param_types.length (); i++)
2671 {
2672 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
2673 len += strlen (m_param_types[i]->get_debug_string ());
2674 if (i + 1 < m_param_types.length ())
2675 {
2676 strcpy (argbuf + len, ", ");
2677 len += 2;
2678 }
2679 }
2680 if (m_is_variadic)
2681 {
2682 if (m_param_types.length ())
2683 {
2684 strcpy (argbuf + len, ", ");
2685 len += 2;
2686 }
2687 strcpy (argbuf + len, "...");
2688 len += 3;
2689 }
2690 argbuf[len] = '\0';
2691
2692 /* ...and use it to get the string for the call as a whole. */
2693 string *result = string::from_printf (m_ctxt,
2694 "%s %s(%s)",
2695 m_return_type->get_debug_string (),
2696 insert,
2697 argbuf);
2698
2699 delete[] argbuf;
2700
2701 return result;
2702}
2703
86d0ac88
DM
2704/* Implementation of recording::memento::write_reproducer for function
2705 types. */
2706
2707void
2708recording::function_type::write_reproducer (reproducer &)
2709{
2710 /* see notes below. */
2711}
2712
2713/* There's a get_pointer within context::new_function_ptr_type:
2714 the type received by client code isn't the memento for the
2715 function_type, but instead the result of get_pointer on it.
2716
2717 Hence we can't directly write a reproducer that gives function_type.
2718 Instead we special-case things within get_pointer, detecting this
2719 case, calling the following function. */
2720
2721void
2722recording::function_type::write_deferred_reproducer (reproducer &r,
2723 memento *ptr_type)
2724{
2725 gcc_assert (ptr_type);
2726 r.make_identifier (this, "function_type");
2727 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to");
2728 const char *param_types_id = r.make_tmp_identifier ("params_for", this);
2729 r.write (" gcc_jit_type *%s[%i] = {\n",
2730 param_types_id,
2731 m_param_types.length ());
2732 int i;
2733 type *param_type;
2734 FOR_EACH_VEC_ELT (m_param_types, i, param_type)
2735 r.write (" %s,\n", r.get_identifier_as_type (param_type));
2736 r.write (" };\n");
2737 r.write (" gcc_jit_type *%s =\n"
2738 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n"
2739 " %s, /* gcc_jit_location *loc */\n"
2740 " %s, /* gcc_jit_type *return_type */\n"
2741 " %i, /* int num_params */\n"
2742 " %s, /* gcc_jit_type **param_types */\n"
2743 " %i); /* int is_variadic */\n",
2744 ptr_id,
2745 r.get_identifier (get_context ()),
2746 "NULL", /* location is not stored */
2747 r.get_identifier_as_type (m_return_type),
2748 m_param_types.length (),
2749 param_types_id,
2750 m_is_variadic);
2751}
2752
35485da9
DM
2753/* The implementation of class gcc::jit::recording::field. */
2754
2755/* Implementation of pure virtual hook recording::memento::replay_into
2756 for recording::field. */
2757
2758void
2759recording::field::replay_into (replayer *r)
2760{
2761 set_playback_obj (r->new_field (playback_location (r, m_loc),
2762 m_type->playback_type (),
2763 playback_string (m_name)));
2764}
2765
2766/* Override the default implementation of
2767 recording::memento::write_to_dump. Dump each field
2768 by dumping a line of the form:
2769 TYPE NAME;
2770 so that we can build up a struct/union field-byfield. */
2771
2772void
2773recording::field::write_to_dump (dump &d)
2774{
2775 d.write (" %s %s;\n",
2776 m_type->get_debug_string (),
2777 m_name->c_str ());
2778}
2779
2780/* Implementation of recording::memento::make_debug_string for
2781 results of new_field. */
2782
2783recording::string *
2784recording::field::make_debug_string ()
2785{
2786 return m_name;
2787}
2788
86d0ac88
DM
2789/* Implementation of recording::memento::write_reproducer for fields. */
2790
2791void
2792recording::field::write_reproducer (reproducer &r)
2793{
2794 const char *id = r.make_identifier (this, "field");
2795 r.write(" gcc_jit_field *%s =\n"
2796 " gcc_jit_context_new_field (%s,\n"
2797 " %s, /* gcc_jit_location *loc */\n"
2798 " %s, /* gcc_jit_type *type, */\n"
2799 " %s); /* const char *name */\n",
2800 id,
2801 r.get_identifier (get_context ()),
2802 r.get_identifier (m_loc),
2803 r.get_identifier_as_type (m_type),
2804 m_name->get_debug_string ());
2805}
2806
35485da9
DM
2807/* The implementation of class gcc::jit::recording::compound_type */
2808
2809/* The constructor for gcc::jit::recording::compound_type. */
2810
2811recording::compound_type::compound_type (context *ctxt,
2812 location *loc,
2813 string *name)
2814: type (ctxt),
2815 m_loc (loc),
2816 m_name (name),
2817 m_fields (NULL)
2818{
2819}
2820
2821/* Set the fields of a compound type.
2822
2823 Implements the post-error-checking part of
2824 gcc_jit_struct_set_fields, and is also used by
2825 gcc_jit_context_new_union_type. */
2826
2827void
2828recording::compound_type::set_fields (location *loc,
2829 int num_fields,
2830 field **field_array)
2831{
2832 m_loc = loc;
2833 gcc_assert (NULL == m_fields);
2834
2835 m_fields = new fields (this, num_fields, field_array);
2836 m_ctxt->record (m_fields);
2837}
2838
2839/* Implementation of pure virtual hook recording::type::dereference for
2840 recording::compound_type. */
2841
2842recording::type *
2843recording::compound_type::dereference ()
2844{
2845 return NULL; /* not a pointer */
2846}
2847
2848/* The implementation of class gcc::jit::recording::struct_. */
2849
2850/* The constructor for gcc::jit::recording::struct_. */
2851
2852recording::struct_::struct_ (context *ctxt,
2853 location *loc,
2854 string *name)
2855: compound_type (ctxt, loc, name)
2856{
2857}
2858
2859/* Implementation of pure virtual hook recording::memento::replay_into
2860 for recording::struct_. */
2861
2862void
2863recording::struct_::replay_into (replayer *r)
2864{
2865 set_playback_obj (
2866 r->new_compound_type (playback_location (r, get_loc ()),
2867 get_name ()->c_str (),
2868 true /* is_struct */));
2869}
2870
86d0ac88
DM
2871const char *
2872recording::struct_::access_as_type (reproducer &r)
2873{
2874 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)",
2875 r.get_identifier (this));
2876}
2877
35485da9
DM
2878/* Implementation of recording::memento::make_debug_string for
2879 structs. */
2880
2881recording::string *
2882recording::struct_::make_debug_string ()
2883{
2884 return string::from_printf (m_ctxt,
2885 "struct %s", get_name ()->c_str ());
2886}
2887
86d0ac88
DM
2888void
2889recording::struct_::write_reproducer (reproducer &r)
2890{
2891 const char *id = r.make_identifier (this, "struct");
2892 r.write (" gcc_jit_struct *%s =\n"
2893 " gcc_jit_context_new_opaque_struct (%s,\n"
2894 " %s, /* gcc_jit_location *loc */\n"
2895 " %s); /* const char *name */\n",
2896 id,
2897 r.get_identifier (get_context ()),
2898 r.get_identifier (get_loc ()),
2899 get_name ()->get_debug_string ());
2900}
2901
35485da9
DM
2902/* The implementation of class gcc::jit::recording::union_. */
2903
2904/* The constructor for gcc::jit::recording::union_. */
2905
2906recording::union_::union_ (context *ctxt,
2907 location *loc,
2908 string *name)
2909: compound_type (ctxt, loc, name)
2910{
2911}
2912
2913/* Implementation of pure virtual hook recording::memento::replay_into
2914 for recording::union_. */
2915
2916void
2917recording::union_::replay_into (replayer *r)
2918{
2919 set_playback_obj (
2920 r->new_compound_type (playback_location (r, get_loc ()),
2921 get_name ()->c_str (),
2922 false /* is_struct */));
2923}
2924
2925/* Implementation of recording::memento::make_debug_string for
2926 unions. */
2927
2928recording::string *
2929recording::union_::make_debug_string ()
2930{
2931 return string::from_printf (m_ctxt,
2932 "union %s", get_name ()->c_str ());
2933}
2934
86d0ac88
DM
2935/* Implementation of recording::memento::write_reproducer for unions. */
2936
2937void
2938recording::union_::write_reproducer (reproducer &r)
2939{
2940 const char *id = r.make_identifier (this, "union");
2941
2942 const char *fields_id = r.make_tmp_identifier ("fields_for", this);
2943 r.write (" gcc_jit_field *%s[%i] = {\n",
2944 fields_id,
2945 get_fields ()->length ());
2946 for (int i = 0; i < get_fields ()->length (); i++)
2947 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i)));
2948 r.write (" };\n");
2949
2950 r.write (" gcc_jit_type *%s =\n"
2951 " gcc_jit_context_new_union_type (%s,\n"
2952 " %s, /* gcc_jit_location *loc */\n"
2953 " %s, /* const char *name */\n"
2954 " %i, /* int num_fields */\n"
2955 " %s); /* gcc_jit_field **fields */\n",
2956 id,
2957 r.get_identifier (get_context ()),
2958 r.get_identifier (get_loc ()),
2959 get_name ()->get_debug_string (),
2960 get_fields ()->length (),
2961 fields_id);
2962}
2963
35485da9
DM
2964/* The implementation of class gcc::jit::recording::fields. */
2965
2966/* The constructor for gcc::jit::recording::fields. */
2967
2968recording::fields::fields (compound_type *struct_or_union,
2969 int num_fields,
2970 field **fields)
2971: memento (struct_or_union->m_ctxt),
2972 m_struct_or_union (struct_or_union),
2973 m_fields ()
2974{
2975 for (int i = 0; i < num_fields; i++)
2976 {
2977 gcc_assert (fields[i]->get_container () == NULL);
2978 fields[i]->set_container (m_struct_or_union);
2979 m_fields.safe_push (fields[i]);
2980 }
2981}
2982
2983/* Implementation of pure virtual hook recording::memento::replay_into
2984 for recording::fields. */
2985
2986void
2987recording::fields::replay_into (replayer *)
2988{
b957b2e0 2989 auto_vec<playback::field *> playback_fields;
35485da9
DM
2990 playback_fields.create (m_fields.length ());
2991 for (unsigned i = 0; i < m_fields.length (); i++)
2992 playback_fields.safe_push (m_fields[i]->playback_field ());
b957b2e0 2993 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
35485da9
DM
2994}
2995
2996/* Override the default implementation of
2997 recording::memento::write_to_dump by writing a union/struct
2998 declaration of this form:
2999
3000 struct/union NAME {
c168eab9
UD
3001 TYPE_1 NAME_1;
3002 TYPE_2 NAME_2;
35485da9 3003 ....
c168eab9 3004 TYPE_N NAME_N;
35485da9
DM
3005 };
3006
3007 to the dump. */
3008
3009void
3010recording::fields::write_to_dump (dump &d)
3011{
3012 int i;
3013 field *f;
3014
3015 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
3016 FOR_EACH_VEC_ELT (m_fields, i, f)
3017 f->write_to_dump (d);
3018 d.write ("};\n");
3019}
3020
86d0ac88
DM
3021/* Implementation of recording::memento::write_reproducer for the fields
3022 subclass. */
3023
3024void
3025recording::fields::write_reproducer (reproducer &r)
3026{
3027 if (m_struct_or_union)
3028 if (NULL == m_struct_or_union->dyn_cast_struct ())
3029 /* We have a union; the fields have already been written by
3030 union::write_reproducer. */
3031 return;
3032
3033 const char *fields_id = r.make_identifier (this, "fields");
3034 r.write (" gcc_jit_field *%s[%i] = {\n",
3035 fields_id,
3036 m_fields.length ());
3037 int i;
3038 field *field;
3039 FOR_EACH_VEC_ELT (m_fields, i, field)
3040 r.write (" %s,\n", r.get_identifier (field));
3041 r.write (" };\n");
3042
3043 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n"
3044 " %s, /* gcc_jit_location *loc */\n"
3045 " %i, /* int num_fields */\n"
3046 " %s); /* gcc_jit_field **fields */\n",
3047 r.get_identifier (m_struct_or_union),
3048 r.get_identifier ((memento *)NULL),
3049 m_fields.length (),
3050 fields_id);
3051}
3052
35485da9
DM
3053/* Implementation of recording::memento::make_debug_string for
3054 field tables. */
3055
3056recording::string *
3057recording::fields::make_debug_string ()
3058{
3059 return string::from_printf (m_ctxt,
3060 "fields");
3061}
3062
3063/* The implementation of class gcc::jit::recording::rvalue. */
3064
3065/* Create a recording::access_field_rvalue instance and add it to
3066 the rvalue's context's list of mementos.
3067
3068 Implements the post-error-checking part of
3069 gcc_jit_rvalue_access_field. */
3070
3071recording::rvalue *
3072recording::rvalue::access_field (recording::location *loc,
3073 field *field)
3074{
3075 recording::rvalue *result =
3076 new access_field_rvalue (m_ctxt, loc, this, field);
3077 m_ctxt->record (result);
3078 return result;
3079}
3080
3081/* Create a recording::dereference_field_rvalue instance and add it to
3082 the rvalue's context's list of mementos.
3083
3084 Implements the post-error-checking part of
3085 gcc_jit_rvalue_dereference_field. */
3086
3087recording::lvalue *
3088recording::rvalue::dereference_field (recording::location *loc,
3089 field *field)
3090{
3091 recording::lvalue *result =
3092 new dereference_field_rvalue (m_ctxt, loc, this, field);
3093 m_ctxt->record (result);
3094 return result;
3095}
3096
3097/* Create a recording::dereference_rvalue instance and add it to the
3098 rvalue's context's list of mementos.
3099
3100 Implements the post-error-checking part of
3101 gcc_jit_rvalue_dereference. */
3102
3103recording::lvalue *
3104recording::rvalue::dereference (recording::location *loc)
3105{
3106 recording::lvalue *result =
3107 new dereference_rvalue (m_ctxt, loc, this);
3108 m_ctxt->record (result);
3109 return result;
3110}
3111
f6f2b019
DM
3112/* An rvalue visitor, for validating that every rvalue within an expression
3113 trees within "STMT" has the correct scope (e.g. no access to locals
3114 of a different function). */
3115
3116class rvalue_usage_validator : public recording::rvalue_visitor
3117{
3118 public:
3119 rvalue_usage_validator (const char *api_funcname,
3120 recording::context *ctxt,
3121 recording::statement *stmt);
3122
3123 void
54ece5e2 3124 visit (recording::rvalue *rvalue) FINAL OVERRIDE;
f6f2b019
DM
3125
3126 private:
3127 const char *m_api_funcname;
3128 recording::context *m_ctxt;
3129 recording::statement *m_stmt;
3130};
3131
3132/* The trivial constructor for rvalue_usage_validator. */
3133
3134rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname,
3135 recording::context *ctxt,
3136 recording::statement *stmt)
3137 : m_api_funcname (api_funcname),
3138 m_ctxt (ctxt),
3139 m_stmt (stmt)
3140{
3141}
3142
3143/* Verify that the given rvalue is in the correct scope. */
3144
3145void
3146rvalue_usage_validator::visit (recording::rvalue *rvalue)
3147{
3148 gcc_assert (m_stmt->get_block ());
3149 recording::function *stmt_scope = m_stmt->get_block ()->get_function ();
3150
3151 /* Most rvalues don't have a scope (only locals and params). */
3152 if (rvalue->get_scope ())
3153 {
3154 if (rvalue->get_scope () != stmt_scope)
3155 m_ctxt->add_error
3156 (rvalue->get_loc (),
3157 "%s:"
3158 " rvalue %s (type: %s)"
3159 " has scope limited to function %s"
3160 " but was used within function %s"
3161 " (in statement: %s)",
3162 m_api_funcname,
3163 rvalue->get_debug_string (),
3164 rvalue->get_type ()->get_debug_string (),
3165 rvalue->get_scope ()->get_debug_string (),
3166 stmt_scope->get_debug_string (),
3167 m_stmt->get_debug_string ());
3168 }
3169 else
3170 {
3171 if (rvalue->dyn_cast_param ())
3172 m_ctxt->add_error
3173 (rvalue->get_loc (),
3174 "%s:"
3175 " param %s (type: %s)"
3176 " was used within function %s"
3177 " (in statement: %s)"
3178 " but is not associated with any function",
3179 m_api_funcname,
3180 rvalue->get_debug_string (),
3181 rvalue->get_type ()->get_debug_string (),
3182 stmt_scope->get_debug_string (),
3183 m_stmt->get_debug_string ());
3184 }
3185}
3186
3187/* Verify that it's valid to use this rvalue (and all expressions
3188 in the tree below it) within the given statement.
3189
3190 For example, we must reject attempts to use a local from one
3191 function within a different function here, or we'll get
3192 an ICE deep inside toplev::main. */
3193
3194void
3195recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s)
3196{
3197 rvalue_usage_validator v (api_funcname,
3198 s->get_context (),
3199 s);
3200
3201 /* Verify that it's OK to use this rvalue within s. */
3202 v.visit (this);
3203
3204 /* Traverse the expression tree below "this", verifying all rvalues
3205 within it. */
3206 visit_children (&v);
3207}
3208
3209/* Set the scope of this rvalue to be the given function. This can only
3210 be done once on a given rvalue. */
3211
3212void
3213recording::rvalue::set_scope (function *scope)
3214{
3215 gcc_assert (scope);
3216 gcc_assert (NULL == m_scope);
3217 m_scope = scope;
3218}
3219
3220
86d0ac88
DM
3221/* Implementation of recording::rvalue::access_as_rvalue for rvalues
3222 themselves.
3223 Instances of rvalue don't need an upcast call. */
3224
3225const char *
3226recording::rvalue::access_as_rvalue (reproducer &r)
3227{
3228 return r.get_identifier (this);
3229}
3230
bd93aa1a
DM
3231/* Return a debug string for the given rvalue, wrapping it in parentheses
3232 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of
3233 stronger precedence that this rvalue's precedence.
3234
3235 For example, given:
3236
3237 MULT
3238 / \
3239 PLUS MINUS
3240 / \ / \
3241 A B C D
3242
3243 we want to emit:
3244
3245 (A + B) * (C - D)
3246
3247 since MULT has strong precedence than PLUS and MINUS, whereas for:
3248
3249 PLUS
3250 / \
3251 MULT DIVIDE
3252 / \ / \
3253 A B C D
3254
3255 we can simply emit:
3256
3257 A * B + C / D
3258
3259 since PLUS has weaker precedence than MULT and DIVIDE. */
3260
3261const char *
3262recording::rvalue::get_debug_string_parens (enum precedence outer_prec)
3263{
3264 enum precedence this_prec = get_precedence ();
3265
3266 /* If this_prec has stronger precedence than outer_prec, we don't
3267 need to wrap this in parens within the outer debug string.
3268 Stronger precedences occur earlier than weaker within the enum,
3269 so this is a less than test. Equal precedences don't need
3270 parentheses. */
3271 if (this_prec <= outer_prec)
3272 return get_debug_string();
3273
3274 /* Otherwise, we need parentheses. */
3275
3276 /* Lazily-build and cache m_parenthesized_string. */
3277 if (!m_parenthesized_string)
3278 {
3279 const char *debug_string = get_debug_string ();
3280 m_parenthesized_string = string::from_printf (get_context (),
3281 "(%s)",
3282 debug_string);
3283 }
3284 gcc_assert (m_parenthesized_string);
3285 return m_parenthesized_string->c_str ();
3286}
3287
86d0ac88 3288
35485da9
DM
3289/* The implementation of class gcc::jit::recording::lvalue. */
3290
3291/* Create a recording::new_access_field_of_lvalue instance and add it to
3292 the lvalue's context's list of mementos.
3293
3294 Implements the post-error-checking part of
3295 gcc_jit_lvalue_access_field. */
3296
3297recording::lvalue *
3298recording::lvalue::access_field (recording::location *loc,
3299 field *field)
3300{
3301 recording::lvalue *result =
3302 new access_field_of_lvalue (m_ctxt, loc, this, field);
3303 m_ctxt->record (result);
3304 return result;
3305}
3306
86d0ac88
DM
3307/* Implementation of recording::rvalue::access_as_rvalue for lvalues.
3308 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue
3309 upcast call. */
3310
3311const char *
3312recording::lvalue::access_as_rvalue (reproducer &r)
3313{
3314 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)",
3315 r.get_identifier (this));
3316}
3317
3318/* Implementation of recording::lvalue::access_as_lvalue for lvalues.
3319 Instances of lvalue don't need to be upcast. */
3320
3321const char *
3322recording::lvalue::access_as_lvalue (reproducer &r)
3323{
3324 return r.get_identifier (this);
3325}
3326
35485da9
DM
3327/* Create a recording::get_address_of_lvalue instance and add it to
3328 the lvalue's context's list of mementos.
3329
3330 Implements the post-error-checking part of
3331 gcc_jit_lvalue_get_address. */
3332
3333recording::rvalue *
3334recording::lvalue::get_address (recording::location *loc)
3335{
3336 recording::rvalue *result =
3337 new get_address_of_lvalue (m_ctxt, loc, this);
3338 m_ctxt->record (result);
3339 return result;
3340}
3341
3342/* The implementation of class gcc::jit::recording::param. */
3343
3344/* Implementation of pure virtual hook recording::memento::replay_into
3345 for recording::param. */
3346
3347void
3348recording::param::replay_into (replayer *r)
3349{
3350 set_playback_obj (r->new_param (playback_location (r, m_loc),
3351 m_type->playback_type (),
3352 m_name->c_str ()));
3353}
3354
86d0ac88
DM
3355/* Implementation of recording::rvalue::access_as_rvalue for params.
3356 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue
3357 upcast call. */
3358
3359const char *
3360recording::param::access_as_rvalue (reproducer &r)
3361{
3362 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)",
3363 r.get_identifier (this));
3364}
3365
3366/* Implementation of recording::lvalue::access_as_lvalue for params.
3367 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue
3368 upcast call. */
3369
3370const char *
3371recording::param::access_as_lvalue (reproducer &r)
3372{
3373 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)",
3374 r.get_identifier (this));
3375}
3376
3377/* Implementation of recording::memento::write_reproducer for params. */
3378
3379void
3380recording::param::write_reproducer (reproducer &r)
3381{
3382 const char *id = r.make_identifier (this, "param");
3383 r.write (" gcc_jit_param *%s =\n"
3384 " gcc_jit_context_new_param (%s,\n"
3385 " %s, /* gcc_jit_location *loc */\n"
3386 " %s, /*gcc_jit_type *type */\n"
3387 " %s); /* const char *name */\n",
3388 id,
3389 r.get_identifier (get_context ()),
3390 r.get_identifier (m_loc),
3391 r.get_identifier_as_type (m_type),
3392 m_name->get_debug_string ());
3393}
35485da9
DM
3394
3395/* The implementation of class gcc::jit::recording::function. */
3396
3397/* gcc::jit::recording::function's constructor. */
3398
3399recording::function::function (context *ctxt,
3400 recording::location *loc,
3401 enum gcc_jit_function_kind kind,
3402 type *return_type,
3403 recording::string *name,
3404 int num_params,
3405 recording::param **params,
3406 int is_variadic,
3407 enum built_in_function builtin_id)
3408: memento (ctxt),
3409 m_loc (loc),
3410 m_kind (kind),
3411 m_return_type (return_type),
3412 m_name (name),
3413 m_params (),
3414 m_is_variadic (is_variadic),
3415 m_builtin_id (builtin_id),
3416 m_locals (),
3417 m_blocks ()
3418{
3419 for (int i = 0; i< num_params; i++)
f6f2b019
DM
3420 {
3421 param *param = params[i];
3422 gcc_assert (param);
3423
3424 /* Associate each param with this function.
3425
3426 Verify that the param doesn't already have a function. */
3427 if (param->get_scope ())
3428 {
3429 /* We've already rejected attempts to reuse a param between
3430 different functions (within gcc_jit_context_new_function), so
3431 if the param *does* already have a function, it must be being
3432 reused within the params array for this function. We must
3433 produce an error for this reuse (blocking the compile), since
3434 otherwise we'd have an ICE later on. */
3435 gcc_assert (this == param->get_scope ());
3436 ctxt->add_error
3437 (loc,
3438 "gcc_jit_context_new_function:"
3439 " parameter %s (type: %s)"
3440 " is used more than once when creating function %s",
3441 param->get_debug_string (),
3442 param->get_type ()->get_debug_string (),
3443 name->c_str ());
3444 }
3445 else
3446 {
3447 /* The normal, non-error case: associate this function with the
3448 param. */
3449 param->set_scope (this);
3450 }
3451
3452 m_params.safe_push (param);
3453 }
35485da9
DM
3454}
3455
3456/* Implementation of pure virtual hook recording::memento::replay_into
3457 for recording::function. */
3458
3459void
3460recording::function::replay_into (replayer *r)
3461{
3462 /* Convert m_params to a vec of playback param. */
b957b2e0 3463 auto_vec <playback::param *> params;
35485da9
DM
3464 int i;
3465 recording::param *param;
3466 params.create (m_params.length ());
3467 FOR_EACH_VEC_ELT (m_params, i, param)
3468 params.safe_push (param->playback_param ());
3469
3470 set_playback_obj (r->new_function (playback_location (r, m_loc),
3471 m_kind,
3472 m_return_type->playback_type (),
3473 m_name->c_str (),
3474 &params,
3475 m_is_variadic,
3476 m_builtin_id));
3477}
3478
3479/* Create a recording::local instance and add it to
3480 the functions's context's list of mementos, and to the function's
3481 list of locals.
3482
3483 Implements the post-error-checking part of
3484 gcc_jit_function_new_local. */
3485
3486recording::lvalue *
3487recording::function::new_local (recording::location *loc,
3488 type *type,
3489 const char *name)
3490{
3491 local *result = new local (this, loc, type, new_string (name));
3492 m_ctxt->record (result);
3493 m_locals.safe_push (result);
3494 return result;
3495}
3496
3497/* Create a recording::block instance and add it to
3498 the functions's context's list of mementos, and to the function's
3499 list of blocks.
3500
3501 Implements the post-error-checking part of
3502 gcc_jit_function_new_block. */
3503
3504recording::block*
3505recording::function::new_block (const char *name)
3506{
3507 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
3508
3509 recording::block *result =
3510 new recording::block (this, m_blocks.length (), new_string (name));
3511 m_ctxt->record (result);
3512 m_blocks.safe_push (result);
3513 return result;
3514}
3515
3516/* Override the default implementation of
3517 recording::memento::write_to_dump by dumping a C-like
3518 representation of the function; either like a prototype
3519 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
3520 all other kinds of function. */
3521
3522void
3523recording::function::write_to_dump (dump &d)
3524{
3525 switch (m_kind)
3526 {
3527 default: gcc_unreachable ();
3528 case GCC_JIT_FUNCTION_EXPORTED:
3529 case GCC_JIT_FUNCTION_IMPORTED:
3530 d.write ("extern ");
3531 break;
3532 case GCC_JIT_FUNCTION_INTERNAL:
3533 d.write ("static ");
3534 break;
3535 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
3536 d.write ("static inline ");
3537 break;
3538 }
3539 d.write ("%s\n", m_return_type->get_debug_string ());
3540
3541 if (d.update_locations ())
3542 m_loc = d.make_location ();
3543
3544 d.write ("%s (", get_debug_string ());
3545
3546 int i;
3547 recording::param *param;
3548 FOR_EACH_VEC_ELT (m_params, i, param)
3549 {
3550 if (i > 0)
3551 d.write (", ");
3552 d.write ("%s %s",
3553 param->get_type ()->get_debug_string (),
3554 param->get_debug_string ());
3555 }
3556 d.write (")");
3557 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
3558 {
3559 d.write ("; /* (imported) */\n\n");
3560 }
3561 else
3562 {
3563 int i;
3564 local *var = NULL;
3565 block *b;
3566 d.write ("\n{\n");
3567
3568 /* Write locals: */
3569 FOR_EACH_VEC_ELT (m_locals, i, var)
3570 var->write_to_dump (d);
3571 if (m_locals.length ())
3572 d.write ("\n");
3573
3574 /* Write each block: */
3575 FOR_EACH_VEC_ELT (m_blocks, i, b)
3576 {
3577 if (i > 0)
3578 d.write ("\n");
3579 b->write_to_dump (d);
3580 }
3581
3582 d.write ("}\n\n");
3583 }
3584}
3585
3586/* Pre-compilation validation of a function, for those things we can't
3587 check until the context is (supposedly) fully-populated. */
3588
3589void
3590recording::function::validate ()
3591{
3592 /* Complain about empty functions with non-void return type. */
3593 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
3594 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
3595 if (0 == m_blocks.length ())
3596 m_ctxt->add_error (m_loc,
3597 "function %s returns non-void (type: %s)"
3598 " but has no blocks",
3599 get_debug_string (),
3600 m_return_type->get_debug_string ());
3601
3602 /* Check that all blocks are terminated. */
3603 int num_invalid_blocks = 0;
3604 {
3605 int i;
3606 block *b;
3607
3608 FOR_EACH_VEC_ELT (m_blocks, i, b)
3609 if (!b->validate ())
3610 num_invalid_blocks++;
3611 }
3612
3613 /* Check that all blocks are reachable. */
6a3603e3
DM
3614 if (!m_ctxt->get_inner_bool_option
3615 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS)
3616 && m_blocks.length () > 0 && 0 == num_invalid_blocks)
35485da9
DM
3617 {
3618 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
3619 flag, starting at the initial block. */
79cafc7a 3620 auto_vec<block *> worklist (m_blocks.length ());
35485da9
DM
3621 worklist.safe_push (m_blocks[0]);
3622 while (worklist.length () > 0)
3623 {
3624 block *b = worklist.pop ();
3625 b->m_is_reachable = true;
3626
3627 /* Add successor blocks that aren't yet marked to the worklist. */
3628 /* We checked that each block has a terminating statement above . */
ec5d0088
DM
3629 vec <block *> successors = b->get_successor_blocks ();
3630 int i;
3631 block *succ;
3632 FOR_EACH_VEC_ELT (successors, i, succ)
3633 if (!succ->m_is_reachable)
3634 worklist.safe_push (succ);
3635 successors.release ();
35485da9
DM
3636 }
3637
3638 /* Now complain about any blocks that haven't been marked. */
3639 {
3640 int i;
3641 block *b;
3642 FOR_EACH_VEC_ELT (m_blocks, i, b)
3643 if (!b->m_is_reachable)
3644 m_ctxt->add_error (b->get_loc (),
3645 "unreachable block: %s",
3646 b->get_debug_string ());
3647 }
3648 }
3649}
3650
3651/* Implements the post-error-checking part of
3652 gcc_jit_function_dump_to_dot. */
3653
3654void
3655recording::function::dump_to_dot (const char *path)
3656{
3657 FILE *fp = fopen (path, "w");
3658 if (!fp)
3659 return;
3660
3661 pretty_printer the_pp;
3662 the_pp.buffer->stream = fp;
3663
3664 pretty_printer *pp = &the_pp;
3665
3666 pp_printf (pp,
3667 "digraph %s {\n", get_debug_string ());
3668
3669 /* Blocks: */
3670 {
3671 int i;
3672 block *b;
3673 FOR_EACH_VEC_ELT (m_blocks, i, b)
3674 b->dump_to_dot (pp);
3675 }
3676
3677 /* Edges: */
3678 {
3679 int i;
3680 block *b;
3681 FOR_EACH_VEC_ELT (m_blocks, i, b)
3682 b->dump_edges_to_dot (pp);
3683 }
3684
3685 pp_printf (pp, "}\n");
3686 pp_flush (pp);
3687 fclose (fp);
3688}
3689
3690/* Implementation of recording::memento::make_debug_string for
3691 functions. */
3692
3693recording::string *
3694recording::function::make_debug_string ()
3695{
3696 return m_name;
3697}
3698
86d0ac88
DM
3699/* A table of enum gcc_jit_function_kind values expressed in string
3700 form. */
3701
3702static const char * const names_of_function_kinds[] = {
3703 "GCC_JIT_FUNCTION_EXPORTED",
3704 "GCC_JIT_FUNCTION_INTERNAL",
3705 "GCC_JIT_FUNCTION_IMPORTED",
3706 "GCC_JIT_FUNCTION_ALWAYS_INLINE"
3707};
3708
3709/* Implementation of recording::memento::write_reproducer for functions. */
3710
3711void
3712recording::function::write_reproducer (reproducer &r)
3713{
3714 const char *id = r.make_identifier (this, "func");
3715
3716 if (m_builtin_id)
3717 {
3718 r.write (" gcc_jit_function *%s =\n"
3719 " gcc_jit_context_get_builtin_function (%s,\n"
3720 " %s);\n",
3721 id,
3722 r.get_identifier (get_context ()),
3723 m_name->get_debug_string ());
3724 return;
3725 }
3726 const char *params_id = r.make_tmp_identifier ("params_for", this);
3727 r.write (" gcc_jit_param *%s[%i] = {\n",
3728 params_id,
3729 m_params.length ());
3730 int i;
3731 param *param;
3732 FOR_EACH_VEC_ELT (m_params, i, param)
3733 r.write (" %s,\n", r.get_identifier (param));
3734 r.write (" };\n");
3735 r.write (" gcc_jit_function *%s =\n"
3736 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n"
3737 " %s, /* gcc_jit_location *loc */\n"
3738 " %s, /* enum gcc_jit_function_kind kind */\n"
3739 " %s, /* gcc_jit_type *return_type */\n"
3740 " %s, /* const char *name */\n"
3741 " %i, /* int num_params */\n"
3742 " %s, /* gcc_jit_param **params */\n"
3743 " %i); /* int is_variadic */\n",
3744 id,
3745 r.get_identifier (get_context ()),
3746 r.get_identifier (m_loc),
3747 names_of_function_kinds[m_kind],
3748 r.get_identifier_as_type (m_return_type),
3749 m_name->get_debug_string (),
3750 m_params.length (),
3751 params_id,
3752 m_is_variadic);
3753}
3754
3755
35485da9
DM
3756/* The implementation of class gcc::jit::recording::block. */
3757
3758/* Create a recording::eval instance and add it to
3759 the block's context's list of mementos, and to the block's
3760 list of statements.
3761
f6f2b019 3762 Implements the heart of gcc_jit_block_add_eval. */
35485da9 3763
f6f2b019 3764recording::statement *
35485da9
DM
3765recording::block::add_eval (recording::location *loc,
3766 recording::rvalue *rvalue)
3767{
3768 statement *result = new eval (this, loc, rvalue);
3769 m_ctxt->record (result);
3770 m_statements.safe_push (result);
f6f2b019 3771 return result;
35485da9
DM
3772}
3773
3774/* Create a recording::assignment instance and add it to
3775 the block's context's list of mementos, and to the block's
3776 list of statements.
3777
f6f2b019 3778 Implements the heart of gcc_jit_block_add_assignment. */
35485da9 3779
f6f2b019 3780recording::statement *
35485da9
DM
3781recording::block::add_assignment (recording::location *loc,
3782 recording::lvalue *lvalue,
3783 recording::rvalue *rvalue)
3784{
3785 statement *result = new assignment (this, loc, lvalue, rvalue);
3786 m_ctxt->record (result);
3787 m_statements.safe_push (result);
f6f2b019 3788 return result;
35485da9
DM
3789}
3790
3791/* Create a recording::assignment_op instance and add it to
3792 the block's context's list of mementos, and to the block's
3793 list of statements.
3794
f6f2b019 3795 Implements the heart of gcc_jit_block_add_assignment_op. */
35485da9 3796
f6f2b019 3797recording::statement *
35485da9
DM
3798recording::block::add_assignment_op (recording::location *loc,
3799 recording::lvalue *lvalue,
3800 enum gcc_jit_binary_op op,
3801 recording::rvalue *rvalue)
3802{
3803 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
3804 m_ctxt->record (result);
3805 m_statements.safe_push (result);
f6f2b019 3806 return result;
35485da9
DM
3807}
3808
3809/* Create a recording::comment instance and add it to
3810 the block's context's list of mementos, and to the block's
3811 list of statements.
3812
f6f2b019 3813 Implements the heart of gcc_jit_block_add_comment. */
35485da9 3814
f6f2b019 3815recording::statement *
35485da9
DM
3816recording::block::add_comment (recording::location *loc,
3817 const char *text)
3818{
3819 statement *result = new comment (this, loc, new_string (text));
3820 m_ctxt->record (result);
3821 m_statements.safe_push (result);
f6f2b019 3822 return result;
35485da9
DM
3823}
3824
3825/* Create a recording::end_with_conditional instance and add it to
3826 the block's context's list of mementos, and to the block's
3827 list of statements.
3828
f6f2b019 3829 Implements the heart of gcc_jit_block_end_with_conditional. */
35485da9 3830
f6f2b019 3831recording::statement *
35485da9
DM
3832recording::block::end_with_conditional (recording::location *loc,
3833 recording::rvalue *boolval,
3834 recording::block *on_true,
3835 recording::block *on_false)
3836{
3837 statement *result = new conditional (this, loc, boolval, on_true, on_false);
3838 m_ctxt->record (result);
3839 m_statements.safe_push (result);
3840 m_has_been_terminated = true;
f6f2b019 3841 return result;
35485da9
DM
3842}
3843
3844/* Create a recording::end_with_jump instance and add it to
3845 the block's context's list of mementos, and to the block's
3846 list of statements.
3847
f6f2b019 3848 Implements the heart of gcc_jit_block_end_with_jump. */
35485da9 3849
f6f2b019 3850recording::statement *
35485da9
DM
3851recording::block::end_with_jump (recording::location *loc,
3852 recording::block *target)
3853{
3854 statement *result = new jump (this, loc, target);
3855 m_ctxt->record (result);
3856 m_statements.safe_push (result);
3857 m_has_been_terminated = true;
f6f2b019 3858 return result;
35485da9
DM
3859}
3860
3861/* Create a recording::end_with_return instance and add it to
3862 the block's context's list of mementos, and to the block's
3863 list of statements.
3864
3865 Implements the post-error-checking parts of
3866 gcc_jit_block_end_with_return and
3867 gcc_jit_block_end_with_void_return. */
3868
f6f2b019 3869recording::statement *
35485da9
DM
3870recording::block::end_with_return (recording::location *loc,
3871 recording::rvalue *rvalue)
3872{
3873 /* This is used by both gcc_jit_function_add_return and
3874 gcc_jit_function_add_void_return; rvalue will be non-NULL for
3875 the former and NULL for the latter. */
3876 statement *result = new return_ (this, loc, rvalue);
3877 m_ctxt->record (result);
3878 m_statements.safe_push (result);
3879 m_has_been_terminated = true;
f6f2b019 3880 return result;
35485da9
DM
3881}
3882
ec5d0088
DM
3883/* Create a recording::switch_ instance and add it to
3884 the block's context's list of mementos, and to the block's
3885 list of statements.
3886
3887 Implements the heart of gcc_jit_block_end_with_switch. */
3888
3889recording::statement *
3890recording::block::end_with_switch (recording::location *loc,
3891 recording::rvalue *expr,
3892 recording::block *default_block,
3893 int num_cases,
3894 recording::case_ **cases)
3895{
3896 statement *result = new switch_ (this, loc,
3897 expr,
3898 default_block,
3899 num_cases,
3900 cases);
3901 m_ctxt->record (result);
3902 m_statements.safe_push (result);
3903 m_has_been_terminated = true;
3904 return result;
3905}
3906
35485da9
DM
3907/* Override the default implementation of
3908 recording::memento::write_to_dump for blocks by writing
3909 an unindented block name as a label, followed by the indented
3910 statements:
3911
3912 BLOCK_NAME:
3913 STATEMENT_1;
3914 STATEMENT_2;
3915 ...
3916 STATEMENT_N; */
3917
3918void
3919recording::block::write_to_dump (dump &d)
3920{
3921 d.write ("%s:\n", get_debug_string ());
3922
3923 int i;
3924 statement *s;
3925 FOR_EACH_VEC_ELT (m_statements, i, s)
3926 s->write_to_dump (d);
3927}
3928
3929/* Validate a block by ensuring that it has been terminated. */
3930
3931bool
3932recording::block::validate ()
3933{
f6f2b019 3934 /* Check for termination. */
35485da9
DM
3935 if (!has_been_terminated ())
3936 {
3937 statement *stmt = get_last_statement ();
3938 location *loc = stmt ? stmt->get_loc () : NULL;
3939 m_func->get_context ()->add_error (loc,
3940 "unterminated block in %s: %s",
3941 m_func->get_debug_string (),
3942 get_debug_string ());
3943 return false;
3944 }
3945
3946 return true;
3947}
3948
3949/* Get the source-location of a block by using that of the first
3950 statement within it, if any. */
3951
3952recording::location *
3953recording::block::get_loc () const
3954{
3955 recording::statement *stmt = get_first_statement ();
3956 if (stmt)
3957 return stmt->get_loc ();
3958 else
3959 return NULL;
3960}
3961
3962/* Get the first statement within a block, if any. */
3963
3964recording::statement *
3965recording::block::get_first_statement () const
3966{
3967 if (m_statements.length ())
3968 return m_statements[0];
3969 else
3970 return NULL;
3971}
3972
3973/* Get the last statement within a block, if any. */
3974
3975recording::statement *
3976recording::block::get_last_statement () const
3977{
3978 if (m_statements.length ())
3979 return m_statements[m_statements.length () - 1];
3980 else
3981 return NULL;
3982}
3983
ec5d0088
DM
3984/* Assuming that this block has been terminated, get the successor blocks
3985 as a vector. Ownership of the vector transfers to the caller, which
3986 must call its release () method.
35485da9
DM
3987
3988 Used when validating functions, and when dumping dot representations
3989 of them. */
3990
ec5d0088
DM
3991vec <recording::block *>
3992recording::block::get_successor_blocks () const
35485da9
DM
3993{
3994 gcc_assert (m_has_been_terminated);
35485da9
DM
3995 statement *last_statement = get_last_statement ();
3996 gcc_assert (last_statement);
ec5d0088 3997 return last_statement->get_successor_blocks ();
35485da9
DM
3998}
3999
4000/* Implementation of pure virtual hook recording::memento::replay_into
4001 for recording::block. */
4002
4003void
4004recording::block::replay_into (replayer *)
4005{
4006 set_playback_obj (m_func->playback_function ()
4007 ->new_block (playback_string (m_name)));
4008}
4009
4010/* Implementation of recording::memento::make_debug_string for
4011 blocks. */
4012
4013recording::string *
4014recording::block::make_debug_string ()
4015{
4016 if (m_name)
4017 return m_name;
4018 else
4019 return string::from_printf (m_ctxt,
4020 "<UNNAMED BLOCK %p>",
4021 (void *)this);
4022}
4023
86d0ac88
DM
4024/* Implementation of recording::memento::write_reproducer for blocks. */
4025
4026void
4027recording::block::write_reproducer (reproducer &r)
4028{
4029 const char *id = r.make_identifier (this, "block");
4030 r.write (" gcc_jit_block *%s =\n"
4031 " gcc_jit_function_new_block (%s, %s);\n",
4032 id,
4033 r.get_identifier (m_func),
4034 m_name ? m_name->get_debug_string () : "NULL");
4035}
4036
35485da9
DM
4037/* Dump a block in graphviz form into PP, capturing the block name (if
4038 any) and the statements. */
4039
4040void
4041recording::block::dump_to_dot (pretty_printer *pp)
4042{
4043 pp_printf (pp,
4044 ("\tblock_%d "
4045 "[shape=record,style=filled,fillcolor=white,label=\"{"),
4046 m_index);
4047 pp_write_text_to_stream (pp);
4048 if (m_name)
4049 {
4050 pp_string (pp, m_name->c_str ());
4051 pp_string (pp, ":");
4052 pp_newline (pp);
4053 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4054 }
4055
4056 int i;
4057 statement *s;
4058 FOR_EACH_VEC_ELT (m_statements, i, s)
4059 {
4060 pp_string (pp, s->get_debug_string ());
4061 pp_newline (pp);
4062 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
4063 }
4064
4065 pp_printf (pp,
4066 "}\"];\n\n");
4067 pp_flush (pp);
4068}
4069
4070/* Dump the out-edges of the block in graphviz form into PP. */
4071
4072void
4073recording::block::dump_edges_to_dot (pretty_printer *pp)
4074{
ec5d0088
DM
4075 vec <block *> successors = get_successor_blocks ();
4076 int i;
4077 block *succ;
4078 FOR_EACH_VEC_ELT (successors, i, succ)
35485da9
DM
4079 pp_printf (pp,
4080 "\tblock_%d:s -> block_%d:n;\n",
ec5d0088
DM
4081 m_index, succ->m_index);
4082 successors.release ();
35485da9
DM
4083}
4084
4085/* The implementation of class gcc::jit::recording::global. */
4086
4087/* Implementation of pure virtual hook recording::memento::replay_into
4088 for recording::global. */
4089
4090void
4091recording::global::replay_into (replayer *r)
4092{
4093 set_playback_obj (r->new_global (playback_location (r, m_loc),
791cfef8 4094 m_kind,
35485da9
DM
4095 m_type->playback_type (),
4096 playback_string (m_name)));
4097}
4098
791cfef8
DM
4099/* Override the default implementation of
4100 recording::memento::write_to_dump for globals.
4101 This will be of the form:
4102
4103 GCC_JIT_GLOBAL_EXPORTED:
4104 "TYPE NAME;"
4105 e.g. "int foo;"
4106
4107 GCC_JIT_GLOBAL_INTERNAL:
4108 "static TYPE NAME;"
4109 e.g. "static int foo;"
4110
4111 GCC_JIT_GLOBAL_IMPORTED:
4112 "extern TYPE NAME;"
4113 e.g. "extern int foo;"
4114
4115 These are written to the top of the dump by
4116 recording::context::dump_to_file. */
4117
4118void
4119recording::global::write_to_dump (dump &d)
4120{
4121 if (d.update_locations ())
4122 m_loc = d.make_location ();
4123
4124 switch (m_kind)
4125 {
4126 default:
4127 gcc_unreachable ();
4128
4129 case GCC_JIT_GLOBAL_EXPORTED:
4130 break;
4131
4132 case GCC_JIT_GLOBAL_INTERNAL:
4133 d.write ("static ");
4134 break;
4135
4136 case GCC_JIT_GLOBAL_IMPORTED:
4137 d.write ("extern ");
4138 break;
4139 }
4140 d.write ("%s %s;\n",
4141 m_type->get_debug_string (),
4142 get_debug_string ());
4143}
4144
86d0ac88
DM
4145/* A table of enum gcc_jit_global_kind values expressed in string
4146 form. */
4147
4148static const char * const global_kind_reproducer_strings[] = {
4149 "GCC_JIT_GLOBAL_EXPORTED",
4150 "GCC_JIT_GLOBAL_INTERNAL",
4151 "GCC_JIT_GLOBAL_IMPORTED"
4152};
4153
4154/* Implementation of recording::memento::write_reproducer for globals. */
4155
4156void
4157recording::global::write_reproducer (reproducer &r)
4158{
4159 const char *id = r.make_identifier (this, "block");
4160 r.write (" gcc_jit_lvalue *%s =\n"
4161 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n"
4162 " %s, /* gcc_jit_location *loc */\n"
4163 " %s, /* enum gcc_jit_global_kind kind */\n"
4164 " %s, /* gcc_jit_type *type */\n"
4165 " %s); /* const char *name */\n",
4166 id,
4167 r.get_identifier (get_context ()),
4168 r.get_identifier (m_loc),
4169 global_kind_reproducer_strings[m_kind],
4170 r.get_identifier_as_type (get_type ()),
4171 m_name->get_debug_string ());
4172}
4173
ccce3b2a
DM
4174/* The implementation of the various const-handling classes:
4175 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
35485da9 4176
ccce3b2a
DM
4177/* Explicit specialization of the various mementos we're interested in. */
4178template class recording::memento_of_new_rvalue_from_const <int>;
4179template class recording::memento_of_new_rvalue_from_const <long>;
4180template class recording::memento_of_new_rvalue_from_const <double>;
4181template class recording::memento_of_new_rvalue_from_const <void *>;
4182
4183/* Implementation of the pure virtual hook recording::memento::replay_into
4184 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
35485da9 4185
ccce3b2a 4186template <typename HOST_TYPE>
35485da9 4187void
ccce3b2a
DM
4188recording::
4189memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
35485da9 4190{
ccce3b2a
DM
4191 set_playback_obj
4192 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
4193 m_value));
35485da9
DM
4194}
4195
86d0ac88
DM
4196/* The make_debug_string and write_reproducer methods vary between the
4197 various
4198 memento_of_new_rvalue_from_const <HOST_TYPE>
4199 classes, so we explicitly write specializations of them.
ccce3b2a
DM
4200
4201 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
4202 namespaces are written out explicitly, which is why most of this file
4203 doesn't abbreviate things by entering the "recording" namespace.
4204
4205 However, these specializations are required to be in the same namespace
4206 as the template, hence we now have to enter the gcc::jit::recording
4207 namespace. */
4208
4209namespace recording
4210{
4211
4212/* The make_debug_string specialization for <int>, which renders it as
4213 (TARGET_TYPE)LITERAL
35485da9
DM
4214 e.g.
4215 "(int)42". */
4216
ccce3b2a
DM
4217template <>
4218string *
4219memento_of_new_rvalue_from_const <int>::make_debug_string ()
35485da9
DM
4220{
4221 return string::from_printf (m_ctxt,
4222 "(%s)%i",
4223 m_type->get_debug_string (),
4224 m_value);
4225}
4226
ec5d0088
DM
4227/* The get_wide_int specialization for <int>. */
4228
4229template <>
4230bool
4231memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const
4232{
4233 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4234 return true;
4235}
4236
86d0ac88
DM
4237/* The write_reproducer specialization for <int>. */
4238
4239template <>
4240void
4241memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r)
4242{
4243 const char *id = r.make_identifier (this, "rvalue");
4244 r.write (" gcc_jit_rvalue *%s =\n"
4245 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n"
4246 " %s, /* gcc_jit_type *numeric_type */\n"
4247 " %i); /* int value */\n",
4248 id,
4249 r.get_identifier (get_context ()),
4250 r.get_identifier_as_type (m_type),
4251 m_value);
4252}
4253
ccce3b2a
DM
4254/* The make_debug_string specialization for <long>, rendering it as
4255 (TARGET_TYPE)LITERAL
4256 e.g.
4257 "(long)42". */
35485da9 4258
ccce3b2a
DM
4259template <>
4260string *
4261memento_of_new_rvalue_from_const <long>::make_debug_string ()
35485da9 4262{
ccce3b2a
DM
4263 return string::from_printf (m_ctxt,
4264 "(%s)%li",
4265 m_type->get_debug_string (),
4266 m_value);
35485da9
DM
4267}
4268
ec5d0088
DM
4269/* The get_wide_int specialization for <long>. */
4270
4271template <>
4272bool
4273memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const
4274{
4275 *out = wi::shwi (m_value, sizeof (m_value) * 8);
4276 return true;
4277}
4278
86d0ac88
DM
4279/* The write_reproducer specialization for <long>. */
4280
4281template <>
4282void
4283recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r)
4284{
4285 const char *id = r.make_identifier (this, "rvalue");
4286
4287 /* We have to special-case LONG_MIN, since e.g.
4288 -9223372036854775808L
4289 is parsed as
4290 -(9223372036854775808L)
4291 and hence we'd get:
4292 error: integer constant is so large that it is unsigned [-Werror]
4293 Workaround this by writing (LONG_MIN + 1) - 1. */
4294 if (m_value == LONG_MIN)
4295 {
4296 r.write (" gcc_jit_rvalue *%s =\n"
4297 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4298 " %s, /* gcc_jit_type *numeric_type */\n"
4299 " %ldL - 1); /* long value */\n",
4300 id,
4301 r.get_identifier (get_context ()),
4302 r.get_identifier_as_type (m_type),
4303 m_value + 1);;
4304 return;
4305 }
4306
4307 r.write (" gcc_jit_rvalue *%s =\n"
4308 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n"
4309 " %s, /* gcc_jit_type *numeric_type */\n"
4310 " %ldL); /* long value */\n",
4311 id,
4312 r.get_identifier (get_context ()),
4313 r.get_identifier_as_type (m_type),
4314 m_value);
4315 }
4316
ccce3b2a
DM
4317/* The make_debug_string specialization for <double>, rendering it as
4318 (TARGET_TYPE)LITERAL
35485da9
DM
4319 e.g.
4320 "(float)42.0". */
4321
ccce3b2a
DM
4322template <>
4323string *
4324memento_of_new_rvalue_from_const <double>::make_debug_string ()
35485da9
DM
4325{
4326 return string::from_printf (m_ctxt,
4327 "(%s)%f",
4328 m_type->get_debug_string (),
4329 m_value);
4330}
4331
ec5d0088
DM
4332/* The get_wide_int specialization for <double>. */
4333
4334template <>
4335bool
4336memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const
4337{
4338 return false;
4339}
4340
86d0ac88
DM
4341/* The write_reproducer specialization for <double>. */
4342
4343template <>
4344void
4345recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r)
4346{
4347 const char *id = r.make_identifier (this, "rvalue");
4348 r.write (" gcc_jit_rvalue *%s =\n"
4349 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n"
4350 " %s, /* gcc_jit_type *numeric_type */\n"
4351 " %f); /* double value */\n",
4352 id,
4353 r.get_identifier (get_context ()),
4354 r.get_identifier_as_type (m_type),
4355 m_value);
4356}
4357
ccce3b2a
DM
4358/* The make_debug_string specialization for <void *>, rendering it as
4359 (TARGET_TYPE)HEX
35485da9
DM
4360 e.g.
4361 "(int *)0xdeadbeef"
4362
4363 Zero is rendered as NULL e.g.
4364 "(int *)NULL". */
4365
ccce3b2a
DM
4366template <>
4367string *
4368memento_of_new_rvalue_from_const <void *>::make_debug_string ()
35485da9
DM
4369{
4370 if (m_value != NULL)
4371 return string::from_printf (m_ctxt,
4372 "(%s)%p",
4373 m_type->get_debug_string (), m_value);
4374 else
4375 return string::from_printf (m_ctxt,
4376 "(%s)NULL",
4377 m_type->get_debug_string ());
4378}
4379
ec5d0088
DM
4380/* The get_wide_int specialization for <void *>. */
4381
4382template <>
4383bool
4384memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const
4385{
4386 return false;
4387}
4388
86d0ac88
DM
4389/* Implementation of recording::memento::write_reproducer for <void *>
4390 values. */
4391
4392template <>
4393void
4394memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r)
4395{
4396 const char *id = r.make_identifier (this, "rvalue");
4397 if (m_value)
4398 r.write (" gcc_jit_rvalue *%s =\n"
4399 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n"
4400 " %s, /* gcc_jit_type *pointer_type */\n"
4401 " (void *)%p); /* void *value */\n",
4402 id,
4403 r.get_identifier (get_context ()),
4404 r.get_identifier_as_type (m_type),
4405 m_value);
4406 else
4407 r.write (" gcc_jit_rvalue *%s =\n"
4408 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n"
4409 " %s); /* gcc_jit_type *pointer_type */\n",
4410 id,
4411 r.get_identifier (get_context ()),
4412 r.get_identifier_as_type (m_type));
4413}
4414
4415/* We're done specializing make_debug_string and write_reproducer, so we
4416 can exit the gcc::jit::recording namespace. */
ccce3b2a
DM
4417
4418} // namespace recording
4419
35485da9
DM
4420/* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
4421
4422/* Implementation of pure virtual hook recording::memento::replay_into
4423 for recording::memento_of_new_string_literal. */
4424
4425void
4426recording::memento_of_new_string_literal::replay_into (replayer *r)
4427{
4428 set_playback_obj (r->new_string_literal (m_value->c_str ()));
4429}
4430
4431/* Implementation of recording::memento::make_debug_string for
4432 string literals. */
4433
4434recording::string *
4435recording::memento_of_new_string_literal::make_debug_string ()
4436{
4437 return string::from_printf (m_ctxt,
450e225b 4438 "%s",
35485da9
DM
4439 m_value->get_debug_string ());
4440}
4441
86d0ac88
DM
4442/* Implementation of recording::memento::write_reproducer for string literal
4443 values. */
4444
4445void
4446recording::memento_of_new_string_literal::write_reproducer (reproducer &r)
4447{
4448 const char *id = r.make_identifier (this, "rvalue");
4449 r.write (" gcc_jit_rvalue *%s =\n"
4450 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n"
4451 " %s); /* const char *value */\n",
4452 id,
4453 r.get_identifier (get_context ()),
4454 m_value->get_debug_string ());
4455}
4456
35485da9
DM
4457/* The implementation of class gcc::jit::recording::unary_op. */
4458
4459/* Implementation of pure virtual hook recording::memento::replay_into
4460 for recording::unary_op. */
4461
4462void
4463recording::unary_op::replay_into (replayer *r)
4464{
4465 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
4466 m_op,
4467 get_type ()->playback_type (),
4468 m_a->playback_rvalue ()));
4469}
4470
f6f2b019
DM
4471/* Implementation of pure virtual hook recording::rvalue::visit_children
4472 for recording::unary_op. */
4473void
4474recording::unary_op::visit_children (rvalue_visitor *v)
4475{
4476 v->visit (m_a);
4477}
4478
35485da9
DM
4479/* Implementation of recording::memento::make_debug_string for
4480 unary ops. */
4481
4482static const char * const unary_op_strings[] = {
4483 "-", /* GCC_JIT_UNARY_OP_MINUS */
4484 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
4485 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
18146f45 4486 "abs ", /* GCC_JIT_UNARY_OP_ABS */
35485da9
DM
4487};
4488
4489recording::string *
4490recording::unary_op::make_debug_string ()
4491{
4492 return string::from_printf (m_ctxt,
4493 "%s(%s)",
4494 unary_op_strings[m_op],
4495 m_a->get_debug_string ());
4496}
4497
86d0ac88
DM
4498static const char * const unary_op_reproducer_strings[] = {
4499 "GCC_JIT_UNARY_OP_MINUS",
4500 "GCC_JIT_UNARY_OP_BITWISE_NEGATE",
4501 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE",
4502 "GCC_JIT_UNARY_OP_ABS"
4503};
4504
4505/* Implementation of recording::memento::write_reproducer for unary ops. */
4506
4507void
4508recording::unary_op::write_reproducer (reproducer &r)
4509{
4510 const char *id = r.make_identifier (this, "rvalue");
4511 r.write (" gcc_jit_rvalue *%s =\n"
4512 " gcc_jit_context_new_unary_op (%s,\n"
4513 " %s, /* gcc_jit_location *loc */\n"
4514 " %s, /* enum gcc_jit_unary_op op */\n"
4515 " %s, /* gcc_jit_type *result_type */\n"
4516 " %s); /* gcc_jit_rvalue *a */\n",
4517 id,
4518 r.get_identifier (get_context ()),
4519 r.get_identifier (m_loc),
4520 unary_op_reproducer_strings[m_op],
4521 r.get_identifier_as_type (get_type ()),
4522 r.get_identifier_as_rvalue (m_a));
4523}
4524
35485da9
DM
4525/* The implementation of class gcc::jit::recording::binary_op. */
4526
4527/* Implementation of pure virtual hook recording::memento::replay_into
4528 for recording::binary_op. */
4529
4530void
4531recording::binary_op::replay_into (replayer *r)
4532{
4533 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
4534 m_op,
4535 get_type ()->playback_type (),
4536 m_a->playback_rvalue (),
4537 m_b->playback_rvalue ()));
4538}
4539
f6f2b019
DM
4540/* Implementation of pure virtual hook recording::rvalue::visit_children
4541 for recording::binary_op. */
4542void
4543recording::binary_op::visit_children (rvalue_visitor *v)
4544{
4545 v->visit (m_a);
4546 v->visit (m_b);
4547}
4548
35485da9
DM
4549/* Implementation of recording::memento::make_debug_string for
4550 binary ops. */
4551
4552static const char * const binary_op_strings[] = {
4553 "+", /* GCC_JIT_BINARY_OP_PLUS */
4554 "-", /* GCC_JIT_BINARY_OP_MINUS */
4555 "*", /* GCC_JIT_BINARY_OP_MULT */
4556 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
4557 "%", /* GCC_JIT_BINARY_OP_MODULO */
4558 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
4559 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4560 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
4561 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4562 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4563 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
4564 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
4565};
4566
4567recording::string *
4568recording::binary_op::make_debug_string ()
4569{
bd93aa1a 4570 enum precedence prec = get_precedence ();
35485da9
DM
4571 return string::from_printf (m_ctxt,
4572 "%s %s %s",
bd93aa1a 4573 m_a->get_debug_string_parens (prec),
35485da9 4574 binary_op_strings[m_op],
bd93aa1a 4575 m_b->get_debug_string_parens (prec));
35485da9
DM
4576}
4577
86d0ac88
DM
4578static const char * const binary_op_reproducer_strings[] = {
4579 "GCC_JIT_BINARY_OP_PLUS",
4580 "GCC_JIT_BINARY_OP_MINUS",
4581 "GCC_JIT_BINARY_OP_MULT",
4582 "GCC_JIT_BINARY_OP_DIVIDE",
4583 "GCC_JIT_BINARY_OP_MODULO",
4584 "GCC_JIT_BINARY_OP_BITWISE_AND",
4585 "GCC_JIT_BINARY_OP_BITWISE_XOR",
4586 "GCC_JIT_BINARY_OP_BITWISE_OR",
4587 "GCC_JIT_BINARY_OP_LOGICAL_AND",
4588 "GCC_JIT_BINARY_OP_LOGICAL_OR",
4589 "GCC_JIT_BINARY_OP_LSHIFT",
4590 "GCC_JIT_BINARY_OP_RSHIFT"
4591};
4592
4593/* Implementation of recording::memento::write_reproducer for binary ops. */
4594
4595void
4596recording::binary_op::write_reproducer (reproducer &r)
4597{
4598 const char *id = r.make_identifier (this, "rvalue");
4599 r.write (" gcc_jit_rvalue *%s =\n"
4600 " gcc_jit_context_new_binary_op (%s,\n"
4601 " %s, /* gcc_jit_location *loc */\n"
4602 " %s, /* enum gcc_jit_binary_op op */\n"
4603 " %s, /* gcc_jit_type *result_type */\n"
4604 " %s, /* gcc_jit_rvalue *a */\n"
4605 " %s); /* gcc_jit_rvalue *b */\n",
4606 id,
4607 r.get_identifier (get_context ()),
4608 r.get_identifier (m_loc),
4609 binary_op_reproducer_strings[m_op],
4610 r.get_identifier_as_type (get_type ()),
4611 r.get_identifier_as_rvalue (m_a),
4612 r.get_identifier_as_rvalue (m_b));
4613}
4614
bd93aa1a
DM
4615namespace recording {
4616static const enum precedence binary_op_precedence[] = {
4617 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */
4618 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */
4619
4620 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */
4621 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */
4622 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */
4623
4624 PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */
4625 PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */
4626 PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */
4627 PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */
4628 PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */
4629 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */
4630 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */
4631};
4632} /* namespace recording */
4633
4634enum recording::precedence
4635recording::binary_op::get_precedence () const
4636{
4637 return binary_op_precedence[m_op];
4638}
4639
35485da9
DM
4640/* The implementation of class gcc::jit::recording::comparison. */
4641
4642/* Implementation of recording::memento::make_debug_string for
4643 comparisons. */
4644
4645static const char * const comparison_strings[] =
4646{
4647 "==", /* GCC_JIT_COMPARISON_EQ */
4648 "!=", /* GCC_JIT_COMPARISON_NE */
4649 "<", /* GCC_JIT_COMPARISON_LT */
4650 "<=", /* GCC_JIT_COMPARISON_LE */
4651 ">", /* GCC_JIT_COMPARISON_GT */
4652 ">=", /* GCC_JIT_COMPARISON_GE */
4653};
4654
4655recording::string *
4656recording::comparison::make_debug_string ()
4657{
bd93aa1a 4658 enum precedence prec = get_precedence ();
35485da9
DM
4659 return string::from_printf (m_ctxt,
4660 "%s %s %s",
bd93aa1a 4661 m_a->get_debug_string_parens (prec),
35485da9 4662 comparison_strings[m_op],
bd93aa1a 4663 m_b->get_debug_string_parens (prec));
35485da9
DM
4664}
4665
86d0ac88
DM
4666/* A table of enum gcc_jit_comparison values expressed in string
4667 form. */
4668
4669static const char * const comparison_reproducer_strings[] =
4670{
4671 "GCC_JIT_COMPARISON_EQ",
4672 "GCC_JIT_COMPARISON_NE",
4673 "GCC_JIT_COMPARISON_LT",
4674 "GCC_JIT_COMPARISON_LE",
4675 "GCC_JIT_COMPARISON_GT",
4676 "GCC_JIT_COMPARISON_GE"
4677};
4678
4679/* Implementation of recording::memento::write_reproducer for comparisons. */
4680
4681void
4682recording::comparison::write_reproducer (reproducer &r)
4683{
4684 const char *id = r.make_identifier (this, "rvalue");
4685 r.write (" gcc_jit_rvalue *%s =\n"
4686 " gcc_jit_context_new_comparison (%s,\n"
4687 " %s, /* gcc_jit_location *loc */\n"
4688 " %s, /* enum gcc_jit_comparison op */\n"
4689 " %s, /* gcc_jit_rvalue *a */\n"
4690 " %s); /* gcc_jit_rvalue *b */\n",
4691 id,
4692 r.get_identifier (get_context ()),
4693 r.get_identifier (m_loc),
4694 comparison_reproducer_strings[m_op],
4695 r.get_identifier_as_rvalue (m_a),
4696 r.get_identifier_as_rvalue (m_b));
4697}
4698
35485da9
DM
4699/* Implementation of pure virtual hook recording::memento::replay_into
4700 for recording::comparison. */
4701
4702void
4703recording::comparison::replay_into (replayer *r)
4704{
4705 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
4706 m_op,
4707 m_a->playback_rvalue (),
4708 m_b->playback_rvalue ()));
4709}
4710
f6f2b019
DM
4711/* Implementation of pure virtual hook recording::rvalue::visit_children
4712 for recording::comparison. */
4713
4714void
4715recording::comparison::visit_children (rvalue_visitor *v)
4716{
4717 v->visit (m_a);
4718 v->visit (m_b);
4719}
4720
bd93aa1a
DM
4721namespace recording {
4722static const enum precedence comparison_precedence[] =
4723{
4724 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */
4725 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */
4726
4727 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LT */
4728 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */
4729 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GT */
4730 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */
4731};
4732} /* namespace recording */
4733
4734enum recording::precedence
4735recording::comparison::get_precedence () const
4736{
4737 return comparison_precedence[m_op];
4738}
4739
35485da9
DM
4740/* Implementation of pure virtual hook recording::memento::replay_into
4741 for recording::cast. */
4742
4743void
4744recording::cast::replay_into (replayer *r)
4745{
4746 set_playback_obj (r->new_cast (playback_location (r, m_loc),
4747 m_rvalue->playback_rvalue (),
4748 get_type ()->playback_type ()));
4749}
4750
f6f2b019
DM
4751/* Implementation of pure virtual hook recording::rvalue::visit_children
4752 for recording::cast. */
4753void
4754recording::cast::visit_children (rvalue_visitor *v)
4755{
4756 v->visit (m_rvalue);
4757}
4758
35485da9
DM
4759/* Implementation of recording::memento::make_debug_string for
4760 casts. */
4761
4762recording::string *
4763recording::cast::make_debug_string ()
4764{
bd93aa1a 4765 enum precedence prec = get_precedence ();
35485da9
DM
4766 return string::from_printf (m_ctxt,
4767 "(%s)%s",
4768 get_type ()->get_debug_string (),
bd93aa1a 4769 m_rvalue->get_debug_string_parens (prec));
35485da9
DM
4770}
4771
86d0ac88
DM
4772/* Implementation of recording::memento::write_reproducer for casts. */
4773
4774void
4775recording::cast::write_reproducer (reproducer &r)
4776{
4777 const char *id = r.make_identifier (this, "rvalue");
4778 r.write (" gcc_jit_rvalue *%s =\n"
4779 " gcc_jit_context_new_cast (%s,\n"
4780 " %s, /* gcc_jit_location *loc */\n"
4781 " %s, /* gcc_jit_rvalue *rvalue */\n"
4782 " %s); /* gcc_jit_type *type */\n",
4783 id,
4784 r.get_identifier (get_context ()),
4785 r.get_identifier (m_loc),
4786 r.get_identifier_as_rvalue (m_rvalue),
4787 r.get_identifier_as_type (get_type ()));
4788}
4789
15c671a7
DM
4790/* The implementation of class gcc::jit::recording::base_call. */
4791
4792/* The constructor for gcc::jit::recording::base_call. */
4793
4794recording::base_call::base_call (context *ctxt,
4795 location *loc,
4796 type *type_,
4797 int numargs,
4798 rvalue **args)
4799: rvalue (ctxt, loc, type_),
4800 m_args (),
4801 m_require_tail_call (0)
4802{
4803 for (int i = 0; i< numargs; i++)
4804 m_args.safe_push (args[i]);
4805}
4806
4807/* Subroutine for use by call and call_though_ptr's write_reproducer
4808 methods. */
4809
4810void
4811recording::base_call::write_reproducer_tail_call (reproducer &r,
4812 const char *id)
4813{
4814 if (m_require_tail_call)
4815 {
4816 r.write (" gcc_jit_rvalue_set_bool_require_tail_call (%s, /* gcc_jit_rvalue *call*/\n"
4817 " %i); /* int require_tail_call*/\n",
4818 id,
4819 1);
4820 }
4821}
4822
35485da9
DM
4823/* The implementation of class gcc::jit::recording::call. */
4824
4825/* The constructor for gcc::jit::recording::call. */
4826
4827recording::call::call (recording::context *ctxt,
4828 recording::location *loc,
4829 recording::function *func,
4830 int numargs,
4831 rvalue **args)
15c671a7
DM
4832: base_call (ctxt, loc, func->get_return_type (), numargs, args),
4833 m_func (func)
35485da9 4834{
35485da9
DM
4835}
4836
4837/* Implementation of pure virtual hook recording::memento::replay_into
4838 for recording::call. */
4839
4840void
4841recording::call::replay_into (replayer *r)
4842{
b957b2e0 4843 auto_vec<playback::rvalue *> playback_args;
35485da9
DM
4844 playback_args.create (m_args.length ());
4845 for (unsigned i = 0; i< m_args.length (); i++)
4846 playback_args.safe_push (m_args[i]->playback_rvalue ());
4847
4848 set_playback_obj (r->new_call (playback_location (r, m_loc),
4849 m_func->playback_function (),
15c671a7
DM
4850 &playback_args,
4851 m_require_tail_call));
35485da9
DM
4852}
4853
f6f2b019
DM
4854/* Implementation of pure virtual hook recording::rvalue::visit_children
4855 for recording::call. */
4856
4857void
4858recording::call::visit_children (rvalue_visitor *v)
4859{
4860 for (unsigned i = 0; i< m_args.length (); i++)
4861 v->visit (m_args[i]);
4862}
4863
35485da9
DM
4864/* Implementation of recording::memento::make_debug_string for
4865 function calls. */
4866
4867recording::string *
4868recording::call::make_debug_string ()
4869{
bd93aa1a 4870 enum precedence prec = get_precedence ();
35485da9
DM
4871 /* First, build a buffer for the arguments. */
4872 /* Calculate length of said buffer. */
4873 size_t sz = 1; /* nil terminator */
4874 for (unsigned i = 0; i< m_args.length (); i++)
4875 {
bd93aa1a 4876 sz += strlen (m_args[i]->get_debug_string_parens (prec));
35485da9
DM
4877 sz += 2; /* ", " separator */
4878 }
4879
4880 /* Now allocate and populate the buffer. */
4881 char *argbuf = new char[sz];
4882 size_t len = 0;
4883
4884 for (unsigned i = 0; i< m_args.length (); i++)
4885 {
bd93aa1a
DM
4886 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
4887 len += strlen (m_args[i]->get_debug_string_parens (prec));
35485da9
DM
4888 if (i + 1 < m_args.length ())
4889 {
4890 strcpy (argbuf + len, ", ");
4891 len += 2;
4892 }
4893 }
4894 argbuf[len] = '\0';
4895
4896 /* ...and use it to get the string for the call as a whole. */
4897 string *result = string::from_printf (m_ctxt,
4898 "%s (%s)",
4899 m_func->get_debug_string (),
4900 argbuf);
4901
4902 delete[] argbuf;
4903
4904 return result;
4905}
4906
86d0ac88
DM
4907void
4908recording::call::write_reproducer (reproducer &r)
4909{
4910 const char *id = r.make_identifier (this, "call");
4911 const char *args_id = r.make_tmp_identifier ("args_for_", this);
4912 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
4913 args_id,
4914 m_args.length ());
4915 for (unsigned i = 0; i< m_args.length (); i++)
4916 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
4917 r.write (" };\n");
4918 r.write (" gcc_jit_rvalue *%s =\n"
4919 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n"
4920 " %s, /* gcc_jit_location *loc */\n"
4921 " %s, /* gcc_jit_function *func */\n"
4922 " %i, /* int numargs */ \n"
4923 " %s); /* gcc_jit_rvalue **args*/\n",
4924 id,
4925 r.get_identifier (get_context ()),
4926 r.get_identifier (m_loc),
4927 r.get_identifier (m_func),
4928 m_args.length (),
4929 args_id);
15c671a7 4930 write_reproducer_tail_call (r, id);
86d0ac88
DM
4931}
4932
35485da9
DM
4933/* The implementation of class gcc::jit::recording::call_through_ptr. */
4934
4935/* The constructor for recording::call_through_ptr. */
4936
4937recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
4938 recording::location *loc,
4939 recording::rvalue *fn_ptr,
4940 int numargs,
4941 rvalue **args)
15c671a7
DM
4942: base_call (ctxt, loc,
4943 fn_ptr->get_type ()->dereference ()
4944 ->as_a_function_type ()->get_return_type (),
4945 numargs, args),
4946 m_fn_ptr (fn_ptr)
35485da9 4947{
35485da9
DM
4948}
4949
4950/* Implementation of pure virtual hook recording::memento::replay_into
4951 for recording::call_through_ptr. */
4952
4953void
4954recording::call_through_ptr::replay_into (replayer *r)
4955{
b957b2e0 4956 auto_vec<playback::rvalue *> playback_args;
35485da9
DM
4957 playback_args.create (m_args.length ());
4958 for (unsigned i = 0; i< m_args.length (); i++)
4959 playback_args.safe_push (m_args[i]->playback_rvalue ());
4960
4961 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
4962 m_fn_ptr->playback_rvalue (),
15c671a7
DM
4963 &playback_args,
4964 m_require_tail_call));
35485da9
DM
4965}
4966
f6f2b019
DM
4967/* Implementation of pure virtual hook recording::rvalue::visit_children
4968 for recording::call_through_ptr. */
4969
4970void
4971recording::call_through_ptr::visit_children (rvalue_visitor *v)
4972{
4973 v->visit (m_fn_ptr);
4974 for (unsigned i = 0; i< m_args.length (); i++)
4975 v->visit (m_args[i]);
4976}
4977
35485da9
DM
4978/* Implementation of recording::memento::make_debug_string for
4979 calls through function ptrs. */
4980
4981recording::string *
4982recording::call_through_ptr::make_debug_string ()
4983{
bd93aa1a 4984 enum precedence prec = get_precedence ();
35485da9
DM
4985 /* First, build a buffer for the arguments. */
4986 /* Calculate length of said buffer. */
4987 size_t sz = 1; /* nil terminator */
4988 for (unsigned i = 0; i< m_args.length (); i++)
4989 {
bd93aa1a 4990 sz += strlen (m_args[i]->get_debug_string_parens (prec));
35485da9
DM
4991 sz += 2; /* ", " separator */
4992 }
4993
4994 /* Now allocate and populate the buffer. */
4995 char *argbuf = new char[sz];
4996 size_t len = 0;
4997
4998 for (unsigned i = 0; i< m_args.length (); i++)
4999 {
bd93aa1a
DM
5000 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec));
5001 len += strlen (m_args[i]->get_debug_string_parens (prec));
35485da9
DM
5002 if (i + 1 < m_args.length ())
5003 {
5004 strcpy (argbuf + len, ", ");
5005 len += 2;
5006 }
5007 }
5008 argbuf[len] = '\0';
5009
5010 /* ...and use it to get the string for the call as a whole. */
5011 string *result = string::from_printf (m_ctxt,
5012 "%s (%s)",
bd93aa1a 5013 m_fn_ptr->get_debug_string_parens (prec),
35485da9
DM
5014 argbuf);
5015
5016 delete[] argbuf;
5017
5018 return result;
5019}
5020
86d0ac88
DM
5021/* Implementation of recording::memento::write_reproducer for
5022 call_through_ptr. */
5023
5024void
5025recording::call_through_ptr::write_reproducer (reproducer &r)
5026{
5027 const char *id = r.make_identifier (this, "call");
5028 const char *args_id = r.make_tmp_identifier ("args_for_", this);
5029 r.write (" gcc_jit_rvalue *%s[%i] = {\n",
5030 args_id,
5031 m_args.length ());
5032 for (unsigned i = 0; i< m_args.length (); i++)
5033 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i]));
5034 r.write (" };\n");
5035 r.write (" gcc_jit_rvalue *%s =\n"
5036 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n"
5037 " %s, /* gcc_jit_location *loc */\n"
5038 " %s, /* gcc_jit_rvalue *fn_ptr */\n"
5039 " %i, /* int numargs */ \n"
5040 " %s); /* gcc_jit_rvalue **args*/\n",
5041 id,
5042 r.get_identifier (get_context ()),
5043 r.get_identifier (m_loc),
5044 r.get_identifier_as_rvalue (m_fn_ptr),
5045 m_args.length (),
5046 args_id);
15c671a7 5047 write_reproducer_tail_call (r, id);
86d0ac88
DM
5048}
5049
35485da9
DM
5050/* The implementation of class gcc::jit::recording::array_access. */
5051
5052/* Implementation of pure virtual hook recording::memento::replay_into
5053 for recording::array_access. */
5054
5055void
5056recording::array_access::replay_into (replayer *r)
5057{
5058 set_playback_obj (
5059 r->new_array_access (playback_location (r, m_loc),
5060 m_ptr->playback_rvalue (),
5061 m_index->playback_rvalue ()));
5062}
5063
f6f2b019
DM
5064/* Implementation of pure virtual hook recording::rvalue::visit_children
5065 for recording::array_access. */
5066
5067void
5068recording::array_access::visit_children (rvalue_visitor *v)
5069{
5070 v->visit (m_ptr);
5071 v->visit (m_index);
5072}
5073
35485da9
DM
5074/* Implementation of recording::memento::make_debug_string for
5075 array accesses. */
5076
5077recording::string *
5078recording::array_access::make_debug_string ()
5079{
bd93aa1a 5080 enum precedence prec = get_precedence ();
35485da9
DM
5081 return string::from_printf (m_ctxt,
5082 "%s[%s]",
bd93aa1a
DM
5083 m_ptr->get_debug_string_parens (prec),
5084 m_index->get_debug_string_parens (prec));
35485da9
DM
5085}
5086
86d0ac88
DM
5087/* Implementation of recording::memento::write_reproducer for
5088 array_access. */
5089
5090void
5091recording::array_access::write_reproducer (reproducer &r)
5092{
5093 const char *id = r.make_identifier (this, "lvalue");
5094 r.write (" gcc_jit_lvalue *%s = \n"
5095 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n"
5096 " %s, /*gcc_jit_location *loc */\n"
5097 " %s, /* gcc_jit_rvalue *ptr */\n"
5098 " %s); /* gcc_jit_rvalue *index */\n",
5099 id,
5100 r.get_identifier (get_context ()),
5101 r.get_identifier (m_loc),
5102 r.get_identifier_as_rvalue (m_ptr),
5103 r.get_identifier_as_rvalue (m_index));
5104}
5105
35485da9
DM
5106/* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
5107
5108/* Implementation of pure virtual hook recording::memento::replay_into
5109 for recording::access_field_of_lvalue. */
5110
5111void
5112recording::access_field_of_lvalue::replay_into (replayer *r)
5113{
5114 set_playback_obj (
5115 m_lvalue->playback_lvalue ()
5116 ->access_field (playback_location (r, m_loc),
5117 m_field->playback_field ()));
5118
5119}
5120
f6f2b019
DM
5121/* Implementation of pure virtual hook recording::rvalue::visit_children
5122 for recording::access_field_of_lvalue. */
5123
5124void
5125recording::access_field_of_lvalue::visit_children (rvalue_visitor *v)
5126{
5127 v->visit (m_lvalue);
5128}
5129
35485da9
DM
5130/* Implementation of recording::memento::make_debug_string for
5131 accessing a field of an lvalue. */
5132
5133recording::string *
5134recording::access_field_of_lvalue::make_debug_string ()
5135{
bd93aa1a 5136 enum precedence prec = get_precedence ();
35485da9
DM
5137 return string::from_printf (m_ctxt,
5138 "%s.%s",
bd93aa1a 5139 m_lvalue->get_debug_string_parens (prec),
35485da9
DM
5140 m_field->get_debug_string ());
5141}
5142
86d0ac88
DM
5143/* Implementation of recording::memento::write_reproducer for
5144 access_field_of_lvalue. */
5145
5146void
5147recording::access_field_of_lvalue::write_reproducer (reproducer &r)
5148{
5149 const char *id = r.make_identifier (this, "lvalue");
5150 r.write (" gcc_jit_lvalue *%s = \n"
5151 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n"
5152 " %s, /*gcc_jit_location *loc */\n"
5153 " %s);\n",
5154 id,
5155 r.get_identifier_as_lvalue (m_lvalue),
5156 r.get_identifier (m_loc),
5157 r.get_identifier (m_field));
5158}
5159
35485da9
DM
5160/* The implementation of class gcc::jit::recording::access_field_rvalue. */
5161
5162/* Implementation of pure virtual hook recording::memento::replay_into
5163 for recording::access_field_rvalue. */
5164
5165void
5166recording::access_field_rvalue::replay_into (replayer *r)
5167{
5168 set_playback_obj (
5169 m_rvalue->playback_rvalue ()
5170 ->access_field (playback_location (r, m_loc),
5171 m_field->playback_field ()));
5172}
5173
f6f2b019
DM
5174/* Implementation of pure virtual hook recording::rvalue::visit_children
5175 for recording::access_field_rvalue. */
5176
5177void
5178recording::access_field_rvalue::visit_children (rvalue_visitor *v)
5179{
5180 v->visit (m_rvalue);
5181}
5182
35485da9
DM
5183/* Implementation of recording::memento::make_debug_string for
5184 accessing a field of an rvalue. */
5185
5186recording::string *
5187recording::access_field_rvalue::make_debug_string ()
5188{
bd93aa1a 5189 enum precedence prec = get_precedence ();
35485da9
DM
5190 return string::from_printf (m_ctxt,
5191 "%s.%s",
bd93aa1a 5192 m_rvalue->get_debug_string_parens (prec),
35485da9
DM
5193 m_field->get_debug_string ());
5194}
5195
86d0ac88
DM
5196/* Implementation of recording::memento::write_reproducer for
5197 access_field_rvalue. */
5198
5199void
5200recording::access_field_rvalue::write_reproducer (reproducer &r)
5201{
5202 const char *id = r.make_identifier (this, "rvalue");
5203 r.write (" gcc_jit_rvalue *%s = \n"
5204 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n"
5205 " %s, /*gcc_jit_location *loc */\n"
5206 " %s);\n",
5207 id,
5208 r.get_identifier_as_rvalue (m_rvalue),
5209 r.get_identifier (m_loc),
5210 r.get_identifier (m_field));
5211}
5212
35485da9
DM
5213/* The implementation of class
5214 gcc::jit::recording::dereference_field_rvalue. */
5215
5216/* Implementation of pure virtual hook recording::memento::replay_into
5217 for recording::dereference_field_rvalue. */
5218
5219void
5220recording::dereference_field_rvalue::replay_into (replayer *r)
5221{
5222 set_playback_obj (
5223 m_rvalue->playback_rvalue ()->
5224 dereference_field (playback_location (r, m_loc),
5225 m_field->playback_field ()));
5226}
5227
f6f2b019
DM
5228/* Implementation of pure virtual hook recording::rvalue::visit_children
5229 for recording::dereference_field_rvalue. */
5230
5231void
5232recording::dereference_field_rvalue::visit_children (rvalue_visitor *v)
5233{
5234 v->visit (m_rvalue);
5235}
5236
35485da9
DM
5237/* Implementation of recording::memento::make_debug_string for
5238 dereferencing a field of an rvalue. */
5239
5240recording::string *
5241recording::dereference_field_rvalue::make_debug_string ()
5242{
bd93aa1a 5243 enum precedence prec = get_precedence ();
35485da9
DM
5244 return string::from_printf (m_ctxt,
5245 "%s->%s",
bd93aa1a 5246 m_rvalue->get_debug_string_parens (prec),
35485da9
DM
5247 m_field->get_debug_string ());
5248}
5249
86d0ac88
DM
5250/* Implementation of recording::memento::write_reproducer for
5251 dereference_field_rvalue. */
5252
5253void
5254recording::dereference_field_rvalue::write_reproducer (reproducer &r)
5255{
5256 const char *id = r.make_identifier (this, "lvalue");
5257 r.write (" gcc_jit_lvalue *%s=\n"
5258 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n"
5259 " %s, /* gcc_jit_location *loc */\n"
5260 " %s); /* gcc_jit_field *field */\n",
5261 id,
5262 r.get_identifier_as_rvalue (m_rvalue),
5263 r.get_identifier (m_loc),
5264 r.get_identifier (m_field));
5265}
5266
35485da9
DM
5267/* The implementation of class gcc::jit::recording::dereference_rvalue. */
5268
5269/* Implementation of pure virtual hook recording::memento::replay_into
5270 for recording::dereference_rvalue. */
5271
5272void
5273recording::dereference_rvalue::replay_into (replayer *r)
5274{
5275 set_playback_obj (
5276 m_rvalue->playback_rvalue ()->
5277 dereference (playback_location (r, m_loc)));
5278}
5279
f6f2b019
DM
5280/* Implementation of pure virtual hook recording::rvalue::visit_children
5281 for recording::dereference_rvalue. */
5282
5283void
5284recording::dereference_rvalue::visit_children (rvalue_visitor *v)
5285{
5286 v->visit (m_rvalue);
5287}
5288
35485da9
DM
5289/* Implementation of recording::memento::make_debug_string for
5290 dereferencing an rvalue. */
5291
5292recording::string *
5293recording::dereference_rvalue::make_debug_string ()
5294{
bd93aa1a 5295 enum precedence prec = get_precedence ();
35485da9
DM
5296 return string::from_printf (m_ctxt,
5297 "*%s",
bd93aa1a 5298 m_rvalue->get_debug_string_parens (prec));
35485da9
DM
5299}
5300
86d0ac88
DM
5301/* Implementation of recording::memento::write_reproducer for
5302 dereference_rvalue. */
5303
5304void
5305recording::dereference_rvalue::write_reproducer (reproducer &r)
5306{
5307 const char *id = r.make_identifier (this, "dereference");
5308 r.write (" gcc_jit_lvalue *%s =\n"
5309 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n"
5310 " %s); /* gcc_jit_location *loc */\n",
5311 id,
5312 r.get_identifier_as_rvalue (m_rvalue),
5313 r.get_identifier (m_loc));
5314}
5315
35485da9
DM
5316/* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
5317
5318/* Implementation of pure virtual hook recording::memento::replay_into
5319 for recording::get_address_of_lvalue. */
5320
5321void
5322recording::get_address_of_lvalue::replay_into (replayer *r)
5323{
5324 set_playback_obj (
5325 m_lvalue->playback_lvalue ()->
5326 get_address (playback_location (r, m_loc)));
5327}
5328
f6f2b019
DM
5329/* Implementation of pure virtual hook recording::rvalue::visit_children
5330 for recording::get_address_of_lvalue. */
5331
5332void
5333recording::get_address_of_lvalue::visit_children (rvalue_visitor *v)
5334{
5335 v->visit (m_lvalue);
5336}
5337
35485da9
DM
5338/* Implementation of recording::memento::make_debug_string for
5339 getting the address of an lvalue. */
5340
5341recording::string *
5342recording::get_address_of_lvalue::make_debug_string ()
5343{
bd93aa1a 5344 enum precedence prec = get_precedence ();
35485da9
DM
5345 return string::from_printf (m_ctxt,
5346 "&%s",
bd93aa1a 5347 m_lvalue->get_debug_string_parens (prec));
35485da9
DM
5348}
5349
86d0ac88
DM
5350/* Implementation of recording::memento::write_reproducer for
5351 get_address_of_lvalue. */
5352
5353void
5354recording::get_address_of_lvalue::write_reproducer (reproducer &r)
5355{
5356 const char *id = r.make_identifier (this, "address_of");
5357 r.write (" gcc_jit_rvalue *%s =\n"
5358 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n"
5359 " %s); /* gcc_jit_location *loc */\n",
5360 id,
5361 r.get_identifier_as_lvalue (m_lvalue),
5362 r.get_identifier (m_loc));
5363}
5364
35485da9
DM
5365/* The implementation of class gcc::jit::recording::local. */
5366
5367/* Implementation of pure virtual hook recording::memento::replay_into
5368 for recording::local. */
5369
5370void
5371recording::local::replay_into (replayer *r)
5372{
5373 set_playback_obj (
5374 m_func->playback_function ()
5375 ->new_local (playback_location (r, m_loc),
5376 m_type->playback_type (),
5377 playback_string (m_name)));
5378}
5379
5380/* Override the default implementation of
5381 recording::memento::write_to_dump for locals by writing
5382 TYPE NAME;
5383 for use at the top of the function body as if it were a
5384 declaration. */
5385
5386void
5387recording::local::write_to_dump (dump &d)
5388{
5389 if (d.update_locations ())
5390 m_loc = d.make_location ();
5391 d.write(" %s %s;\n",
5392 m_type->get_debug_string (),
5393 get_debug_string ());
5394}
5395
86d0ac88
DM
5396void
5397recording::local::write_reproducer (reproducer &r)
5398{
5399 const char *id = r.make_identifier (this, "local");
5400 r.write (" gcc_jit_lvalue *%s =\n"
5401 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n"
5402 " %s, /* gcc_jit_location *loc */\n"
5403 " %s, /* gcc_jit_type *type */\n"
5404 " %s); /* const char *name */\n",
5405 id,
5406 r.get_identifier (m_func),
5407 r.get_identifier (m_loc),
5408 r.get_identifier_as_type (m_type),
5409 m_name->get_debug_string ());
5410}
5411
35485da9
DM
5412/* The implementation of class gcc::jit::recording::statement. */
5413
5414/* We poison the default implementation of
5415 gcc::jit::recording::statement::get_successor_blocks
5416 since this vfunc must only ever be called on terminator
5417 statements. */
5418
ec5d0088
DM
5419vec <recording::block *>
5420recording::statement::get_successor_blocks () const
35485da9
DM
5421{
5422 /* The base class implementation is for non-terminating statements,
5423 and thus should never be called. */
5424 gcc_unreachable ();
ec5d0088
DM
5425 vec <block *> result;
5426 result.create (0);
5427 return result;
35485da9
DM
5428}
5429
5430/* Extend the default implementation of
5431 recording::memento::write_to_dump for statements by (if requested)
5432 updating the location of the statement to the current location in
5433 the dumpfile. */
5434
5435void
5436recording::statement::write_to_dump (dump &d)
5437{
5438 memento::write_to_dump (d);
5439 if (d.update_locations ())
5440 m_loc = d.make_location ();
5441}
5442
5443/* The implementation of class gcc::jit::recording::eval. */
5444
5445/* Implementation of pure virtual hook recording::memento::replay_into
5446 for recording::eval. */
5447
5448void
5449recording::eval::replay_into (replayer *r)
5450{
5451 playback_block (get_block ())
5452 ->add_eval (playback_location (r),
5453 m_rvalue->playback_rvalue ());
5454}
5455
5456/* Implementation of recording::memento::make_debug_string for
5457 an eval statement. */
5458
5459recording::string *
5460recording::eval::make_debug_string ()
5461{
5462 return string::from_printf (m_ctxt,
5463 "(void)%s;",
5464 m_rvalue->get_debug_string ());
5465}
5466
86d0ac88
DM
5467/* Implementation of recording::memento::write_reproducer for
5468 eval statements. */
5469
5470void
5471recording::eval::write_reproducer (reproducer &r)
5472{
5473 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n"
5474 " %s, /* gcc_jit_location *loc */\n"
5475 " %s); /* gcc_jit_rvalue *rvalue */\n",
5476 r.get_identifier (get_block ()),
5477 r.get_identifier (get_loc ()),
5478 r.get_identifier_as_rvalue (m_rvalue));
5479}
5480
35485da9
DM
5481/* The implementation of class gcc::jit::recording::assignment. */
5482
5483/* Implementation of pure virtual hook recording::memento::replay_into
5484 for recording::assignment. */
5485
5486void
5487recording::assignment::replay_into (replayer *r)
5488{
5489 playback_block (get_block ())
5490 ->add_assignment (playback_location (r),
5491 m_lvalue->playback_lvalue (),
5492 m_rvalue->playback_rvalue ());
5493}
5494
5495/* Implementation of recording::memento::make_debug_string for
5496 an assignment statement. */
5497
5498recording::string *
5499recording::assignment::make_debug_string ()
5500{
5501 return string::from_printf (m_ctxt,
5502 "%s = %s;",
5503 m_lvalue->get_debug_string (),
5504 m_rvalue->get_debug_string ());
5505}
5506
86d0ac88
DM
5507/* Implementation of recording::memento::write_reproducer for
5508 assignment statements. */
5509
5510void
5511recording::assignment::write_reproducer (reproducer &r)
5512{
5513 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n"
5514 " %s, /* gcc_jit_location *loc */\n"
5515 " %s, /* gcc_jit_lvalue *lvalue */\n"
5516 " %s); /* gcc_jit_rvalue *rvalue */\n",
5517 r.get_identifier (get_block ()),
5518 r.get_identifier (get_loc ()),
5519 r.get_identifier_as_lvalue (m_lvalue),
5520 r.get_identifier_as_rvalue (m_rvalue));
5521}
5522
35485da9
DM
5523/* The implementation of class gcc::jit::recording::assignment_op. */
5524
5525/* Implementation of pure virtual hook recording::memento::replay_into
5526 for recording::assignment_op. */
5527
5528void
5529recording::assignment_op::replay_into (replayer *r)
5530{
5531 playback::type *result_type =
5532 m_lvalue->playback_lvalue ()->get_type ();
5533
5534 playback::rvalue *binary_op =
5535 r->new_binary_op (playback_location (r),
5536 m_op,
5537 result_type,
5538 m_lvalue->playback_rvalue (),
5539 m_rvalue->playback_rvalue ());
5540
5541 playback_block (get_block ())
5542 ->add_assignment (playback_location (r),
5543 m_lvalue->playback_lvalue (),
5544 binary_op);
5545}
5546
5547/* Implementation of recording::memento::make_debug_string for
5548 an assignment_op statement. */
5549
5550recording::string *
5551recording::assignment_op::make_debug_string ()
5552{
5553 return string::from_printf (m_ctxt,
5554 "%s %s= %s;",
5555 m_lvalue->get_debug_string (),
5556 binary_op_strings[m_op],
5557 m_rvalue->get_debug_string ());
5558}
5559
86d0ac88
DM
5560/* Implementation of recording::memento::write_reproducer for
5561 assignment_op statements. */
5562
5563void
5564recording::assignment_op::write_reproducer (reproducer &r)
5565{
5566 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n"
5567 " %s, /* gcc_jit_location *loc */\n"
5568 " %s, /* gcc_jit_lvalue *lvalue */\n"
5569 " %s, /* enum gcc_jit_binary_op op */\n"
5570 " %s); /* gcc_jit_rvalue *rvalue */\n",
5571 r.get_identifier (get_block ()),
5572 r.get_identifier (get_loc ()),
5573 r.get_identifier_as_lvalue (m_lvalue),
5574 binary_op_reproducer_strings[m_op],
5575 r.get_identifier_as_rvalue (m_rvalue));
5576}
5577
35485da9
DM
5578/* The implementation of class gcc::jit::recording::comment. */
5579
5580/* Implementation of pure virtual hook recording::memento::replay_into
5581 for recording::comment. */
5582
5583void
5584recording::comment::replay_into (replayer *r)
5585{
5586 playback_block (get_block ())
5587 ->add_comment (playback_location (r),
5588 m_text->c_str ());
5589}
5590
5591/* Implementation of recording::memento::make_debug_string for
5592 a comment "statement". */
5593
5594recording::string *
5595recording::comment::make_debug_string ()
5596{
5597 return string::from_printf (m_ctxt,
5598 "/* %s */",
5599 m_text->c_str ());
5600}
5601
86d0ac88
DM
5602/* Implementation of recording::memento::write_reproducer for
5603 comments. */
5604
5605void
5606recording::comment::write_reproducer (reproducer &r)
5607{
5608 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n"
5609 " %s, /* gcc_jit_location *loc */\n"
5610 " %s); /* const char *text */\n",
5611 r.get_identifier (get_block ()),
5612 r.get_identifier (get_loc ()),
5613 m_text->get_debug_string ());
5614}
5615
35485da9
DM
5616/* The implementation of class gcc::jit::recording::conditional. */
5617
5618/* Implementation of pure virtual hook recording::memento::replay_into
5619 for recording::conditional. */
5620
5621void
5622recording::conditional::replay_into (replayer *r)
5623{
5624 playback_block (get_block ())
5625 ->add_conditional (playback_location (r),
5626 m_boolval->playback_rvalue (),
5627 playback_block (m_on_true),
5628 playback_block (m_on_false));
5629}
5630
5631/* Override the poisoned default implementation of
5632 gcc::jit::recording::statement::get_successor_blocks
5633
5634 A conditional jump has 2 successor blocks. */
5635
ec5d0088
DM
5636vec <recording::block *>
5637recording::conditional::get_successor_blocks () const
35485da9 5638{
ec5d0088
DM
5639 vec <block *> result;
5640 result.create (2);
5641 result.quick_push (m_on_true);
5642 result.quick_push (m_on_false);
5643 return result;
35485da9
DM
5644}
5645
5646/* Implementation of recording::memento::make_debug_string for
5647 a conditional jump statement. */
5648
5649recording::string *
5650recording::conditional::make_debug_string ()
5651{
5652 if (m_on_false)
5653 return string::from_printf (m_ctxt,
5654 "if (%s) goto %s; else goto %s;",
5655 m_boolval->get_debug_string (),
5656 m_on_true->get_debug_string (),
5657 m_on_false->get_debug_string ());
5658 else
5659 return string::from_printf (m_ctxt,
5660 "if (%s) goto %s;",
5661 m_boolval->get_debug_string (),
5662 m_on_true->get_debug_string ());
5663}
5664
86d0ac88
DM
5665/* Implementation of recording::memento::write_reproducer for
5666 conditional statements. */
5667
5668void
5669recording::conditional::write_reproducer (reproducer &r)
5670{
5671 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n"
5672 " %s, /* gcc_jit_location *loc */\n"
5673 " %s, /* gcc_jit_rvalue *boolval */\n"
5674 " %s, /* gcc_jit_block *on_true */\n"
5675 " %s); /* gcc_jit_block *on_false */\n",
5676 r.get_identifier (get_block ()),
5677 r.get_identifier (get_loc ()),
5678 r.get_identifier_as_rvalue (m_boolval),
5679 r.get_identifier (m_on_true),
5680 r.get_identifier (m_on_false));
5681}
5682
35485da9
DM
5683/* The implementation of class gcc::jit::recording::jump. */
5684
5685/* Implementation of pure virtual hook recording::memento::replay_into
5686 for recording::jump. */
5687
5688void
5689recording::jump::replay_into (replayer *r)
5690{
5691 playback_block (get_block ())
5692 ->add_jump (playback_location (r),
5693 m_target->playback_block ());
5694}
5695
5696/* Override the poisoned default implementation of
5697 gcc::jit::recording::statement::get_successor_blocks
5698
5699 An unconditional jump has 1 successor block. */
5700
ec5d0088
DM
5701vec <recording::block *>
5702recording::jump::get_successor_blocks () const
35485da9 5703{
ec5d0088
DM
5704 vec <block *> result;
5705 result.create (1);
5706 result.quick_push (m_target);
5707 return result;
35485da9
DM
5708}
5709
5710/* Implementation of recording::memento::make_debug_string for
5711 a unconditional jump statement. */
5712
5713recording::string *
5714recording::jump::make_debug_string ()
5715{
5716 return string::from_printf (m_ctxt,
5717 "goto %s;",
5718 m_target->get_debug_string ());
5719}
5720
86d0ac88
DM
5721/* Implementation of recording::memento::write_reproducer for
5722 jump statements. */
5723
5724void
5725recording::jump::write_reproducer (reproducer &r)
5726{
5727 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n"
5728 " %s, /* gcc_jit_location *loc */\n"
5729 " %s); /* gcc_jit_block *target */\n",
5730 r.get_identifier (get_block ()),
5731 r.get_identifier (get_loc ()),
5732 r.get_identifier (m_target));
5733}
5734
35485da9
DM
5735/* The implementation of class gcc::jit::recording::return_. */
5736
5737/* Implementation of pure virtual hook recording::memento::replay_into
5738 for recording::return_. */
5739
5740void
5741recording::return_::replay_into (replayer *r)
5742{
5743 playback_block (get_block ())
5744 ->add_return (playback_location (r),
5745 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
5746}
5747
5748/* Override the poisoned default implementation of
5749 gcc::jit::recording::statement::get_successor_blocks
5750
5751 A return statement has no successor block. */
5752
ec5d0088
DM
5753vec <recording::block *>
5754recording::return_::get_successor_blocks () const
35485da9 5755{
ec5d0088
DM
5756 vec <block *> result;
5757 result.create (0);
5758 return result;
35485da9
DM
5759}
5760
5761/* Implementation of recording::memento::make_debug_string for
5762 a return statement (covers both those with and without rvalues). */
5763
5764recording::string *
5765recording::return_::make_debug_string ()
5766{
5767 if (m_rvalue)
5768 return string::from_printf (m_ctxt,
5769 "return %s;",
5770 m_rvalue->get_debug_string ());
5771 else
5772 return string::from_printf (m_ctxt,
5773 "return;");
5774}
5775
86d0ac88
DM
5776/* Implementation of recording::memento::write_reproducer for
5777 return statements. */
5778
5779void
5780recording::return_::write_reproducer (reproducer &r)
5781{
5782 if (m_rvalue)
5783 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n"
5784 " %s, /* gcc_jit_location *loc */\n"
5785 " %s); /* gcc_jit_rvalue *rvalue */\n",
5786 r.get_identifier (get_block ()),
5787 r.get_identifier (get_loc ()),
5788 r.get_identifier_as_rvalue (m_rvalue));
5789 else
5790 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n"
5791 " %s); /* gcc_jit_location *loc */\n",
5792 r.get_identifier (get_block ()),
5793 r.get_identifier (get_loc ()));
5794}
5795
ec5d0088
DM
5796/* The implementation of class gcc::jit::recording::case_. */
5797
5798void
5799recording::case_::write_reproducer (reproducer &r)
5800{
5801 const char *id = r.make_identifier (this, "case");
5802 const char *fmt =
5803 " gcc_jit_case *%s = \n"
5804 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n"
5805 " %s, /* gcc_jit_rvalue *min_value */\n"
5806 " %s, /* gcc_jit_rvalue *max_value */\n"
5807 " %s); /* gcc_jit_block *dest_block */\n";
5808 r.write (fmt,
5809 id,
5810 r.get_identifier (get_context ()),
5811 r.get_identifier_as_rvalue (m_min_value),
5812 r.get_identifier_as_rvalue (m_max_value),
5813 r.get_identifier (m_dest_block));
5814}
5815
5816recording::string *
5817recording::case_::make_debug_string ()
5818{
5819 return string::from_printf (get_context (),
5820 "case %s ... %s: goto %s;",
5821 m_min_value->get_debug_string (),
5822 m_max_value->get_debug_string (),
5823 m_dest_block->get_debug_string ());
5824}
5825
5826/* The implementation of class gcc::jit::recording::switch_. */
5827
5828/* gcc::jit::recording::switch_'s constructor. */
5829
5830recording::switch_::switch_ (block *b,
5831 location *loc,
5832 rvalue *expr,
5833 block *default_block,
5834 int num_cases,
5835 case_ **cases)
5836: statement (b, loc),
5837 m_expr (expr),
5838 m_default_block (default_block)
5839{
5840 m_cases.reserve_exact (num_cases);
5841 for (int i = 0; i< num_cases; i++)
5842 m_cases.quick_push (cases[i]);
5843}
5844
5845/* Implementation of pure virtual hook recording::memento::replay_into
5846 for recording::switch_. */
5847
5848void
5849recording::switch_::replay_into (replayer *r)
5850{
5851 auto_vec <playback::case_> pcases;
5852 int i;
5853 recording::case_ *rcase;
5854 pcases.reserve_exact (m_cases.length ());
5855 FOR_EACH_VEC_ELT (m_cases, i, rcase)
5856 {
5857 playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (),
5858 rcase->get_max_value ()->playback_rvalue (),
5859 rcase->get_dest_block ()->playback_block ());
5860 pcases.safe_push (pcase);
5861 }
5862 playback_block (get_block ())
5863 ->add_switch (playback_location (r),
5864 m_expr->playback_rvalue (),
5865 m_default_block->playback_block (),
5866 &pcases);
5867}
5868
5869/* Override the poisoned default implementation of
5870 gcc::jit::recording::statement::get_successor_blocks
5871
5872 A switch statement has (NUM_CASES + 1) successor blocks. */
5873
5874vec <recording::block *>
5875recording::switch_::get_successor_blocks () const
5876{
5877 vec <block *> result;
5878 result.create (m_cases.length () + 1);
5879 result.quick_push (m_default_block);
5880 int i;
5881 case_ *c;
5882 FOR_EACH_VEC_ELT (m_cases, i, c)
5883 result.quick_push (c->get_dest_block ());
5884 return result;
5885}
5886
5887/* Implementation of recording::memento::make_debug_string for
5888 a switch statement. */
5889
5890recording::string *
5891recording::switch_::make_debug_string ()
5892{
5893 auto_vec <char> cases_str;
5894 int i;
5895 case_ *c;
5896 FOR_EACH_VEC_ELT (m_cases, i, c)
5897 {
5898 size_t len = strlen (c->get_debug_string ());
5899 unsigned idx = cases_str.length ();
5900 cases_str.safe_grow (idx + 1 + len);
5901 cases_str[idx] = ' ';
5902 memcpy (&(cases_str[idx + 1]),
5903 c->get_debug_string (),
5904 len);
5905 }
5906 cases_str.safe_push ('\0');
5907
5908 return string::from_printf (m_ctxt,
5909 "switch (%s) {default: goto %s;%s}",
5910 m_expr->get_debug_string (),
5911 m_default_block->get_debug_string (),
5912 &cases_str[0]);
5913}
5914
5915/* Implementation of recording::memento::write_reproducer for
5916 switch statements. */
5917
5918void
5919recording::switch_::write_reproducer (reproducer &r)
5920{
5921 r.make_identifier (this, "switch");
5922 int i;
5923 case_ *c;
5924 const char *cases_id =
5925 r.make_tmp_identifier ("cases_for", this);
5926 r.write (" gcc_jit_case *%s[%i] = {\n",
5927 cases_id,
5928 m_cases.length ());
5929 FOR_EACH_VEC_ELT (m_cases, i, c)
5930 r.write (" %s,\n", r.get_identifier (c));
5931 r.write (" };\n");
5932 const char *fmt =
5933 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n"
5934 " %s, /* gcc_jit_location *loc */\n"
5935 " %s, /* gcc_jit_rvalue *expr */\n"
5936 " %s, /* gcc_jit_block *default_block */\n"
5937 " %i, /* int num_cases */\n"
5938 " %s); /* gcc_jit_case **cases */\n";
5939 r.write (fmt,
5940 r.get_identifier (get_block ()),
5941 r.get_identifier (get_loc ()),
5942 r.get_identifier_as_rvalue (m_expr),
5943 r.get_identifier (m_default_block),
5944 m_cases.length (),
5945 cases_id);
5946}
5947
35485da9
DM
5948} // namespace gcc::jit
5949
5950} // namespace gcc