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