comparison gcc/jit/jit-recording.c @ 111:04ced10e8804

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