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