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