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