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