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