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