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