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