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