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