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