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