]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/jit/jit-recording.c
jit: API change to gcc_jit_context_new_global
[thirdparty/gcc.git] / gcc / jit / jit-recording.c
1 /* Internals of libgccjit: classes for recording calls made to the JIT API.
2 Copyright (C) 2013-2015 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
27 #include <pthread.h>
28
29 #include "jit-common.h"
30 #include "jit-builtins.h"
31 #include "jit-logging.h"
32 #include "jit-recording.h"
33 #include "jit-playback.h"
34
35 namespace gcc {
36 namespace jit {
37
38 // class dump
39
40 dump::dump (recording::context &ctxt,
41 const char *filename,
42 bool update_locations)
43 : m_ctxt (ctxt),
44 m_filename (filename),
45 m_update_locations (update_locations),
46 m_line (0),
47 m_column (0)
48 {
49 m_file = fopen (filename, "w");
50 if (!m_file)
51 ctxt.add_error (NULL,
52 "error opening dump file %s for writing: %s",
53 filename,
54 xstrerror (errno));
55 }
56
57 dump::~dump ()
58 {
59 if (m_file)
60 {
61 int err = fclose (m_file);
62 if (err)
63 m_ctxt.add_error (NULL,
64 "error closing dump file %s: %s",
65 m_filename,
66 xstrerror (errno));
67 }
68 }
69
70 /* Write the given message to the dump, using printf-formatting
71 conventions, updating the line/column within the dump.
72
73 Emit an error on the context if a failure occurs. */
74
75 void
76 dump::write (const char *fmt, ...)
77 {
78 va_list ap;
79 char *buf = NULL;
80
81 /* If there was an error opening the file, we've already reported it.
82 Don't attempt further work. */
83 if (!m_file)
84 return;
85
86 va_start (ap, fmt);
87 vasprintf (&buf, fmt, ap);
88 va_end (ap);
89
90 if (!buf)
91 {
92 m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s",
93 m_filename);
94 return;
95 }
96
97 if (fwrite (buf, strlen (buf), 1, m_file) != 1)
98 m_ctxt.add_error (NULL, "error writing to dump file %s",
99 m_filename);
100
101 /* Update line/column: */
102 for (const char *ptr = buf; *ptr; ptr++)
103 {
104 if ('\n' == *ptr)
105 {
106 m_line++;
107 m_column = 0;
108 }
109 else
110 m_column++;
111 }
112
113 free (buf);
114 }
115
116 /* Construct a gcc::jit::recording::location instance for the current
117 location within the dump. */
118
119 recording::location *
120 dump::make_location () const
121 {
122 return m_ctxt.new_location (m_filename, m_line, m_column);
123 }
124
125 /**********************************************************************
126 Recording.
127 **********************************************************************/
128
129 /* Get the playback::location for the given recording::location,
130 handling a NULL input with a NULL output. */
131
132 playback::location *
133 recording::playback_location (replayer *r, recording::location *loc)
134 {
135 if (loc)
136 return loc->playback_location (r);
137 else
138 return NULL;
139 }
140
141 /* Get a const char * for the given recording::string
142 handling a NULL input with a NULL output. */
143
144 const char *
145 recording::playback_string (recording::string *str)
146 {
147 if (str)
148 return str->c_str ();
149 else
150 return NULL;
151 }
152
153 /* Get the playback::block for the given recording::block,
154 handling a NULL input with a NULL output. */
155
156 playback::block *
157 recording::playback_block (recording::block *b)
158 {
159 if (b)
160 return b->playback_block ();
161 else
162 return NULL;
163 }
164
165 /* Methods of cc::jit::recording::context. */
166
167 /* The constructor for gcc::jit::recording::context, used by
168 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */
169
170 recording::context::context (context *parent_ctxt)
171 : log_user (NULL),
172 m_parent_ctxt (parent_ctxt),
173 m_error_count (0),
174 m_first_error_str (NULL),
175 m_owns_first_error_str (false),
176 m_last_error_str (NULL),
177 m_owns_last_error_str (false),
178 m_mementos (),
179 m_compound_types (),
180 m_globals (),
181 m_functions (),
182 m_FILE_type (NULL),
183 m_builtins_manager(NULL)
184 {
185 if (parent_ctxt)
186 {
187 /* Inherit options from parent. */
188 for (unsigned i = 0;
189 i < sizeof (m_str_options) / sizeof (m_str_options[0]);
190 i++)
191 {
192 const char *parent_opt = parent_ctxt->m_str_options[i];
193 m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL;
194 }
195 memcpy (m_int_options,
196 parent_ctxt->m_int_options,
197 sizeof (m_int_options));
198 memcpy (m_bool_options,
199 parent_ctxt->m_bool_options,
200 sizeof (m_bool_options));
201 set_logger (parent_ctxt->get_logger ());
202 }
203 else
204 {
205 memset (m_str_options, 0, sizeof (m_str_options));
206 memset (m_int_options, 0, sizeof (m_int_options));
207 memset (m_bool_options, 0, sizeof (m_bool_options));
208 }
209
210 memset (m_basic_types, 0, sizeof (m_basic_types));
211 }
212
213 /* The destructor for gcc::jit::recording::context, implicitly used by
214 gcc_jit_context_release. */
215
216 recording::context::~context ()
217 {
218 JIT_LOG_SCOPE (get_logger ());
219 int i;
220 memento *m;
221 FOR_EACH_VEC_ELT (m_mementos, i, m)
222 {
223 delete m;
224 }
225
226 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i)
227 free (m_str_options[i]);
228
229 if (m_builtins_manager)
230 delete m_builtins_manager;
231
232 if (m_owns_first_error_str)
233 free (m_first_error_str);
234
235 if (m_owns_last_error_str)
236 if (m_last_error_str != m_first_error_str)
237 free (m_last_error_str);
238 }
239
240 /* Add the given mememto to the list of those tracked by this
241 gcc::jit::recording::context, so that e.g. it can be deleted
242 when this context is released. */
243
244 void
245 recording::context::record (memento *m)
246 {
247 gcc_assert (m);
248
249 m_mementos.safe_push (m);
250 }
251
252 /* Replay this context (and any parents) into the given replayer. */
253
254 void
255 recording::context::replay_into (replayer *r)
256 {
257 JIT_LOG_SCOPE (get_logger ());
258 int i;
259 memento *m;
260
261 /* If we have a parent context, we must replay it. This will
262 recursively walk backwards up the historical tree, then replay things
263 forwards "in historical order", starting with the ultimate parent
264 context, until we reach the "this" context.
265
266 Note that we fully replay the parent, then fully replay the child,
267 which means that inter-context references can only exist from child
268 to parent, not the other way around.
269
270 All of this replaying is suboptimal - it would be better to do the
271 work for the parent context *once*, rather than replaying the parent
272 every time we replay each child. However, fixing this requires deep
273 surgery to lifetime-management: we'd need every context family tree
274 to have its own GC heap, and to initialize the GCC code to use that
275 heap (with a mutex on such a heap). */
276 if (m_parent_ctxt)
277 m_parent_ctxt->replay_into (r);
278
279 if (r->errors_occurred ())
280 return;
281
282 /* Replay this context's saved operations into r. */
283 FOR_EACH_VEC_ELT (m_mementos, i, m)
284 {
285 /* Disabled low-level debugging, here if we need it: print what
286 we're replaying.
287 Note that the calls to get_debug_string might lead to more
288 mementos being created for the strings.
289 This can also be used to exercise the debug_string
290 machinery. */
291 if (0)
292 printf ("context %p replaying (%p): %s\n",
293 (void *)this, (void *)m, m->get_debug_string ());
294
295 m->replay_into (r);
296
297 if (r->errors_occurred ())
298 return;
299 }
300 }
301
302 /* During a playback, we associate objects from the recording with
303 their counterparts during this playback.
304
305 For simplicity, we store this within the recording objects.
306
307 The following method cleans away these associations, to ensure that
308 we never have out-of-date associations lingering on subsequent
309 playbacks (the objects pointed to are GC-managed, but the
310 recording objects don't own refs to them). */
311
312 void
313 recording::context::disassociate_from_playback ()
314 {
315 JIT_LOG_SCOPE (get_logger ());
316 int i;
317 memento *m;
318
319 if (m_parent_ctxt)
320 m_parent_ctxt->disassociate_from_playback ();
321
322 FOR_EACH_VEC_ELT (m_mementos, i, m)
323 {
324 m->set_playback_obj (NULL);
325 }
326 }
327
328 /* Create a recording::string instance and add it to this context's list
329 of mementos.
330
331 This creates a fresh copy of the given 0-terminated buffer. */
332
333 recording::string *
334 recording::context::new_string (const char *text)
335 {
336 if (!text)
337 return NULL;
338
339 recording::string *result = new string (this, text);
340 record (result);
341 return result;
342 }
343
344 /* Create a recording::location instance and add it to this context's
345 list of mementos.
346
347 Implements the post-error-checking part of
348 gcc_jit_context_new_location. */
349
350 recording::location *
351 recording::context::new_location (const char *filename,
352 int line,
353 int column)
354 {
355 recording::location *result =
356 new recording::location (this,
357 new_string (filename),
358 line, column);
359 record (result);
360 return result;
361 }
362
363 /* If we haven't seen this enum value yet, create a recording::type
364 instance and add it to this context's list of mementos.
365
366 If we have seen it before, reuse our cached value, so that repeated
367 calls on the context give the same object.
368
369 If we have a parent context, the cache is within the ultimate
370 ancestor context.
371
372 Implements the post-error-checking part of
373 gcc_jit_context_get_type. */
374
375 recording::type *
376 recording::context::get_type (enum gcc_jit_types kind)
377 {
378 if (!m_basic_types[kind])
379 {
380 if (m_parent_ctxt)
381 m_basic_types[kind] = m_parent_ctxt->get_type (kind);
382 else
383 {
384 recording::type *result = new memento_of_get_type (this, kind);
385 record (result);
386 m_basic_types[kind] = result;
387 }
388 }
389
390 return m_basic_types[kind];
391 }
392
393 /* Get a recording::type instance for the given size and signedness.
394 This is implemented in terms of recording::context::get_type
395 above.
396
397 Implements the post-error-checking part of
398 gcc_jit_context_get_int_type. */
399
400 recording::type *
401 recording::context::get_int_type (int num_bytes, int is_signed)
402 {
403 /* We can't use a switch here since some of the values are macros affected
404 by options; e.g. i386.h has
405 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
406 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros
407 are in bits, rather than bytes.
408 */
409 const int num_bits = num_bytes * 8;
410 if (num_bits == INT_TYPE_SIZE)
411 return get_type (is_signed
412 ? GCC_JIT_TYPE_INT
413 : GCC_JIT_TYPE_UNSIGNED_INT);
414 if (num_bits == CHAR_TYPE_SIZE)
415 return get_type (is_signed
416 ? GCC_JIT_TYPE_SIGNED_CHAR
417 : GCC_JIT_TYPE_UNSIGNED_CHAR);
418 if (num_bits == SHORT_TYPE_SIZE)
419 return get_type (is_signed
420 ? GCC_JIT_TYPE_SHORT
421 : GCC_JIT_TYPE_UNSIGNED_SHORT);
422 if (num_bits == LONG_TYPE_SIZE)
423 return get_type (is_signed
424 ? GCC_JIT_TYPE_LONG
425 : GCC_JIT_TYPE_UNSIGNED_LONG);
426 if (num_bits == LONG_LONG_TYPE_SIZE)
427 return get_type (is_signed
428 ? GCC_JIT_TYPE_LONG_LONG
429 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG);
430
431 /* Some other size, not corresponding to the C int types. */
432 /* To be written: support arbitrary other sizes, sharing by
433 memoizing at the recording::context level? */
434 gcc_unreachable ();
435 }
436
437 /* Create a recording::type instance and add it to this context's list
438 of mementos.
439
440 Implements the post-error-checking part of
441 gcc_jit_context_new_array_type. */
442
443 recording::type *
444 recording::context::new_array_type (recording::location *loc,
445 recording::type *element_type,
446 int num_elements)
447 {
448 if (struct_ *s = element_type->dyn_cast_struct ())
449 if (!s->get_fields ())
450 {
451 add_error (NULL,
452 "cannot create an array of type %s"
453 " until the fields have been set",
454 s->get_name ()->c_str ());
455 return NULL;
456 }
457 recording::type *result =
458 new recording::array_type (this, loc, element_type, num_elements);
459 record (result);
460 return result;
461 }
462
463 /* Create a recording::field instance and add it to this context's list
464 of mementos.
465
466 Implements the post-error-checking part of
467 gcc_jit_context_new_field. */
468
469 recording::field *
470 recording::context::new_field (recording::location *loc,
471 recording::type *type,
472 const char *name)
473 {
474 recording::field *result =
475 new recording::field (this, loc, type, new_string (name));
476 record (result);
477 return result;
478 }
479
480 /* Create a recording::struct_ instance and add it to this context's
481 list of mementos and list of compound types.
482
483 Implements the post-error-checking part of
484 gcc_jit_context_new_struct_type. */
485
486 recording::struct_ *
487 recording::context::new_struct_type (recording::location *loc,
488 const char *name)
489 {
490 recording::struct_ *result = new struct_ (this, loc, new_string (name));
491 record (result);
492 m_compound_types.safe_push (result);
493 return result;
494 }
495
496 /* Create a recording::union_ instance and add it to this context's
497 list of mementos and list of compound types.
498
499 Implements the first post-error-checking part of
500 gcc_jit_context_new_union_type. */
501
502 recording::union_ *
503 recording::context::new_union_type (recording::location *loc,
504 const char *name)
505 {
506 recording::union_ *result = new union_ (this, loc, new_string (name));
507 record (result);
508 m_compound_types.safe_push (result);
509 return result;
510 }
511
512 /* Create a recording::function_type instance and add it to this context's
513 list of mementos.
514
515 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */
516
517 recording::function_type *
518 recording::context::new_function_type (recording::type *return_type,
519 int num_params,
520 recording::type **param_types,
521 int is_variadic)
522 {
523 recording::function_type *fn_type
524 = new function_type (this,
525 return_type,
526 num_params,
527 param_types,
528 is_variadic);
529 record (fn_type);
530 return fn_type;
531 }
532
533 /* Create a recording::type instance and add it to this context's list
534 of mementos.
535
536 Implements the post-error-checking part of
537 gcc_jit_context_new_function_ptr_type. */
538
539 recording::type *
540 recording::context::new_function_ptr_type (recording::location *, /* unused loc */
541 recording::type *return_type,
542 int num_params,
543 recording::type **param_types,
544 int is_variadic)
545 {
546 recording::function_type *fn_type
547 = new_function_type (return_type,
548 num_params,
549 param_types,
550 is_variadic);
551
552 /* Return a pointer-type to the the function type. */
553 return fn_type->get_pointer ();
554 }
555
556 /* Create a recording::param instance and add it to this context's list
557 of mementos.
558
559 Implements the post-error-checking part of
560 gcc_jit_context_new_param. */
561
562 recording::param *
563 recording::context::new_param (recording::location *loc,
564 recording::type *type,
565 const char *name)
566 {
567 recording::param *result = new recording::param (this, loc, type, new_string (name));
568 record (result);
569 return result;
570 }
571
572 /* Create a recording::function instance and add it to this context's list
573 of mementos and list of functions.
574
575 Implements the post-error-checking part of
576 gcc_jit_context_new_function. */
577
578 recording::function *
579 recording::context::new_function (recording::location *loc,
580 enum gcc_jit_function_kind kind,
581 recording::type *return_type,
582 const char *name,
583 int num_params,
584 recording::param **params,
585 int is_variadic,
586 enum built_in_function builtin_id)
587 {
588 recording::function *result =
589 new recording::function (this,
590 loc, kind, return_type,
591 new_string (name),
592 num_params, params, is_variadic,
593 builtin_id);
594 record (result);
595 m_functions.safe_push (result);
596
597 return result;
598 }
599
600 /* Locate the builtins_manager (if any) for this family of contexts,
601 creating it if it doesn't exist already.
602
603 All of the recording contexts in a family share one builtins_manager:
604 if we have a child context, follow the parent links to get the
605 ultimate ancestor context, and look for it/store it there. */
606
607 builtins_manager *
608 recording::context::get_builtins_manager ()
609 {
610 if (m_parent_ctxt)
611 return m_parent_ctxt->get_builtins_manager ();
612
613 if (!m_builtins_manager)
614 m_builtins_manager = new builtins_manager (this);
615
616 return m_builtins_manager;
617 }
618
619 /* Get a recording::function instance, which is lazily-created and added
620 to the context's lists of mementos.
621
622 Implements the post-error-checking part of
623 gcc_jit_context_get_builtin_function. */
624
625 recording::function *
626 recording::context::get_builtin_function (const char *name)
627 {
628 builtins_manager *bm = get_builtins_manager ();
629 return bm->get_builtin_function (name);
630 }
631
632 /* Create a recording::global instance and add it to this context's list
633 of mementos.
634
635 Implements the post-error-checking part of
636 gcc_jit_context_new_global. */
637
638 recording::lvalue *
639 recording::context::new_global (recording::location *loc,
640 enum gcc_jit_global_kind kind,
641 recording::type *type,
642 const char *name)
643 {
644 recording::global *result =
645 new recording::global (this, loc, kind, type, new_string (name));
646 record (result);
647 m_globals.safe_push (result);
648
649 return result;
650 }
651
652 /* Create a recording::memento_of_new_string_literal instance and add it
653 to this context's list of mementos.
654
655 Implements the post-error-checking part of
656 gcc_jit_context_new_string_literal. */
657
658 recording::rvalue *
659 recording::context::new_string_literal (const char *value)
660 {
661 recording::rvalue *result =
662 new memento_of_new_string_literal (this, NULL, new_string (value));
663 record (result);
664 return result;
665 }
666
667 /* Create a recording::unary_op instance and add it to this context's
668 list of mementos.
669
670 Implements the post-error-checking part of
671 gcc_jit_context_new_unary_op. */
672
673 recording::rvalue *
674 recording::context::new_unary_op (recording::location *loc,
675 enum gcc_jit_unary_op op,
676 recording::type *result_type,
677 recording::rvalue *a)
678 {
679 recording::rvalue *result =
680 new unary_op (this, loc, op, result_type, a);
681 record (result);
682 return result;
683 }
684
685 /* Create a recording::binary_op instance and add it to this context's
686 list of mementos.
687
688 Implements the post-error-checking part of
689 gcc_jit_context_new_binary_op. */
690
691 recording::rvalue *
692 recording::context::new_binary_op (recording::location *loc,
693 enum gcc_jit_binary_op op,
694 recording::type *result_type,
695 recording::rvalue *a,
696 recording::rvalue *b)
697 {
698 recording::rvalue *result =
699 new binary_op (this, loc, op, result_type, a, b);
700 record (result);
701 return result;
702 }
703
704 /* Create a recording::comparison instance and add it to this context's
705 list of mementos.
706
707 Implements the post-error-checking part of
708 gcc_jit_context_new_comparison. */
709
710 recording::rvalue *
711 recording::context::new_comparison (recording::location *loc,
712 enum gcc_jit_comparison op,
713 recording::rvalue *a,
714 recording::rvalue *b)
715 {
716 recording::rvalue *result = new comparison (this, loc, op, a, b);
717 record (result);
718 return result;
719 }
720
721 /* Create a recording::cast instance and add it to this context's list
722 of mementos.
723
724 Implements the post-error-checking part of
725 gcc_jit_context_new_cast. */
726
727 recording::rvalue *
728 recording::context::new_cast (recording::location *loc,
729 recording::rvalue *expr,
730 recording::type *type_)
731 {
732 recording::rvalue *result = new cast (this, loc, expr, type_);
733 record (result);
734 return result;
735 }
736
737 /* Create a recording::call instance and add it to this context's list
738 of mementos.
739
740 Implements the post-error-checking part of
741 gcc_jit_context_new_call. */
742
743 recording::rvalue *
744 recording::context::new_call (recording::location *loc,
745 function *func,
746 int numargs , recording::rvalue **args)
747 {
748 recording::rvalue *result = new call (this, loc, func, numargs, args);
749 record (result);
750 return result;
751 }
752
753 /* Create a recording::call_through_ptr instance and add it to this
754 context's list of mementos.
755
756 Implements the post-error-checking part of
757 gcc_jit_context_new_call_through_ptr. */
758
759 recording::rvalue *
760 recording::context::new_call_through_ptr (recording::location *loc,
761 recording::rvalue *fn_ptr,
762 int numargs,
763 recording::rvalue **args)
764 {
765 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args);
766 record (result);
767 return result;
768 }
769
770 /* Create a recording::array_access instance and add it to this context's list
771 of mementos.
772
773 Implements the post-error-checking part of
774 gcc_jit_context_new_array_access. */
775
776 recording::lvalue *
777 recording::context::new_array_access (recording::location *loc,
778 recording::rvalue *ptr,
779 recording::rvalue *index)
780 {
781 recording::lvalue *result = new array_access (this, loc, ptr, index);
782 record (result);
783 return result;
784 }
785
786 /* Set the given string option for this context, or add an error if
787 it's not recognized.
788
789 Implements the post-error-checking part of
790 gcc_jit_context_set_str_option. */
791
792 void
793 recording::context::set_str_option (enum gcc_jit_str_option opt,
794 const char *value)
795 {
796 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS)
797 {
798 add_error (NULL,
799 "unrecognized (enum gcc_jit_str_option) value: %i", opt);
800 return;
801 }
802 free (m_str_options[opt]);
803 m_str_options[opt] = value ? xstrdup (value) : NULL;
804 }
805
806 /* Set the given integer option for this context, or add an error if
807 it's not recognized.
808
809 Implements the post-error-checking part of
810 gcc_jit_context_set_int_option. */
811
812 void
813 recording::context::set_int_option (enum gcc_jit_int_option opt,
814 int value)
815 {
816 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS)
817 {
818 add_error (NULL,
819 "unrecognized (enum gcc_jit_int_option) value: %i", opt);
820 return;
821 }
822 m_int_options[opt] = value;
823 }
824
825 /* Set the given boolean option for this context, or add an error if
826 it's not recognized.
827
828 Implements the post-error-checking part of
829 gcc_jit_context_set_bool_option. */
830
831 void
832 recording::context::set_bool_option (enum gcc_jit_bool_option opt,
833 int value)
834 {
835 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS)
836 {
837 add_error (NULL,
838 "unrecognized (enum gcc_jit_bool_option) value: %i", opt);
839 return;
840 }
841 m_bool_options[opt] = value ? true : false;
842 }
843
844 /* Add the given dumpname/out_ptr pair to this context's list of requested
845 dumps.
846
847 Implements the post-error-checking part of
848 gcc_jit_context_enable_dump. */
849
850 void
851 recording::context::enable_dump (const char *dumpname,
852 char **out_ptr)
853 {
854 requested_dump d;
855 gcc_assert (dumpname);
856 gcc_assert (out_ptr);
857
858 d.m_dumpname = dumpname;
859 d.m_out_ptr = out_ptr;
860 *out_ptr = NULL;
861 m_requested_dumps.safe_push (d);
862 }
863
864 /* Validate this context, and if it passes, compile it within a
865 mutex.
866
867 Implements the post-error-checking part of
868 gcc_jit_context_compile. */
869
870 result *
871 recording::context::compile ()
872 {
873 JIT_LOG_SCOPE (get_logger ());
874
875 validate ();
876
877 if (errors_occurred ())
878 return NULL;
879
880 /* Set up a playback context. */
881 ::gcc::jit::playback::context replayer (this);
882
883 /* Use it. */
884 result *result_obj = replayer.compile ();
885
886 return result_obj;
887 }
888
889 /* Format the given error using printf's conventions, print
890 it to stderr, and add it to the context. */
891
892 void
893 recording::context::add_error (location *loc, const char *fmt, ...)
894 {
895 va_list ap;
896 va_start (ap, fmt);
897 add_error_va (loc, fmt, ap);
898 va_end (ap);
899 }
900
901 /* Format the given error using printf's conventions, print
902 it to stderr, and add it to the context. */
903
904 void
905 recording::context::add_error_va (location *loc, const char *fmt, va_list ap)
906 {
907 char *malloced_msg;
908 const char *errmsg;
909 bool has_ownership;
910
911 JIT_LOG_SCOPE (get_logger ());
912
913 vasprintf (&malloced_msg, fmt, ap);
914 if (malloced_msg)
915 {
916 errmsg = malloced_msg;
917 has_ownership = true;
918 }
919 else
920 {
921 errmsg = "out of memory generating error message";
922 has_ownership = false;
923 }
924 if (get_logger ())
925 get_logger ()->log ("error %i: %s", m_error_count, errmsg);
926
927 const char *ctxt_progname =
928 get_str_option (GCC_JIT_STR_OPTION_PROGNAME);
929 if (!ctxt_progname)
930 ctxt_progname = "libgccjit.so";
931
932 if (loc)
933 fprintf (stderr, "%s: %s: error: %s\n",
934 ctxt_progname,
935 loc->get_debug_string (),
936 errmsg);
937 else
938 fprintf (stderr, "%s: error: %s\n",
939 ctxt_progname,
940 errmsg);
941
942 if (!m_error_count)
943 {
944 m_first_error_str = const_cast <char *> (errmsg);
945 m_owns_first_error_str = has_ownership;
946 }
947
948 if (m_owns_last_error_str)
949 if (m_last_error_str != m_first_error_str)
950 free (m_last_error_str);
951 m_last_error_str = const_cast <char *> (errmsg);
952 m_owns_last_error_str = has_ownership;
953
954 m_error_count++;
955 }
956
957 /* Get the message for the first error that occurred on this context, or
958 NULL if no errors have occurred on it.
959
960 Implements the post-error-checking part of
961 gcc_jit_context_get_first_error. */
962
963 const char *
964 recording::context::get_first_error () const
965 {
966 return m_first_error_str;
967 }
968
969 /* Get the message for the last error that occurred on this context, or
970 NULL if no errors have occurred on it.
971
972 Implements the post-error-checking part of
973 gcc_jit_context_get_last_error. */
974
975 const char *
976 recording::context::get_last_error () const
977 {
978 return m_last_error_str;
979 }
980
981 /* Lazily generate and record a recording::type representing an opaque
982 struct named "FILE".
983
984 For use if client code tries to dereference the result of
985 get_type (GCC_JIT_TYPE_FILE_PTR). */
986
987 recording::type *
988 recording::context::get_opaque_FILE_type ()
989 {
990 if (!m_FILE_type)
991 m_FILE_type = new_struct_type (NULL, "FILE");
992 return m_FILE_type;
993 }
994
995 /* Dump a C-like representation of the given context to the given path.
996 If UPDATE_LOCATIONS is true, update the locations within the
997 context's mementos to point to the dumpfile.
998
999 Implements the post-error-checking part of
1000 gcc_jit_context_dump_to_file. */
1001
1002 void
1003 recording::context::dump_to_file (const char *path, bool update_locations)
1004 {
1005 int i;
1006 dump d (*this, path, update_locations);
1007
1008 /* Forward declaration of structs and unions. */
1009 compound_type *st;
1010 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1011 {
1012 d.write ("%s;\n\n", st->get_debug_string ());
1013 }
1014
1015 /* Content of structs, where set. */
1016 FOR_EACH_VEC_ELT (m_compound_types, i, st)
1017 if (st->get_fields ())
1018 {
1019 st->get_fields ()->write_to_dump (d);
1020 d.write ("\n");
1021 }
1022
1023 /* Globals. */
1024 global *g;
1025 FOR_EACH_VEC_ELT (m_globals, i, g)
1026 {
1027 g->write_to_dump (d);
1028 }
1029 if (!m_globals.is_empty ())
1030 d.write ("\n");
1031
1032 function *fn;
1033 FOR_EACH_VEC_ELT (m_functions, i, fn)
1034 {
1035 fn->write_to_dump (d);
1036 }
1037 }
1038
1039 /* Copy the requested dumps within this context and all ancestors into
1040 OUT. */
1041
1042 void
1043 recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out)
1044 {
1045 if (m_parent_ctxt)
1046 m_parent_ctxt->get_all_requested_dumps (out);
1047
1048 out->reserve (m_requested_dumps.length ());
1049 out->splice (m_requested_dumps);
1050 }
1051
1052 /* This is a pre-compilation check for the context (and any parents).
1053
1054 Detect errors within the context, adding errors if any are found. */
1055
1056 void
1057 recording::context::validate ()
1058 {
1059 JIT_LOG_SCOPE (get_logger ());
1060
1061 if (m_parent_ctxt)
1062 m_parent_ctxt->validate ();
1063
1064 int i;
1065 function *fn;
1066 FOR_EACH_VEC_ELT (m_functions, i, fn)
1067 fn->validate ();
1068 }
1069
1070 /* The implementation of class gcc::jit::recording::memento. */
1071
1072 /* Get a (const char *) debug description of the given memento, by
1073 calling the pure-virtual make_debug_string hook, caching the
1074 result.
1075
1076 It is intended that this should only be called in debugging and
1077 error-handling paths, so this doesn't need to be particularly
1078 optimized. */
1079
1080 const char *
1081 recording::memento::get_debug_string ()
1082 {
1083 if (!m_debug_string)
1084 m_debug_string = make_debug_string ();
1085 return m_debug_string->c_str ();
1086 }
1087
1088 /* Default implementation of recording::memento::write_to_dump, writing
1089 an indented form of the memento's debug string to the dump. */
1090
1091 void
1092 recording::memento::write_to_dump (dump &d)
1093 {
1094 d.write(" %s\n", get_debug_string ());
1095 }
1096
1097 /* The implementation of class gcc::jit::recording::string. */
1098
1099 /* Constructor for gcc::jit::recording::string::string, allocating a
1100 copy of the given text using new char[]. */
1101
1102 recording::string::string (context *ctxt, const char *text)
1103 : memento (ctxt)
1104 {
1105 m_len = strlen (text);
1106 m_buffer = new char[m_len + 1];
1107 strcpy (m_buffer, text);
1108 }
1109
1110 /* Destructor for gcc::jit::recording::string::string. */
1111
1112 recording::string::~string ()
1113 {
1114 delete[] m_buffer;
1115 }
1116
1117 /* Function for making gcc::jit::recording::string instances on a
1118 context via printf-style formatting.
1119
1120 It is intended that this should only be called in debugging and
1121 error-handling paths, so this doesn't need to be particularly
1122 optimized, hence the double-copy of the string is acceptable. */
1123
1124 recording::string *
1125 recording::string::from_printf (context *ctxt, const char *fmt, ...)
1126 {
1127 va_list ap;
1128 char *buf = NULL;
1129 recording::string *result;
1130
1131 va_start (ap, fmt);
1132 vasprintf (&buf, fmt, ap);
1133 va_end (ap);
1134
1135 if (!buf)
1136 {
1137 ctxt->add_error (NULL, "malloc failure");
1138 return NULL;
1139 }
1140
1141 result = ctxt->new_string (buf);
1142 free (buf);
1143 return result;
1144 }
1145
1146 /* Implementation of recording::memento::make_debug_string for strings,
1147 wrapping the given string in quotes and escaping as necessary. */
1148
1149 recording::string *
1150 recording::string::make_debug_string ()
1151 {
1152 /* Hack to avoid infinite recursion into strings when logging all
1153 mementos: don't re-escape strings: */
1154 if (m_buffer[0] == '"')
1155 return this;
1156
1157 /* Wrap in quotes and do escaping etc */
1158
1159 size_t sz = (1 /* opening quote */
1160 + (m_len * 2) /* each char might get escaped */
1161 + 1 /* closing quote */
1162 + 1); /* nil termintator */
1163 char *tmp = new char[sz];
1164 size_t len = 0;
1165
1166 #define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0)
1167 APPEND('"'); /* opening quote */
1168 for (size_t i = 0; i < m_len ; i++)
1169 {
1170 char ch = m_buffer[i];
1171 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"')
1172 APPEND('\\');
1173 APPEND(ch);
1174 }
1175 APPEND('"'); /* closing quote */
1176 #undef APPEND
1177 tmp[len] = '\0'; /* nil termintator */
1178
1179 string *result = m_ctxt->new_string (tmp);
1180
1181 delete[] tmp;
1182 return result;
1183 }
1184
1185 /* The implementation of class gcc::jit::recording::location. */
1186
1187 /* Implementation of recording::memento::replay_into for locations.
1188
1189 Create a new playback::location and store it into the
1190 recording::location's m_playback_obj field. */
1191
1192 void
1193 recording::location::replay_into (replayer *r)
1194 {
1195 m_playback_obj = r->new_location (this,
1196 m_filename->c_str (),
1197 m_line,
1198 m_column);
1199 }
1200
1201 /* Implementation of recording::memento::make_debug_string for locations,
1202 turning them into the usual form:
1203 FILENAME:LINE:COLUMN
1204 like we do when emitting diagnostics. */
1205
1206 recording::string *
1207 recording::location::make_debug_string ()
1208 {
1209 return string::from_printf (m_ctxt,
1210 "%s:%i:%i",
1211 m_filename->c_str (), m_line, m_column);
1212 }
1213
1214 /* The implementation of class gcc::jit::recording::type. */
1215
1216 /* Given a type T, get the type T*.
1217
1218 If this doesn't already exist, generate a new memento_of_get_pointer
1219 instance and add it to this type's context's list of mementos.
1220
1221 Otherwise, use the cached type.
1222
1223 Implements the post-error-checking part of
1224 gcc_jit_type_get_pointer. */
1225
1226 recording::type *
1227 recording::type::get_pointer ()
1228 {
1229 if (!m_pointer_to_this_type)
1230 {
1231 m_pointer_to_this_type = new memento_of_get_pointer (this);
1232 m_ctxt->record (m_pointer_to_this_type);
1233 }
1234 return m_pointer_to_this_type;
1235 }
1236
1237 /* Given a type T, get the type const T.
1238
1239 Implements the post-error-checking part of
1240 gcc_jit_type_get_const. */
1241
1242 recording::type *
1243 recording::type::get_const ()
1244 {
1245 recording::type *result = new memento_of_get_const (this);
1246 m_ctxt->record (result);
1247 return result;
1248 }
1249
1250 /* Given a type T, get the type volatile T.
1251
1252 Implements the post-error-checking part of
1253 gcc_jit_type_get_volatile. */
1254
1255 recording::type *
1256 recording::type::get_volatile ()
1257 {
1258 recording::type *result = new memento_of_get_volatile (this);
1259 m_ctxt->record (result);
1260 return result;
1261 }
1262
1263 /* Implementation of pure virtual hook recording::type::dereference for
1264 recording::memento_of_get_type. */
1265
1266 recording::type *
1267 recording::memento_of_get_type::dereference ()
1268 {
1269 switch (m_kind)
1270 {
1271 default: gcc_unreachable ();
1272
1273 case GCC_JIT_TYPE_VOID:
1274 return NULL;
1275
1276 case GCC_JIT_TYPE_VOID_PTR:
1277 return m_ctxt->get_type (GCC_JIT_TYPE_VOID);
1278
1279 case GCC_JIT_TYPE_BOOL:
1280 case GCC_JIT_TYPE_CHAR:
1281 case GCC_JIT_TYPE_SIGNED_CHAR:
1282 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1283 case GCC_JIT_TYPE_SHORT:
1284 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1285 case GCC_JIT_TYPE_INT:
1286 case GCC_JIT_TYPE_UNSIGNED_INT:
1287 case GCC_JIT_TYPE_LONG:
1288 case GCC_JIT_TYPE_UNSIGNED_LONG:
1289 case GCC_JIT_TYPE_LONG_LONG:
1290 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1291 case GCC_JIT_TYPE_FLOAT:
1292 case GCC_JIT_TYPE_DOUBLE:
1293 case GCC_JIT_TYPE_LONG_DOUBLE:
1294 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1295 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1296 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
1297 /* Not a pointer: */
1298 return NULL;
1299
1300 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1301 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const ();
1302
1303 case GCC_JIT_TYPE_SIZE_T:
1304 /* Not a pointer: */
1305 return NULL;
1306
1307 case GCC_JIT_TYPE_FILE_PTR:
1308 /* Give the client code back an opaque "struct FILE". */
1309 return m_ctxt->get_opaque_FILE_type ();
1310 }
1311 }
1312
1313 /* Implementation of pure virtual hook recording::type::is_int for
1314 recording::memento_of_get_type. */
1315
1316 bool
1317 recording::memento_of_get_type::is_int () const
1318 {
1319 switch (m_kind)
1320 {
1321 default: gcc_unreachable ();
1322
1323 case GCC_JIT_TYPE_VOID:
1324 return false;
1325
1326 case GCC_JIT_TYPE_VOID_PTR:
1327 return false;
1328
1329 case GCC_JIT_TYPE_BOOL:
1330 return false;
1331
1332 case GCC_JIT_TYPE_CHAR:
1333 case GCC_JIT_TYPE_SIGNED_CHAR:
1334 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1335 case GCC_JIT_TYPE_SHORT:
1336 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1337 case GCC_JIT_TYPE_INT:
1338 case GCC_JIT_TYPE_UNSIGNED_INT:
1339 case GCC_JIT_TYPE_LONG:
1340 case GCC_JIT_TYPE_UNSIGNED_LONG:
1341 case GCC_JIT_TYPE_LONG_LONG:
1342 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1343 return true;
1344
1345 case GCC_JIT_TYPE_FLOAT:
1346 case GCC_JIT_TYPE_DOUBLE:
1347 case GCC_JIT_TYPE_LONG_DOUBLE:
1348 return false;
1349
1350 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1351 return false;
1352
1353 case GCC_JIT_TYPE_SIZE_T:
1354 return true;
1355
1356 case GCC_JIT_TYPE_FILE_PTR:
1357 return false;
1358
1359 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1360 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1361 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
1362 return false;
1363 }
1364 }
1365
1366 /* Implementation of pure virtual hook recording::type::is_float for
1367 recording::memento_of_get_type. */
1368
1369 bool
1370 recording::memento_of_get_type::is_float () const
1371 {
1372 switch (m_kind)
1373 {
1374 default: gcc_unreachable ();
1375
1376 case GCC_JIT_TYPE_VOID:
1377 return false;
1378
1379 case GCC_JIT_TYPE_VOID_PTR:
1380 return false;
1381
1382 case GCC_JIT_TYPE_BOOL:
1383 return false;
1384
1385 case GCC_JIT_TYPE_CHAR:
1386 case GCC_JIT_TYPE_SIGNED_CHAR:
1387 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1388 case GCC_JIT_TYPE_SHORT:
1389 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1390 case GCC_JIT_TYPE_INT:
1391 case GCC_JIT_TYPE_UNSIGNED_INT:
1392 case GCC_JIT_TYPE_LONG:
1393 case GCC_JIT_TYPE_UNSIGNED_LONG:
1394 case GCC_JIT_TYPE_LONG_LONG:
1395 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1396 return false;
1397
1398 case GCC_JIT_TYPE_FLOAT:
1399 case GCC_JIT_TYPE_DOUBLE:
1400 case GCC_JIT_TYPE_LONG_DOUBLE:
1401 return true;
1402
1403 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1404 return false;
1405
1406 case GCC_JIT_TYPE_SIZE_T:
1407 return false;
1408
1409 case GCC_JIT_TYPE_FILE_PTR:
1410 return false;
1411
1412 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1413 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1414 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
1415 return true;
1416 }
1417 }
1418
1419 /* Implementation of pure virtual hook recording::type::is_bool for
1420 recording::memento_of_get_type. */
1421
1422 bool
1423 recording::memento_of_get_type::is_bool () const
1424 {
1425 switch (m_kind)
1426 {
1427 default: gcc_unreachable ();
1428
1429 case GCC_JIT_TYPE_VOID:
1430 return false;
1431
1432 case GCC_JIT_TYPE_VOID_PTR:
1433 return false;
1434
1435 case GCC_JIT_TYPE_BOOL:
1436 return true;
1437
1438 case GCC_JIT_TYPE_CHAR:
1439 case GCC_JIT_TYPE_SIGNED_CHAR:
1440 case GCC_JIT_TYPE_UNSIGNED_CHAR:
1441 case GCC_JIT_TYPE_SHORT:
1442 case GCC_JIT_TYPE_UNSIGNED_SHORT:
1443 case GCC_JIT_TYPE_INT:
1444 case GCC_JIT_TYPE_UNSIGNED_INT:
1445 case GCC_JIT_TYPE_LONG:
1446 case GCC_JIT_TYPE_UNSIGNED_LONG:
1447 case GCC_JIT_TYPE_LONG_LONG:
1448 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG:
1449 return false;
1450
1451 case GCC_JIT_TYPE_FLOAT:
1452 case GCC_JIT_TYPE_DOUBLE:
1453 case GCC_JIT_TYPE_LONG_DOUBLE:
1454 return false;
1455
1456 case GCC_JIT_TYPE_CONST_CHAR_PTR:
1457 return false;
1458
1459 case GCC_JIT_TYPE_SIZE_T:
1460 return false;
1461
1462 case GCC_JIT_TYPE_FILE_PTR:
1463 return false;
1464
1465 case GCC_JIT_TYPE_COMPLEX_FLOAT:
1466 case GCC_JIT_TYPE_COMPLEX_DOUBLE:
1467 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE:
1468 return false;
1469 }
1470 }
1471
1472 /* Implementation of pure virtual hook recording::memento::replay_into
1473 for recording::memento_of_get_type. */
1474
1475 void
1476 recording::memento_of_get_type::replay_into (replayer *r)
1477 {
1478 set_playback_obj (r->get_type (m_kind));
1479 }
1480
1481 /* The implementation of class gcc::jit::recording::memento_of_get_type. */
1482
1483 /* Descriptive strings for each of enum gcc_jit_types. */
1484
1485 static const char * const get_type_strings[] = {
1486 "void", /* GCC_JIT_TYPE_VOID */
1487 "void *", /* GCC_JIT_TYPE_VOID_PTR */
1488
1489 "bool", /* GCC_JIT_TYPE_BOOL */
1490
1491 "char", /* GCC_JIT_TYPE_CHAR */
1492 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */
1493 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */
1494
1495 "short", /* GCC_JIT_TYPE_SHORT */
1496 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */
1497
1498 "int", /* GCC_JIT_TYPE_INT */
1499 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */
1500
1501 "long", /* GCC_JIT_TYPE_LONG */
1502 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */
1503
1504 "long long", /* GCC_JIT_TYPE_LONG_LONG */
1505 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */
1506
1507 "float", /* GCC_JIT_TYPE_FLOAT */
1508 "double", /* GCC_JIT_TYPE_DOUBLE */
1509 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */
1510
1511 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */
1512
1513 "size_t", /* GCC_JIT_TYPE_SIZE_T */
1514
1515 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */
1516
1517 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */
1518 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */
1519 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */
1520
1521 };
1522
1523 /* Implementation of recording::memento::make_debug_string for
1524 results of get_type, using a simple table of type names. */
1525
1526 recording::string *
1527 recording::memento_of_get_type::make_debug_string ()
1528 {
1529 return m_ctxt->new_string (get_type_strings[m_kind]);
1530 }
1531
1532 /* The implementation of class gcc::jit::recording::memento_of_get_pointer. */
1533
1534 /* Override of default implementation of
1535 recording::type::accepts_writes_from for get_pointer.
1536
1537 Require a pointer type, and allowing writes to
1538 (const T *) from a (T*), but not the other way around. */
1539
1540 bool
1541 recording::memento_of_get_pointer::accepts_writes_from (type *rtype)
1542 {
1543 /* Must be a pointer type: */
1544 type *rtype_points_to = rtype->is_pointer ();
1545 if (!rtype_points_to)
1546 return false;
1547
1548 /* It's OK to assign to a (const T *) from a (T *). */
1549 return m_other_type->unqualified ()
1550 ->accepts_writes_from (rtype_points_to);
1551 }
1552
1553 /* Implementation of pure virtual hook recording::memento::replay_into
1554 for recording::memento_of_get_pointer. */
1555
1556 void
1557 recording::memento_of_get_pointer::replay_into (replayer *)
1558 {
1559 set_playback_obj (m_other_type->playback_type ()->get_pointer ());
1560 }
1561
1562 /* Implementation of recording::memento::make_debug_string for
1563 results of get_pointer, adding " *" to the underlying type,
1564 with special-casing to handle function pointer types. */
1565
1566 recording::string *
1567 recording::memento_of_get_pointer::make_debug_string ()
1568 {
1569 /* Special-case function pointer types, to put the "*" in parens between
1570 the return type and the params (for one level of dereferencing, at
1571 least). */
1572 if (function_type *fn_type = m_other_type->dyn_cast_function_type ())
1573 return fn_type->make_debug_string_with_ptr ();
1574
1575 return string::from_printf (m_ctxt,
1576 "%s *", m_other_type->get_debug_string ());
1577 }
1578
1579 /* The implementation of class gcc::jit::recording::memento_of_get_const. */
1580
1581 /* Implementation of pure virtual hook recording::memento::replay_into
1582 for recording::memento_of_get_const. */
1583
1584 void
1585 recording::memento_of_get_const::replay_into (replayer *)
1586 {
1587 set_playback_obj (m_other_type->playback_type ()->get_const ());
1588 }
1589
1590 /* Implementation of recording::memento::make_debug_string for
1591 results of get_const, prepending "const ". */
1592
1593 recording::string *
1594 recording::memento_of_get_const::make_debug_string ()
1595 {
1596 return string::from_printf (m_ctxt,
1597 "const %s", m_other_type->get_debug_string ());
1598 }
1599
1600 /* The implementation of class gcc::jit::recording::memento_of_get_volatile. */
1601
1602 /* Implementation of pure virtual hook recording::memento::replay_into
1603 for recording::memento_of_get_volatile. */
1604
1605 void
1606 recording::memento_of_get_volatile::replay_into (replayer *)
1607 {
1608 set_playback_obj (m_other_type->playback_type ()->get_volatile ());
1609 }
1610
1611 /* Implementation of recording::memento::make_debug_string for
1612 results of get_volatile, prepending "volatile ". */
1613
1614 recording::string *
1615 recording::memento_of_get_volatile::make_debug_string ()
1616 {
1617 return string::from_printf (m_ctxt,
1618 "volatile %s", m_other_type->get_debug_string ());
1619 }
1620
1621 /* The implementation of class gcc::jit::recording::array_type */
1622
1623 /* Implementation of pure virtual hook recording::type::dereference for
1624 recording::array_type. */
1625
1626 recording::type *
1627 recording::array_type::dereference ()
1628 {
1629 return m_element_type;
1630 }
1631
1632 /* Implementation of pure virtual hook recording::memento::replay_into
1633 for recording::array_type. */
1634
1635 void
1636 recording::array_type::replay_into (replayer *r)
1637 {
1638 set_playback_obj (r->new_array_type (playback_location (r, m_loc),
1639 m_element_type->playback_type (),
1640 m_num_elements));
1641 }
1642
1643 /* Implementation of recording::memento::make_debug_string for
1644 results of new_array_type. */
1645
1646 recording::string *
1647 recording::array_type::make_debug_string ()
1648 {
1649 return string::from_printf (m_ctxt,
1650 "%s[%d]",
1651 m_element_type->get_debug_string (),
1652 m_num_elements);
1653 }
1654
1655 /* The implementation of class gcc::jit::recording::function_type */
1656
1657 /* Constructor for gcc::jit::recording::function_type. */
1658
1659 recording::function_type::function_type (context *ctxt,
1660 type *return_type,
1661 int num_params,
1662 type **param_types,
1663 int is_variadic)
1664 : type (ctxt),
1665 m_return_type (return_type),
1666 m_param_types (),
1667 m_is_variadic (is_variadic)
1668 {
1669 for (int i = 0; i< num_params; i++)
1670 m_param_types.safe_push (param_types[i]);
1671 }
1672
1673 /* Implementation of pure virtual hook recording::type::dereference for
1674 recording::function_type. */
1675
1676 recording::type *
1677 recording::function_type::dereference ()
1678 {
1679 return NULL;
1680 }
1681
1682 /* Implementation of pure virtual hook recording::memento::replay_into
1683 for recording::function_type. */
1684
1685 void
1686 recording::function_type::replay_into (replayer *r)
1687 {
1688 /* Convert m_param_types to a vec of playback type. */
1689 auto_vec <playback::type *> param_types;
1690 int i;
1691 recording::type *type;
1692 param_types.create (m_param_types.length ());
1693 FOR_EACH_VEC_ELT (m_param_types, i, type)
1694 param_types.safe_push (type->playback_type ());
1695
1696 set_playback_obj (r->new_function_type (m_return_type->playback_type (),
1697 &param_types,
1698 m_is_variadic));
1699 }
1700
1701 /* Special-casing for make_debug_string for get_pointer results for
1702 handling (one level) of pointers to functions. */
1703
1704 recording::string *
1705 recording::function_type::make_debug_string_with_ptr ()
1706 {
1707 return make_debug_string_with ("(*) ");
1708 }
1709
1710 /* Implementation of recording::memento::make_debug_string for
1711 results of new_function_type. */
1712
1713 recording::string *
1714 recording::function_type::make_debug_string ()
1715 {
1716 return make_debug_string_with ("");
1717 }
1718
1719 /* Build a debug string representation of the form:
1720
1721 RESULT_TYPE INSERT (PARAM_TYPES)
1722
1723 for use when handling 0 and 1 level of indirection to this
1724 function type. */
1725
1726 recording::string *
1727 recording::function_type::make_debug_string_with (const char *insert)
1728 {
1729 /* First, build a buffer for the arguments. */
1730 /* Calculate length of said buffer. */
1731 size_t sz = 1; /* nil terminator */
1732 for (unsigned i = 0; i< m_param_types.length (); i++)
1733 {
1734 sz += strlen (m_param_types[i]->get_debug_string ());
1735 sz += 2; /* ", " separator */
1736 }
1737 if (m_is_variadic)
1738 sz += 5; /* ", ..." separator and ellipsis */
1739
1740 /* Now allocate and populate the buffer. */
1741 char *argbuf = new char[sz];
1742 size_t len = 0;
1743
1744 for (unsigned i = 0; i< m_param_types.length (); i++)
1745 {
1746 strcpy (argbuf + len, m_param_types[i]->get_debug_string ());
1747 len += strlen (m_param_types[i]->get_debug_string ());
1748 if (i + 1 < m_param_types.length ())
1749 {
1750 strcpy (argbuf + len, ", ");
1751 len += 2;
1752 }
1753 }
1754 if (m_is_variadic)
1755 {
1756 if (m_param_types.length ())
1757 {
1758 strcpy (argbuf + len, ", ");
1759 len += 2;
1760 }
1761 strcpy (argbuf + len, "...");
1762 len += 3;
1763 }
1764 argbuf[len] = '\0';
1765
1766 /* ...and use it to get the string for the call as a whole. */
1767 string *result = string::from_printf (m_ctxt,
1768 "%s %s(%s)",
1769 m_return_type->get_debug_string (),
1770 insert,
1771 argbuf);
1772
1773 delete[] argbuf;
1774
1775 return result;
1776 }
1777
1778 /* The implementation of class gcc::jit::recording::field. */
1779
1780 /* Implementation of pure virtual hook recording::memento::replay_into
1781 for recording::field. */
1782
1783 void
1784 recording::field::replay_into (replayer *r)
1785 {
1786 set_playback_obj (r->new_field (playback_location (r, m_loc),
1787 m_type->playback_type (),
1788 playback_string (m_name)));
1789 }
1790
1791 /* Override the default implementation of
1792 recording::memento::write_to_dump. Dump each field
1793 by dumping a line of the form:
1794 TYPE NAME;
1795 so that we can build up a struct/union field-byfield. */
1796
1797 void
1798 recording::field::write_to_dump (dump &d)
1799 {
1800 d.write (" %s %s;\n",
1801 m_type->get_debug_string (),
1802 m_name->c_str ());
1803 }
1804
1805 /* Implementation of recording::memento::make_debug_string for
1806 results of new_field. */
1807
1808 recording::string *
1809 recording::field::make_debug_string ()
1810 {
1811 return m_name;
1812 }
1813
1814 /* The implementation of class gcc::jit::recording::compound_type */
1815
1816 /* The constructor for gcc::jit::recording::compound_type. */
1817
1818 recording::compound_type::compound_type (context *ctxt,
1819 location *loc,
1820 string *name)
1821 : type (ctxt),
1822 m_loc (loc),
1823 m_name (name),
1824 m_fields (NULL)
1825 {
1826 }
1827
1828 /* Set the fields of a compound type.
1829
1830 Implements the post-error-checking part of
1831 gcc_jit_struct_set_fields, and is also used by
1832 gcc_jit_context_new_union_type. */
1833
1834 void
1835 recording::compound_type::set_fields (location *loc,
1836 int num_fields,
1837 field **field_array)
1838 {
1839 m_loc = loc;
1840 gcc_assert (NULL == m_fields);
1841
1842 m_fields = new fields (this, num_fields, field_array);
1843 m_ctxt->record (m_fields);
1844 }
1845
1846 /* Implementation of pure virtual hook recording::type::dereference for
1847 recording::compound_type. */
1848
1849 recording::type *
1850 recording::compound_type::dereference ()
1851 {
1852 return NULL; /* not a pointer */
1853 }
1854
1855 /* The implementation of class gcc::jit::recording::struct_. */
1856
1857 /* The constructor for gcc::jit::recording::struct_. */
1858
1859 recording::struct_::struct_ (context *ctxt,
1860 location *loc,
1861 string *name)
1862 : compound_type (ctxt, loc, name)
1863 {
1864 }
1865
1866 /* Implementation of pure virtual hook recording::memento::replay_into
1867 for recording::struct_. */
1868
1869 void
1870 recording::struct_::replay_into (replayer *r)
1871 {
1872 set_playback_obj (
1873 r->new_compound_type (playback_location (r, get_loc ()),
1874 get_name ()->c_str (),
1875 true /* is_struct */));
1876 }
1877
1878 /* Implementation of recording::memento::make_debug_string for
1879 structs. */
1880
1881 recording::string *
1882 recording::struct_::make_debug_string ()
1883 {
1884 return string::from_printf (m_ctxt,
1885 "struct %s", get_name ()->c_str ());
1886 }
1887
1888 /* The implementation of class gcc::jit::recording::union_. */
1889
1890 /* The constructor for gcc::jit::recording::union_. */
1891
1892 recording::union_::union_ (context *ctxt,
1893 location *loc,
1894 string *name)
1895 : compound_type (ctxt, loc, name)
1896 {
1897 }
1898
1899 /* Implementation of pure virtual hook recording::memento::replay_into
1900 for recording::union_. */
1901
1902 void
1903 recording::union_::replay_into (replayer *r)
1904 {
1905 set_playback_obj (
1906 r->new_compound_type (playback_location (r, get_loc ()),
1907 get_name ()->c_str (),
1908 false /* is_struct */));
1909 }
1910
1911 /* Implementation of recording::memento::make_debug_string for
1912 unions. */
1913
1914 recording::string *
1915 recording::union_::make_debug_string ()
1916 {
1917 return string::from_printf (m_ctxt,
1918 "union %s", get_name ()->c_str ());
1919 }
1920
1921 /* The implementation of class gcc::jit::recording::fields. */
1922
1923 /* The constructor for gcc::jit::recording::fields. */
1924
1925 recording::fields::fields (compound_type *struct_or_union,
1926 int num_fields,
1927 field **fields)
1928 : memento (struct_or_union->m_ctxt),
1929 m_struct_or_union (struct_or_union),
1930 m_fields ()
1931 {
1932 for (int i = 0; i < num_fields; i++)
1933 {
1934 gcc_assert (fields[i]->get_container () == NULL);
1935 fields[i]->set_container (m_struct_or_union);
1936 m_fields.safe_push (fields[i]);
1937 }
1938 }
1939
1940 /* Implementation of pure virtual hook recording::memento::replay_into
1941 for recording::fields. */
1942
1943 void
1944 recording::fields::replay_into (replayer *)
1945 {
1946 auto_vec<playback::field *> playback_fields;
1947 playback_fields.create (m_fields.length ());
1948 for (unsigned i = 0; i < m_fields.length (); i++)
1949 playback_fields.safe_push (m_fields[i]->playback_field ());
1950 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields);
1951 }
1952
1953 /* Override the default implementation of
1954 recording::memento::write_to_dump by writing a union/struct
1955 declaration of this form:
1956
1957 struct/union NAME {
1958 TYPE_1 NAME_1;
1959 TYPE_2 NAME_2;
1960 ....
1961 TYPE_N NAME_N;
1962 };
1963
1964 to the dump. */
1965
1966 void
1967 recording::fields::write_to_dump (dump &d)
1968 {
1969 int i;
1970 field *f;
1971
1972 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ());
1973 FOR_EACH_VEC_ELT (m_fields, i, f)
1974 f->write_to_dump (d);
1975 d.write ("};\n");
1976 }
1977
1978 /* Implementation of recording::memento::make_debug_string for
1979 field tables. */
1980
1981 recording::string *
1982 recording::fields::make_debug_string ()
1983 {
1984 return string::from_printf (m_ctxt,
1985 "fields");
1986 }
1987
1988 /* The implementation of class gcc::jit::recording::rvalue. */
1989
1990 /* Create a recording::access_field_rvalue instance and add it to
1991 the rvalue's context's list of mementos.
1992
1993 Implements the post-error-checking part of
1994 gcc_jit_rvalue_access_field. */
1995
1996 recording::rvalue *
1997 recording::rvalue::access_field (recording::location *loc,
1998 field *field)
1999 {
2000 recording::rvalue *result =
2001 new access_field_rvalue (m_ctxt, loc, this, field);
2002 m_ctxt->record (result);
2003 return result;
2004 }
2005
2006 /* Create a recording::dereference_field_rvalue instance and add it to
2007 the rvalue's context's list of mementos.
2008
2009 Implements the post-error-checking part of
2010 gcc_jit_rvalue_dereference_field. */
2011
2012 recording::lvalue *
2013 recording::rvalue::dereference_field (recording::location *loc,
2014 field *field)
2015 {
2016 recording::lvalue *result =
2017 new dereference_field_rvalue (m_ctxt, loc, this, field);
2018 m_ctxt->record (result);
2019 return result;
2020 }
2021
2022 /* Create a recording::dereference_rvalue instance and add it to the
2023 rvalue's context's list of mementos.
2024
2025 Implements the post-error-checking part of
2026 gcc_jit_rvalue_dereference. */
2027
2028 recording::lvalue *
2029 recording::rvalue::dereference (recording::location *loc)
2030 {
2031 recording::lvalue *result =
2032 new dereference_rvalue (m_ctxt, loc, this);
2033 m_ctxt->record (result);
2034 return result;
2035 }
2036
2037 /* The implementation of class gcc::jit::recording::lvalue. */
2038
2039 /* Create a recording::new_access_field_of_lvalue instance and add it to
2040 the lvalue's context's list of mementos.
2041
2042 Implements the post-error-checking part of
2043 gcc_jit_lvalue_access_field. */
2044
2045 recording::lvalue *
2046 recording::lvalue::access_field (recording::location *loc,
2047 field *field)
2048 {
2049 recording::lvalue *result =
2050 new access_field_of_lvalue (m_ctxt, loc, this, field);
2051 m_ctxt->record (result);
2052 return result;
2053 }
2054
2055 /* Create a recording::get_address_of_lvalue instance and add it to
2056 the lvalue's context's list of mementos.
2057
2058 Implements the post-error-checking part of
2059 gcc_jit_lvalue_get_address. */
2060
2061 recording::rvalue *
2062 recording::lvalue::get_address (recording::location *loc)
2063 {
2064 recording::rvalue *result =
2065 new get_address_of_lvalue (m_ctxt, loc, this);
2066 m_ctxt->record (result);
2067 return result;
2068 }
2069
2070 /* The implementation of class gcc::jit::recording::param. */
2071
2072 /* Implementation of pure virtual hook recording::memento::replay_into
2073 for recording::param. */
2074
2075 void
2076 recording::param::replay_into (replayer *r)
2077 {
2078 set_playback_obj (r->new_param (playback_location (r, m_loc),
2079 m_type->playback_type (),
2080 m_name->c_str ()));
2081 }
2082
2083
2084 /* The implementation of class gcc::jit::recording::function. */
2085
2086 /* gcc::jit::recording::function's constructor. */
2087
2088 recording::function::function (context *ctxt,
2089 recording::location *loc,
2090 enum gcc_jit_function_kind kind,
2091 type *return_type,
2092 recording::string *name,
2093 int num_params,
2094 recording::param **params,
2095 int is_variadic,
2096 enum built_in_function builtin_id)
2097 : memento (ctxt),
2098 m_loc (loc),
2099 m_kind (kind),
2100 m_return_type (return_type),
2101 m_name (name),
2102 m_params (),
2103 m_is_variadic (is_variadic),
2104 m_builtin_id (builtin_id),
2105 m_locals (),
2106 m_blocks ()
2107 {
2108 for (int i = 0; i< num_params; i++)
2109 m_params.safe_push (params[i]);
2110 }
2111
2112 /* Implementation of pure virtual hook recording::memento::replay_into
2113 for recording::function. */
2114
2115 void
2116 recording::function::replay_into (replayer *r)
2117 {
2118 /* Convert m_params to a vec of playback param. */
2119 auto_vec <playback::param *> params;
2120 int i;
2121 recording::param *param;
2122 params.create (m_params.length ());
2123 FOR_EACH_VEC_ELT (m_params, i, param)
2124 params.safe_push (param->playback_param ());
2125
2126 set_playback_obj (r->new_function (playback_location (r, m_loc),
2127 m_kind,
2128 m_return_type->playback_type (),
2129 m_name->c_str (),
2130 &params,
2131 m_is_variadic,
2132 m_builtin_id));
2133 }
2134
2135 /* Create a recording::local instance and add it to
2136 the functions's context's list of mementos, and to the function's
2137 list of locals.
2138
2139 Implements the post-error-checking part of
2140 gcc_jit_function_new_local. */
2141
2142 recording::lvalue *
2143 recording::function::new_local (recording::location *loc,
2144 type *type,
2145 const char *name)
2146 {
2147 local *result = new local (this, loc, type, new_string (name));
2148 m_ctxt->record (result);
2149 m_locals.safe_push (result);
2150 return result;
2151 }
2152
2153 /* Create a recording::block instance and add it to
2154 the functions's context's list of mementos, and to the function's
2155 list of blocks.
2156
2157 Implements the post-error-checking part of
2158 gcc_jit_function_new_block. */
2159
2160 recording::block*
2161 recording::function::new_block (const char *name)
2162 {
2163 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED);
2164
2165 recording::block *result =
2166 new recording::block (this, m_blocks.length (), new_string (name));
2167 m_ctxt->record (result);
2168 m_blocks.safe_push (result);
2169 return result;
2170 }
2171
2172 /* Override the default implementation of
2173 recording::memento::write_to_dump by dumping a C-like
2174 representation of the function; either like a prototype
2175 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for
2176 all other kinds of function. */
2177
2178 void
2179 recording::function::write_to_dump (dump &d)
2180 {
2181 switch (m_kind)
2182 {
2183 default: gcc_unreachable ();
2184 case GCC_JIT_FUNCTION_EXPORTED:
2185 case GCC_JIT_FUNCTION_IMPORTED:
2186 d.write ("extern ");
2187 break;
2188 case GCC_JIT_FUNCTION_INTERNAL:
2189 d.write ("static ");
2190 break;
2191 case GCC_JIT_FUNCTION_ALWAYS_INLINE:
2192 d.write ("static inline ");
2193 break;
2194 }
2195 d.write ("%s\n", m_return_type->get_debug_string ());
2196
2197 if (d.update_locations ())
2198 m_loc = d.make_location ();
2199
2200 d.write ("%s (", get_debug_string ());
2201
2202 int i;
2203 recording::param *param;
2204 FOR_EACH_VEC_ELT (m_params, i, param)
2205 {
2206 if (i > 0)
2207 d.write (", ");
2208 d.write ("%s %s",
2209 param->get_type ()->get_debug_string (),
2210 param->get_debug_string ());
2211 }
2212 d.write (")");
2213 if (m_kind == GCC_JIT_FUNCTION_IMPORTED)
2214 {
2215 d.write ("; /* (imported) */\n\n");
2216 }
2217 else
2218 {
2219 int i;
2220 local *var = NULL;
2221 block *b;
2222 d.write ("\n{\n");
2223
2224 /* Write locals: */
2225 FOR_EACH_VEC_ELT (m_locals, i, var)
2226 var->write_to_dump (d);
2227 if (m_locals.length ())
2228 d.write ("\n");
2229
2230 /* Write each block: */
2231 FOR_EACH_VEC_ELT (m_blocks, i, b)
2232 {
2233 if (i > 0)
2234 d.write ("\n");
2235 b->write_to_dump (d);
2236 }
2237
2238 d.write ("}\n\n");
2239 }
2240 }
2241
2242 /* Pre-compilation validation of a function, for those things we can't
2243 check until the context is (supposedly) fully-populated. */
2244
2245 void
2246 recording::function::validate ()
2247 {
2248 /* Complain about empty functions with non-void return type. */
2249 if (m_kind != GCC_JIT_FUNCTION_IMPORTED
2250 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID))
2251 if (0 == m_blocks.length ())
2252 m_ctxt->add_error (m_loc,
2253 "function %s returns non-void (type: %s)"
2254 " but has no blocks",
2255 get_debug_string (),
2256 m_return_type->get_debug_string ());
2257
2258 /* Check that all blocks are terminated. */
2259 int num_invalid_blocks = 0;
2260 {
2261 int i;
2262 block *b;
2263
2264 FOR_EACH_VEC_ELT (m_blocks, i, b)
2265 if (!b->validate ())
2266 num_invalid_blocks++;
2267 }
2268
2269 /* Check that all blocks are reachable. */
2270 if (m_blocks.length () > 0 && 0 == num_invalid_blocks)
2271 {
2272 /* Iteratively walk the graph of blocks, marking their "m_is_reachable"
2273 flag, starting at the initial block. */
2274 auto_vec<block *> worklist (m_blocks.length ());
2275 worklist.safe_push (m_blocks[0]);
2276 while (worklist.length () > 0)
2277 {
2278 block *b = worklist.pop ();
2279 b->m_is_reachable = true;
2280
2281 /* Add successor blocks that aren't yet marked to the worklist. */
2282 /* We checked that each block has a terminating statement above . */
2283 block *next1, *next2;
2284 int n = b->get_successor_blocks (&next1, &next2);
2285 switch (n)
2286 {
2287 default:
2288 gcc_unreachable ();
2289 case 2:
2290 if (!next2->m_is_reachable)
2291 worklist.safe_push (next2);
2292 /* fallthrough */
2293 case 1:
2294 if (!next1->m_is_reachable)
2295 worklist.safe_push (next1);
2296 break;
2297 case 0:
2298 break;
2299 }
2300 }
2301
2302 /* Now complain about any blocks that haven't been marked. */
2303 {
2304 int i;
2305 block *b;
2306 FOR_EACH_VEC_ELT (m_blocks, i, b)
2307 if (!b->m_is_reachable)
2308 m_ctxt->add_error (b->get_loc (),
2309 "unreachable block: %s",
2310 b->get_debug_string ());
2311 }
2312 }
2313 }
2314
2315 /* Implements the post-error-checking part of
2316 gcc_jit_function_dump_to_dot. */
2317
2318 void
2319 recording::function::dump_to_dot (const char *path)
2320 {
2321 FILE *fp = fopen (path, "w");
2322 if (!fp)
2323 return;
2324
2325 pretty_printer the_pp;
2326 the_pp.buffer->stream = fp;
2327
2328 pretty_printer *pp = &the_pp;
2329
2330 pp_printf (pp,
2331 "digraph %s {\n", get_debug_string ());
2332
2333 /* Blocks: */
2334 {
2335 int i;
2336 block *b;
2337 FOR_EACH_VEC_ELT (m_blocks, i, b)
2338 b->dump_to_dot (pp);
2339 }
2340
2341 /* Edges: */
2342 {
2343 int i;
2344 block *b;
2345 FOR_EACH_VEC_ELT (m_blocks, i, b)
2346 b->dump_edges_to_dot (pp);
2347 }
2348
2349 pp_printf (pp, "}\n");
2350 pp_flush (pp);
2351 fclose (fp);
2352 }
2353
2354 /* Implementation of recording::memento::make_debug_string for
2355 functions. */
2356
2357 recording::string *
2358 recording::function::make_debug_string ()
2359 {
2360 return m_name;
2361 }
2362
2363 /* The implementation of class gcc::jit::recording::block. */
2364
2365 /* Create a recording::eval instance and add it to
2366 the block's context's list of mementos, and to the block's
2367 list of statements.
2368
2369 Implements the post-error-checking part of
2370 gcc_jit_block_add_eval. */
2371
2372 void
2373 recording::block::add_eval (recording::location *loc,
2374 recording::rvalue *rvalue)
2375 {
2376 statement *result = new eval (this, loc, rvalue);
2377 m_ctxt->record (result);
2378 m_statements.safe_push (result);
2379 }
2380
2381 /* Create a recording::assignment instance and add it to
2382 the block's context's list of mementos, and to the block's
2383 list of statements.
2384
2385 Implements the post-error-checking part of
2386 gcc_jit_block_add_assignment. */
2387
2388 void
2389 recording::block::add_assignment (recording::location *loc,
2390 recording::lvalue *lvalue,
2391 recording::rvalue *rvalue)
2392 {
2393 statement *result = new assignment (this, loc, lvalue, rvalue);
2394 m_ctxt->record (result);
2395 m_statements.safe_push (result);
2396 }
2397
2398 /* Create a recording::assignment_op instance and add it to
2399 the block's context's list of mementos, and to the block's
2400 list of statements.
2401
2402 Implements the post-error-checking part of
2403 gcc_jit_block_add_assignment_op. */
2404
2405 void
2406 recording::block::add_assignment_op (recording::location *loc,
2407 recording::lvalue *lvalue,
2408 enum gcc_jit_binary_op op,
2409 recording::rvalue *rvalue)
2410 {
2411 statement *result = new assignment_op (this, loc, lvalue, op, rvalue);
2412 m_ctxt->record (result);
2413 m_statements.safe_push (result);
2414 }
2415
2416 /* Create a recording::comment instance and add it to
2417 the block's context's list of mementos, and to the block's
2418 list of statements.
2419
2420 Implements the post-error-checking part of
2421 gcc_jit_block_add_comment. */
2422
2423 void
2424 recording::block::add_comment (recording::location *loc,
2425 const char *text)
2426 {
2427 statement *result = new comment (this, loc, new_string (text));
2428 m_ctxt->record (result);
2429 m_statements.safe_push (result);
2430 }
2431
2432 /* Create a recording::end_with_conditional instance and add it to
2433 the block's context's list of mementos, and to the block's
2434 list of statements.
2435
2436 Implements the post-error-checking part of
2437 gcc_jit_block_end_with_conditional. */
2438
2439 void
2440 recording::block::end_with_conditional (recording::location *loc,
2441 recording::rvalue *boolval,
2442 recording::block *on_true,
2443 recording::block *on_false)
2444 {
2445 statement *result = new conditional (this, loc, boolval, on_true, on_false);
2446 m_ctxt->record (result);
2447 m_statements.safe_push (result);
2448 m_has_been_terminated = true;
2449 }
2450
2451 /* Create a recording::end_with_jump instance and add it to
2452 the block's context's list of mementos, and to the block's
2453 list of statements.
2454
2455 Implements the post-error-checking part of
2456 gcc_jit_block_end_with_jump. */
2457
2458 void
2459 recording::block::end_with_jump (recording::location *loc,
2460 recording::block *target)
2461 {
2462 statement *result = new jump (this, loc, target);
2463 m_ctxt->record (result);
2464 m_statements.safe_push (result);
2465 m_has_been_terminated = true;
2466 }
2467
2468 /* Create a recording::end_with_return instance and add it to
2469 the block's context's list of mementos, and to the block's
2470 list of statements.
2471
2472 Implements the post-error-checking parts of
2473 gcc_jit_block_end_with_return and
2474 gcc_jit_block_end_with_void_return. */
2475
2476 void
2477 recording::block::end_with_return (recording::location *loc,
2478 recording::rvalue *rvalue)
2479 {
2480 /* This is used by both gcc_jit_function_add_return and
2481 gcc_jit_function_add_void_return; rvalue will be non-NULL for
2482 the former and NULL for the latter. */
2483 statement *result = new return_ (this, loc, rvalue);
2484 m_ctxt->record (result);
2485 m_statements.safe_push (result);
2486 m_has_been_terminated = true;
2487 }
2488
2489 /* Override the default implementation of
2490 recording::memento::write_to_dump for blocks by writing
2491 an unindented block name as a label, followed by the indented
2492 statements:
2493
2494 BLOCK_NAME:
2495 STATEMENT_1;
2496 STATEMENT_2;
2497 ...
2498 STATEMENT_N; */
2499
2500 void
2501 recording::block::write_to_dump (dump &d)
2502 {
2503 d.write ("%s:\n", get_debug_string ());
2504
2505 int i;
2506 statement *s;
2507 FOR_EACH_VEC_ELT (m_statements, i, s)
2508 s->write_to_dump (d);
2509 }
2510
2511 /* Validate a block by ensuring that it has been terminated. */
2512
2513 bool
2514 recording::block::validate ()
2515 {
2516 if (!has_been_terminated ())
2517 {
2518 statement *stmt = get_last_statement ();
2519 location *loc = stmt ? stmt->get_loc () : NULL;
2520 m_func->get_context ()->add_error (loc,
2521 "unterminated block in %s: %s",
2522 m_func->get_debug_string (),
2523 get_debug_string ());
2524 return false;
2525 }
2526
2527 return true;
2528 }
2529
2530 /* Get the source-location of a block by using that of the first
2531 statement within it, if any. */
2532
2533 recording::location *
2534 recording::block::get_loc () const
2535 {
2536 recording::statement *stmt = get_first_statement ();
2537 if (stmt)
2538 return stmt->get_loc ();
2539 else
2540 return NULL;
2541 }
2542
2543 /* Get the first statement within a block, if any. */
2544
2545 recording::statement *
2546 recording::block::get_first_statement () const
2547 {
2548 if (m_statements.length ())
2549 return m_statements[0];
2550 else
2551 return NULL;
2552 }
2553
2554 /* Get the last statement within a block, if any. */
2555
2556 recording::statement *
2557 recording::block::get_last_statement () const
2558 {
2559 if (m_statements.length ())
2560 return m_statements[m_statements.length () - 1];
2561 else
2562 return NULL;
2563 }
2564
2565 /* Assuming that this block has been terminated, get the number of
2566 successor blocks, which will be 0, 1 or 2, for return, unconditional
2567 jump, and conditional jump respectively.
2568 NEXT1 and NEXT2 must be non-NULL. The first successor block (if any)
2569 is written to NEXT1, and the second (if any) to NEXT2.
2570
2571 Used when validating functions, and when dumping dot representations
2572 of them. */
2573
2574 int
2575 recording::block::get_successor_blocks (block **next1, block **next2) const
2576 {
2577 gcc_assert (m_has_been_terminated);
2578 gcc_assert (next1);
2579 gcc_assert (next2);
2580 statement *last_statement = get_last_statement ();
2581 gcc_assert (last_statement);
2582 return last_statement->get_successor_blocks (next1, next2);
2583 }
2584
2585 /* Implementation of pure virtual hook recording::memento::replay_into
2586 for recording::block. */
2587
2588 void
2589 recording::block::replay_into (replayer *)
2590 {
2591 set_playback_obj (m_func->playback_function ()
2592 ->new_block (playback_string (m_name)));
2593 }
2594
2595 /* Implementation of recording::memento::make_debug_string for
2596 blocks. */
2597
2598 recording::string *
2599 recording::block::make_debug_string ()
2600 {
2601 if (m_name)
2602 return m_name;
2603 else
2604 return string::from_printf (m_ctxt,
2605 "<UNNAMED BLOCK %p>",
2606 (void *)this);
2607 }
2608
2609 /* Dump a block in graphviz form into PP, capturing the block name (if
2610 any) and the statements. */
2611
2612 void
2613 recording::block::dump_to_dot (pretty_printer *pp)
2614 {
2615 pp_printf (pp,
2616 ("\tblock_%d "
2617 "[shape=record,style=filled,fillcolor=white,label=\"{"),
2618 m_index);
2619 pp_write_text_to_stream (pp);
2620 if (m_name)
2621 {
2622 pp_string (pp, m_name->c_str ());
2623 pp_string (pp, ":");
2624 pp_newline (pp);
2625 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
2626 }
2627
2628 int i;
2629 statement *s;
2630 FOR_EACH_VEC_ELT (m_statements, i, s)
2631 {
2632 pp_string (pp, s->get_debug_string ());
2633 pp_newline (pp);
2634 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/);
2635 }
2636
2637 pp_printf (pp,
2638 "}\"];\n\n");
2639 pp_flush (pp);
2640 }
2641
2642 /* Dump the out-edges of the block in graphviz form into PP. */
2643
2644 void
2645 recording::block::dump_edges_to_dot (pretty_printer *pp)
2646 {
2647 block *next[2];
2648 int num_succs = get_successor_blocks (&next[0], &next[1]);
2649 for (int i = 0; i < num_succs; i++)
2650 pp_printf (pp,
2651 "\tblock_%d:s -> block_%d:n;\n",
2652 m_index, next[i]->m_index);
2653 }
2654
2655 /* The implementation of class gcc::jit::recording::global. */
2656
2657 /* Implementation of pure virtual hook recording::memento::replay_into
2658 for recording::global. */
2659
2660 void
2661 recording::global::replay_into (replayer *r)
2662 {
2663 set_playback_obj (r->new_global (playback_location (r, m_loc),
2664 m_kind,
2665 m_type->playback_type (),
2666 playback_string (m_name)));
2667 }
2668
2669 /* Override the default implementation of
2670 recording::memento::write_to_dump for globals.
2671 This will be of the form:
2672
2673 GCC_JIT_GLOBAL_EXPORTED:
2674 "TYPE NAME;"
2675 e.g. "int foo;"
2676
2677 GCC_JIT_GLOBAL_INTERNAL:
2678 "static TYPE NAME;"
2679 e.g. "static int foo;"
2680
2681 GCC_JIT_GLOBAL_IMPORTED:
2682 "extern TYPE NAME;"
2683 e.g. "extern int foo;"
2684
2685 These are written to the top of the dump by
2686 recording::context::dump_to_file. */
2687
2688 void
2689 recording::global::write_to_dump (dump &d)
2690 {
2691 if (d.update_locations ())
2692 m_loc = d.make_location ();
2693
2694 switch (m_kind)
2695 {
2696 default:
2697 gcc_unreachable ();
2698
2699 case GCC_JIT_GLOBAL_EXPORTED:
2700 break;
2701
2702 case GCC_JIT_GLOBAL_INTERNAL:
2703 d.write ("static ");
2704 break;
2705
2706 case GCC_JIT_GLOBAL_IMPORTED:
2707 d.write ("extern ");
2708 break;
2709 }
2710 d.write ("%s %s;\n",
2711 m_type->get_debug_string (),
2712 get_debug_string ());
2713 }
2714
2715 /* The implementation of the various const-handling classes:
2716 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
2717
2718 /* Explicit specialization of the various mementos we're interested in. */
2719 template class recording::memento_of_new_rvalue_from_const <int>;
2720 template class recording::memento_of_new_rvalue_from_const <long>;
2721 template class recording::memento_of_new_rvalue_from_const <double>;
2722 template class recording::memento_of_new_rvalue_from_const <void *>;
2723
2724 /* Implementation of the pure virtual hook recording::memento::replay_into
2725 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */
2726
2727 template <typename HOST_TYPE>
2728 void
2729 recording::
2730 memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r)
2731 {
2732 set_playback_obj
2733 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (),
2734 m_value));
2735 }
2736
2737 /* The make_debug_string method varies between the various
2738 memento_of_new_rvalue_from_const <HOST_TYPE> classes, so we explicitly
2739 write specializations of it.
2740
2741 I (dmalcolm) find the code to be clearer if the "recording" vs "playback"
2742 namespaces are written out explicitly, which is why most of this file
2743 doesn't abbreviate things by entering the "recording" namespace.
2744
2745 However, these specializations are required to be in the same namespace
2746 as the template, hence we now have to enter the gcc::jit::recording
2747 namespace. */
2748
2749 namespace recording
2750 {
2751
2752 /* The make_debug_string specialization for <int>, which renders it as
2753 (TARGET_TYPE)LITERAL
2754 e.g.
2755 "(int)42". */
2756
2757 template <>
2758 string *
2759 memento_of_new_rvalue_from_const <int>::make_debug_string ()
2760 {
2761 return string::from_printf (m_ctxt,
2762 "(%s)%i",
2763 m_type->get_debug_string (),
2764 m_value);
2765 }
2766
2767 /* The make_debug_string specialization for <long>, rendering it as
2768 (TARGET_TYPE)LITERAL
2769 e.g.
2770 "(long)42". */
2771
2772 template <>
2773 string *
2774 memento_of_new_rvalue_from_const <long>::make_debug_string ()
2775 {
2776 return string::from_printf (m_ctxt,
2777 "(%s)%li",
2778 m_type->get_debug_string (),
2779 m_value);
2780 }
2781
2782 /* The make_debug_string specialization for <double>, rendering it as
2783 (TARGET_TYPE)LITERAL
2784 e.g.
2785 "(float)42.0". */
2786
2787 template <>
2788 string *
2789 memento_of_new_rvalue_from_const <double>::make_debug_string ()
2790 {
2791 return string::from_printf (m_ctxt,
2792 "(%s)%f",
2793 m_type->get_debug_string (),
2794 m_value);
2795 }
2796
2797 /* The make_debug_string specialization for <void *>, rendering it as
2798 (TARGET_TYPE)HEX
2799 e.g.
2800 "(int *)0xdeadbeef"
2801
2802 Zero is rendered as NULL e.g.
2803 "(int *)NULL". */
2804
2805 template <>
2806 string *
2807 memento_of_new_rvalue_from_const <void *>::make_debug_string ()
2808 {
2809 if (m_value != NULL)
2810 return string::from_printf (m_ctxt,
2811 "(%s)%p",
2812 m_type->get_debug_string (), m_value);
2813 else
2814 return string::from_printf (m_ctxt,
2815 "(%s)NULL",
2816 m_type->get_debug_string ());
2817 }
2818
2819 /* We're done specializing make_debug_string, so we can exit the
2820 gcc::jit::recording namespace. */
2821
2822 } // namespace recording
2823
2824 /* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */
2825
2826 /* Implementation of pure virtual hook recording::memento::replay_into
2827 for recording::memento_of_new_string_literal. */
2828
2829 void
2830 recording::memento_of_new_string_literal::replay_into (replayer *r)
2831 {
2832 set_playback_obj (r->new_string_literal (m_value->c_str ()));
2833 }
2834
2835 /* Implementation of recording::memento::make_debug_string for
2836 string literals. */
2837
2838 recording::string *
2839 recording::memento_of_new_string_literal::make_debug_string ()
2840 {
2841 return string::from_printf (m_ctxt,
2842 m_value->get_debug_string ());
2843 }
2844
2845 /* The implementation of class gcc::jit::recording::unary_op. */
2846
2847 /* Implementation of pure virtual hook recording::memento::replay_into
2848 for recording::unary_op. */
2849
2850 void
2851 recording::unary_op::replay_into (replayer *r)
2852 {
2853 set_playback_obj (r->new_unary_op (playback_location (r, m_loc),
2854 m_op,
2855 get_type ()->playback_type (),
2856 m_a->playback_rvalue ()));
2857 }
2858
2859 /* Implementation of recording::memento::make_debug_string for
2860 unary ops. */
2861
2862 static const char * const unary_op_strings[] = {
2863 "-", /* GCC_JIT_UNARY_OP_MINUS */
2864 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */
2865 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */
2866 "abs ", /* GCC_JIT_UNARY_OP_ABS */
2867 };
2868
2869 recording::string *
2870 recording::unary_op::make_debug_string ()
2871 {
2872 return string::from_printf (m_ctxt,
2873 "%s(%s)",
2874 unary_op_strings[m_op],
2875 m_a->get_debug_string ());
2876 }
2877
2878 /* The implementation of class gcc::jit::recording::binary_op. */
2879
2880 /* Implementation of pure virtual hook recording::memento::replay_into
2881 for recording::binary_op. */
2882
2883 void
2884 recording::binary_op::replay_into (replayer *r)
2885 {
2886 set_playback_obj (r->new_binary_op (playback_location (r, m_loc),
2887 m_op,
2888 get_type ()->playback_type (),
2889 m_a->playback_rvalue (),
2890 m_b->playback_rvalue ()));
2891 }
2892
2893 /* Implementation of recording::memento::make_debug_string for
2894 binary ops. */
2895
2896 static const char * const binary_op_strings[] = {
2897 "+", /* GCC_JIT_BINARY_OP_PLUS */
2898 "-", /* GCC_JIT_BINARY_OP_MINUS */
2899 "*", /* GCC_JIT_BINARY_OP_MULT */
2900 "/", /* GCC_JIT_BINARY_OP_DIVIDE */
2901 "%", /* GCC_JIT_BINARY_OP_MODULO */
2902 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */
2903 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */
2904 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */
2905 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */
2906 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */
2907 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */
2908 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */
2909 };
2910
2911 recording::string *
2912 recording::binary_op::make_debug_string ()
2913 {
2914 return string::from_printf (m_ctxt,
2915 "%s %s %s",
2916 m_a->get_debug_string (),
2917 binary_op_strings[m_op],
2918 m_b->get_debug_string ());
2919 }
2920
2921 /* The implementation of class gcc::jit::recording::comparison. */
2922
2923 /* Implementation of recording::memento::make_debug_string for
2924 comparisons. */
2925
2926 static const char * const comparison_strings[] =
2927 {
2928 "==", /* GCC_JIT_COMPARISON_EQ */
2929 "!=", /* GCC_JIT_COMPARISON_NE */
2930 "<", /* GCC_JIT_COMPARISON_LT */
2931 "<=", /* GCC_JIT_COMPARISON_LE */
2932 ">", /* GCC_JIT_COMPARISON_GT */
2933 ">=", /* GCC_JIT_COMPARISON_GE */
2934 };
2935
2936 recording::string *
2937 recording::comparison::make_debug_string ()
2938 {
2939 return string::from_printf (m_ctxt,
2940 "%s %s %s",
2941 m_a->get_debug_string (),
2942 comparison_strings[m_op],
2943 m_b->get_debug_string ());
2944 }
2945
2946 /* Implementation of pure virtual hook recording::memento::replay_into
2947 for recording::comparison. */
2948
2949 void
2950 recording::comparison::replay_into (replayer *r)
2951 {
2952 set_playback_obj (r->new_comparison (playback_location (r, m_loc),
2953 m_op,
2954 m_a->playback_rvalue (),
2955 m_b->playback_rvalue ()));
2956 }
2957
2958 /* Implementation of pure virtual hook recording::memento::replay_into
2959 for recording::cast. */
2960
2961 void
2962 recording::cast::replay_into (replayer *r)
2963 {
2964 set_playback_obj (r->new_cast (playback_location (r, m_loc),
2965 m_rvalue->playback_rvalue (),
2966 get_type ()->playback_type ()));
2967 }
2968
2969 /* Implementation of recording::memento::make_debug_string for
2970 casts. */
2971
2972 recording::string *
2973 recording::cast::make_debug_string ()
2974 {
2975 return string::from_printf (m_ctxt,
2976 "(%s)%s",
2977 get_type ()->get_debug_string (),
2978 m_rvalue->get_debug_string ());
2979 }
2980
2981 /* The implementation of class gcc::jit::recording::call. */
2982
2983 /* The constructor for gcc::jit::recording::call. */
2984
2985 recording::call::call (recording::context *ctxt,
2986 recording::location *loc,
2987 recording::function *func,
2988 int numargs,
2989 rvalue **args)
2990 : rvalue (ctxt, loc, func->get_return_type ()),
2991 m_func (func),
2992 m_args ()
2993 {
2994 for (int i = 0; i< numargs; i++)
2995 m_args.safe_push (args[i]);
2996 }
2997
2998 /* Implementation of pure virtual hook recording::memento::replay_into
2999 for recording::call. */
3000
3001 void
3002 recording::call::replay_into (replayer *r)
3003 {
3004 auto_vec<playback::rvalue *> playback_args;
3005 playback_args.create (m_args.length ());
3006 for (unsigned i = 0; i< m_args.length (); i++)
3007 playback_args.safe_push (m_args[i]->playback_rvalue ());
3008
3009 set_playback_obj (r->new_call (playback_location (r, m_loc),
3010 m_func->playback_function (),
3011 &playback_args));
3012 }
3013
3014 /* Implementation of recording::memento::make_debug_string for
3015 function calls. */
3016
3017 recording::string *
3018 recording::call::make_debug_string ()
3019 {
3020 /* First, build a buffer for the arguments. */
3021 /* Calculate length of said buffer. */
3022 size_t sz = 1; /* nil terminator */
3023 for (unsigned i = 0; i< m_args.length (); i++)
3024 {
3025 sz += strlen (m_args[i]->get_debug_string ());
3026 sz += 2; /* ", " separator */
3027 }
3028
3029 /* Now allocate and populate the buffer. */
3030 char *argbuf = new char[sz];
3031 size_t len = 0;
3032
3033 for (unsigned i = 0; i< m_args.length (); i++)
3034 {
3035 strcpy (argbuf + len, m_args[i]->get_debug_string ());
3036 len += strlen (m_args[i]->get_debug_string ());
3037 if (i + 1 < m_args.length ())
3038 {
3039 strcpy (argbuf + len, ", ");
3040 len += 2;
3041 }
3042 }
3043 argbuf[len] = '\0';
3044
3045 /* ...and use it to get the string for the call as a whole. */
3046 string *result = string::from_printf (m_ctxt,
3047 "%s (%s)",
3048 m_func->get_debug_string (),
3049 argbuf);
3050
3051 delete[] argbuf;
3052
3053 return result;
3054 }
3055
3056 /* The implementation of class gcc::jit::recording::call_through_ptr. */
3057
3058 /* The constructor for recording::call_through_ptr. */
3059
3060 recording::call_through_ptr::call_through_ptr (recording::context *ctxt,
3061 recording::location *loc,
3062 recording::rvalue *fn_ptr,
3063 int numargs,
3064 rvalue **args)
3065 : rvalue (ctxt, loc,
3066 fn_ptr->get_type ()->dereference ()
3067 ->as_a_function_type ()->get_return_type ()),
3068 m_fn_ptr (fn_ptr),
3069 m_args ()
3070 {
3071 for (int i = 0; i< numargs; i++)
3072 m_args.safe_push (args[i]);
3073 }
3074
3075 /* Implementation of pure virtual hook recording::memento::replay_into
3076 for recording::call_through_ptr. */
3077
3078 void
3079 recording::call_through_ptr::replay_into (replayer *r)
3080 {
3081 auto_vec<playback::rvalue *> playback_args;
3082 playback_args.create (m_args.length ());
3083 for (unsigned i = 0; i< m_args.length (); i++)
3084 playback_args.safe_push (m_args[i]->playback_rvalue ());
3085
3086 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc),
3087 m_fn_ptr->playback_rvalue (),
3088 &playback_args));
3089 }
3090
3091 /* Implementation of recording::memento::make_debug_string for
3092 calls through function ptrs. */
3093
3094 recording::string *
3095 recording::call_through_ptr::make_debug_string ()
3096 {
3097 /* First, build a buffer for the arguments. */
3098 /* Calculate length of said buffer. */
3099 size_t sz = 1; /* nil terminator */
3100 for (unsigned i = 0; i< m_args.length (); i++)
3101 {
3102 sz += strlen (m_args[i]->get_debug_string ());
3103 sz += 2; /* ", " separator */
3104 }
3105
3106 /* Now allocate and populate the buffer. */
3107 char *argbuf = new char[sz];
3108 size_t len = 0;
3109
3110 for (unsigned i = 0; i< m_args.length (); i++)
3111 {
3112 strcpy (argbuf + len, m_args[i]->get_debug_string ());
3113 len += strlen (m_args[i]->get_debug_string ());
3114 if (i + 1 < m_args.length ())
3115 {
3116 strcpy (argbuf + len, ", ");
3117 len += 2;
3118 }
3119 }
3120 argbuf[len] = '\0';
3121
3122 /* ...and use it to get the string for the call as a whole. */
3123 string *result = string::from_printf (m_ctxt,
3124 "%s (%s)",
3125 m_fn_ptr->get_debug_string (),
3126 argbuf);
3127
3128 delete[] argbuf;
3129
3130 return result;
3131 }
3132
3133 /* The implementation of class gcc::jit::recording::array_access. */
3134
3135 /* Implementation of pure virtual hook recording::memento::replay_into
3136 for recording::array_access. */
3137
3138 void
3139 recording::array_access::replay_into (replayer *r)
3140 {
3141 set_playback_obj (
3142 r->new_array_access (playback_location (r, m_loc),
3143 m_ptr->playback_rvalue (),
3144 m_index->playback_rvalue ()));
3145 }
3146
3147 /* Implementation of recording::memento::make_debug_string for
3148 array accesses. */
3149
3150 recording::string *
3151 recording::array_access::make_debug_string ()
3152 {
3153 return string::from_printf (m_ctxt,
3154 "%s[%s]",
3155 m_ptr->get_debug_string (),
3156 m_index->get_debug_string ());
3157 }
3158
3159 /* The implementation of class gcc::jit::recording::access_field_of_lvalue. */
3160
3161 /* Implementation of pure virtual hook recording::memento::replay_into
3162 for recording::access_field_of_lvalue. */
3163
3164 void
3165 recording::access_field_of_lvalue::replay_into (replayer *r)
3166 {
3167 set_playback_obj (
3168 m_lvalue->playback_lvalue ()
3169 ->access_field (playback_location (r, m_loc),
3170 m_field->playback_field ()));
3171
3172 }
3173
3174 /* Implementation of recording::memento::make_debug_string for
3175 accessing a field of an lvalue. */
3176
3177 recording::string *
3178 recording::access_field_of_lvalue::make_debug_string ()
3179 {
3180 return string::from_printf (m_ctxt,
3181 "%s.%s",
3182 m_lvalue->get_debug_string (),
3183 m_field->get_debug_string ());
3184 }
3185
3186 /* The implementation of class gcc::jit::recording::access_field_rvalue. */
3187
3188 /* Implementation of pure virtual hook recording::memento::replay_into
3189 for recording::access_field_rvalue. */
3190
3191 void
3192 recording::access_field_rvalue::replay_into (replayer *r)
3193 {
3194 set_playback_obj (
3195 m_rvalue->playback_rvalue ()
3196 ->access_field (playback_location (r, m_loc),
3197 m_field->playback_field ()));
3198 }
3199
3200 /* Implementation of recording::memento::make_debug_string for
3201 accessing a field of an rvalue. */
3202
3203 recording::string *
3204 recording::access_field_rvalue::make_debug_string ()
3205 {
3206 return string::from_printf (m_ctxt,
3207 "%s.%s",
3208 m_rvalue->get_debug_string (),
3209 m_field->get_debug_string ());
3210 }
3211
3212 /* The implementation of class
3213 gcc::jit::recording::dereference_field_rvalue. */
3214
3215 /* Implementation of pure virtual hook recording::memento::replay_into
3216 for recording::dereference_field_rvalue. */
3217
3218 void
3219 recording::dereference_field_rvalue::replay_into (replayer *r)
3220 {
3221 set_playback_obj (
3222 m_rvalue->playback_rvalue ()->
3223 dereference_field (playback_location (r, m_loc),
3224 m_field->playback_field ()));
3225 }
3226
3227 /* Implementation of recording::memento::make_debug_string for
3228 dereferencing a field of an rvalue. */
3229
3230 recording::string *
3231 recording::dereference_field_rvalue::make_debug_string ()
3232 {
3233 return string::from_printf (m_ctxt,
3234 "%s->%s",
3235 m_rvalue->get_debug_string (),
3236 m_field->get_debug_string ());
3237 }
3238
3239 /* The implementation of class gcc::jit::recording::dereference_rvalue. */
3240
3241 /* Implementation of pure virtual hook recording::memento::replay_into
3242 for recording::dereference_rvalue. */
3243
3244 void
3245 recording::dereference_rvalue::replay_into (replayer *r)
3246 {
3247 set_playback_obj (
3248 m_rvalue->playback_rvalue ()->
3249 dereference (playback_location (r, m_loc)));
3250 }
3251
3252 /* Implementation of recording::memento::make_debug_string for
3253 dereferencing an rvalue. */
3254
3255 recording::string *
3256 recording::dereference_rvalue::make_debug_string ()
3257 {
3258 return string::from_printf (m_ctxt,
3259 "*%s",
3260 m_rvalue->get_debug_string ());
3261 }
3262
3263 /* The implementation of class gcc::jit::recording::get_address_of_lvalue. */
3264
3265 /* Implementation of pure virtual hook recording::memento::replay_into
3266 for recording::get_address_of_lvalue. */
3267
3268 void
3269 recording::get_address_of_lvalue::replay_into (replayer *r)
3270 {
3271 set_playback_obj (
3272 m_lvalue->playback_lvalue ()->
3273 get_address (playback_location (r, m_loc)));
3274 }
3275
3276 /* Implementation of recording::memento::make_debug_string for
3277 getting the address of an lvalue. */
3278
3279 recording::string *
3280 recording::get_address_of_lvalue::make_debug_string ()
3281 {
3282 return string::from_printf (m_ctxt,
3283 "&%s",
3284 m_lvalue->get_debug_string ());
3285 }
3286
3287 /* The implementation of class gcc::jit::recording::local. */
3288
3289 /* Implementation of pure virtual hook recording::memento::replay_into
3290 for recording::local. */
3291
3292 void
3293 recording::local::replay_into (replayer *r)
3294 {
3295 set_playback_obj (
3296 m_func->playback_function ()
3297 ->new_local (playback_location (r, m_loc),
3298 m_type->playback_type (),
3299 playback_string (m_name)));
3300 }
3301
3302 /* Override the default implementation of
3303 recording::memento::write_to_dump for locals by writing
3304 TYPE NAME;
3305 for use at the top of the function body as if it were a
3306 declaration. */
3307
3308 void
3309 recording::local::write_to_dump (dump &d)
3310 {
3311 if (d.update_locations ())
3312 m_loc = d.make_location ();
3313 d.write(" %s %s;\n",
3314 m_type->get_debug_string (),
3315 get_debug_string ());
3316 }
3317
3318 /* The implementation of class gcc::jit::recording::statement. */
3319
3320 /* We poison the default implementation of
3321 gcc::jit::recording::statement::get_successor_blocks
3322 since this vfunc must only ever be called on terminator
3323 statements. */
3324
3325 int
3326 recording::statement::get_successor_blocks (block **/*out_next1*/,
3327 block **/*out_next2*/) const
3328 {
3329 /* The base class implementation is for non-terminating statements,
3330 and thus should never be called. */
3331 gcc_unreachable ();
3332 return 0;
3333 }
3334
3335 /* Extend the default implementation of
3336 recording::memento::write_to_dump for statements by (if requested)
3337 updating the location of the statement to the current location in
3338 the dumpfile. */
3339
3340 void
3341 recording::statement::write_to_dump (dump &d)
3342 {
3343 memento::write_to_dump (d);
3344 if (d.update_locations ())
3345 m_loc = d.make_location ();
3346 }
3347
3348 /* The implementation of class gcc::jit::recording::eval. */
3349
3350 /* Implementation of pure virtual hook recording::memento::replay_into
3351 for recording::eval. */
3352
3353 void
3354 recording::eval::replay_into (replayer *r)
3355 {
3356 playback_block (get_block ())
3357 ->add_eval (playback_location (r),
3358 m_rvalue->playback_rvalue ());
3359 }
3360
3361 /* Implementation of recording::memento::make_debug_string for
3362 an eval statement. */
3363
3364 recording::string *
3365 recording::eval::make_debug_string ()
3366 {
3367 return string::from_printf (m_ctxt,
3368 "(void)%s;",
3369 m_rvalue->get_debug_string ());
3370 }
3371
3372 /* The implementation of class gcc::jit::recording::assignment. */
3373
3374 /* Implementation of pure virtual hook recording::memento::replay_into
3375 for recording::assignment. */
3376
3377 void
3378 recording::assignment::replay_into (replayer *r)
3379 {
3380 playback_block (get_block ())
3381 ->add_assignment (playback_location (r),
3382 m_lvalue->playback_lvalue (),
3383 m_rvalue->playback_rvalue ());
3384 }
3385
3386 /* Implementation of recording::memento::make_debug_string for
3387 an assignment statement. */
3388
3389 recording::string *
3390 recording::assignment::make_debug_string ()
3391 {
3392 return string::from_printf (m_ctxt,
3393 "%s = %s;",
3394 m_lvalue->get_debug_string (),
3395 m_rvalue->get_debug_string ());
3396 }
3397
3398 /* The implementation of class gcc::jit::recording::assignment_op. */
3399
3400 /* Implementation of pure virtual hook recording::memento::replay_into
3401 for recording::assignment_op. */
3402
3403 void
3404 recording::assignment_op::replay_into (replayer *r)
3405 {
3406 playback::type *result_type =
3407 m_lvalue->playback_lvalue ()->get_type ();
3408
3409 playback::rvalue *binary_op =
3410 r->new_binary_op (playback_location (r),
3411 m_op,
3412 result_type,
3413 m_lvalue->playback_rvalue (),
3414 m_rvalue->playback_rvalue ());
3415
3416 playback_block (get_block ())
3417 ->add_assignment (playback_location (r),
3418 m_lvalue->playback_lvalue (),
3419 binary_op);
3420 }
3421
3422 /* Implementation of recording::memento::make_debug_string for
3423 an assignment_op statement. */
3424
3425 recording::string *
3426 recording::assignment_op::make_debug_string ()
3427 {
3428 return string::from_printf (m_ctxt,
3429 "%s %s= %s;",
3430 m_lvalue->get_debug_string (),
3431 binary_op_strings[m_op],
3432 m_rvalue->get_debug_string ());
3433 }
3434
3435 /* The implementation of class gcc::jit::recording::comment. */
3436
3437 /* Implementation of pure virtual hook recording::memento::replay_into
3438 for recording::comment. */
3439
3440 void
3441 recording::comment::replay_into (replayer *r)
3442 {
3443 playback_block (get_block ())
3444 ->add_comment (playback_location (r),
3445 m_text->c_str ());
3446 }
3447
3448 /* Implementation of recording::memento::make_debug_string for
3449 a comment "statement". */
3450
3451 recording::string *
3452 recording::comment::make_debug_string ()
3453 {
3454 return string::from_printf (m_ctxt,
3455 "/* %s */",
3456 m_text->c_str ());
3457 }
3458
3459 /* The implementation of class gcc::jit::recording::conditional. */
3460
3461 /* Implementation of pure virtual hook recording::memento::replay_into
3462 for recording::conditional. */
3463
3464 void
3465 recording::conditional::replay_into (replayer *r)
3466 {
3467 playback_block (get_block ())
3468 ->add_conditional (playback_location (r),
3469 m_boolval->playback_rvalue (),
3470 playback_block (m_on_true),
3471 playback_block (m_on_false));
3472 }
3473
3474 /* Override the poisoned default implementation of
3475 gcc::jit::recording::statement::get_successor_blocks
3476
3477 A conditional jump has 2 successor blocks. */
3478
3479 int
3480 recording::conditional::get_successor_blocks (block **out_next1,
3481 block **out_next2) const
3482 {
3483 *out_next1 = m_on_true;
3484 *out_next2 = m_on_false;
3485 return 2;
3486 }
3487
3488 /* Implementation of recording::memento::make_debug_string for
3489 a conditional jump statement. */
3490
3491 recording::string *
3492 recording::conditional::make_debug_string ()
3493 {
3494 if (m_on_false)
3495 return string::from_printf (m_ctxt,
3496 "if (%s) goto %s; else goto %s;",
3497 m_boolval->get_debug_string (),
3498 m_on_true->get_debug_string (),
3499 m_on_false->get_debug_string ());
3500 else
3501 return string::from_printf (m_ctxt,
3502 "if (%s) goto %s;",
3503 m_boolval->get_debug_string (),
3504 m_on_true->get_debug_string ());
3505 }
3506
3507 /* The implementation of class gcc::jit::recording::jump. */
3508
3509 /* Implementation of pure virtual hook recording::memento::replay_into
3510 for recording::jump. */
3511
3512 void
3513 recording::jump::replay_into (replayer *r)
3514 {
3515 playback_block (get_block ())
3516 ->add_jump (playback_location (r),
3517 m_target->playback_block ());
3518 }
3519
3520 /* Override the poisoned default implementation of
3521 gcc::jit::recording::statement::get_successor_blocks
3522
3523 An unconditional jump has 1 successor block. */
3524
3525 int
3526 recording::jump::get_successor_blocks (block **out_next1,
3527 block **/*out_next2*/) const
3528 {
3529 *out_next1 = m_target;
3530 return 1;
3531 }
3532
3533 /* Implementation of recording::memento::make_debug_string for
3534 a unconditional jump statement. */
3535
3536 recording::string *
3537 recording::jump::make_debug_string ()
3538 {
3539 return string::from_printf (m_ctxt,
3540 "goto %s;",
3541 m_target->get_debug_string ());
3542 }
3543
3544 /* The implementation of class gcc::jit::recording::return_. */
3545
3546 /* Implementation of pure virtual hook recording::memento::replay_into
3547 for recording::return_. */
3548
3549 void
3550 recording::return_::replay_into (replayer *r)
3551 {
3552 playback_block (get_block ())
3553 ->add_return (playback_location (r),
3554 m_rvalue ? m_rvalue->playback_rvalue () : NULL);
3555 }
3556
3557 /* Override the poisoned default implementation of
3558 gcc::jit::recording::statement::get_successor_blocks
3559
3560 A return statement has no successor block. */
3561
3562 int
3563 recording::return_::get_successor_blocks (block **/*out_next1*/,
3564 block **/*out_next2*/) const
3565 {
3566 return 0;
3567 }
3568
3569 /* Implementation of recording::memento::make_debug_string for
3570 a return statement (covers both those with and without rvalues). */
3571
3572 recording::string *
3573 recording::return_::make_debug_string ()
3574 {
3575 if (m_rvalue)
3576 return string::from_printf (m_ctxt,
3577 "return %s;",
3578 m_rvalue->get_debug_string ());
3579 else
3580 return string::from_printf (m_ctxt,
3581 "return;");
3582 }
3583
3584 } // namespace gcc::jit
3585
3586 } // namespace gcc