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