1/* Internals of libgccjit: classes for recording calls made to the JIT API. 2 Copyright (C) 2013-2015 Free Software Foundation, Inc. 3 Contributed by David Malcolm <dmalcolm@redhat.com>. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it 8under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3, or (at your option) 10any later version. 11 12GCC is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING3. If not see 19<http://www.gnu.org/licenses/>. */ 20 21#include "config.h" 22#include "system.h" 23#include "coretypes.h" 24#include "tm.h" 25#include "pretty-print.h" 26#include "hash-map.h" 27#include "toplev.h" 28 29#include <pthread.h> 30 31#include "jit-common.h" 32#include "jit-builtins.h" 33#include "jit-logging.h" 34#include "jit-recording.h" 35#include "jit-playback.h" 36 37namespace gcc { 38namespace jit { 39 40// class dump 41 42dump::dump (recording::context &ctxt, 43 const char *filename, 44 bool update_locations) 45: m_ctxt (ctxt), 46 m_filename (filename), 47 m_update_locations (update_locations), 48 m_line (0), 49 m_column (0) 50{ 51 m_file = fopen (filename, "w"); 52 if (!m_file) 53 ctxt.add_error (NULL, 54 "error opening dump file %s for writing: %s", 55 filename, 56 xstrerror (errno)); 57} 58 59dump::~dump () 60{ 61 if (m_file) 62 { 63 int err = fclose (m_file); 64 if (err) 65 m_ctxt.add_error (NULL, 66 "error closing dump file %s: %s", 67 m_filename, 68 xstrerror (errno)); 69 } 70} 71 72/* Write the given message to the dump, using printf-formatting 73 conventions, updating the line/column within the dump. 74 75 Emit an error on the context if a failure occurs. */ 76 77void 78dump::write (const char *fmt, ...) 79{ 80 int len; 81 va_list ap; 82 char *buf; 83 84 /* If there was an error opening the file, we've already reported it. 85 Don't attempt further work. */ 86 if (!m_file) 87 return; 88 89 va_start (ap, fmt); 90 len = vasprintf (&buf, fmt, ap); 91 va_end (ap); 92 93 if (buf == NULL || len < 0) 94 { 95 m_ctxt.add_error (NULL, "malloc failure writing to dumpfile %s", 96 m_filename); 97 return; 98 } 99 100 if (fwrite (buf, strlen (buf), 1, m_file) != 1) 101 m_ctxt.add_error (NULL, "error writing to dump file %s", 102 m_filename); 103 104 /* Flush after each line, to ease debugging crashes. */ 105 fflush (m_file); 106 107 /* Update line/column: */ 108 for (const char *ptr = buf; *ptr; ptr++) 109 { 110 if ('\n' == *ptr) 111 { 112 m_line++; 113 m_column = 0; 114 } 115 else 116 m_column++; 117 } 118 119 free (buf); 120} 121 122/* Construct a gcc::jit::recording::location instance for the current 123 location within the dump. */ 124 125recording::location * 126dump::make_location () const 127{ 128 return m_ctxt.new_location (m_filename, m_line, m_column, 129 /* We need to flag such locations as *not* 130 created by the user, so that 131 reproducer::get_identifier can cope with 132 them appearing *after* the memento that 133 refers to them. */ 134 false); 135} 136 137/* A collection of allocations, all of which can be released together, to 138 avoid needing to track and release them individually. */ 139 140class allocator 141{ 142 public: 143 ~allocator (); 144 145 char * 146 xstrdup_printf (const char *, ...) 147 ATTRIBUTE_RETURNS_NONNULL 148 GNU_PRINTF(2, 3); 149 150 char * 151 xstrdup_printf_va (const char *, va_list ap) 152 ATTRIBUTE_RETURNS_NONNULL 153 GNU_PRINTF(2, 0); 154 155 private: 156 auto_vec <void *> m_buffers; 157}; 158 159/* allocator's destructor. Call "free" on all of the allocations. */ 160 161allocator::~allocator () 162{ 163 unsigned i; 164 void *buffer; 165 FOR_EACH_VEC_ELT (m_buffers, i, buffer) 166 free (buffer); 167} 168 169/* Formatted printing, allocating to a buffer (or exiting the process if 170 the allocation fails). 171 172 The buffer exists until the allocator is cleaned up, and is freed at 173 that point, so the caller doesn't need to track the result. */ 174 175char * 176allocator::xstrdup_printf (const char *fmt, ...) 177{ 178 char *result; 179 va_list ap; 180 va_start (ap, fmt); 181 result = xstrdup_printf_va (fmt, ap); 182 va_end (ap); 183 return result; 184} 185 186/* Formatted printing, allocating to a buffer (or exiting the process if 187 the allocation fails). 188 189 The buffer exists until the allocator is cleaned up, and is freed at 190 that point, so the caller doesn't need to track the result. */ 191 192char * 193allocator::xstrdup_printf_va (const char *fmt, va_list ap) 194{ 195 char *result = xvasprintf (fmt, ap); 196 m_buffers.safe_push (result); 197 return result; 198} 199 200/* gcc::jit::reproducer is a subclass of gcc::jit::dump, used for 201 implementing gcc_jit_context_dump_reproducer_to_file. */ 202 203class reproducer : public dump 204{ 205 public: 206 reproducer (recording::context &ctxt, 207 const char *filename); 208 209 void 210 write_params (const vec <recording::context *> &contexts); 211 212 void 213 write_args (const vec <recording::context *> &contexts); 214 215 const char * 216 make_identifier (recording::memento *m, const char *prefix); 217 218 const char * 219 make_tmp_identifier (const char *prefix, recording::memento *m); 220 221 const char * 222 get_identifier (recording::context *ctxt); 223 224 const char * 225 get_identifier (recording::memento *m); 226 227 const char * 228 get_identifier_as_rvalue (recording::rvalue *m); 229 230 const char * 231 get_identifier_as_lvalue (recording::lvalue *m); 232 233 const char * 234 get_identifier_as_type (recording::type *m); 235 236 char * 237 xstrdup_printf (const char *, ...) 238 ATTRIBUTE_RETURNS_NONNULL 239 GNU_PRINTF(2, 3); 240 241 private: 242 hash_map<recording::memento *, const char *> m_identifiers; 243 allocator m_allocator; 244}; 245 246/* gcc::jit::reproducer's constructor. */ 247 248reproducer::reproducer (recording::context &ctxt, 249 const char *filename) : 250 dump (ctxt, filename, 0), 251 m_identifiers (), 252 m_allocator () 253{ 254} 255 256/* Write out a list of contexts as a set of parameters within a 257 C function declaration. */ 258 259void 260reproducer::write_params (const vec <recording::context *> &contexts) 261{ 262 unsigned i; 263 recording::context *ctxt; 264 FOR_EACH_VEC_ELT (contexts, i, ctxt) 265 { 266 write ("gcc_jit_context *%s", 267 get_identifier (ctxt)); 268 if (i < contexts.length () - 1) 269 write (",\n" 270 " "); 271 } 272} 273 274/* Write out a list of contexts as a set of arguments within a call 275 to a C function. */ 276 277void 278reproducer::write_args (const vec <recording::context *> &contexts) 279{ 280 unsigned i; 281 recording::context *ctxt; 282 FOR_EACH_VEC_ELT (contexts, i, ctxt) 283 { 284 write ("%s", 285 get_identifier (ctxt)); 286 if (i < contexts.length () - 1) 287 write (",\n" 288 " "); 289 } 290} 291 292/* Generate a C identifier for the given memento, associating the generated 293 buffer with the memento (for future calls to get_identifier et al). 294 295 The reproducer will eventually clean up the buffer in its dtor. */ 296const char * 297reproducer::make_identifier (recording::memento *m, const char *prefix) 298{ 299 char *result; 300 if (strlen (m->get_debug_string ()) < 100) 301 { 302 result = m_allocator.xstrdup_printf ("%s_%s_%p", 303 prefix, 304 m->get_debug_string (), 305 (void *) m); 306 for (char *p = result; *p; p++) 307 if (!ISALNUM (*p)) 308 *p = '_'; 309 } 310 else 311 result = m_allocator.xstrdup_printf ("%s_%p", 312 prefix, (void *) m); 313 m_identifiers.put (m, result); 314 return result; 315} 316 317/* Generate a C identifier for a temporary variable. 318 The reproducer will eventually clean up the buffer in its dtor. */ 319 320const char * 321reproducer::make_tmp_identifier (const char *prefix, recording::memento *m) 322{ 323 return m_allocator.xstrdup_printf ("%s_%s", 324 prefix, get_identifier (m)); 325} 326 327/* Generate a C identifier for the given context. 328 The reproducer will eventually clean up the buffer in its dtor. */ 329 330const char * 331reproducer::get_identifier (recording::context *ctxt) 332{ 333 return m_allocator.xstrdup_printf ("ctxt_%p", 334 (void *)ctxt); 335} 336 337/* Locate the C identifier for the given memento, which is assumed to 338 have already been created via make_identifier. */ 339 340const char * 341reproducer::get_identifier (recording::memento *m) 342{ 343 if (!m) 344 return "NULL"; 345 346 /* gcc_jit_context_dump_to_file (, , 1) generates and writes locations, 347 and hence these locations appear in the context's memento list 348 out-of-order: they appear in the context's memento list *after* 349 the memento that refers to them. For this case, it's simplest to 350 pretend that they're NULL when writing out the code to recreate the 351 memento that uses them. */ 352 if (recording::location *loc = m->dyn_cast_location ()) 353 if (!loc->created_by_user ()) 354 return "NULL"; 355 356 const char **slot = m_identifiers.get (m); 357 if (!slot) 358 { 359 get_context ().add_error (NULL, 360 "unable to find identifier for %p: %s", 361 (void *)m, 362 m->get_debug_string ()); 363 gcc_unreachable (); 364 } 365 return *slot; 366} 367 368/* Locate the C identifier for the given rvalue, wrapping it within 369 a gcc_*_as_rvalue upcast if necessary. */ 370 371const char * 372reproducer::get_identifier_as_rvalue (recording::rvalue *m) 373{ 374 return m->access_as_rvalue (*this); 375} 376 377/* Locate the C identifier for the given lvalue, wrapping it within 378 a gcc_*_as_lvalue upcast if necessary. */ 379 380const char * 381reproducer::get_identifier_as_lvalue (recording::lvalue *m) 382{ 383 return m->access_as_lvalue (*this); 384} 385 386/* Locate the C identifier for the given type, wrapping it within 387 a gcc_*_as_type upcast if necessary. */ 388 389const char * 390reproducer::get_identifier_as_type (recording::type *m) 391{ 392 return m->access_as_type (*this); 393} 394 395/* Formatted printing, allocating to a buffer (or exiting the process if 396 the allocation fails). 397 398 The buffer exists until the allocator is cleaned up, and is freed at 399 that point, so the caller doesn't need to track the result. 400 401 Note that we can't use ggc_printf since we're not within the compiler 402 proper (when within gcc_jit_context_dump_reproducer_to_file). */ 403 404char * 405reproducer::xstrdup_printf (const char *fmt, ...) 406{ 407 char *result; 408 va_list ap; 409 va_start (ap, fmt); 410 result = m_allocator.xstrdup_printf_va (fmt, ap); 411 va_end (ap); 412 return result; 413} 414 415/********************************************************************** 416 Recording. 417 **********************************************************************/ 418 419/* Get the playback::location for the given recording::location, 420 handling a NULL input with a NULL output. */ 421 422playback::location * 423recording::playback_location (replayer *r, recording::location *loc) 424{ 425 if (loc) 426 return loc->playback_location (r); 427 else 428 return NULL; 429} 430 431/* Get a const char * for the given recording::string 432 handling a NULL input with a NULL output. */ 433 434const char * 435recording::playback_string (recording::string *str) 436{ 437 if (str) 438 return str->c_str (); 439 else 440 return NULL; 441} 442 443/* Get the playback::block for the given recording::block, 444 handling a NULL input with a NULL output. */ 445 446playback::block * 447recording::playback_block (recording::block *b) 448{ 449 if (b) 450 return b->playback_block (); 451 else 452 return NULL; 453} 454 455/* Methods of cc::jit::recording::context. */ 456 457/* The constructor for gcc::jit::recording::context, used by 458 gcc_jit_context_acquire and gcc_jit_context_new_child_context. */ 459 460recording::context::context (context *parent_ctxt) 461 : log_user (NULL), 462 m_parent_ctxt (parent_ctxt), 463 m_toplevel_ctxt (m_parent_ctxt ? m_parent_ctxt->m_toplevel_ctxt : this), 464 m_error_count (0), 465 m_first_error_str (NULL), 466 m_owns_first_error_str (false), 467 m_last_error_str (NULL), 468 m_owns_last_error_str (false), 469 m_mementos (), 470 m_compound_types (), 471 m_globals (), 472 m_functions (), 473 m_FILE_type (NULL), 474 m_builtins_manager(NULL) 475{ 476 if (parent_ctxt) 477 { 478 /* Inherit options from parent. */ 479 for (unsigned i = 0; 480 i < sizeof (m_str_options) / sizeof (m_str_options[0]); 481 i++) 482 { 483 const char *parent_opt = parent_ctxt->m_str_options[i]; 484 m_str_options[i] = parent_opt ? xstrdup (parent_opt) : NULL; 485 } 486 memcpy (m_int_options, 487 parent_ctxt->m_int_options, 488 sizeof (m_int_options)); 489 memcpy (m_bool_options, 490 parent_ctxt->m_bool_options, 491 sizeof (m_bool_options)); 492 memcpy (m_inner_bool_options, 493 parent_ctxt->m_inner_bool_options, 494 sizeof (m_inner_bool_options)); 495 set_logger (parent_ctxt->get_logger ()); 496 } 497 else 498 { 499 memset (m_str_options, 0, sizeof (m_str_options)); 500 memset (m_int_options, 0, sizeof (m_int_options)); 501 memset (m_bool_options, 0, sizeof (m_bool_options)); 502 memset (m_inner_bool_options, 0, sizeof (m_inner_bool_options)); 503 } 504 505 memset (m_basic_types, 0, sizeof (m_basic_types)); 506} 507 508/* The destructor for gcc::jit::recording::context, implicitly used by 509 gcc_jit_context_release. */ 510 511recording::context::~context () 512{ 513 JIT_LOG_SCOPE (get_logger ()); 514 int i; 515 memento *m; 516 FOR_EACH_VEC_ELT (m_mementos, i, m) 517 { 518 delete m; 519 } 520 521 for (i = 0; i < GCC_JIT_NUM_STR_OPTIONS; ++i) 522 free (m_str_options[i]); 523 524 char *optname; 525 FOR_EACH_VEC_ELT (m_command_line_options, i, optname) 526 free (optname); 527 528 if (m_builtins_manager) 529 delete m_builtins_manager; 530 531 if (m_owns_first_error_str) 532 free (m_first_error_str); 533 534 if (m_owns_last_error_str) 535 if (m_last_error_str != m_first_error_str) 536 free (m_last_error_str); 537} 538 539/* Add the given mememto to the list of those tracked by this 540 gcc::jit::recording::context, so that e.g. it can be deleted 541 when this context is released. */ 542 543void 544recording::context::record (memento *m) 545{ 546 gcc_assert (m); 547 548 m_mementos.safe_push (m); 549} 550 551/* Replay this context (and any parents) into the given replayer. */ 552 553void 554recording::context::replay_into (replayer *r) 555{ 556 JIT_LOG_SCOPE (get_logger ()); 557 int i; 558 memento *m; 559 560 /* If we have a parent context, we must replay it. This will 561 recursively walk backwards up the historical tree, then replay things 562 forwards "in historical order", starting with the ultimate parent 563 context, until we reach the "this" context. 564 565 Note that we fully replay the parent, then fully replay the child, 566 which means that inter-context references can only exist from child 567 to parent, not the other way around. 568 569 All of this replaying is suboptimal - it would be better to do the 570 work for the parent context *once*, rather than replaying the parent 571 every time we replay each child. However, fixing this requires deep 572 surgery to lifetime-management: we'd need every context family tree 573 to have its own GC heap, and to initialize the GCC code to use that 574 heap (with a mutex on such a heap). */ 575 if (m_parent_ctxt) 576 m_parent_ctxt->replay_into (r); 577 578 if (r->errors_occurred ()) 579 return; 580 581 /* Replay this context's saved operations into r. */ 582 FOR_EACH_VEC_ELT (m_mementos, i, m) 583 { 584 /* Disabled low-level debugging, here if we need it: print what 585 we're replaying. 586 Note that the calls to get_debug_string might lead to more 587 mementos being created for the strings. 588 This can also be used to exercise the debug_string 589 machinery. */ 590 if (0) 591 printf ("context %p replaying (%p): %s\n", 592 (void *)this, (void *)m, m->get_debug_string ()); 593 594 m->replay_into (r); 595 596 if (r->errors_occurred ()) 597 return; 598 } 599} 600 601/* During a playback, we associate objects from the recording with 602 their counterparts during this playback. 603 604 For simplicity, we store this within the recording objects. 605 606 The following method cleans away these associations, to ensure that 607 we never have out-of-date associations lingering on subsequent 608 playbacks (the objects pointed to are GC-managed, but the 609 recording objects don't own refs to them). */ 610 611void 612recording::context::disassociate_from_playback () 613{ 614 JIT_LOG_SCOPE (get_logger ()); 615 int i; 616 memento *m; 617 618 if (m_parent_ctxt) 619 m_parent_ctxt->disassociate_from_playback (); 620 621 FOR_EACH_VEC_ELT (m_mementos, i, m) 622 { 623 m->set_playback_obj (NULL); 624 } 625} 626 627/* Create a recording::string instance and add it to this context's list 628 of mementos. 629 630 This creates a fresh copy of the given 0-terminated buffer. */ 631 632recording::string * 633recording::context::new_string (const char *text) 634{ 635 if (!text) 636 return NULL; 637 638 recording::string *result = new string (this, text); 639 record (result); 640 return result; 641} 642 643/* Create a recording::location instance and add it to this context's 644 list of mementos. 645 646 Implements the post-error-checking part of 647 gcc_jit_context_new_location. */ 648 649recording::location * 650recording::context::new_location (const char *filename, 651 int line, 652 int column, 653 bool created_by_user) 654{ 655 recording::location *result = 656 new recording::location (this, 657 new_string (filename), 658 line, column, 659 created_by_user); 660 record (result); 661 return result; 662} 663 664/* If we haven't seen this enum value yet, create a recording::type 665 instance and add it to this context's list of mementos. 666 667 If we have seen it before, reuse our cached value, so that repeated 668 calls on the context give the same object. 669 670 If we have a parent context, the cache is within the ultimate 671 ancestor context. 672 673 Implements the post-error-checking part of 674 gcc_jit_context_get_type. */ 675 676recording::type * 677recording::context::get_type (enum gcc_jit_types kind) 678{ 679 if (!m_basic_types[kind]) 680 { 681 if (m_parent_ctxt) 682 m_basic_types[kind] = m_parent_ctxt->get_type (kind); 683 else 684 { 685 recording::type *result = new memento_of_get_type (this, kind); 686 record (result); 687 m_basic_types[kind] = result; 688 } 689 } 690 691 return m_basic_types[kind]; 692} 693 694/* Get a recording::type instance for the given size and signedness. 695 This is implemented in terms of recording::context::get_type 696 above. 697 698 Implements the post-error-checking part of 699 gcc_jit_context_get_int_type. */ 700 701recording::type * 702recording::context::get_int_type (int num_bytes, int is_signed) 703{ 704 /* We can't use a switch here since some of the values are macros affected 705 by options; e.g. i386.h has 706 #define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD) 707 Compare with tree.c's make_or_reuse_type. Note that the _SIZE macros 708 are in bits, rather than bytes. 709 */ 710 const int num_bits = num_bytes * 8; 711 if (num_bits == INT_TYPE_SIZE) 712 return get_type (is_signed 713 ? GCC_JIT_TYPE_INT 714 : GCC_JIT_TYPE_UNSIGNED_INT); 715 if (num_bits == CHAR_TYPE_SIZE) 716 return get_type (is_signed 717 ? GCC_JIT_TYPE_SIGNED_CHAR 718 : GCC_JIT_TYPE_UNSIGNED_CHAR); 719 if (num_bits == SHORT_TYPE_SIZE) 720 return get_type (is_signed 721 ? GCC_JIT_TYPE_SHORT 722 : GCC_JIT_TYPE_UNSIGNED_SHORT); 723 if (num_bits == LONG_TYPE_SIZE) 724 return get_type (is_signed 725 ? GCC_JIT_TYPE_LONG 726 : GCC_JIT_TYPE_UNSIGNED_LONG); 727 if (num_bits == LONG_LONG_TYPE_SIZE) 728 return get_type (is_signed 729 ? GCC_JIT_TYPE_LONG_LONG 730 : GCC_JIT_TYPE_UNSIGNED_LONG_LONG); 731 732 /* Some other size, not corresponding to the C int types. */ 733 /* To be written: support arbitrary other sizes, sharing by 734 memoizing at the recording::context level? */ 735 gcc_unreachable (); 736} 737 738/* Create a recording::type instance and add it to this context's list 739 of mementos. 740 741 Implements the post-error-checking part of 742 gcc_jit_context_new_array_type. */ 743 744recording::type * 745recording::context::new_array_type (recording::location *loc, 746 recording::type *element_type, 747 int num_elements) 748{ 749 if (struct_ *s = element_type->dyn_cast_struct ()) 750 if (!s->get_fields ()) 751 { 752 add_error (NULL, 753 "cannot create an array of type %s" 754 " until the fields have been set", 755 s->get_name ()->c_str ()); 756 return NULL; 757 } 758 recording::type *result = 759 new recording::array_type (this, loc, element_type, num_elements); 760 record (result); 761 return result; 762} 763 764/* Create a recording::field instance and add it to this context's list 765 of mementos. 766 767 Implements the post-error-checking part of 768 gcc_jit_context_new_field. */ 769 770recording::field * 771recording::context::new_field (recording::location *loc, 772 recording::type *type, 773 const char *name) 774{ 775 recording::field *result = 776 new recording::field (this, loc, type, new_string (name)); 777 record (result); 778 return result; 779} 780 781/* Create a recording::struct_ instance and add it to this context's 782 list of mementos and list of compound types. 783 784 Implements the post-error-checking part of 785 gcc_jit_context_new_struct_type. */ 786 787recording::struct_ * 788recording::context::new_struct_type (recording::location *loc, 789 const char *name) 790{ 791 recording::struct_ *result = new struct_ (this, loc, new_string (name)); 792 record (result); 793 m_compound_types.safe_push (result); 794 return result; 795} 796 797/* Create a recording::union_ instance and add it to this context's 798 list of mementos and list of compound types. 799 800 Implements the first post-error-checking part of 801 gcc_jit_context_new_union_type. */ 802 803recording::union_ * 804recording::context::new_union_type (recording::location *loc, 805 const char *name) 806{ 807 recording::union_ *result = new union_ (this, loc, new_string (name)); 808 record (result); 809 m_compound_types.safe_push (result); 810 return result; 811} 812 813/* Create a recording::function_type instance and add it to this context's 814 list of mementos. 815 816 Used by new_function_ptr_type and by builtins_manager::make_fn_type. */ 817 818recording::function_type * 819recording::context::new_function_type (recording::type *return_type, 820 int num_params, 821 recording::type **param_types, 822 int is_variadic) 823{ 824 recording::function_type *fn_type 825 = new function_type (this, 826 return_type, 827 num_params, 828 param_types, 829 is_variadic); 830 record (fn_type); 831 return fn_type; 832} 833 834/* Create a recording::type instance and add it to this context's list 835 of mementos. 836 837 Implements the post-error-checking part of 838 gcc_jit_context_new_function_ptr_type. */ 839 840recording::type * 841recording::context::new_function_ptr_type (recording::location *, /* unused loc */ 842 recording::type *return_type, 843 int num_params, 844 recording::type **param_types, 845 int is_variadic) 846{ 847 recording::function_type *fn_type 848 = new_function_type (return_type, 849 num_params, 850 param_types, 851 is_variadic); 852 853 /* Return a pointer-type to the the function type. */ 854 return fn_type->get_pointer (); 855} 856 857/* Create a recording::param instance and add it to this context's list 858 of mementos. 859 860 Implements the post-error-checking part of 861 gcc_jit_context_new_param. */ 862 863recording::param * 864recording::context::new_param (recording::location *loc, 865 recording::type *type, 866 const char *name) 867{ 868 recording::param *result = new recording::param (this, loc, type, new_string (name)); 869 record (result); 870 return result; 871} 872 873/* Create a recording::function instance and add it to this context's list 874 of mementos and list of functions. 875 876 Implements the post-error-checking part of 877 gcc_jit_context_new_function. */ 878 879recording::function * 880recording::context::new_function (recording::location *loc, 881 enum gcc_jit_function_kind kind, 882 recording::type *return_type, 883 const char *name, 884 int num_params, 885 recording::param **params, 886 int is_variadic, 887 enum built_in_function builtin_id) 888{ 889 recording::function *result = 890 new recording::function (this, 891 loc, kind, return_type, 892 new_string (name), 893 num_params, params, is_variadic, 894 builtin_id); 895 record (result); 896 m_functions.safe_push (result); 897 898 return result; 899} 900 901/* Locate the builtins_manager (if any) for this family of contexts, 902 creating it if it doesn't exist already. 903 904 All of the recording contexts in a family share one builtins_manager: 905 if we have a child context, follow the parent links to get the 906 ultimate ancestor context, and look for it/store it there. */ 907 908builtins_manager * 909recording::context::get_builtins_manager () 910{ 911 if (m_parent_ctxt) 912 return m_parent_ctxt->get_builtins_manager (); 913 914 if (!m_builtins_manager) 915 m_builtins_manager = new builtins_manager (this); 916 917 return m_builtins_manager; 918} 919 920/* Get a recording::function instance, which is lazily-created and added 921 to the context's lists of mementos. 922 923 Implements the post-error-checking part of 924 gcc_jit_context_get_builtin_function. */ 925 926recording::function * 927recording::context::get_builtin_function (const char *name) 928{ 929 builtins_manager *bm = get_builtins_manager (); 930 return bm->get_builtin_function (name); 931} 932 933/* Create a recording::global instance and add it to this context's list 934 of mementos. 935 936 Implements the post-error-checking part of 937 gcc_jit_context_new_global. */ 938 939recording::lvalue * 940recording::context::new_global (recording::location *loc, 941 enum gcc_jit_global_kind kind, 942 recording::type *type, 943 const char *name) 944{ 945 recording::global *result = 946 new recording::global (this, loc, kind, type, new_string (name)); 947 record (result); 948 m_globals.safe_push (result); 949 950 return result; 951} 952 953/* Create a recording::memento_of_new_string_literal instance and add it 954 to this context's list of mementos. 955 956 Implements the post-error-checking part of 957 gcc_jit_context_new_string_literal. */ 958 959recording::rvalue * 960recording::context::new_string_literal (const char *value) 961{ 962 recording::rvalue *result = 963 new memento_of_new_string_literal (this, NULL, new_string (value)); 964 record (result); 965 return result; 966} 967 968/* Create a recording::unary_op instance and add it to this context's 969 list of mementos. 970 971 Implements the post-error-checking part of 972 gcc_jit_context_new_unary_op. */ 973 974recording::rvalue * 975recording::context::new_unary_op (recording::location *loc, 976 enum gcc_jit_unary_op op, 977 recording::type *result_type, 978 recording::rvalue *a) 979{ 980 recording::rvalue *result = 981 new unary_op (this, loc, op, result_type, a); 982 record (result); 983 return result; 984} 985 986/* Create a recording::binary_op instance and add it to this context's 987 list of mementos. 988 989 Implements the post-error-checking part of 990 gcc_jit_context_new_binary_op. */ 991 992recording::rvalue * 993recording::context::new_binary_op (recording::location *loc, 994 enum gcc_jit_binary_op op, 995 recording::type *result_type, 996 recording::rvalue *a, 997 recording::rvalue *b) 998{ 999 recording::rvalue *result = 1000 new binary_op (this, loc, op, result_type, a, b); 1001 record (result); 1002 return result; 1003} 1004 1005/* Create a recording::comparison instance and add it to this context's 1006 list of mementos. 1007 1008 Implements the post-error-checking part of 1009 gcc_jit_context_new_comparison. */ 1010 1011recording::rvalue * 1012recording::context::new_comparison (recording::location *loc, 1013 enum gcc_jit_comparison op, 1014 recording::rvalue *a, 1015 recording::rvalue *b) 1016{ 1017 recording::rvalue *result = new comparison (this, loc, op, a, b); 1018 record (result); 1019 return result; 1020} 1021 1022/* Create a recording::cast instance and add it to this context's list 1023 of mementos. 1024 1025 Implements the post-error-checking part of 1026 gcc_jit_context_new_cast. */ 1027 1028recording::rvalue * 1029recording::context::new_cast (recording::location *loc, 1030 recording::rvalue *expr, 1031 recording::type *type_) 1032{ 1033 recording::rvalue *result = new cast (this, loc, expr, type_); 1034 record (result); 1035 return result; 1036} 1037 1038/* Create a recording::call instance and add it to this context's list 1039 of mementos. 1040 1041 Implements the post-error-checking part of 1042 gcc_jit_context_new_call. */ 1043 1044recording::rvalue * 1045recording::context::new_call (recording::location *loc, 1046 function *func, 1047 int numargs , recording::rvalue **args) 1048{ 1049 recording::rvalue *result = new call (this, loc, func, numargs, args); 1050 record (result); 1051 return result; 1052} 1053 1054/* Create a recording::call_through_ptr instance and add it to this 1055 context's list of mementos. 1056 1057 Implements the post-error-checking part of 1058 gcc_jit_context_new_call_through_ptr. */ 1059 1060recording::rvalue * 1061recording::context::new_call_through_ptr (recording::location *loc, 1062 recording::rvalue *fn_ptr, 1063 int numargs, 1064 recording::rvalue **args) 1065 { 1066 recording::rvalue *result = new call_through_ptr (this, loc, fn_ptr, numargs, args); 1067 record (result); 1068 return result; 1069} 1070 1071/* Create a recording::array_access instance and add it to this context's list 1072 of mementos. 1073 1074 Implements the post-error-checking part of 1075 gcc_jit_context_new_array_access. */ 1076 1077recording::lvalue * 1078recording::context::new_array_access (recording::location *loc, 1079 recording::rvalue *ptr, 1080 recording::rvalue *index) 1081{ 1082 recording::lvalue *result = new array_access (this, loc, ptr, index); 1083 record (result); 1084 return result; 1085} 1086 1087/* Create a recording::case_ instance and add it to this context's list 1088 of mementos. 1089 1090 Implements the post-error-checking part of 1091 gcc_jit_context_new_case. */ 1092 1093recording::case_ * 1094recording::context::new_case (recording::rvalue *min_value, 1095 recording::rvalue *max_value, 1096 recording::block *block) 1097{ 1098 recording::case_ *result = new case_ (this, min_value, max_value, block); 1099 record (result); 1100 return result; 1101} 1102 1103/* Set the given string option for this context, or add an error if 1104 it's not recognized. 1105 1106 Implements the post-error-checking part of 1107 gcc_jit_context_set_str_option. */ 1108 1109void 1110recording::context::set_str_option (enum gcc_jit_str_option opt, 1111 const char *value) 1112{ 1113 if (opt < 0 || opt >= GCC_JIT_NUM_STR_OPTIONS) 1114 { 1115 add_error (NULL, 1116 "unrecognized (enum gcc_jit_str_option) value: %i", opt); 1117 return; 1118 } 1119 free (m_str_options[opt]); 1120 m_str_options[opt] = value ? xstrdup (value) : NULL; 1121 log_str_option (opt); 1122} 1123 1124/* Set the given integer option for this context, or add an error if 1125 it's not recognized. 1126 1127 Implements the post-error-checking part of 1128 gcc_jit_context_set_int_option. */ 1129 1130void 1131recording::context::set_int_option (enum gcc_jit_int_option opt, 1132 int value) 1133{ 1134 if (opt < 0 || opt >= GCC_JIT_NUM_INT_OPTIONS) 1135 { 1136 add_error (NULL, 1137 "unrecognized (enum gcc_jit_int_option) value: %i", opt); 1138 return; 1139 } 1140 m_int_options[opt] = value; 1141 log_int_option (opt); 1142} 1143 1144/* Set the given boolean option for this context, or add an error if 1145 it's not recognized. 1146 1147 Implements the post-error-checking part of 1148 gcc_jit_context_set_bool_option. */ 1149 1150void 1151recording::context::set_bool_option (enum gcc_jit_bool_option opt, 1152 int value) 1153{ 1154 if (opt < 0 || opt >= GCC_JIT_NUM_BOOL_OPTIONS) 1155 { 1156 add_error (NULL, 1157 "unrecognized (enum gcc_jit_bool_option) value: %i", opt); 1158 return; 1159 } 1160 m_bool_options[opt] = value ? true : false; 1161 log_bool_option (opt); 1162} 1163 1164void 1165recording::context::set_inner_bool_option (enum inner_bool_option inner_opt, 1166 int value) 1167{ 1168 gcc_assert (inner_opt >= 0 && inner_opt < NUM_INNER_BOOL_OPTIONS); 1169 m_inner_bool_options[inner_opt] = value ? true : false; 1170 log_inner_bool_option (inner_opt); 1171} 1172 1173 1174/* Add the given optname to this context's list of extra options. 1175 1176 Implements the post-error-checking part of 1177 gcc_jit_context_add_command_line_option. */ 1178 1179void 1180recording::context::add_command_line_option (const char *optname) 1181{ 1182 m_command_line_options.safe_push (xstrdup (optname)); 1183} 1184 1185/* Add any user-provided extra options, starting with any from 1186 parent contexts. 1187 Called by playback::context::make_fake_args. */ 1188 1189void 1190recording::context::append_command_line_options (vec <char *> *argvec) 1191{ 1192 if (m_parent_ctxt) 1193 m_parent_ctxt->append_command_line_options (argvec); 1194 1195 int i; 1196 char *optname; 1197 FOR_EACH_VEC_ELT (m_command_line_options, i, optname) 1198 argvec->safe_push (xstrdup (optname)); 1199} 1200 1201/* Add the given dumpname/out_ptr pair to this context's list of requested 1202 dumps. 1203 1204 Implements the post-error-checking part of 1205 gcc_jit_context_enable_dump. */ 1206 1207void 1208recording::context::enable_dump (const char *dumpname, 1209 char **out_ptr) 1210{ 1211 requested_dump d; 1212 gcc_assert (dumpname); 1213 gcc_assert (out_ptr); 1214 1215 d.m_dumpname = dumpname; 1216 d.m_out_ptr = out_ptr; 1217 *out_ptr = NULL; 1218 m_requested_dumps.safe_push (d); 1219} 1220 1221/* Validate this context, and if it passes, compile it to memory 1222 (within a mutex). 1223 1224 Implements the post-error-checking part of 1225 gcc_jit_context_compile. */ 1226 1227result * 1228recording::context::compile () 1229{ 1230 JIT_LOG_SCOPE (get_logger ()); 1231 1232 log_all_options (); 1233 1234 validate (); 1235 1236 if (errors_occurred ()) 1237 return NULL; 1238 1239 /* Set up a compile_to_memory playback context. */ 1240 ::gcc::jit::playback::compile_to_memory replayer (this); 1241 1242 /* Use it. */ 1243 replayer.compile (); 1244 1245 /* Get the jit::result (or NULL) from the 1246 compile_to_memory playback context. */ 1247 return replayer.get_result_obj (); 1248} 1249 1250/* Validate this context, and if it passes, compile it to a file 1251 (within a mutex). 1252 1253 Implements the post-error-checking part of 1254 gcc_jit_context_compile_to_file. */ 1255 1256void 1257recording::context::compile_to_file (enum gcc_jit_output_kind output_kind, 1258 const char *output_path) 1259{ 1260 JIT_LOG_SCOPE (get_logger ()); 1261 1262 log_all_options (); 1263 1264 validate (); 1265 1266 if (errors_occurred ()) 1267 return; 1268 1269 /* Set up a compile_to_file playback context. */ 1270 ::gcc::jit::playback::compile_to_file replayer (this, 1271 output_kind, 1272 output_path); 1273 1274 /* Use it. */ 1275 replayer.compile (); 1276} 1277 1278/* Format the given error using printf's conventions, print 1279 it to stderr, and add it to the context. */ 1280 1281void 1282recording::context::add_error (location *loc, const char *fmt, ...) 1283{ 1284 va_list ap; 1285 va_start (ap, fmt); 1286 add_error_va (loc, fmt, ap); 1287 va_end (ap); 1288} 1289 1290/* Format the given error using printf's conventions, print 1291 it to stderr, and add it to the context. */ 1292 1293void 1294recording::context::add_error_va (location *loc, const char *fmt, va_list ap) 1295{ 1296 int len; 1297 char *malloced_msg; 1298 const char *errmsg; 1299 bool has_ownership; 1300 1301 JIT_LOG_SCOPE (get_logger ()); 1302 1303 len = vasprintf (&malloced_msg, fmt, ap); 1304 if (malloced_msg == NULL || len < 0) 1305 { 1306 errmsg = "out of memory generating error message"; 1307 has_ownership = false; 1308 } 1309 else 1310 { 1311 errmsg = malloced_msg; 1312 has_ownership = true; 1313 } 1314 if (get_logger ()) 1315 get_logger ()->log ("error %i: %s", m_error_count, errmsg); 1316 1317 const char *ctxt_progname = 1318 get_str_option (GCC_JIT_STR_OPTION_PROGNAME); 1319 if (!ctxt_progname) 1320 ctxt_progname = "libgccjit.so"; 1321 1322 if (loc) 1323 fprintf (stderr, "%s: %s: error: %s\n", 1324 ctxt_progname, 1325 loc->get_debug_string (), 1326 errmsg); 1327 else 1328 fprintf (stderr, "%s: error: %s\n", 1329 ctxt_progname, 1330 errmsg); 1331 1332 if (!m_error_count) 1333 { 1334 m_first_error_str = const_cast <char *> (errmsg); 1335 m_owns_first_error_str = has_ownership; 1336 } 1337 1338 if (m_owns_last_error_str) 1339 if (m_last_error_str != m_first_error_str) 1340 free (m_last_error_str); 1341 m_last_error_str = const_cast <char *> (errmsg); 1342 m_owns_last_error_str = has_ownership; 1343 1344 m_error_count++; 1345} 1346 1347/* Get the message for the first error that occurred on this context, or 1348 NULL if no errors have occurred on it. 1349 1350 Implements the post-error-checking part of 1351 gcc_jit_context_get_first_error. */ 1352 1353const char * 1354recording::context::get_first_error () const 1355{ 1356 return m_first_error_str; 1357} 1358 1359/* Get the message for the last error that occurred on this context, or 1360 NULL if no errors have occurred on it. 1361 1362 Implements the post-error-checking part of 1363 gcc_jit_context_get_last_error. */ 1364 1365const char * 1366recording::context::get_last_error () const 1367{ 1368 return m_last_error_str; 1369} 1370 1371/* Lazily generate and record a recording::type representing an opaque 1372 struct named "FILE". 1373 1374 For use if client code tries to dereference the result of 1375 get_type (GCC_JIT_TYPE_FILE_PTR). */ 1376 1377recording::type * 1378recording::context::get_opaque_FILE_type () 1379{ 1380 if (!m_FILE_type) 1381 m_FILE_type = new_struct_type (NULL, "FILE"); 1382 return m_FILE_type; 1383} 1384 1385/* Dump a C-like representation of the given context to the given path. 1386 If UPDATE_LOCATIONS is true, update the locations within the 1387 context's mementos to point to the dumpfile. 1388 1389 Implements the post-error-checking part of 1390 gcc_jit_context_dump_to_file. */ 1391 1392void 1393recording::context::dump_to_file (const char *path, bool update_locations) 1394{ 1395 int i; 1396 dump d (*this, path, update_locations); 1397 1398 /* Forward declaration of structs and unions. */ 1399 compound_type *st; 1400 FOR_EACH_VEC_ELT (m_compound_types, i, st) 1401 { 1402 d.write ("%s;\n\n", st->get_debug_string ()); 1403 } 1404 1405 /* Content of structs, where set. */ 1406 FOR_EACH_VEC_ELT (m_compound_types, i, st) 1407 if (st->get_fields ()) 1408 { 1409 st->get_fields ()->write_to_dump (d); 1410 d.write ("\n"); 1411 } 1412 1413 /* Globals. */ 1414 global *g; 1415 FOR_EACH_VEC_ELT (m_globals, i, g) 1416 { 1417 g->write_to_dump (d); 1418 } 1419 if (!m_globals.is_empty ()) 1420 d.write ("\n"); 1421 1422 function *fn; 1423 FOR_EACH_VEC_ELT (m_functions, i, fn) 1424 { 1425 fn->write_to_dump (d); 1426 } 1427} 1428 1429static const char * const 1430 str_option_reproducer_strings[GCC_JIT_NUM_STR_OPTIONS] = { 1431 "GCC_JIT_STR_OPTION_PROGNAME" 1432}; 1433 1434static const char * const 1435 int_option_reproducer_strings[GCC_JIT_NUM_INT_OPTIONS] = { 1436 "GCC_JIT_INT_OPTION_OPTIMIZATION_LEVEL" 1437}; 1438 1439static const char * const 1440 bool_option_reproducer_strings[GCC_JIT_NUM_BOOL_OPTIONS] = { 1441 "GCC_JIT_BOOL_OPTION_DEBUGINFO", 1442 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_TREE", 1443 "GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE", 1444 "GCC_JIT_BOOL_OPTION_DUMP_GENERATED_CODE", 1445 "GCC_JIT_BOOL_OPTION_DUMP_SUMMARY", 1446 "GCC_JIT_BOOL_OPTION_DUMP_EVERYTHING", 1447 "GCC_JIT_BOOL_OPTION_SELFCHECK_GC", 1448 "GCC_JIT_BOOL_OPTION_KEEP_INTERMEDIATES" 1449}; 1450 1451static const char * const 1452 inner_bool_option_reproducer_strings[NUM_INNER_BOOL_OPTIONS] = { 1453 "gcc_jit_context_set_bool_allow_unreachable_blocks" 1454}; 1455 1456/* Write the current value of all options to the log file (if any). */ 1457 1458void 1459recording::context::log_all_options () const 1460{ 1461 int opt_idx; 1462 1463 if (!get_logger ()) 1464 return; 1465 1466 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++) 1467 log_str_option ((enum gcc_jit_str_option)opt_idx); 1468 1469 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++) 1470 log_int_option ((enum gcc_jit_int_option)opt_idx); 1471 1472 for (opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++) 1473 log_bool_option ((enum gcc_jit_bool_option)opt_idx); 1474 for (opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++) 1475 log_inner_bool_option ((enum inner_bool_option)opt_idx); 1476} 1477 1478/* Write the current value of the given string option to the 1479 log file (if any). */ 1480 1481void 1482recording::context::log_str_option (enum gcc_jit_str_option opt) const 1483{ 1484 gcc_assert (opt < GCC_JIT_NUM_STR_OPTIONS); 1485 if (get_logger ()) 1486 { 1487 if (m_str_options[opt]) 1488 log ("%s: \"%s\"", 1489 str_option_reproducer_strings[opt], 1490 m_str_options[opt]); 1491 else 1492 log ("%s: NULL", 1493 str_option_reproducer_strings[opt]); 1494 } 1495} 1496 1497/* Write the current value of the given int option to the 1498 log file (if any). */ 1499 1500void 1501recording::context::log_int_option (enum gcc_jit_int_option opt) const 1502{ 1503 gcc_assert (opt < GCC_JIT_NUM_INT_OPTIONS); 1504 if (get_logger ()) 1505 log ("%s: %i", 1506 int_option_reproducer_strings[opt], 1507 m_int_options[opt]); 1508} 1509 1510/* Write the current value of the given bool option to the 1511 log file (if any). */ 1512 1513void 1514recording::context::log_bool_option (enum gcc_jit_bool_option opt) const 1515{ 1516 gcc_assert (opt < GCC_JIT_NUM_BOOL_OPTIONS); 1517 if (get_logger ()) 1518 log ("%s: %s", 1519 bool_option_reproducer_strings[opt], 1520 m_bool_options[opt] ? "true" : "false"); 1521} 1522 1523/* Write the current value of the given "inner" bool option to the 1524 log file (if any). */ 1525 1526void 1527recording::context::log_inner_bool_option (enum inner_bool_option opt) const 1528{ 1529 gcc_assert (opt < NUM_INNER_BOOL_OPTIONS); 1530 if (get_logger ()) 1531 log ("%s: %s", 1532 inner_bool_option_reproducer_strings[opt], 1533 m_inner_bool_options[opt] ? "true" : "false"); 1534} 1535 1536/* Write C source code to PATH that attempts to replay the API 1537 calls made to this context (and its parents), for use in 1538 minimizing test cases for libgccjit. 1539 1540 Implements the post-error-checking part of 1541 gcc_jit_context_dump_reproducer_to_file. */ 1542 1543void 1544recording::context::dump_reproducer_to_file (const char *path) 1545{ 1546 JIT_LOG_SCOPE (get_logger ()); 1547 reproducer r (*this, path); 1548 1549 /* Generate the "ancestry" of this context, as a list. */ 1550 auto_vec <context *> ascending_contexts; 1551 for (context *ctxt = this; ctxt; ctxt = ctxt->m_parent_ctxt) 1552 ascending_contexts.safe_push (ctxt); 1553 1554 /* Reverse the list, giving a list of contexts from 1555 top-most parent context down through to youngest child context. 1556 We will use this list as the parameters of the functions in 1557 our generated file. */ 1558 unsigned num_ctxts = ascending_contexts.length (); 1559 auto_vec <context *> contexts (num_ctxts); 1560 for (unsigned i = 0; i < num_ctxts; i++) 1561 contexts.safe_push (ascending_contexts[num_ctxts - (i + 1)]); 1562 1563 /* contexts[0] should be the top-level context. */ 1564 gcc_assert (contexts[0]); 1565 gcc_assert (contexts[0]->m_toplevel_ctxt == contexts[0]); 1566 1567 /* The final element in contexts should be "this". */ 1568 gcc_assert (contexts[contexts.length () - 1] == this); 1569 gcc_assert (contexts[contexts.length () - 1]->m_toplevel_ctxt 1570 == contexts[0]); 1571 1572 r.write ("/* This code was autogenerated by" 1573 " gcc_jit_context_dump_reproducer_to_file.\n\n"); 1574 print_version (r.get_file (), " ", false); 1575 r.write ("*/\n"); 1576 r.write ("#include <libgccjit.h>\n\n"); 1577 r.write ("#pragma GCC diagnostic ignored \"-Wunused-variable\"\n\n"); 1578 r.write ("static void\nset_options ("); 1579 r.write_params (contexts); 1580 r.write (");\n\n"); 1581 r.write ("static void\ncreate_code ("); 1582 r.write_params (contexts); 1583 r.write (");\n\n"); 1584 r.write ("int\nmain (int argc, const char **argv)\n"); 1585 r.write ("{\n"); 1586 for (unsigned i = 0; i < num_ctxts; i++) 1587 r.write (" gcc_jit_context *%s;\n", 1588 r.get_identifier (contexts[i])); 1589 r.write (" gcc_jit_result *result;\n" 1590 "\n"); 1591 1592 /* Create the contexts. 1593 The top-level context is acquired from a clean slate, the others as 1594 children of the prior context. */ 1595 r.write (" %s = gcc_jit_context_acquire ();\n", 1596 r.get_identifier (contexts[0])); 1597 for (unsigned i = 1; i < num_ctxts; i++) 1598 r.write (" %s = gcc_jit_context_new_child_context (%s);\n", 1599 r.get_identifier (contexts[i]), 1600 r.get_identifier (contexts[i - 1])); 1601 r.write (" set_options ("); 1602 r.write_args (contexts); 1603 r.write (");\n"); 1604 r.write (" create_code ("); 1605 r.write_args (contexts); 1606 r.write (");\n"); 1607 1608 r.write (" result = gcc_jit_context_compile (%s);\n", 1609 r.get_identifier (this)); 1610 1611 for (unsigned i = num_ctxts; i > 0; i--) 1612 r.write (" gcc_jit_context_release (%s);\n", 1613 r.get_identifier (contexts[i - 1])); 1614 1615 r.write (" gcc_jit_result_release (result);\n" 1616 " return 0;\n" 1617 "}\n\n"); 1618 1619 /* Define (char *) variables for use in calls to 1620 gcc_jit_context_enable_dump. */ 1621 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++) 1622 { 1623 if (m_requested_dumps.length ()) 1624 { 1625 r.write ("/* Requested dumps for %s. */\n", 1626 r.get_identifier (contexts[ctxt_idx])); 1627 for (unsigned i = 0; i < m_requested_dumps.length (); i++) 1628 r.write ("static char *dump_%p;\n", 1629 (void *)&m_requested_dumps[i]); 1630 r.write ("\n"); 1631 } 1632 } 1633 1634 /* Write out values of options. */ 1635 r.write ("static void\nset_options ("); 1636 r.write_params (contexts); 1637 r.write (")\n{\n"); 1638 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++) 1639 { 1640 if (ctxt_idx > 0) 1641 r.write ("\n"); 1642 1643 r.write (" /* Set options for %s. */\n", 1644 r.get_identifier (contexts[ctxt_idx])); 1645 1646 r.write (" /* String options. */\n"); 1647 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_STR_OPTIONS; opt_idx++) 1648 { 1649 r.write (" gcc_jit_context_set_str_option (%s,\n" 1650 " %s,\n", 1651 r.get_identifier (contexts[ctxt_idx]), 1652 str_option_reproducer_strings[opt_idx]); 1653 if (m_str_options[opt_idx]) 1654 r.write (" \"%s\");\n", 1655 m_str_options[opt_idx]); 1656 else 1657 r.write (" NULL);\n"); 1658 } 1659 r.write (" /* Int options. */\n"); 1660 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_INT_OPTIONS; opt_idx++) 1661 r.write (" gcc_jit_context_set_int_option (%s,\n" 1662 " %s,\n" 1663 " %i);\n", 1664 r.get_identifier (contexts[ctxt_idx]), 1665 int_option_reproducer_strings[opt_idx], 1666 m_int_options[opt_idx]); 1667 r.write (" /* Boolean options. */\n"); 1668 for (int opt_idx = 0; opt_idx < GCC_JIT_NUM_BOOL_OPTIONS; opt_idx++) 1669 r.write (" gcc_jit_context_set_bool_option (%s,\n" 1670 " %s,\n" 1671 " %i);\n", 1672 r.get_identifier (contexts[ctxt_idx]), 1673 bool_option_reproducer_strings[opt_idx], 1674 m_bool_options[opt_idx]); 1675 for (int opt_idx = 0; opt_idx < NUM_INNER_BOOL_OPTIONS; opt_idx++) 1676 r.write (" %s (%s, %i);\n", 1677 inner_bool_option_reproducer_strings[opt_idx], 1678 r.get_identifier (contexts[ctxt_idx]), 1679 m_inner_bool_options[opt_idx]); 1680 1681 if (!m_command_line_options.is_empty ()) 1682 { 1683 int i; 1684 char *optname; 1685 r.write (" /* User-provided command-line options. */\n"); 1686 FOR_EACH_VEC_ELT (m_command_line_options, i, optname) 1687 r.write (" gcc_jit_context_add_command_line_option (%s, \"%s\");\n", 1688 r.get_identifier (contexts[ctxt_idx]), 1689 optname); 1690 } 1691 1692 if (m_requested_dumps.length ()) 1693 { 1694 r.write (" /* Requested dumps. */\n"); 1695 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */ 1696 for (unsigned i = 0; i < m_requested_dumps.length (); i++) 1697 { 1698 r.write (" gcc_jit_context_enable_dump (%s,\n" 1699 " \"%s\",\n" 1700 " &dump_%p);\n", 1701 r.get_identifier (contexts[ctxt_idx]), 1702 m_requested_dumps[i].m_dumpname, 1703 (void *)&m_requested_dumps[i]); 1704 } 1705 } 1706 } 1707 r.write ("}\n\n"); 1708 1709 r.write ("static void\ncreate_code ("); 1710 r.write_params (contexts); 1711 r.write (")\n" 1712 "{\n"); 1713 for (unsigned ctxt_idx = 0; ctxt_idx < num_ctxts; ctxt_idx++) 1714 { 1715 memento *m; 1716 int i; 1717 if (ctxt_idx > 0) 1718 r.write ("\n\n"); 1719 1720 r.write (" /* Replay of API calls for %s. */\n", 1721 r.get_identifier (contexts[ctxt_idx])); 1722 FOR_EACH_VEC_ELT (contexts[ctxt_idx]->m_mementos, i, m) 1723 m->write_reproducer (r); 1724 } 1725 r.write ("}\n"); 1726} 1727 1728/* Copy the requested dumps within this context and all ancestors into 1729 OUT. */ 1730 1731void 1732recording::context::get_all_requested_dumps (vec <recording::requested_dump> *out) 1733{ 1734 if (m_parent_ctxt) 1735 m_parent_ctxt->get_all_requested_dumps (out); 1736 1737 out->reserve (m_requested_dumps.length ()); 1738 out->splice (m_requested_dumps); 1739} 1740 1741/* This is a pre-compilation check for the context (and any parents). 1742 1743 Detect errors within the context, adding errors if any are found. */ 1744 1745void 1746recording::context::validate () 1747{ 1748 JIT_LOG_SCOPE (get_logger ()); 1749 1750 if (m_parent_ctxt) 1751 m_parent_ctxt->validate (); 1752 1753 int i; 1754 function *fn; 1755 FOR_EACH_VEC_ELT (m_functions, i, fn) 1756 fn->validate (); 1757} 1758 1759/* The implementation of class gcc::jit::recording::memento. */ 1760 1761/* Get a (const char *) debug description of the given memento, by 1762 calling the pure-virtual make_debug_string hook, caching the 1763 result. 1764 1765 It is intended that this should only be called in debugging and 1766 error-handling paths, so this doesn't need to be particularly 1767 optimized. */ 1768 1769const char * 1770recording::memento::get_debug_string () 1771{ 1772 if (!m_debug_string) 1773 m_debug_string = make_debug_string (); 1774 return m_debug_string->c_str (); 1775} 1776 1777/* Default implementation of recording::memento::write_to_dump, writing 1778 an indented form of the memento's debug string to the dump. */ 1779 1780void 1781recording::memento::write_to_dump (dump &d) 1782{ 1783 d.write(" %s\n", get_debug_string ()); 1784} 1785 1786/* The implementation of class gcc::jit::recording::string. */ 1787 1788/* Constructor for gcc::jit::recording::string::string, allocating a 1789 copy of the given text using new char[]. */ 1790 1791recording::string::string (context *ctxt, const char *text) 1792 : memento (ctxt) 1793{ 1794 m_len = strlen (text); 1795 m_buffer = new char[m_len + 1]; 1796 strcpy (m_buffer, text); 1797} 1798 1799/* Destructor for gcc::jit::recording::string::string. */ 1800 1801recording::string::~string () 1802{ 1803 delete[] m_buffer; 1804} 1805 1806/* Function for making gcc::jit::recording::string instances on a 1807 context via printf-style formatting. 1808 1809 It is intended that this should only be called in debugging and 1810 error-handling paths, so this doesn't need to be particularly 1811 optimized, hence the double-copy of the string is acceptable. */ 1812 1813recording::string * 1814recording::string::from_printf (context *ctxt, const char *fmt, ...) 1815{ 1816 int len; 1817 va_list ap; 1818 char *buf; 1819 recording::string *result; 1820 1821 va_start (ap, fmt); 1822 len = vasprintf (&buf, fmt, ap); 1823 va_end (ap); 1824 1825 if (buf == NULL || len < 0) 1826 { 1827 ctxt->add_error (NULL, "malloc failure"); 1828 return NULL; 1829 } 1830 1831 result = ctxt->new_string (buf); 1832 free (buf); 1833 return result; 1834} 1835 1836/* Implementation of recording::memento::make_debug_string for strings, 1837 wrapping the given string in quotes and escaping as necessary. */ 1838 1839recording::string * 1840recording::string::make_debug_string () 1841{ 1842 /* Hack to avoid infinite recursion into strings when logging all 1843 mementos: don't re-escape strings: */ 1844 if (m_buffer[0] == '"') 1845 return this; 1846 1847 /* Wrap in quotes and do escaping etc */ 1848 1849 size_t sz = (1 /* opening quote */ 1850 + (m_len * 2) /* each char might get escaped */ 1851 + 1 /* closing quote */ 1852 + 1); /* nil termintator */ 1853 char *tmp = new char[sz]; 1854 size_t len = 0; 1855 1856#define APPEND(CH) do { gcc_assert (len < sz); tmp[len++] = (CH); } while (0) 1857 APPEND('"'); /* opening quote */ 1858 for (size_t i = 0; i < m_len ; i++) 1859 { 1860 char ch = m_buffer[i]; 1861 if (ch == '\t' || ch == '\n' || ch == '\\' || ch == '"') 1862 APPEND('\\'); 1863 APPEND(ch); 1864 } 1865 APPEND('"'); /* closing quote */ 1866#undef APPEND 1867 tmp[len] = '\0'; /* nil termintator */ 1868 1869 string *result = m_ctxt->new_string (tmp); 1870 1871 delete[] tmp; 1872 return result; 1873} 1874 1875/* Implementation of recording::memento::write_reproducer for strings. */ 1876 1877void 1878recording::string::write_reproducer (reproducer &) 1879{ 1880 /* Empty. */ 1881} 1882 1883/* The implementation of class gcc::jit::recording::location. */ 1884 1885/* Implementation of recording::memento::replay_into for locations. 1886 1887 Create a new playback::location and store it into the 1888 recording::location's m_playback_obj field. */ 1889 1890void 1891recording::location::replay_into (replayer *r) 1892{ 1893 m_playback_obj = r->new_location (this, 1894 m_filename->c_str (), 1895 m_line, 1896 m_column); 1897} 1898 1899/* Implementation of recording::memento::make_debug_string for locations, 1900 turning them into the usual form: 1901 FILENAME:LINE:COLUMN 1902 like we do when emitting diagnostics. */ 1903 1904recording::string * 1905recording::location::make_debug_string () 1906{ 1907 return string::from_printf (m_ctxt, 1908 "%s:%i:%i", 1909 m_filename->c_str (), m_line, m_column); 1910} 1911 1912/* Implementation of recording::memento::write_reproducer for locations. */ 1913 1914void 1915recording::location::write_reproducer (reproducer &r) 1916{ 1917 const char *id = r.make_identifier (this, "loc"); 1918 r.write (" gcc_jit_location *%s =\n" 1919 " gcc_jit_context_new_location (%s, /* gcc_jit_context *ctxt */\n" 1920 " %s, /* const char *filename */\n" 1921 " %i, /* int line */\n" 1922 " %i);/* int column */\n", 1923 id, 1924 r.get_identifier (get_context ()), 1925 m_filename->get_debug_string (), 1926 m_line, m_column); 1927} 1928 1929/* The implementation of class gcc::jit::recording::type. */ 1930 1931/* Given a type T, get the type T*. 1932 1933 If this doesn't already exist, generate a new memento_of_get_pointer 1934 instance and add it to this type's context's list of mementos. 1935 1936 Otherwise, use the cached type. 1937 1938 Implements the post-error-checking part of 1939 gcc_jit_type_get_pointer. */ 1940 1941recording::type * 1942recording::type::get_pointer () 1943{ 1944 if (!m_pointer_to_this_type) 1945 { 1946 m_pointer_to_this_type = new memento_of_get_pointer (this); 1947 m_ctxt->record (m_pointer_to_this_type); 1948 } 1949 return m_pointer_to_this_type; 1950} 1951 1952/* Given a type T, get the type const T. 1953 1954 Implements the post-error-checking part of 1955 gcc_jit_type_get_const. */ 1956 1957recording::type * 1958recording::type::get_const () 1959{ 1960 recording::type *result = new memento_of_get_const (this); 1961 m_ctxt->record (result); 1962 return result; 1963} 1964 1965/* Given a type T, get the type volatile T. 1966 1967 Implements the post-error-checking part of 1968 gcc_jit_type_get_volatile. */ 1969 1970recording::type * 1971recording::type::get_volatile () 1972{ 1973 recording::type *result = new memento_of_get_volatile (this); 1974 m_ctxt->record (result); 1975 return result; 1976} 1977 1978const char * 1979recording::type::access_as_type (reproducer &r) 1980{ 1981 return r.get_identifier (this); 1982} 1983 1984/* Implementation of pure virtual hook recording::type::dereference for 1985 recording::memento_of_get_type. */ 1986 1987recording::type * 1988recording::memento_of_get_type::dereference () 1989{ 1990 switch (m_kind) 1991 { 1992 default: gcc_unreachable (); 1993 1994 case GCC_JIT_TYPE_VOID: 1995 return NULL; 1996 1997 case GCC_JIT_TYPE_VOID_PTR: 1998 return m_ctxt->get_type (GCC_JIT_TYPE_VOID); 1999 2000 case GCC_JIT_TYPE_BOOL: 2001 case GCC_JIT_TYPE_CHAR: 2002 case GCC_JIT_TYPE_SIGNED_CHAR: 2003 case GCC_JIT_TYPE_UNSIGNED_CHAR: 2004 case GCC_JIT_TYPE_SHORT: 2005 case GCC_JIT_TYPE_UNSIGNED_SHORT: 2006 case GCC_JIT_TYPE_INT: 2007 case GCC_JIT_TYPE_UNSIGNED_INT: 2008 case GCC_JIT_TYPE_LONG: 2009 case GCC_JIT_TYPE_UNSIGNED_LONG: 2010 case GCC_JIT_TYPE_LONG_LONG: 2011 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG: 2012 case GCC_JIT_TYPE_FLOAT: 2013 case GCC_JIT_TYPE_DOUBLE: 2014 case GCC_JIT_TYPE_LONG_DOUBLE: 2015 case GCC_JIT_TYPE_COMPLEX_FLOAT: 2016 case GCC_JIT_TYPE_COMPLEX_DOUBLE: 2017 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE: 2018 /* Not a pointer: */ 2019 return NULL; 2020 2021 case GCC_JIT_TYPE_CONST_CHAR_PTR: 2022 return m_ctxt->get_type (GCC_JIT_TYPE_CHAR)->get_const (); 2023 2024 case GCC_JIT_TYPE_SIZE_T: 2025 /* Not a pointer: */ 2026 return NULL; 2027 2028 case GCC_JIT_TYPE_FILE_PTR: 2029 /* Give the client code back an opaque "struct FILE". */ 2030 return m_ctxt->get_opaque_FILE_type (); 2031 } 2032} 2033 2034/* Implementation of pure virtual hook recording::type::is_int for 2035 recording::memento_of_get_type. */ 2036 2037bool 2038recording::memento_of_get_type::is_int () const 2039{ 2040 switch (m_kind) 2041 { 2042 default: gcc_unreachable (); 2043 2044 case GCC_JIT_TYPE_VOID: 2045 return false; 2046 2047 case GCC_JIT_TYPE_VOID_PTR: 2048 return false; 2049 2050 case GCC_JIT_TYPE_BOOL: 2051 return false; 2052 2053 case GCC_JIT_TYPE_CHAR: 2054 case GCC_JIT_TYPE_SIGNED_CHAR: 2055 case GCC_JIT_TYPE_UNSIGNED_CHAR: 2056 case GCC_JIT_TYPE_SHORT: 2057 case GCC_JIT_TYPE_UNSIGNED_SHORT: 2058 case GCC_JIT_TYPE_INT: 2059 case GCC_JIT_TYPE_UNSIGNED_INT: 2060 case GCC_JIT_TYPE_LONG: 2061 case GCC_JIT_TYPE_UNSIGNED_LONG: 2062 case GCC_JIT_TYPE_LONG_LONG: 2063 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG: 2064 return true; 2065 2066 case GCC_JIT_TYPE_FLOAT: 2067 case GCC_JIT_TYPE_DOUBLE: 2068 case GCC_JIT_TYPE_LONG_DOUBLE: 2069 return false; 2070 2071 case GCC_JIT_TYPE_CONST_CHAR_PTR: 2072 return false; 2073 2074 case GCC_JIT_TYPE_SIZE_T: 2075 return true; 2076 2077 case GCC_JIT_TYPE_FILE_PTR: 2078 return false; 2079 2080 case GCC_JIT_TYPE_COMPLEX_FLOAT: 2081 case GCC_JIT_TYPE_COMPLEX_DOUBLE: 2082 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE: 2083 return false; 2084 } 2085} 2086 2087/* Implementation of pure virtual hook recording::type::is_float for 2088 recording::memento_of_get_type. */ 2089 2090bool 2091recording::memento_of_get_type::is_float () const 2092{ 2093 switch (m_kind) 2094 { 2095 default: gcc_unreachable (); 2096 2097 case GCC_JIT_TYPE_VOID: 2098 return false; 2099 2100 case GCC_JIT_TYPE_VOID_PTR: 2101 return false; 2102 2103 case GCC_JIT_TYPE_BOOL: 2104 return false; 2105 2106 case GCC_JIT_TYPE_CHAR: 2107 case GCC_JIT_TYPE_SIGNED_CHAR: 2108 case GCC_JIT_TYPE_UNSIGNED_CHAR: 2109 case GCC_JIT_TYPE_SHORT: 2110 case GCC_JIT_TYPE_UNSIGNED_SHORT: 2111 case GCC_JIT_TYPE_INT: 2112 case GCC_JIT_TYPE_UNSIGNED_INT: 2113 case GCC_JIT_TYPE_LONG: 2114 case GCC_JIT_TYPE_UNSIGNED_LONG: 2115 case GCC_JIT_TYPE_LONG_LONG: 2116 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG: 2117 return false; 2118 2119 case GCC_JIT_TYPE_FLOAT: 2120 case GCC_JIT_TYPE_DOUBLE: 2121 case GCC_JIT_TYPE_LONG_DOUBLE: 2122 return true; 2123 2124 case GCC_JIT_TYPE_CONST_CHAR_PTR: 2125 return false; 2126 2127 case GCC_JIT_TYPE_SIZE_T: 2128 return false; 2129 2130 case GCC_JIT_TYPE_FILE_PTR: 2131 return false; 2132 2133 case GCC_JIT_TYPE_COMPLEX_FLOAT: 2134 case GCC_JIT_TYPE_COMPLEX_DOUBLE: 2135 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE: 2136 return true; 2137 } 2138} 2139 2140/* Implementation of pure virtual hook recording::type::is_bool for 2141 recording::memento_of_get_type. */ 2142 2143bool 2144recording::memento_of_get_type::is_bool () const 2145{ 2146 switch (m_kind) 2147 { 2148 default: gcc_unreachable (); 2149 2150 case GCC_JIT_TYPE_VOID: 2151 return false; 2152 2153 case GCC_JIT_TYPE_VOID_PTR: 2154 return false; 2155 2156 case GCC_JIT_TYPE_BOOL: 2157 return true; 2158 2159 case GCC_JIT_TYPE_CHAR: 2160 case GCC_JIT_TYPE_SIGNED_CHAR: 2161 case GCC_JIT_TYPE_UNSIGNED_CHAR: 2162 case GCC_JIT_TYPE_SHORT: 2163 case GCC_JIT_TYPE_UNSIGNED_SHORT: 2164 case GCC_JIT_TYPE_INT: 2165 case GCC_JIT_TYPE_UNSIGNED_INT: 2166 case GCC_JIT_TYPE_LONG: 2167 case GCC_JIT_TYPE_UNSIGNED_LONG: 2168 case GCC_JIT_TYPE_LONG_LONG: 2169 case GCC_JIT_TYPE_UNSIGNED_LONG_LONG: 2170 return false; 2171 2172 case GCC_JIT_TYPE_FLOAT: 2173 case GCC_JIT_TYPE_DOUBLE: 2174 case GCC_JIT_TYPE_LONG_DOUBLE: 2175 return false; 2176 2177 case GCC_JIT_TYPE_CONST_CHAR_PTR: 2178 return false; 2179 2180 case GCC_JIT_TYPE_SIZE_T: 2181 return false; 2182 2183 case GCC_JIT_TYPE_FILE_PTR: 2184 return false; 2185 2186 case GCC_JIT_TYPE_COMPLEX_FLOAT: 2187 case GCC_JIT_TYPE_COMPLEX_DOUBLE: 2188 case GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE: 2189 return false; 2190 } 2191} 2192 2193/* Implementation of pure virtual hook recording::memento::replay_into 2194 for recording::memento_of_get_type. */ 2195 2196void 2197recording::memento_of_get_type::replay_into (replayer *r) 2198{ 2199 set_playback_obj (r->get_type (m_kind)); 2200} 2201 2202/* The implementation of class gcc::jit::recording::memento_of_get_type. */ 2203 2204/* Descriptive strings for each of enum gcc_jit_types. */ 2205 2206static const char * const get_type_strings[] = { 2207 "void", /* GCC_JIT_TYPE_VOID */ 2208 "void *", /* GCC_JIT_TYPE_VOID_PTR */ 2209 2210 "bool", /* GCC_JIT_TYPE_BOOL */ 2211 2212 "char", /* GCC_JIT_TYPE_CHAR */ 2213 "signed char", /* GCC_JIT_TYPE_SIGNED_CHAR */ 2214 "unsigned char", /* GCC_JIT_TYPE_UNSIGNED_CHAR */ 2215 2216 "short", /* GCC_JIT_TYPE_SHORT */ 2217 "unsigned short", /* GCC_JIT_TYPE_UNSIGNED_SHORT */ 2218 2219 "int", /* GCC_JIT_TYPE_INT */ 2220 "unsigned int", /* GCC_JIT_TYPE_UNSIGNED_INT */ 2221 2222 "long", /* GCC_JIT_TYPE_LONG */ 2223 "unsigned long", /* GCC_JIT_TYPE_UNSIGNED_LONG, */ 2224 2225 "long long", /* GCC_JIT_TYPE_LONG_LONG */ 2226 "unsigned long long", /* GCC_JIT_TYPE_UNSIGNED_LONG_LONG */ 2227 2228 "float", /* GCC_JIT_TYPE_FLOAT */ 2229 "double", /* GCC_JIT_TYPE_DOUBLE */ 2230 "long double", /* GCC_JIT_TYPE_LONG_DOUBLE */ 2231 2232 "const char *", /* GCC_JIT_TYPE_CONST_CHAR_PTR */ 2233 2234 "size_t", /* GCC_JIT_TYPE_SIZE_T */ 2235 2236 "FILE *", /* GCC_JIT_TYPE_FILE_PTR */ 2237 2238 "complex float", /* GCC_JIT_TYPE_COMPLEX_FLOAT */ 2239 "complex double", /* GCC_JIT_TYPE_COMPLEX_DOUBLE */ 2240 "complex long double" /* GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE */ 2241 2242}; 2243 2244/* Implementation of recording::memento::make_debug_string for 2245 results of get_type, using a simple table of type names. */ 2246 2247recording::string * 2248recording::memento_of_get_type::make_debug_string () 2249{ 2250 return m_ctxt->new_string (get_type_strings[m_kind]); 2251} 2252 2253static const char * const get_type_enum_strings[] = { 2254 "GCC_JIT_TYPE_VOID", 2255 "GCC_JIT_TYPE_VOID_PTR", 2256 "GCC_JIT_TYPE_BOOL", 2257 "GCC_JIT_TYPE_CHAR", 2258 "GCC_JIT_TYPE_SIGNED_CHAR", 2259 "GCC_JIT_TYPE_UNSIGNED_CHAR", 2260 "GCC_JIT_TYPE_SHORT", 2261 "GCC_JIT_TYPE_UNSIGNED_SHORT", 2262 "GCC_JIT_TYPE_INT", 2263 "GCC_JIT_TYPE_UNSIGNED_INT", 2264 "GCC_JIT_TYPE_LONG", 2265 "GCC_JIT_TYPE_UNSIGNED_LONG", 2266 "GCC_JIT_TYPE_LONG_LONG", 2267 "GCC_JIT_TYPE_UNSIGNED_LONG_LONG", 2268 "GCC_JIT_TYPE_FLOAT", 2269 "GCC_JIT_TYPE_DOUBLE", 2270 "GCC_JIT_TYPE_LONG_DOUBLE", 2271 "GCC_JIT_TYPE_CONST_CHAR_PTR", 2272 "GCC_JIT_TYPE_SIZE_T", 2273 "GCC_JIT_TYPE_FILE_PTR", 2274 "GCC_JIT_TYPE_COMPLEX_FLOAT", 2275 "GCC_JIT_TYPE_COMPLEX_DOUBLE", 2276 "GCC_JIT_TYPE_COMPLEX_LONG_DOUBLE" 2277}; 2278 2279void 2280recording::memento_of_get_type::write_reproducer (reproducer &r) 2281{ 2282 const char *id = r.make_identifier (this, "type"); 2283 r.write (" gcc_jit_type *%s = gcc_jit_context_get_type (%s, %s);\n", 2284 id, 2285 r.get_identifier (get_context ()), 2286 get_type_enum_strings[m_kind]); 2287} 2288 2289/* The implementation of class gcc::jit::recording::memento_of_get_pointer. */ 2290 2291/* Override of default implementation of 2292 recording::type::accepts_writes_from for get_pointer. 2293 2294 Require a pointer type, and allowing writes to 2295 (const T *) from a (T*), but not the other way around. */ 2296 2297bool 2298recording::memento_of_get_pointer::accepts_writes_from (type *rtype) 2299{ 2300 /* Must be a pointer type: */ 2301 type *rtype_points_to = rtype->is_pointer (); 2302 if (!rtype_points_to) 2303 return false; 2304 2305 /* It's OK to assign to a (const T *) from a (T *). */ 2306 return m_other_type->unqualified () 2307 ->accepts_writes_from (rtype_points_to); 2308} 2309 2310/* Implementation of pure virtual hook recording::memento::replay_into 2311 for recording::memento_of_get_pointer. */ 2312 2313void 2314recording::memento_of_get_pointer::replay_into (replayer *) 2315{ 2316 set_playback_obj (m_other_type->playback_type ()->get_pointer ()); 2317} 2318 2319/* Implementation of recording::memento::make_debug_string for 2320 results of get_pointer, adding " *" to the underlying type, 2321 with special-casing to handle function pointer types. */ 2322 2323recording::string * 2324recording::memento_of_get_pointer::make_debug_string () 2325{ 2326 /* Special-case function pointer types, to put the "*" in parens between 2327 the return type and the params (for one level of dereferencing, at 2328 least). */ 2329 if (function_type *fn_type = m_other_type->dyn_cast_function_type ()) 2330 return fn_type->make_debug_string_with_ptr (); 2331 2332 return string::from_printf (m_ctxt, 2333 "%s *", m_other_type->get_debug_string ()); 2334} 2335 2336/* Implementation of recording::memento::write_reproducer for get_pointer. */ 2337 2338void 2339recording::memento_of_get_pointer::write_reproducer (reproducer &r) 2340{ 2341 /* We need to special-case function pointer types; see the notes in 2342 recording::function_type::write_deferred_reproducer. */ 2343 if (function_type *fn_type = m_other_type->dyn_cast_function_type ()) 2344 { 2345 fn_type->write_deferred_reproducer (r, this); 2346 return; 2347 } 2348 2349 const char *id = r.make_identifier (this, "type"); 2350 r.write (" gcc_jit_type *%s =\n" 2351 " gcc_jit_type_get_pointer (%s);\n", 2352 id, 2353 r.get_identifier_as_type (m_other_type)); 2354} 2355 2356/* The implementation of class gcc::jit::recording::memento_of_get_const. */ 2357 2358/* Implementation of pure virtual hook recording::memento::replay_into 2359 for recording::memento_of_get_const. */ 2360 2361void 2362recording::memento_of_get_const::replay_into (replayer *) 2363{ 2364 set_playback_obj (m_other_type->playback_type ()->get_const ()); 2365} 2366 2367/* Implementation of recording::memento::make_debug_string for 2368 results of get_const, prepending "const ". */ 2369 2370recording::string * 2371recording::memento_of_get_const::make_debug_string () 2372{ 2373 return string::from_printf (m_ctxt, 2374 "const %s", m_other_type->get_debug_string ()); 2375} 2376 2377/* Implementation of recording::memento::write_reproducer for const types. */ 2378 2379void 2380recording::memento_of_get_const::write_reproducer (reproducer &r) 2381{ 2382 const char *id = r.make_identifier (this, "type"); 2383 r.write (" gcc_jit_type *%s =\n" 2384 " gcc_jit_type_get_const (%s);\n", 2385 id, 2386 r.get_identifier_as_type (m_other_type)); 2387} 2388 2389/* The implementation of class gcc::jit::recording::memento_of_get_volatile. */ 2390 2391/* Implementation of pure virtual hook recording::memento::replay_into 2392 for recording::memento_of_get_volatile. */ 2393 2394void 2395recording::memento_of_get_volatile::replay_into (replayer *) 2396{ 2397 set_playback_obj (m_other_type->playback_type ()->get_volatile ()); 2398} 2399 2400/* Implementation of recording::memento::make_debug_string for 2401 results of get_volatile, prepending "volatile ". */ 2402 2403recording::string * 2404recording::memento_of_get_volatile::make_debug_string () 2405{ 2406 return string::from_printf (m_ctxt, 2407 "volatile %s", m_other_type->get_debug_string ()); 2408} 2409 2410/* Implementation of recording::memento::write_reproducer for volatile 2411 types. */ 2412 2413void 2414recording::memento_of_get_volatile::write_reproducer (reproducer &r) 2415{ 2416 const char *id = r.make_identifier (this, "type"); 2417 r.write (" gcc_jit_type *%s =\n" 2418 " gcc_jit_type_get_volatile (%s);\n", 2419 id, 2420 r.get_identifier_as_type (m_other_type)); 2421} 2422 2423/* The implementation of class gcc::jit::recording::array_type */ 2424 2425/* Implementation of pure virtual hook recording::type::dereference for 2426 recording::array_type. */ 2427 2428recording::type * 2429recording::array_type::dereference () 2430{ 2431 return m_element_type; 2432} 2433 2434/* Implementation of pure virtual hook recording::memento::replay_into 2435 for recording::array_type. */ 2436 2437void 2438recording::array_type::replay_into (replayer *r) 2439{ 2440 set_playback_obj (r->new_array_type (playback_location (r, m_loc), 2441 m_element_type->playback_type (), 2442 m_num_elements)); 2443} 2444 2445/* Implementation of recording::memento::make_debug_string for 2446 results of new_array_type. */ 2447 2448recording::string * 2449recording::array_type::make_debug_string () 2450{ 2451 return string::from_printf (m_ctxt, 2452 "%s[%d]", 2453 m_element_type->get_debug_string (), 2454 m_num_elements); 2455} 2456 2457/* Implementation of recording::memento::write_reproducer for array 2458 types. */ 2459 2460void 2461recording::array_type::write_reproducer (reproducer &r) 2462{ 2463 const char *id = r.make_identifier (this, "array_type"); 2464 r.write (" gcc_jit_type *%s =\n" 2465 " gcc_jit_context_new_array_type (%s,\n" 2466 " %s, /* gcc_jit_location *loc */\n" 2467 " %s, /* gcc_jit_type *element_type */\n" 2468 " %i); /* int num_elements */\n", 2469 id, 2470 r.get_identifier (get_context ()), 2471 r.get_identifier (m_loc), 2472 r.get_identifier_as_type (m_element_type), 2473 m_num_elements); 2474} 2475 2476/* The implementation of class gcc::jit::recording::function_type */ 2477 2478/* Constructor for gcc::jit::recording::function_type. */ 2479 2480recording::function_type::function_type (context *ctxt, 2481 type *return_type, 2482 int num_params, 2483 type **param_types, 2484 int is_variadic) 2485: type (ctxt), 2486 m_return_type (return_type), 2487 m_param_types (), 2488 m_is_variadic (is_variadic) 2489{ 2490 for (int i = 0; i< num_params; i++) 2491 m_param_types.safe_push (param_types[i]); 2492} 2493 2494/* Implementation of pure virtual hook recording::type::dereference for 2495 recording::function_type. */ 2496 2497recording::type * 2498recording::function_type::dereference () 2499{ 2500 return NULL; 2501} 2502 2503/* Implementation of pure virtual hook recording::memento::replay_into 2504 for recording::function_type. */ 2505 2506void 2507recording::function_type::replay_into (replayer *r) 2508{ 2509 /* Convert m_param_types to a vec of playback type. */ 2510 auto_vec <playback::type *> param_types; 2511 int i; 2512 recording::type *type; 2513 param_types.create (m_param_types.length ()); 2514 FOR_EACH_VEC_ELT (m_param_types, i, type) 2515 param_types.safe_push (type->playback_type ()); 2516 2517 set_playback_obj (r->new_function_type (m_return_type->playback_type (), 2518 ¶m_types, 2519 m_is_variadic)); 2520} 2521 2522/* Special-casing for make_debug_string for get_pointer results for 2523 handling (one level) of pointers to functions. */ 2524 2525recording::string * 2526recording::function_type::make_debug_string_with_ptr () 2527{ 2528 return make_debug_string_with ("(*) "); 2529} 2530 2531/* Implementation of recording::memento::make_debug_string for 2532 results of new_function_type. */ 2533 2534recording::string * 2535recording::function_type::make_debug_string () 2536{ 2537 return make_debug_string_with (""); 2538} 2539 2540/* Build a debug string representation of the form: 2541 2542 RESULT_TYPE INSERT (PARAM_TYPES) 2543 2544 for use when handling 0 and 1 level of indirection to this 2545 function type. */ 2546 2547recording::string * 2548recording::function_type::make_debug_string_with (const char *insert) 2549{ 2550 /* First, build a buffer for the arguments. */ 2551 /* Calculate length of said buffer. */ 2552 size_t sz = 1; /* nil terminator */ 2553 for (unsigned i = 0; i< m_param_types.length (); i++) 2554 { 2555 sz += strlen (m_param_types[i]->get_debug_string ()); 2556 sz += 2; /* ", " separator */ 2557 } 2558 if (m_is_variadic) 2559 sz += 5; /* ", ..." separator and ellipsis */ 2560 2561 /* Now allocate and populate the buffer. */ 2562 char *argbuf = new char[sz]; 2563 size_t len = 0; 2564 2565 for (unsigned i = 0; i< m_param_types.length (); i++) 2566 { 2567 strcpy (argbuf + len, m_param_types[i]->get_debug_string ()); 2568 len += strlen (m_param_types[i]->get_debug_string ()); 2569 if (i + 1 < m_param_types.length ()) 2570 { 2571 strcpy (argbuf + len, ", "); 2572 len += 2; 2573 } 2574 } 2575 if (m_is_variadic) 2576 { 2577 if (m_param_types.length ()) 2578 { 2579 strcpy (argbuf + len, ", "); 2580 len += 2; 2581 } 2582 strcpy (argbuf + len, "..."); 2583 len += 3; 2584 } 2585 argbuf[len] = '\0'; 2586 2587 /* ...and use it to get the string for the call as a whole. */ 2588 string *result = string::from_printf (m_ctxt, 2589 "%s %s(%s)", 2590 m_return_type->get_debug_string (), 2591 insert, 2592 argbuf); 2593 2594 delete[] argbuf; 2595 2596 return result; 2597} 2598 2599/* Implementation of recording::memento::write_reproducer for function 2600 types. */ 2601 2602void 2603recording::function_type::write_reproducer (reproducer &) 2604{ 2605 /* see notes below. */ 2606} 2607 2608/* There's a get_pointer within context::new_function_ptr_type: 2609 the type received by client code isn't the memento for the 2610 function_type, but instead the result of get_pointer on it. 2611 2612 Hence we can't directly write a reproducer that gives function_type. 2613 Instead we special-case things within get_pointer, detecting this 2614 case, calling the following function. */ 2615 2616void 2617recording::function_type::write_deferred_reproducer (reproducer &r, 2618 memento *ptr_type) 2619{ 2620 gcc_assert (ptr_type); 2621 r.make_identifier (this, "function_type"); 2622 const char *ptr_id = r.make_identifier (ptr_type, "ptr_to"); 2623 const char *param_types_id = r.make_tmp_identifier ("params_for", this); 2624 r.write (" gcc_jit_type *%s[%i] = {\n", 2625 param_types_id, 2626 m_param_types.length ()); 2627 int i; 2628 type *param_type; 2629 FOR_EACH_VEC_ELT (m_param_types, i, param_type) 2630 r.write (" %s,\n", r.get_identifier_as_type (param_type)); 2631 r.write (" };\n"); 2632 r.write (" gcc_jit_type *%s =\n" 2633 " gcc_jit_context_new_function_ptr_type (%s, /* gcc_jit_context *ctxt */\n" 2634 " %s, /* gcc_jit_location *loc */\n" 2635 " %s, /* gcc_jit_type *return_type */\n" 2636 " %i, /* int num_params */\n" 2637 " %s, /* gcc_jit_type **param_types */\n" 2638 " %i); /* int is_variadic */\n", 2639 ptr_id, 2640 r.get_identifier (get_context ()), 2641 "NULL", /* location is not stored */ 2642 r.get_identifier_as_type (m_return_type), 2643 m_param_types.length (), 2644 param_types_id, 2645 m_is_variadic); 2646} 2647 2648/* The implementation of class gcc::jit::recording::field. */ 2649 2650/* Implementation of pure virtual hook recording::memento::replay_into 2651 for recording::field. */ 2652 2653void 2654recording::field::replay_into (replayer *r) 2655{ 2656 set_playback_obj (r->new_field (playback_location (r, m_loc), 2657 m_type->playback_type (), 2658 playback_string (m_name))); 2659} 2660 2661/* Override the default implementation of 2662 recording::memento::write_to_dump. Dump each field 2663 by dumping a line of the form: 2664 TYPE NAME; 2665 so that we can build up a struct/union field-byfield. */ 2666 2667void 2668recording::field::write_to_dump (dump &d) 2669{ 2670 d.write (" %s %s;\n", 2671 m_type->get_debug_string (), 2672 m_name->c_str ()); 2673} 2674 2675/* Implementation of recording::memento::make_debug_string for 2676 results of new_field. */ 2677 2678recording::string * 2679recording::field::make_debug_string () 2680{ 2681 return m_name; 2682} 2683 2684/* Implementation of recording::memento::write_reproducer for fields. */ 2685 2686void 2687recording::field::write_reproducer (reproducer &r) 2688{ 2689 const char *id = r.make_identifier (this, "field"); 2690 r.write(" gcc_jit_field *%s =\n" 2691 " gcc_jit_context_new_field (%s,\n" 2692 " %s, /* gcc_jit_location *loc */\n" 2693 " %s, /* gcc_jit_type *type, */\n" 2694 " %s); /* const char *name */\n", 2695 id, 2696 r.get_identifier (get_context ()), 2697 r.get_identifier (m_loc), 2698 r.get_identifier_as_type (m_type), 2699 m_name->get_debug_string ()); 2700} 2701 2702/* The implementation of class gcc::jit::recording::compound_type */ 2703 2704/* The constructor for gcc::jit::recording::compound_type. */ 2705 2706recording::compound_type::compound_type (context *ctxt, 2707 location *loc, 2708 string *name) 2709: type (ctxt), 2710 m_loc (loc), 2711 m_name (name), 2712 m_fields (NULL) 2713{ 2714} 2715 2716/* Set the fields of a compound type. 2717 2718 Implements the post-error-checking part of 2719 gcc_jit_struct_set_fields, and is also used by 2720 gcc_jit_context_new_union_type. */ 2721 2722void 2723recording::compound_type::set_fields (location *loc, 2724 int num_fields, 2725 field **field_array) 2726{ 2727 m_loc = loc; 2728 gcc_assert (NULL == m_fields); 2729 2730 m_fields = new fields (this, num_fields, field_array); 2731 m_ctxt->record (m_fields); 2732} 2733 2734/* Implementation of pure virtual hook recording::type::dereference for 2735 recording::compound_type. */ 2736 2737recording::type * 2738recording::compound_type::dereference () 2739{ 2740 return NULL; /* not a pointer */ 2741} 2742 2743/* The implementation of class gcc::jit::recording::struct_. */ 2744 2745/* The constructor for gcc::jit::recording::struct_. */ 2746 2747recording::struct_::struct_ (context *ctxt, 2748 location *loc, 2749 string *name) 2750: compound_type (ctxt, loc, name) 2751{ 2752} 2753 2754/* Implementation of pure virtual hook recording::memento::replay_into 2755 for recording::struct_. */ 2756 2757void 2758recording::struct_::replay_into (replayer *r) 2759{ 2760 set_playback_obj ( 2761 r->new_compound_type (playback_location (r, get_loc ()), 2762 get_name ()->c_str (), 2763 true /* is_struct */)); 2764} 2765 2766const char * 2767recording::struct_::access_as_type (reproducer &r) 2768{ 2769 return r.xstrdup_printf ("gcc_jit_struct_as_type (%s)", 2770 r.get_identifier (this)); 2771} 2772 2773/* Implementation of recording::memento::make_debug_string for 2774 structs. */ 2775 2776recording::string * 2777recording::struct_::make_debug_string () 2778{ 2779 return string::from_printf (m_ctxt, 2780 "struct %s", get_name ()->c_str ()); 2781} 2782 2783void 2784recording::struct_::write_reproducer (reproducer &r) 2785{ 2786 const char *id = r.make_identifier (this, "struct"); 2787 r.write (" gcc_jit_struct *%s =\n" 2788 " gcc_jit_context_new_opaque_struct (%s,\n" 2789 " %s, /* gcc_jit_location *loc */\n" 2790 " %s); /* const char *name */\n", 2791 id, 2792 r.get_identifier (get_context ()), 2793 r.get_identifier (get_loc ()), 2794 get_name ()->get_debug_string ()); 2795} 2796 2797/* The implementation of class gcc::jit::recording::union_. */ 2798 2799/* The constructor for gcc::jit::recording::union_. */ 2800 2801recording::union_::union_ (context *ctxt, 2802 location *loc, 2803 string *name) 2804: compound_type (ctxt, loc, name) 2805{ 2806} 2807 2808/* Implementation of pure virtual hook recording::memento::replay_into 2809 for recording::union_. */ 2810 2811void 2812recording::union_::replay_into (replayer *r) 2813{ 2814 set_playback_obj ( 2815 r->new_compound_type (playback_location (r, get_loc ()), 2816 get_name ()->c_str (), 2817 false /* is_struct */)); 2818} 2819 2820/* Implementation of recording::memento::make_debug_string for 2821 unions. */ 2822 2823recording::string * 2824recording::union_::make_debug_string () 2825{ 2826 return string::from_printf (m_ctxt, 2827 "union %s", get_name ()->c_str ()); 2828} 2829 2830/* Implementation of recording::memento::write_reproducer for unions. */ 2831 2832void 2833recording::union_::write_reproducer (reproducer &r) 2834{ 2835 const char *id = r.make_identifier (this, "union"); 2836 2837 const char *fields_id = r.make_tmp_identifier ("fields_for", this); 2838 r.write (" gcc_jit_field *%s[%i] = {\n", 2839 fields_id, 2840 get_fields ()->length ()); 2841 for (int i = 0; i < get_fields ()->length (); i++) 2842 r.write (" %s,\n", r.get_identifier (get_fields ()->get_field (i))); 2843 r.write (" };\n"); 2844 2845 r.write (" gcc_jit_type *%s =\n" 2846 " gcc_jit_context_new_union_type (%s,\n" 2847 " %s, /* gcc_jit_location *loc */\n" 2848 " %s, /* const char *name */\n" 2849 " %i, /* int num_fields */\n" 2850 " %s); /* gcc_jit_field **fields */\n", 2851 id, 2852 r.get_identifier (get_context ()), 2853 r.get_identifier (get_loc ()), 2854 get_name ()->get_debug_string (), 2855 get_fields ()->length (), 2856 fields_id); 2857} 2858 2859/* The implementation of class gcc::jit::recording::fields. */ 2860 2861/* The constructor for gcc::jit::recording::fields. */ 2862 2863recording::fields::fields (compound_type *struct_or_union, 2864 int num_fields, 2865 field **fields) 2866: memento (struct_or_union->m_ctxt), 2867 m_struct_or_union (struct_or_union), 2868 m_fields () 2869{ 2870 for (int i = 0; i < num_fields; i++) 2871 { 2872 gcc_assert (fields[i]->get_container () == NULL); 2873 fields[i]->set_container (m_struct_or_union); 2874 m_fields.safe_push (fields[i]); 2875 } 2876} 2877 2878/* Implementation of pure virtual hook recording::memento::replay_into 2879 for recording::fields. */ 2880 2881void 2882recording::fields::replay_into (replayer *) 2883{ 2884 auto_vec<playback::field *> playback_fields; 2885 playback_fields.create (m_fields.length ()); 2886 for (unsigned i = 0; i < m_fields.length (); i++) 2887 playback_fields.safe_push (m_fields[i]->playback_field ()); 2888 m_struct_or_union->playback_compound_type ()->set_fields (&playback_fields); 2889} 2890 2891/* Override the default implementation of 2892 recording::memento::write_to_dump by writing a union/struct 2893 declaration of this form: 2894 2895 struct/union NAME { 2896 TYPE_1 NAME_1; 2897 TYPE_2 NAME_2; 2898 .... 2899 TYPE_N NAME_N; 2900 }; 2901 2902 to the dump. */ 2903 2904void 2905recording::fields::write_to_dump (dump &d) 2906{ 2907 int i; 2908 field *f; 2909 2910 d.write ("%s\n{\n", m_struct_or_union->get_debug_string ()); 2911 FOR_EACH_VEC_ELT (m_fields, i, f) 2912 f->write_to_dump (d); 2913 d.write ("};\n"); 2914} 2915 2916/* Implementation of recording::memento::write_reproducer for the fields 2917 subclass. */ 2918 2919void 2920recording::fields::write_reproducer (reproducer &r) 2921{ 2922 if (m_struct_or_union) 2923 if (NULL == m_struct_or_union->dyn_cast_struct ()) 2924 /* We have a union; the fields have already been written by 2925 union::write_reproducer. */ 2926 return; 2927 2928 const char *fields_id = r.make_identifier (this, "fields"); 2929 r.write (" gcc_jit_field *%s[%i] = {\n", 2930 fields_id, 2931 m_fields.length ()); 2932 int i; 2933 field *field; 2934 FOR_EACH_VEC_ELT (m_fields, i, field) 2935 r.write (" %s,\n", r.get_identifier (field)); 2936 r.write (" };\n"); 2937 2938 r.write (" gcc_jit_struct_set_fields (%s, /* gcc_jit_struct *struct_type */\n" 2939 " %s, /* gcc_jit_location *loc */\n" 2940 " %i, /* int num_fields */\n" 2941 " %s); /* gcc_jit_field **fields */\n", 2942 r.get_identifier (m_struct_or_union), 2943 r.get_identifier ((memento *)NULL), 2944 m_fields.length (), 2945 fields_id); 2946} 2947 2948/* Implementation of recording::memento::make_debug_string for 2949 field tables. */ 2950 2951recording::string * 2952recording::fields::make_debug_string () 2953{ 2954 return string::from_printf (m_ctxt, 2955 "fields"); 2956} 2957 2958/* The implementation of class gcc::jit::recording::rvalue. */ 2959 2960/* Create a recording::access_field_rvalue instance and add it to 2961 the rvalue's context's list of mementos. 2962 2963 Implements the post-error-checking part of 2964 gcc_jit_rvalue_access_field. */ 2965 2966recording::rvalue * 2967recording::rvalue::access_field (recording::location *loc, 2968 field *field) 2969{ 2970 recording::rvalue *result = 2971 new access_field_rvalue (m_ctxt, loc, this, field); 2972 m_ctxt->record (result); 2973 return result; 2974} 2975 2976/* Create a recording::dereference_field_rvalue instance and add it to 2977 the rvalue's context's list of mementos. 2978 2979 Implements the post-error-checking part of 2980 gcc_jit_rvalue_dereference_field. */ 2981 2982recording::lvalue * 2983recording::rvalue::dereference_field (recording::location *loc, 2984 field *field) 2985{ 2986 recording::lvalue *result = 2987 new dereference_field_rvalue (m_ctxt, loc, this, field); 2988 m_ctxt->record (result); 2989 return result; 2990} 2991 2992/* Create a recording::dereference_rvalue instance and add it to the 2993 rvalue's context's list of mementos. 2994 2995 Implements the post-error-checking part of 2996 gcc_jit_rvalue_dereference. */ 2997 2998recording::lvalue * 2999recording::rvalue::dereference (recording::location *loc) 3000{ 3001 recording::lvalue *result = 3002 new dereference_rvalue (m_ctxt, loc, this); 3003 m_ctxt->record (result); 3004 return result; 3005} 3006 3007/* An rvalue visitor, for validating that every rvalue within an expression 3008 trees within "STMT" has the correct scope (e.g. no access to locals 3009 of a different function). */ 3010 3011class rvalue_usage_validator : public recording::rvalue_visitor 3012{ 3013 public: 3014 rvalue_usage_validator (const char *api_funcname, 3015 recording::context *ctxt, 3016 recording::statement *stmt); 3017 3018 void 3019 visit (recording::rvalue *rvalue); 3020 3021 private: 3022 const char *m_api_funcname; 3023 recording::context *m_ctxt; 3024 recording::statement *m_stmt; 3025}; 3026 3027/* The trivial constructor for rvalue_usage_validator. */ 3028 3029rvalue_usage_validator::rvalue_usage_validator (const char *api_funcname, 3030 recording::context *ctxt, 3031 recording::statement *stmt) 3032 : m_api_funcname (api_funcname), 3033 m_ctxt (ctxt), 3034 m_stmt (stmt) 3035{ 3036} 3037 3038/* Verify that the given rvalue is in the correct scope. */ 3039 3040void 3041rvalue_usage_validator::visit (recording::rvalue *rvalue) 3042{ 3043 gcc_assert (m_stmt->get_block ()); 3044 recording::function *stmt_scope = m_stmt->get_block ()->get_function (); 3045 3046 /* Most rvalues don't have a scope (only locals and params). */ 3047 if (rvalue->get_scope ()) 3048 { 3049 if (rvalue->get_scope () != stmt_scope) 3050 m_ctxt->add_error 3051 (rvalue->get_loc (), 3052 "%s:" 3053 " rvalue %s (type: %s)" 3054 " has scope limited to function %s" 3055 " but was used within function %s" 3056 " (in statement: %s)", 3057 m_api_funcname, 3058 rvalue->get_debug_string (), 3059 rvalue->get_type ()->get_debug_string (), 3060 rvalue->get_scope ()->get_debug_string (), 3061 stmt_scope->get_debug_string (), 3062 m_stmt->get_debug_string ()); 3063 } 3064 else 3065 { 3066 if (rvalue->dyn_cast_param ()) 3067 m_ctxt->add_error 3068 (rvalue->get_loc (), 3069 "%s:" 3070 " param %s (type: %s)" 3071 " was used within function %s" 3072 " (in statement: %s)" 3073 " but is not associated with any function", 3074 m_api_funcname, 3075 rvalue->get_debug_string (), 3076 rvalue->get_type ()->get_debug_string (), 3077 stmt_scope->get_debug_string (), 3078 m_stmt->get_debug_string ()); 3079 } 3080} 3081 3082/* Verify that it's valid to use this rvalue (and all expressions 3083 in the tree below it) within the given statement. 3084 3085 For example, we must reject attempts to use a local from one 3086 function within a different function here, or we'll get 3087 an ICE deep inside toplev::main. */ 3088 3089void 3090recording::rvalue::verify_valid_within_stmt (const char *api_funcname, statement *s) 3091{ 3092 rvalue_usage_validator v (api_funcname, 3093 s->get_context (), 3094 s); 3095 3096 /* Verify that it's OK to use this rvalue within s. */ 3097 v.visit (this); 3098 3099 /* Traverse the expression tree below "this", verifying all rvalues 3100 within it. */ 3101 visit_children (&v); 3102} 3103 3104/* Set the scope of this rvalue to be the given function. This can only 3105 be done once on a given rvalue. */ 3106 3107void 3108recording::rvalue::set_scope (function *scope) 3109{ 3110 gcc_assert (scope); 3111 gcc_assert (NULL == m_scope); 3112 m_scope = scope; 3113} 3114 3115 3116/* Implementation of recording::rvalue::access_as_rvalue for rvalues 3117 themselves. 3118 Instances of rvalue don't need an upcast call. */ 3119 3120const char * 3121recording::rvalue::access_as_rvalue (reproducer &r) 3122{ 3123 return r.get_identifier (this); 3124} 3125 3126/* Return a debug string for the given rvalue, wrapping it in parentheses 3127 if needed to mimic C's precedence rules, i.e. if OUTER_PREC is of 3128 stronger precedence that this rvalue's precedence. 3129 3130 For example, given: 3131 3132 MULT 3133 / \ 3134 PLUS MINUS 3135 / \ / \ 3136 A B C D 3137 3138 we want to emit: 3139 3140 (A + B) * (C - D) 3141 3142 since MULT has strong precedence than PLUS and MINUS, whereas for: 3143 3144 PLUS 3145 / \ 3146 MULT DIVIDE 3147 / \ / \ 3148 A B C D 3149 3150 we can simply emit: 3151 3152 A * B + C / D 3153 3154 since PLUS has weaker precedence than MULT and DIVIDE. */ 3155 3156const char * 3157recording::rvalue::get_debug_string_parens (enum precedence outer_prec) 3158{ 3159 enum precedence this_prec = get_precedence (); 3160 3161 /* If this_prec has stronger precedence than outer_prec, we don't 3162 need to wrap this in parens within the outer debug string. 3163 Stronger precedences occur earlier than weaker within the enum, 3164 so this is a less than test. Equal precedences don't need 3165 parentheses. */ 3166 if (this_prec <= outer_prec) 3167 return get_debug_string(); 3168 3169 /* Otherwise, we need parentheses. */ 3170 3171 /* Lazily-build and cache m_parenthesized_string. */ 3172 if (!m_parenthesized_string) 3173 { 3174 const char *debug_string = get_debug_string (); 3175 m_parenthesized_string = string::from_printf (get_context (), 3176 "(%s)", 3177 debug_string); 3178 } 3179 gcc_assert (m_parenthesized_string); 3180 return m_parenthesized_string->c_str (); 3181} 3182 3183 3184/* The implementation of class gcc::jit::recording::lvalue. */ 3185 3186/* Create a recording::new_access_field_of_lvalue instance and add it to 3187 the lvalue's context's list of mementos. 3188 3189 Implements the post-error-checking part of 3190 gcc_jit_lvalue_access_field. */ 3191 3192recording::lvalue * 3193recording::lvalue::access_field (recording::location *loc, 3194 field *field) 3195{ 3196 recording::lvalue *result = 3197 new access_field_of_lvalue (m_ctxt, loc, this, field); 3198 m_ctxt->record (result); 3199 return result; 3200} 3201 3202/* Implementation of recording::rvalue::access_as_rvalue for lvalues. 3203 Instances of lvalue need to be wrapped in a gcc_jit_lvalue_as_rvalue 3204 upcast call. */ 3205 3206const char * 3207recording::lvalue::access_as_rvalue (reproducer &r) 3208{ 3209 return r.xstrdup_printf ("gcc_jit_lvalue_as_rvalue (%s)", 3210 r.get_identifier (this)); 3211} 3212 3213/* Implementation of recording::lvalue::access_as_lvalue for lvalues. 3214 Instances of lvalue don't need to be upcast. */ 3215 3216const char * 3217recording::lvalue::access_as_lvalue (reproducer &r) 3218{ 3219 return r.get_identifier (this); 3220} 3221 3222/* Create a recording::get_address_of_lvalue instance and add it to 3223 the lvalue's context's list of mementos. 3224 3225 Implements the post-error-checking part of 3226 gcc_jit_lvalue_get_address. */ 3227 3228recording::rvalue * 3229recording::lvalue::get_address (recording::location *loc) 3230{ 3231 recording::rvalue *result = 3232 new get_address_of_lvalue (m_ctxt, loc, this); 3233 m_ctxt->record (result); 3234 return result; 3235} 3236 3237/* The implementation of class gcc::jit::recording::param. */ 3238 3239/* Implementation of pure virtual hook recording::memento::replay_into 3240 for recording::param. */ 3241 3242void 3243recording::param::replay_into (replayer *r) 3244{ 3245 set_playback_obj (r->new_param (playback_location (r, m_loc), 3246 m_type->playback_type (), 3247 m_name->c_str ())); 3248} 3249 3250/* Implementation of recording::rvalue::access_as_rvalue for params. 3251 Instances of param need to be wrapped in a gcc_jit_param_as_rvalue 3252 upcast call. */ 3253 3254const char * 3255recording::param::access_as_rvalue (reproducer &r) 3256{ 3257 return r.xstrdup_printf ("gcc_jit_param_as_rvalue (%s)", 3258 r.get_identifier (this)); 3259} 3260 3261/* Implementation of recording::lvalue::access_as_lvalue for params. 3262 Instances of param need to be wrapped in a gcc_jit_param_as_lvalue 3263 upcast call. */ 3264 3265const char * 3266recording::param::access_as_lvalue (reproducer &r) 3267{ 3268 return r.xstrdup_printf ("gcc_jit_param_as_lvalue (%s)", 3269 r.get_identifier (this)); 3270} 3271 3272/* Implementation of recording::memento::write_reproducer for params. */ 3273 3274void 3275recording::param::write_reproducer (reproducer &r) 3276{ 3277 const char *id = r.make_identifier (this, "param"); 3278 r.write (" gcc_jit_param *%s =\n" 3279 " gcc_jit_context_new_param (%s,\n" 3280 " %s, /* gcc_jit_location *loc */\n" 3281 " %s, /*gcc_jit_type *type */\n" 3282 " %s); /* const char *name */\n", 3283 id, 3284 r.get_identifier (get_context ()), 3285 r.get_identifier (m_loc), 3286 r.get_identifier_as_type (m_type), 3287 m_name->get_debug_string ()); 3288} 3289 3290/* The implementation of class gcc::jit::recording::function. */ 3291 3292/* gcc::jit::recording::function's constructor. */ 3293 3294recording::function::function (context *ctxt, 3295 recording::location *loc, 3296 enum gcc_jit_function_kind kind, 3297 type *return_type, 3298 recording::string *name, 3299 int num_params, 3300 recording::param **params, 3301 int is_variadic, 3302 enum built_in_function builtin_id) 3303: memento (ctxt), 3304 m_loc (loc), 3305 m_kind (kind), 3306 m_return_type (return_type), 3307 m_name (name), 3308 m_params (), 3309 m_is_variadic (is_variadic), 3310 m_builtin_id (builtin_id), 3311 m_locals (), 3312 m_blocks () 3313{ 3314 for (int i = 0; i< num_params; i++) 3315 { 3316 param *param = params[i]; 3317 gcc_assert (param); 3318 3319 /* Associate each param with this function. 3320 3321 Verify that the param doesn't already have a function. */ 3322 if (param->get_scope ()) 3323 { 3324 /* We've already rejected attempts to reuse a param between 3325 different functions (within gcc_jit_context_new_function), so 3326 if the param *does* already have a function, it must be being 3327 reused within the params array for this function. We must 3328 produce an error for this reuse (blocking the compile), since 3329 otherwise we'd have an ICE later on. */ 3330 gcc_assert (this == param->get_scope ()); 3331 ctxt->add_error 3332 (loc, 3333 "gcc_jit_context_new_function:" 3334 " parameter %s (type: %s)" 3335 " is used more than once when creating function %s", 3336 param->get_debug_string (), 3337 param->get_type ()->get_debug_string (), 3338 name->c_str ()); 3339 } 3340 else 3341 { 3342 /* The normal, non-error case: associate this function with the 3343 param. */ 3344 param->set_scope (this); 3345 } 3346 3347 m_params.safe_push (param); 3348 } 3349} 3350 3351/* Implementation of pure virtual hook recording::memento::replay_into 3352 for recording::function. */ 3353 3354void 3355recording::function::replay_into (replayer *r) 3356{ 3357 /* Convert m_params to a vec of playback param. */ 3358 auto_vec <playback::param *> params; 3359 int i; 3360 recording::param *param; 3361 params.create (m_params.length ()); 3362 FOR_EACH_VEC_ELT (m_params, i, param) 3363 params.safe_push (param->playback_param ()); 3364 3365 set_playback_obj (r->new_function (playback_location (r, m_loc), 3366 m_kind, 3367 m_return_type->playback_type (), 3368 m_name->c_str (), 3369 ¶ms, 3370 m_is_variadic, 3371 m_builtin_id)); 3372} 3373 3374/* Create a recording::local instance and add it to 3375 the functions's context's list of mementos, and to the function's 3376 list of locals. 3377 3378 Implements the post-error-checking part of 3379 gcc_jit_function_new_local. */ 3380 3381recording::lvalue * 3382recording::function::new_local (recording::location *loc, 3383 type *type, 3384 const char *name) 3385{ 3386 local *result = new local (this, loc, type, new_string (name)); 3387 m_ctxt->record (result); 3388 m_locals.safe_push (result); 3389 return result; 3390} 3391 3392/* Create a recording::block instance and add it to 3393 the functions's context's list of mementos, and to the function's 3394 list of blocks. 3395 3396 Implements the post-error-checking part of 3397 gcc_jit_function_new_block. */ 3398 3399recording::block* 3400recording::function::new_block (const char *name) 3401{ 3402 gcc_assert (m_kind != GCC_JIT_FUNCTION_IMPORTED); 3403 3404 recording::block *result = 3405 new recording::block (this, m_blocks.length (), new_string (name)); 3406 m_ctxt->record (result); 3407 m_blocks.safe_push (result); 3408 return result; 3409} 3410 3411/* Override the default implementation of 3412 recording::memento::write_to_dump by dumping a C-like 3413 representation of the function; either like a prototype 3414 for GCC_JIT_FUNCTION_IMPORTED, or like a full definition for 3415 all other kinds of function. */ 3416 3417void 3418recording::function::write_to_dump (dump &d) 3419{ 3420 switch (m_kind) 3421 { 3422 default: gcc_unreachable (); 3423 case GCC_JIT_FUNCTION_EXPORTED: 3424 case GCC_JIT_FUNCTION_IMPORTED: 3425 d.write ("extern "); 3426 break; 3427 case GCC_JIT_FUNCTION_INTERNAL: 3428 d.write ("static "); 3429 break; 3430 case GCC_JIT_FUNCTION_ALWAYS_INLINE: 3431 d.write ("static inline "); 3432 break; 3433 } 3434 d.write ("%s\n", m_return_type->get_debug_string ()); 3435 3436 if (d.update_locations ()) 3437 m_loc = d.make_location (); 3438 3439 d.write ("%s (", get_debug_string ()); 3440 3441 int i; 3442 recording::param *param; 3443 FOR_EACH_VEC_ELT (m_params, i, param) 3444 { 3445 if (i > 0) 3446 d.write (", "); 3447 d.write ("%s %s", 3448 param->get_type ()->get_debug_string (), 3449 param->get_debug_string ()); 3450 } 3451 d.write (")"); 3452 if (m_kind == GCC_JIT_FUNCTION_IMPORTED) 3453 { 3454 d.write ("; /* (imported) */\n\n"); 3455 } 3456 else 3457 { 3458 int i; 3459 local *var = NULL; 3460 block *b; 3461 d.write ("\n{\n"); 3462 3463 /* Write locals: */ 3464 FOR_EACH_VEC_ELT (m_locals, i, var) 3465 var->write_to_dump (d); 3466 if (m_locals.length ()) 3467 d.write ("\n"); 3468 3469 /* Write each block: */ 3470 FOR_EACH_VEC_ELT (m_blocks, i, b) 3471 { 3472 if (i > 0) 3473 d.write ("\n"); 3474 b->write_to_dump (d); 3475 } 3476 3477 d.write ("}\n\n"); 3478 } 3479} 3480 3481/* Pre-compilation validation of a function, for those things we can't 3482 check until the context is (supposedly) fully-populated. */ 3483 3484void 3485recording::function::validate () 3486{ 3487 /* Complain about empty functions with non-void return type. */ 3488 if (m_kind != GCC_JIT_FUNCTION_IMPORTED 3489 && m_return_type != m_ctxt->get_type (GCC_JIT_TYPE_VOID)) 3490 if (0 == m_blocks.length ()) 3491 m_ctxt->add_error (m_loc, 3492 "function %s returns non-void (type: %s)" 3493 " but has no blocks", 3494 get_debug_string (), 3495 m_return_type->get_debug_string ()); 3496 3497 /* Check that all blocks are terminated. */ 3498 int num_invalid_blocks = 0; 3499 { 3500 int i; 3501 block *b; 3502 3503 FOR_EACH_VEC_ELT (m_blocks, i, b) 3504 if (!b->validate ()) 3505 num_invalid_blocks++; 3506 } 3507 3508 /* Check that all blocks are reachable. */ 3509 if (!m_ctxt->get_inner_bool_option 3510 (INNER_BOOL_OPTION_ALLOW_UNREACHABLE_BLOCKS) 3511 && m_blocks.length () > 0 && 0 == num_invalid_blocks) 3512 { 3513 /* Iteratively walk the graph of blocks, marking their "m_is_reachable" 3514 flag, starting at the initial block. */ 3515 auto_vec<block *> worklist (m_blocks.length ()); 3516 worklist.safe_push (m_blocks[0]); 3517 while (worklist.length () > 0) 3518 { 3519 block *b = worklist.pop (); 3520 b->m_is_reachable = true; 3521 3522 /* Add successor blocks that aren't yet marked to the worklist. */ 3523 /* We checked that each block has a terminating statement above . */ 3524 vec <block *> successors = b->get_successor_blocks (); 3525 int i; 3526 block *succ; 3527 FOR_EACH_VEC_ELT (successors, i, succ) 3528 if (!succ->m_is_reachable) 3529 worklist.safe_push (succ); 3530 successors.release (); 3531 } 3532 3533 /* Now complain about any blocks that haven't been marked. */ 3534 { 3535 int i; 3536 block *b; 3537 FOR_EACH_VEC_ELT (m_blocks, i, b) 3538 if (!b->m_is_reachable) 3539 m_ctxt->add_error (b->get_loc (), 3540 "unreachable block: %s", 3541 b->get_debug_string ()); 3542 } 3543 } 3544} 3545 3546/* Implements the post-error-checking part of 3547 gcc_jit_function_dump_to_dot. */ 3548 3549void 3550recording::function::dump_to_dot (const char *path) 3551{ 3552 FILE *fp = fopen (path, "w"); 3553 if (!fp) 3554 return; 3555 3556 pretty_printer the_pp; 3557 the_pp.buffer->stream = fp; 3558 3559 pretty_printer *pp = &the_pp; 3560 3561 pp_printf (pp, 3562 "digraph %s {\n", get_debug_string ()); 3563 3564 /* Blocks: */ 3565 { 3566 int i; 3567 block *b; 3568 FOR_EACH_VEC_ELT (m_blocks, i, b) 3569 b->dump_to_dot (pp); 3570 } 3571 3572 /* Edges: */ 3573 { 3574 int i; 3575 block *b; 3576 FOR_EACH_VEC_ELT (m_blocks, i, b) 3577 b->dump_edges_to_dot (pp); 3578 } 3579 3580 pp_printf (pp, "}\n"); 3581 pp_flush (pp); 3582 fclose (fp); 3583} 3584 3585/* Implementation of recording::memento::make_debug_string for 3586 functions. */ 3587 3588recording::string * 3589recording::function::make_debug_string () 3590{ 3591 return m_name; 3592} 3593 3594/* A table of enum gcc_jit_function_kind values expressed in string 3595 form. */ 3596 3597static const char * const names_of_function_kinds[] = { 3598 "GCC_JIT_FUNCTION_EXPORTED", 3599 "GCC_JIT_FUNCTION_INTERNAL", 3600 "GCC_JIT_FUNCTION_IMPORTED", 3601 "GCC_JIT_FUNCTION_ALWAYS_INLINE" 3602}; 3603 3604/* Implementation of recording::memento::write_reproducer for functions. */ 3605 3606void 3607recording::function::write_reproducer (reproducer &r) 3608{ 3609 const char *id = r.make_identifier (this, "func"); 3610 3611 if (m_builtin_id) 3612 { 3613 r.write (" gcc_jit_function *%s =\n" 3614 " gcc_jit_context_get_builtin_function (%s,\n" 3615 " %s);\n", 3616 id, 3617 r.get_identifier (get_context ()), 3618 m_name->get_debug_string ()); 3619 return; 3620 } 3621 const char *params_id = r.make_tmp_identifier ("params_for", this); 3622 r.write (" gcc_jit_param *%s[%i] = {\n", 3623 params_id, 3624 m_params.length ()); 3625 int i; 3626 param *param; 3627 FOR_EACH_VEC_ELT (m_params, i, param) 3628 r.write (" %s,\n", r.get_identifier (param)); 3629 r.write (" };\n"); 3630 r.write (" gcc_jit_function *%s =\n" 3631 " gcc_jit_context_new_function (%s, /* gcc_jit_context *ctxt */\n" 3632 " %s, /* gcc_jit_location *loc */\n" 3633 " %s, /* enum gcc_jit_function_kind kind */\n" 3634 " %s, /* gcc_jit_type *return_type */\n" 3635 " %s, /* const char *name */\n" 3636 " %i, /* int num_params */\n" 3637 " %s, /* gcc_jit_param **params */\n" 3638 " %i); /* int is_variadic */\n", 3639 id, 3640 r.get_identifier (get_context ()), 3641 r.get_identifier (m_loc), 3642 names_of_function_kinds[m_kind], 3643 r.get_identifier_as_type (m_return_type), 3644 m_name->get_debug_string (), 3645 m_params.length (), 3646 params_id, 3647 m_is_variadic); 3648} 3649 3650 3651/* The implementation of class gcc::jit::recording::block. */ 3652 3653/* Create a recording::eval instance and add it to 3654 the block's context's list of mementos, and to the block's 3655 list of statements. 3656 3657 Implements the heart of gcc_jit_block_add_eval. */ 3658 3659recording::statement * 3660recording::block::add_eval (recording::location *loc, 3661 recording::rvalue *rvalue) 3662{ 3663 statement *result = new eval (this, loc, rvalue); 3664 m_ctxt->record (result); 3665 m_statements.safe_push (result); 3666 return result; 3667} 3668 3669/* Create a recording::assignment instance and add it to 3670 the block's context's list of mementos, and to the block's 3671 list of statements. 3672 3673 Implements the heart of gcc_jit_block_add_assignment. */ 3674 3675recording::statement * 3676recording::block::add_assignment (recording::location *loc, 3677 recording::lvalue *lvalue, 3678 recording::rvalue *rvalue) 3679{ 3680 statement *result = new assignment (this, loc, lvalue, rvalue); 3681 m_ctxt->record (result); 3682 m_statements.safe_push (result); 3683 return result; 3684} 3685 3686/* Create a recording::assignment_op instance and add it to 3687 the block's context's list of mementos, and to the block's 3688 list of statements. 3689 3690 Implements the heart of gcc_jit_block_add_assignment_op. */ 3691 3692recording::statement * 3693recording::block::add_assignment_op (recording::location *loc, 3694 recording::lvalue *lvalue, 3695 enum gcc_jit_binary_op op, 3696 recording::rvalue *rvalue) 3697{ 3698 statement *result = new assignment_op (this, loc, lvalue, op, rvalue); 3699 m_ctxt->record (result); 3700 m_statements.safe_push (result); 3701 return result; 3702} 3703 3704/* Create a recording::comment instance and add it to 3705 the block's context's list of mementos, and to the block's 3706 list of statements. 3707 3708 Implements the heart of gcc_jit_block_add_comment. */ 3709 3710recording::statement * 3711recording::block::add_comment (recording::location *loc, 3712 const char *text) 3713{ 3714 statement *result = new comment (this, loc, new_string (text)); 3715 m_ctxt->record (result); 3716 m_statements.safe_push (result); 3717 return result; 3718} 3719 3720/* Create a recording::end_with_conditional instance and add it to 3721 the block's context's list of mementos, and to the block's 3722 list of statements. 3723 3724 Implements the heart of gcc_jit_block_end_with_conditional. */ 3725 3726recording::statement * 3727recording::block::end_with_conditional (recording::location *loc, 3728 recording::rvalue *boolval, 3729 recording::block *on_true, 3730 recording::block *on_false) 3731{ 3732 statement *result = new conditional (this, loc, boolval, on_true, on_false); 3733 m_ctxt->record (result); 3734 m_statements.safe_push (result); 3735 m_has_been_terminated = true; 3736 return result; 3737} 3738 3739/* Create a recording::end_with_jump instance and add it to 3740 the block's context's list of mementos, and to the block's 3741 list of statements. 3742 3743 Implements the heart of gcc_jit_block_end_with_jump. */ 3744 3745recording::statement * 3746recording::block::end_with_jump (recording::location *loc, 3747 recording::block *target) 3748{ 3749 statement *result = new jump (this, loc, target); 3750 m_ctxt->record (result); 3751 m_statements.safe_push (result); 3752 m_has_been_terminated = true; 3753 return result; 3754} 3755 3756/* Create a recording::end_with_return instance and add it to 3757 the block's context's list of mementos, and to the block's 3758 list of statements. 3759 3760 Implements the post-error-checking parts of 3761 gcc_jit_block_end_with_return and 3762 gcc_jit_block_end_with_void_return. */ 3763 3764recording::statement * 3765recording::block::end_with_return (recording::location *loc, 3766 recording::rvalue *rvalue) 3767{ 3768 /* This is used by both gcc_jit_function_add_return and 3769 gcc_jit_function_add_void_return; rvalue will be non-NULL for 3770 the former and NULL for the latter. */ 3771 statement *result = new return_ (this, loc, rvalue); 3772 m_ctxt->record (result); 3773 m_statements.safe_push (result); 3774 m_has_been_terminated = true; 3775 return result; 3776} 3777 3778/* Create a recording::switch_ instance and add it to 3779 the block's context's list of mementos, and to the block's 3780 list of statements. 3781 3782 Implements the heart of gcc_jit_block_end_with_switch. */ 3783 3784recording::statement * 3785recording::block::end_with_switch (recording::location *loc, 3786 recording::rvalue *expr, 3787 recording::block *default_block, 3788 int num_cases, 3789 recording::case_ **cases) 3790{ 3791 statement *result = new switch_ (this, loc, 3792 expr, 3793 default_block, 3794 num_cases, 3795 cases); 3796 m_ctxt->record (result); 3797 m_statements.safe_push (result); 3798 m_has_been_terminated = true; 3799 return result; 3800} 3801 3802/* Override the default implementation of 3803 recording::memento::write_to_dump for blocks by writing 3804 an unindented block name as a label, followed by the indented 3805 statements: 3806 3807 BLOCK_NAME: 3808 STATEMENT_1; 3809 STATEMENT_2; 3810 ... 3811 STATEMENT_N; */ 3812 3813void 3814recording::block::write_to_dump (dump &d) 3815{ 3816 d.write ("%s:\n", get_debug_string ()); 3817 3818 int i; 3819 statement *s; 3820 FOR_EACH_VEC_ELT (m_statements, i, s) 3821 s->write_to_dump (d); 3822} 3823 3824/* Validate a block by ensuring that it has been terminated. */ 3825 3826bool 3827recording::block::validate () 3828{ 3829 /* Check for termination. */ 3830 if (!has_been_terminated ()) 3831 { 3832 statement *stmt = get_last_statement (); 3833 location *loc = stmt ? stmt->get_loc () : NULL; 3834 m_func->get_context ()->add_error (loc, 3835 "unterminated block in %s: %s", 3836 m_func->get_debug_string (), 3837 get_debug_string ()); 3838 return false; 3839 } 3840 3841 return true; 3842} 3843 3844/* Get the source-location of a block by using that of the first 3845 statement within it, if any. */ 3846 3847recording::location * 3848recording::block::get_loc () const 3849{ 3850 recording::statement *stmt = get_first_statement (); 3851 if (stmt) 3852 return stmt->get_loc (); 3853 else 3854 return NULL; 3855} 3856 3857/* Get the first statement within a block, if any. */ 3858 3859recording::statement * 3860recording::block::get_first_statement () const 3861{ 3862 if (m_statements.length ()) 3863 return m_statements[0]; 3864 else 3865 return NULL; 3866} 3867 3868/* Get the last statement within a block, if any. */ 3869 3870recording::statement * 3871recording::block::get_last_statement () const 3872{ 3873 if (m_statements.length ()) 3874 return m_statements[m_statements.length () - 1]; 3875 else 3876 return NULL; 3877} 3878 3879/* Assuming that this block has been terminated, get the successor blocks 3880 as a vector. Ownership of the vector transfers to the caller, which 3881 must call its release () method. 3882 3883 Used when validating functions, and when dumping dot representations 3884 of them. */ 3885 3886vec <recording::block *> 3887recording::block::get_successor_blocks () const 3888{ 3889 gcc_assert (m_has_been_terminated); 3890 statement *last_statement = get_last_statement (); 3891 gcc_assert (last_statement); 3892 return last_statement->get_successor_blocks (); 3893} 3894 3895/* Implementation of pure virtual hook recording::memento::replay_into 3896 for recording::block. */ 3897 3898void 3899recording::block::replay_into (replayer *) 3900{ 3901 set_playback_obj (m_func->playback_function () 3902 ->new_block (playback_string (m_name))); 3903} 3904 3905/* Implementation of recording::memento::make_debug_string for 3906 blocks. */ 3907 3908recording::string * 3909recording::block::make_debug_string () 3910{ 3911 if (m_name) 3912 return m_name; 3913 else 3914 return string::from_printf (m_ctxt, 3915 "<UNNAMED BLOCK %p>", 3916 (void *)this); 3917} 3918 3919/* Implementation of recording::memento::write_reproducer for blocks. */ 3920 3921void 3922recording::block::write_reproducer (reproducer &r) 3923{ 3924 const char *id = r.make_identifier (this, "block"); 3925 r.write (" gcc_jit_block *%s =\n" 3926 " gcc_jit_function_new_block (%s, %s);\n", 3927 id, 3928 r.get_identifier (m_func), 3929 m_name ? m_name->get_debug_string () : "NULL"); 3930} 3931 3932/* Dump a block in graphviz form into PP, capturing the block name (if 3933 any) and the statements. */ 3934 3935void 3936recording::block::dump_to_dot (pretty_printer *pp) 3937{ 3938 pp_printf (pp, 3939 ("\tblock_%d " 3940 "[shape=record,style=filled,fillcolor=white,label=\"{"), 3941 m_index); 3942 pp_write_text_to_stream (pp); 3943 if (m_name) 3944 { 3945 pp_string (pp, m_name->c_str ()); 3946 pp_string (pp, ":"); 3947 pp_newline (pp); 3948 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/); 3949 } 3950 3951 int i; 3952 statement *s; 3953 FOR_EACH_VEC_ELT (m_statements, i, s) 3954 { 3955 pp_string (pp, s->get_debug_string ()); 3956 pp_newline (pp); 3957 pp_write_text_as_dot_label_to_stream (pp, true /*for_record*/); 3958 } 3959 3960 pp_printf (pp, 3961 "}\"];\n\n"); 3962 pp_flush (pp); 3963} 3964 3965/* Dump the out-edges of the block in graphviz form into PP. */ 3966 3967void 3968recording::block::dump_edges_to_dot (pretty_printer *pp) 3969{ 3970 vec <block *> successors = get_successor_blocks (); 3971 int i; 3972 block *succ; 3973 FOR_EACH_VEC_ELT (successors, i, succ) 3974 pp_printf (pp, 3975 "\tblock_%d:s -> block_%d:n;\n", 3976 m_index, succ->m_index); 3977 successors.release (); 3978} 3979 3980/* The implementation of class gcc::jit::recording::global. */ 3981 3982/* Implementation of pure virtual hook recording::memento::replay_into 3983 for recording::global. */ 3984 3985void 3986recording::global::replay_into (replayer *r) 3987{ 3988 set_playback_obj (r->new_global (playback_location (r, m_loc), 3989 m_kind, 3990 m_type->playback_type (), 3991 playback_string (m_name))); 3992} 3993 3994/* Override the default implementation of 3995 recording::memento::write_to_dump for globals. 3996 This will be of the form: 3997 3998 GCC_JIT_GLOBAL_EXPORTED: 3999 "TYPE NAME;" 4000 e.g. "int foo;" 4001 4002 GCC_JIT_GLOBAL_INTERNAL: 4003 "static TYPE NAME;" 4004 e.g. "static int foo;" 4005 4006 GCC_JIT_GLOBAL_IMPORTED: 4007 "extern TYPE NAME;" 4008 e.g. "extern int foo;" 4009 4010 These are written to the top of the dump by 4011 recording::context::dump_to_file. */ 4012 4013void 4014recording::global::write_to_dump (dump &d) 4015{ 4016 if (d.update_locations ()) 4017 m_loc = d.make_location (); 4018 4019 switch (m_kind) 4020 { 4021 default: 4022 gcc_unreachable (); 4023 4024 case GCC_JIT_GLOBAL_EXPORTED: 4025 break; 4026 4027 case GCC_JIT_GLOBAL_INTERNAL: 4028 d.write ("static "); 4029 break; 4030 4031 case GCC_JIT_GLOBAL_IMPORTED: 4032 d.write ("extern "); 4033 break; 4034 } 4035 d.write ("%s %s;\n", 4036 m_type->get_debug_string (), 4037 get_debug_string ()); 4038} 4039 4040/* A table of enum gcc_jit_global_kind values expressed in string 4041 form. */ 4042 4043static const char * const global_kind_reproducer_strings[] = { 4044 "GCC_JIT_GLOBAL_EXPORTED", 4045 "GCC_JIT_GLOBAL_INTERNAL", 4046 "GCC_JIT_GLOBAL_IMPORTED" 4047}; 4048 4049/* Implementation of recording::memento::write_reproducer for globals. */ 4050 4051void 4052recording::global::write_reproducer (reproducer &r) 4053{ 4054 const char *id = r.make_identifier (this, "block"); 4055 r.write (" gcc_jit_lvalue *%s =\n" 4056 " gcc_jit_context_new_global (%s, /* gcc_jit_context *ctxt */\n" 4057 " %s, /* gcc_jit_location *loc */\n" 4058 " %s, /* enum gcc_jit_global_kind kind */\n" 4059 " %s, /* gcc_jit_type *type */\n" 4060 " %s); /* const char *name */\n", 4061 id, 4062 r.get_identifier (get_context ()), 4063 r.get_identifier (m_loc), 4064 global_kind_reproducer_strings[m_kind], 4065 r.get_identifier_as_type (get_type ()), 4066 m_name->get_debug_string ()); 4067} 4068 4069/* The implementation of the various const-handling classes: 4070 gcc::jit::recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */ 4071 4072/* Explicit specialization of the various mementos we're interested in. */ 4073template class recording::memento_of_new_rvalue_from_const <int>; 4074template class recording::memento_of_new_rvalue_from_const <long>; 4075template class recording::memento_of_new_rvalue_from_const <double>; 4076template class recording::memento_of_new_rvalue_from_const <void *>; 4077 4078/* Implementation of the pure virtual hook recording::memento::replay_into 4079 for recording::memento_of_new_rvalue_from_const <HOST_TYPE>. */ 4080 4081template <typename HOST_TYPE> 4082void 4083recording:: 4084memento_of_new_rvalue_from_const <HOST_TYPE>::replay_into (replayer *r) 4085{ 4086 set_playback_obj 4087 (r->new_rvalue_from_const <HOST_TYPE> (m_type->playback_type (), 4088 m_value)); 4089} 4090 4091/* The make_debug_string and write_reproducer methods vary between the 4092 various 4093 memento_of_new_rvalue_from_const <HOST_TYPE> 4094 classes, so we explicitly write specializations of them. 4095 4096 I (dmalcolm) find the code to be clearer if the "recording" vs "playback" 4097 namespaces are written out explicitly, which is why most of this file 4098 doesn't abbreviate things by entering the "recording" namespace. 4099 4100 However, these specializations are required to be in the same namespace 4101 as the template, hence we now have to enter the gcc::jit::recording 4102 namespace. */ 4103 4104namespace recording 4105{ 4106 4107/* The make_debug_string specialization for <int>, which renders it as 4108 (TARGET_TYPE)LITERAL 4109 e.g. 4110 "(int)42". */ 4111 4112template <> 4113string * 4114memento_of_new_rvalue_from_const <int>::make_debug_string () 4115{ 4116 return string::from_printf (m_ctxt, 4117 "(%s)%i", 4118 m_type->get_debug_string (), 4119 m_value); 4120} 4121 4122/* The get_wide_int specialization for <int>. */ 4123 4124template <> 4125bool 4126memento_of_new_rvalue_from_const <int>::get_wide_int (wide_int *out) const 4127{ 4128 *out = wi::shwi (m_value, sizeof (m_value) * 8); 4129 return true; 4130} 4131 4132/* The write_reproducer specialization for <int>. */ 4133 4134template <> 4135void 4136memento_of_new_rvalue_from_const <int>::write_reproducer (reproducer &r) 4137{ 4138 const char *id = r.make_identifier (this, "rvalue"); 4139 r.write (" gcc_jit_rvalue *%s =\n" 4140 " gcc_jit_context_new_rvalue_from_int (%s, /* gcc_jit_context *ctxt */\n" 4141 " %s, /* gcc_jit_type *numeric_type */\n" 4142 " %i); /* int value */\n", 4143 id, 4144 r.get_identifier (get_context ()), 4145 r.get_identifier_as_type (m_type), 4146 m_value); 4147} 4148 4149/* The make_debug_string specialization for <long>, rendering it as 4150 (TARGET_TYPE)LITERAL 4151 e.g. 4152 "(long)42". */ 4153 4154template <> 4155string * 4156memento_of_new_rvalue_from_const <long>::make_debug_string () 4157{ 4158 return string::from_printf (m_ctxt, 4159 "(%s)%li", 4160 m_type->get_debug_string (), 4161 m_value); 4162} 4163 4164/* The get_wide_int specialization for <long>. */ 4165 4166template <> 4167bool 4168memento_of_new_rvalue_from_const <long>::get_wide_int (wide_int *out) const 4169{ 4170 *out = wi::shwi (m_value, sizeof (m_value) * 8); 4171 return true; 4172} 4173 4174/* The write_reproducer specialization for <long>. */ 4175 4176template <> 4177void 4178recording::memento_of_new_rvalue_from_const <long>::write_reproducer (reproducer &r) 4179{ 4180 const char *id = r.make_identifier (this, "rvalue"); 4181 4182 /* We have to special-case LONG_MIN, since e.g. 4183 -9223372036854775808L 4184 is parsed as 4185 -(9223372036854775808L) 4186 and hence we'd get: 4187 error: integer constant is so large that it is unsigned [-Werror] 4188 Workaround this by writing (LONG_MIN + 1) - 1. */ 4189 if (m_value == LONG_MIN) 4190 { 4191 r.write (" gcc_jit_rvalue *%s =\n" 4192 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n" 4193 " %s, /* gcc_jit_type *numeric_type */\n" 4194 " %ldL - 1); /* long value */\n", 4195 id, 4196 r.get_identifier (get_context ()), 4197 r.get_identifier_as_type (m_type), 4198 m_value + 1);; 4199 return; 4200 } 4201 4202 r.write (" gcc_jit_rvalue *%s =\n" 4203 " gcc_jit_context_new_rvalue_from_long (%s, /* gcc_jit_context *ctxt */\n" 4204 " %s, /* gcc_jit_type *numeric_type */\n" 4205 " %ldL); /* long value */\n", 4206 id, 4207 r.get_identifier (get_context ()), 4208 r.get_identifier_as_type (m_type), 4209 m_value); 4210 } 4211 4212/* The make_debug_string specialization for <double>, rendering it as 4213 (TARGET_TYPE)LITERAL 4214 e.g. 4215 "(float)42.0". */ 4216 4217template <> 4218string * 4219memento_of_new_rvalue_from_const <double>::make_debug_string () 4220{ 4221 return string::from_printf (m_ctxt, 4222 "(%s)%f", 4223 m_type->get_debug_string (), 4224 m_value); 4225} 4226 4227/* The get_wide_int specialization for <double>. */ 4228 4229template <> 4230bool 4231memento_of_new_rvalue_from_const <double>::get_wide_int (wide_int *) const 4232{ 4233 return false; 4234} 4235 4236/* The write_reproducer specialization for <double>. */ 4237 4238template <> 4239void 4240recording::memento_of_new_rvalue_from_const <double>::write_reproducer (reproducer &r) 4241{ 4242 const char *id = r.make_identifier (this, "rvalue"); 4243 r.write (" gcc_jit_rvalue *%s =\n" 4244 " gcc_jit_context_new_rvalue_from_double (%s, /* gcc_jit_context *ctxt */\n" 4245 " %s, /* gcc_jit_type *numeric_type */\n" 4246 " %f); /* double value */\n", 4247 id, 4248 r.get_identifier (get_context ()), 4249 r.get_identifier_as_type (m_type), 4250 m_value); 4251} 4252 4253/* The make_debug_string specialization for <void *>, rendering it as 4254 (TARGET_TYPE)HEX 4255 e.g. 4256 "(int *)0xdeadbeef" 4257 4258 Zero is rendered as NULL e.g. 4259 "(int *)NULL". */ 4260 4261template <> 4262string * 4263memento_of_new_rvalue_from_const <void *>::make_debug_string () 4264{ 4265 if (m_value != NULL) 4266 return string::from_printf (m_ctxt, 4267 "(%s)%p", 4268 m_type->get_debug_string (), m_value); 4269 else 4270 return string::from_printf (m_ctxt, 4271 "(%s)NULL", 4272 m_type->get_debug_string ()); 4273} 4274 4275/* The get_wide_int specialization for <void *>. */ 4276 4277template <> 4278bool 4279memento_of_new_rvalue_from_const <void *>::get_wide_int (wide_int *) const 4280{ 4281 return false; 4282} 4283 4284/* Implementation of recording::memento::write_reproducer for <void *> 4285 values. */ 4286 4287template <> 4288void 4289memento_of_new_rvalue_from_const <void *>::write_reproducer (reproducer &r) 4290{ 4291 const char *id = r.make_identifier (this, "rvalue"); 4292 if (m_value) 4293 r.write (" gcc_jit_rvalue *%s =\n" 4294 " gcc_jit_context_new_rvalue_from_ptr (%s, /* gcc_jit_context *ctxt */\n" 4295 " %s, /* gcc_jit_type *pointer_type */\n" 4296 " (void *)%p); /* void *value */\n", 4297 id, 4298 r.get_identifier (get_context ()), 4299 r.get_identifier_as_type (m_type), 4300 m_value); 4301 else 4302 r.write (" gcc_jit_rvalue *%s =\n" 4303 " gcc_jit_context_null (%s, /* gcc_jit_context *ctxt */\n" 4304 " %s); /* gcc_jit_type *pointer_type */\n", 4305 id, 4306 r.get_identifier (get_context ()), 4307 r.get_identifier_as_type (m_type)); 4308} 4309 4310/* We're done specializing make_debug_string and write_reproducer, so we 4311 can exit the gcc::jit::recording namespace. */ 4312 4313} // namespace recording 4314 4315/* The implementation of class gcc::jit::recording::memento_of_new_string_literal. */ 4316 4317/* Implementation of pure virtual hook recording::memento::replay_into 4318 for recording::memento_of_new_string_literal. */ 4319 4320void 4321recording::memento_of_new_string_literal::replay_into (replayer *r) 4322{ 4323 set_playback_obj (r->new_string_literal (m_value->c_str ())); 4324} 4325 4326/* Implementation of recording::memento::make_debug_string for 4327 string literals. */ 4328 4329recording::string * 4330recording::memento_of_new_string_literal::make_debug_string () 4331{ 4332 return string::from_printf (m_ctxt, 4333 "%s", 4334 m_value->get_debug_string ()); 4335} 4336 4337/* Implementation of recording::memento::write_reproducer for string literal 4338 values. */ 4339 4340void 4341recording::memento_of_new_string_literal::write_reproducer (reproducer &r) 4342{ 4343 const char *id = r.make_identifier (this, "rvalue"); 4344 r.write (" gcc_jit_rvalue *%s =\n" 4345 " gcc_jit_context_new_string_literal (%s, /* gcc_jit_context *ctxt */\n" 4346 " %s); /* const char *value */\n", 4347 id, 4348 r.get_identifier (get_context ()), 4349 m_value->get_debug_string ()); 4350} 4351 4352/* The implementation of class gcc::jit::recording::unary_op. */ 4353 4354/* Implementation of pure virtual hook recording::memento::replay_into 4355 for recording::unary_op. */ 4356 4357void 4358recording::unary_op::replay_into (replayer *r) 4359{ 4360 set_playback_obj (r->new_unary_op (playback_location (r, m_loc), 4361 m_op, 4362 get_type ()->playback_type (), 4363 m_a->playback_rvalue ())); 4364} 4365 4366/* Implementation of pure virtual hook recording::rvalue::visit_children 4367 for recording::unary_op. */ 4368void 4369recording::unary_op::visit_children (rvalue_visitor *v) 4370{ 4371 v->visit (m_a); 4372} 4373 4374/* Implementation of recording::memento::make_debug_string for 4375 unary ops. */ 4376 4377static const char * const unary_op_strings[] = { 4378 "-", /* GCC_JIT_UNARY_OP_MINUS */ 4379 "~", /* GCC_JIT_UNARY_OP_BITWISE_NEGATE */ 4380 "!", /* GCC_JIT_UNARY_OP_LOGICAL_NEGATE */ 4381 "abs ", /* GCC_JIT_UNARY_OP_ABS */ 4382}; 4383 4384recording::string * 4385recording::unary_op::make_debug_string () 4386{ 4387 return string::from_printf (m_ctxt, 4388 "%s(%s)", 4389 unary_op_strings[m_op], 4390 m_a->get_debug_string ()); 4391} 4392 4393static const char * const unary_op_reproducer_strings[] = { 4394 "GCC_JIT_UNARY_OP_MINUS", 4395 "GCC_JIT_UNARY_OP_BITWISE_NEGATE", 4396 "GCC_JIT_UNARY_OP_LOGICAL_NEGATE", 4397 "GCC_JIT_UNARY_OP_ABS" 4398}; 4399 4400/* Implementation of recording::memento::write_reproducer for unary ops. */ 4401 4402void 4403recording::unary_op::write_reproducer (reproducer &r) 4404{ 4405 const char *id = r.make_identifier (this, "rvalue"); 4406 r.write (" gcc_jit_rvalue *%s =\n" 4407 " gcc_jit_context_new_unary_op (%s,\n" 4408 " %s, /* gcc_jit_location *loc */\n" 4409 " %s, /* enum gcc_jit_unary_op op */\n" 4410 " %s, /* gcc_jit_type *result_type */\n" 4411 " %s); /* gcc_jit_rvalue *a */\n", 4412 id, 4413 r.get_identifier (get_context ()), 4414 r.get_identifier (m_loc), 4415 unary_op_reproducer_strings[m_op], 4416 r.get_identifier_as_type (get_type ()), 4417 r.get_identifier_as_rvalue (m_a)); 4418} 4419 4420/* The implementation of class gcc::jit::recording::binary_op. */ 4421 4422/* Implementation of pure virtual hook recording::memento::replay_into 4423 for recording::binary_op. */ 4424 4425void 4426recording::binary_op::replay_into (replayer *r) 4427{ 4428 set_playback_obj (r->new_binary_op (playback_location (r, m_loc), 4429 m_op, 4430 get_type ()->playback_type (), 4431 m_a->playback_rvalue (), 4432 m_b->playback_rvalue ())); 4433} 4434 4435/* Implementation of pure virtual hook recording::rvalue::visit_children 4436 for recording::binary_op. */ 4437void 4438recording::binary_op::visit_children (rvalue_visitor *v) 4439{ 4440 v->visit (m_a); 4441 v->visit (m_b); 4442} 4443 4444/* Implementation of recording::memento::make_debug_string for 4445 binary ops. */ 4446 4447static const char * const binary_op_strings[] = { 4448 "+", /* GCC_JIT_BINARY_OP_PLUS */ 4449 "-", /* GCC_JIT_BINARY_OP_MINUS */ 4450 "*", /* GCC_JIT_BINARY_OP_MULT */ 4451 "/", /* GCC_JIT_BINARY_OP_DIVIDE */ 4452 "%", /* GCC_JIT_BINARY_OP_MODULO */ 4453 "&", /* GCC_JIT_BINARY_OP_BITWISE_AND */ 4454 "^", /* GCC_JIT_BINARY_OP_BITWISE_XOR */ 4455 "|", /* GCC_JIT_BINARY_OP_BITWISE_OR */ 4456 "&&", /* GCC_JIT_BINARY_OP_LOGICAL_AND */ 4457 "||", /* GCC_JIT_BINARY_OP_LOGICAL_OR */ 4458 "<<", /* GCC_JIT_BINARY_OP_LSHIFT */ 4459 ">>", /* GCC_JIT_BINARY_OP_RSHIFT */ 4460}; 4461 4462recording::string * 4463recording::binary_op::make_debug_string () 4464{ 4465 enum precedence prec = get_precedence (); 4466 return string::from_printf (m_ctxt, 4467 "%s %s %s", 4468 m_a->get_debug_string_parens (prec), 4469 binary_op_strings[m_op], 4470 m_b->get_debug_string_parens (prec)); 4471} 4472 4473static const char * const binary_op_reproducer_strings[] = { 4474 "GCC_JIT_BINARY_OP_PLUS", 4475 "GCC_JIT_BINARY_OP_MINUS", 4476 "GCC_JIT_BINARY_OP_MULT", 4477 "GCC_JIT_BINARY_OP_DIVIDE", 4478 "GCC_JIT_BINARY_OP_MODULO", 4479 "GCC_JIT_BINARY_OP_BITWISE_AND", 4480 "GCC_JIT_BINARY_OP_BITWISE_XOR", 4481 "GCC_JIT_BINARY_OP_BITWISE_OR", 4482 "GCC_JIT_BINARY_OP_LOGICAL_AND", 4483 "GCC_JIT_BINARY_OP_LOGICAL_OR", 4484 "GCC_JIT_BINARY_OP_LSHIFT", 4485 "GCC_JIT_BINARY_OP_RSHIFT" 4486}; 4487 4488/* Implementation of recording::memento::write_reproducer for binary ops. */ 4489 4490void 4491recording::binary_op::write_reproducer (reproducer &r) 4492{ 4493 const char *id = r.make_identifier (this, "rvalue"); 4494 r.write (" gcc_jit_rvalue *%s =\n" 4495 " gcc_jit_context_new_binary_op (%s,\n" 4496 " %s, /* gcc_jit_location *loc */\n" 4497 " %s, /* enum gcc_jit_binary_op op */\n" 4498 " %s, /* gcc_jit_type *result_type */\n" 4499 " %s, /* gcc_jit_rvalue *a */\n" 4500 " %s); /* gcc_jit_rvalue *b */\n", 4501 id, 4502 r.get_identifier (get_context ()), 4503 r.get_identifier (m_loc), 4504 binary_op_reproducer_strings[m_op], 4505 r.get_identifier_as_type (get_type ()), 4506 r.get_identifier_as_rvalue (m_a), 4507 r.get_identifier_as_rvalue (m_b)); 4508} 4509 4510namespace recording { 4511static const enum precedence binary_op_precedence[] = { 4512 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_PLUS */ 4513 PRECEDENCE_ADDITIVE, /* GCC_JIT_BINARY_OP_MINUS */ 4514 4515 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MULT */ 4516 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_DIVIDE */ 4517 PRECEDENCE_MULTIPLICATIVE, /* GCC_JIT_BINARY_OP_MODULO */ 4518 4519 PRECEDENCE_BITWISE_AND, /* GCC_JIT_BINARY_OP_BITWISE_AND */ 4520 PRECEDENCE_BITWISE_XOR, /* GCC_JIT_BINARY_OP_BITWISE_XOR */ 4521 PRECEDENCE_BITWISE_IOR, /* GCC_JIT_BINARY_OP_BITWISE_OR */ 4522 PRECEDENCE_LOGICAL_AND, /* GCC_JIT_BINARY_OP_LOGICAL_AND */ 4523 PRECEDENCE_LOGICAL_OR, /* GCC_JIT_BINARY_OP_LOGICAL_OR */ 4524 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_LSHIFT */ 4525 PRECEDENCE_SHIFT, /* GCC_JIT_BINARY_OP_RSHIFT */ 4526}; 4527} /* namespace recording */ 4528 4529enum recording::precedence 4530recording::binary_op::get_precedence () const 4531{ 4532 return binary_op_precedence[m_op]; 4533} 4534 4535/* The implementation of class gcc::jit::recording::comparison. */ 4536 4537/* Implementation of recording::memento::make_debug_string for 4538 comparisons. */ 4539 4540static const char * const comparison_strings[] = 4541{ 4542 "==", /* GCC_JIT_COMPARISON_EQ */ 4543 "!=", /* GCC_JIT_COMPARISON_NE */ 4544 "<", /* GCC_JIT_COMPARISON_LT */ 4545 "<=", /* GCC_JIT_COMPARISON_LE */ 4546 ">", /* GCC_JIT_COMPARISON_GT */ 4547 ">=", /* GCC_JIT_COMPARISON_GE */ 4548}; 4549 4550recording::string * 4551recording::comparison::make_debug_string () 4552{ 4553 enum precedence prec = get_precedence (); 4554 return string::from_printf (m_ctxt, 4555 "%s %s %s", 4556 m_a->get_debug_string_parens (prec), 4557 comparison_strings[m_op], 4558 m_b->get_debug_string_parens (prec)); 4559} 4560 4561/* A table of enum gcc_jit_comparison values expressed in string 4562 form. */ 4563 4564static const char * const comparison_reproducer_strings[] = 4565{ 4566 "GCC_JIT_COMPARISON_EQ", 4567 "GCC_JIT_COMPARISON_NE", 4568 "GCC_JIT_COMPARISON_LT", 4569 "GCC_JIT_COMPARISON_LE", 4570 "GCC_JIT_COMPARISON_GT", 4571 "GCC_JIT_COMPARISON_GE" 4572}; 4573 4574/* Implementation of recording::memento::write_reproducer for comparisons. */ 4575 4576void 4577recording::comparison::write_reproducer (reproducer &r) 4578{ 4579 const char *id = r.make_identifier (this, "rvalue"); 4580 r.write (" gcc_jit_rvalue *%s =\n" 4581 " gcc_jit_context_new_comparison (%s,\n" 4582 " %s, /* gcc_jit_location *loc */\n" 4583 " %s, /* enum gcc_jit_comparison op */\n" 4584 " %s, /* gcc_jit_rvalue *a */\n" 4585 " %s); /* gcc_jit_rvalue *b */\n", 4586 id, 4587 r.get_identifier (get_context ()), 4588 r.get_identifier (m_loc), 4589 comparison_reproducer_strings[m_op], 4590 r.get_identifier_as_rvalue (m_a), 4591 r.get_identifier_as_rvalue (m_b)); 4592} 4593 4594/* Implementation of pure virtual hook recording::memento::replay_into 4595 for recording::comparison. */ 4596 4597void 4598recording::comparison::replay_into (replayer *r) 4599{ 4600 set_playback_obj (r->new_comparison (playback_location (r, m_loc), 4601 m_op, 4602 m_a->playback_rvalue (), 4603 m_b->playback_rvalue ())); 4604} 4605 4606/* Implementation of pure virtual hook recording::rvalue::visit_children 4607 for recording::comparison. */ 4608 4609void 4610recording::comparison::visit_children (rvalue_visitor *v) 4611{ 4612 v->visit (m_a); 4613 v->visit (m_b); 4614} 4615 4616namespace recording { 4617static const enum precedence comparison_precedence[] = 4618{ 4619 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_EQ */ 4620 PRECEDENCE_EQUALITY, /* GCC_JIT_COMPARISON_NE */ 4621 4622 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LT */ 4623 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_LE */ 4624 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GT */ 4625 PRECEDENCE_RELATIONAL, /* GCC_JIT_COMPARISON_GE */ 4626}; 4627} /* namespace recording */ 4628 4629enum recording::precedence 4630recording::comparison::get_precedence () const 4631{ 4632 return comparison_precedence[m_op]; 4633} 4634 4635/* Implementation of pure virtual hook recording::memento::replay_into 4636 for recording::cast. */ 4637 4638void 4639recording::cast::replay_into (replayer *r) 4640{ 4641 set_playback_obj (r->new_cast (playback_location (r, m_loc), 4642 m_rvalue->playback_rvalue (), 4643 get_type ()->playback_type ())); 4644} 4645 4646/* Implementation of pure virtual hook recording::rvalue::visit_children 4647 for recording::cast. */ 4648void 4649recording::cast::visit_children (rvalue_visitor *v) 4650{ 4651 v->visit (m_rvalue); 4652} 4653 4654/* Implementation of recording::memento::make_debug_string for 4655 casts. */ 4656 4657recording::string * 4658recording::cast::make_debug_string () 4659{ 4660 enum precedence prec = get_precedence (); 4661 return string::from_printf (m_ctxt, 4662 "(%s)%s", 4663 get_type ()->get_debug_string (), 4664 m_rvalue->get_debug_string_parens (prec)); 4665} 4666 4667/* Implementation of recording::memento::write_reproducer for casts. */ 4668 4669void 4670recording::cast::write_reproducer (reproducer &r) 4671{ 4672 const char *id = r.make_identifier (this, "rvalue"); 4673 r.write (" gcc_jit_rvalue *%s =\n" 4674 " gcc_jit_context_new_cast (%s,\n" 4675 " %s, /* gcc_jit_location *loc */\n" 4676 " %s, /* gcc_jit_rvalue *rvalue */\n" 4677 " %s); /* gcc_jit_type *type */\n", 4678 id, 4679 r.get_identifier (get_context ()), 4680 r.get_identifier (m_loc), 4681 r.get_identifier_as_rvalue (m_rvalue), 4682 r.get_identifier_as_type (get_type ())); 4683} 4684 4685/* The implementation of class gcc::jit::recording::call. */ 4686 4687/* The constructor for gcc::jit::recording::call. */ 4688 4689recording::call::call (recording::context *ctxt, 4690 recording::location *loc, 4691 recording::function *func, 4692 int numargs, 4693 rvalue **args) 4694: rvalue (ctxt, loc, func->get_return_type ()), 4695 m_func (func), 4696 m_args () 4697{ 4698 for (int i = 0; i< numargs; i++) 4699 m_args.safe_push (args[i]); 4700} 4701 4702/* Implementation of pure virtual hook recording::memento::replay_into 4703 for recording::call. */ 4704 4705void 4706recording::call::replay_into (replayer *r) 4707{ 4708 auto_vec<playback::rvalue *> playback_args; 4709 playback_args.create (m_args.length ()); 4710 for (unsigned i = 0; i< m_args.length (); i++) 4711 playback_args.safe_push (m_args[i]->playback_rvalue ()); 4712 4713 set_playback_obj (r->new_call (playback_location (r, m_loc), 4714 m_func->playback_function (), 4715 &playback_args)); 4716} 4717 4718/* Implementation of pure virtual hook recording::rvalue::visit_children 4719 for recording::call. */ 4720 4721void 4722recording::call::visit_children (rvalue_visitor *v) 4723{ 4724 for (unsigned i = 0; i< m_args.length (); i++) 4725 v->visit (m_args[i]); 4726} 4727 4728/* Implementation of recording::memento::make_debug_string for 4729 function calls. */ 4730 4731recording::string * 4732recording::call::make_debug_string () 4733{ 4734 enum precedence prec = get_precedence (); 4735 /* First, build a buffer for the arguments. */ 4736 /* Calculate length of said buffer. */ 4737 size_t sz = 1; /* nil terminator */ 4738 for (unsigned i = 0; i< m_args.length (); i++) 4739 { 4740 sz += strlen (m_args[i]->get_debug_string_parens (prec)); 4741 sz += 2; /* ", " separator */ 4742 } 4743 4744 /* Now allocate and populate the buffer. */ 4745 char *argbuf = new char[sz]; 4746 size_t len = 0; 4747 4748 for (unsigned i = 0; i< m_args.length (); i++) 4749 { 4750 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec)); 4751 len += strlen (m_args[i]->get_debug_string_parens (prec)); 4752 if (i + 1 < m_args.length ()) 4753 { 4754 strcpy (argbuf + len, ", "); 4755 len += 2; 4756 } 4757 } 4758 argbuf[len] = '\0'; 4759 4760 /* ...and use it to get the string for the call as a whole. */ 4761 string *result = string::from_printf (m_ctxt, 4762 "%s (%s)", 4763 m_func->get_debug_string (), 4764 argbuf); 4765 4766 delete[] argbuf; 4767 4768 return result; 4769} 4770 4771void 4772recording::call::write_reproducer (reproducer &r) 4773{ 4774 const char *id = r.make_identifier (this, "call"); 4775 const char *args_id = r.make_tmp_identifier ("args_for_", this); 4776 r.write (" gcc_jit_rvalue *%s[%i] = {\n", 4777 args_id, 4778 m_args.length ()); 4779 for (unsigned i = 0; i< m_args.length (); i++) 4780 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i])); 4781 r.write (" };\n"); 4782 r.write (" gcc_jit_rvalue *%s =\n" 4783 " gcc_jit_context_new_call (%s, /* gcc_jit_context *ctxt */\n" 4784 " %s, /* gcc_jit_location *loc */\n" 4785 " %s, /* gcc_jit_function *func */\n" 4786 " %i, /* int numargs */ \n" 4787 " %s); /* gcc_jit_rvalue **args*/\n", 4788 id, 4789 r.get_identifier (get_context ()), 4790 r.get_identifier (m_loc), 4791 r.get_identifier (m_func), 4792 m_args.length (), 4793 args_id); 4794} 4795 4796/* The implementation of class gcc::jit::recording::call_through_ptr. */ 4797 4798/* The constructor for recording::call_through_ptr. */ 4799 4800recording::call_through_ptr::call_through_ptr (recording::context *ctxt, 4801 recording::location *loc, 4802 recording::rvalue *fn_ptr, 4803 int numargs, 4804 rvalue **args) 4805: rvalue (ctxt, loc, 4806 fn_ptr->get_type ()->dereference () 4807 ->as_a_function_type ()->get_return_type ()), 4808 m_fn_ptr (fn_ptr), 4809 m_args () 4810{ 4811 for (int i = 0; i< numargs; i++) 4812 m_args.safe_push (args[i]); 4813} 4814 4815/* Implementation of pure virtual hook recording::memento::replay_into 4816 for recording::call_through_ptr. */ 4817 4818void 4819recording::call_through_ptr::replay_into (replayer *r) 4820{ 4821 auto_vec<playback::rvalue *> playback_args; 4822 playback_args.create (m_args.length ()); 4823 for (unsigned i = 0; i< m_args.length (); i++) 4824 playback_args.safe_push (m_args[i]->playback_rvalue ()); 4825 4826 set_playback_obj (r->new_call_through_ptr (playback_location (r, m_loc), 4827 m_fn_ptr->playback_rvalue (), 4828 &playback_args)); 4829} 4830 4831/* Implementation of pure virtual hook recording::rvalue::visit_children 4832 for recording::call_through_ptr. */ 4833 4834void 4835recording::call_through_ptr::visit_children (rvalue_visitor *v) 4836{ 4837 v->visit (m_fn_ptr); 4838 for (unsigned i = 0; i< m_args.length (); i++) 4839 v->visit (m_args[i]); 4840} 4841 4842/* Implementation of recording::memento::make_debug_string for 4843 calls through function ptrs. */ 4844 4845recording::string * 4846recording::call_through_ptr::make_debug_string () 4847{ 4848 enum precedence prec = get_precedence (); 4849 /* First, build a buffer for the arguments. */ 4850 /* Calculate length of said buffer. */ 4851 size_t sz = 1; /* nil terminator */ 4852 for (unsigned i = 0; i< m_args.length (); i++) 4853 { 4854 sz += strlen (m_args[i]->get_debug_string_parens (prec)); 4855 sz += 2; /* ", " separator */ 4856 } 4857 4858 /* Now allocate and populate the buffer. */ 4859 char *argbuf = new char[sz]; 4860 size_t len = 0; 4861 4862 for (unsigned i = 0; i< m_args.length (); i++) 4863 { 4864 strcpy (argbuf + len, m_args[i]->get_debug_string_parens (prec)); 4865 len += strlen (m_args[i]->get_debug_string_parens (prec)); 4866 if (i + 1 < m_args.length ()) 4867 { 4868 strcpy (argbuf + len, ", "); 4869 len += 2; 4870 } 4871 } 4872 argbuf[len] = '\0'; 4873 4874 /* ...and use it to get the string for the call as a whole. */ 4875 string *result = string::from_printf (m_ctxt, 4876 "%s (%s)", 4877 m_fn_ptr->get_debug_string_parens (prec), 4878 argbuf); 4879 4880 delete[] argbuf; 4881 4882 return result; 4883} 4884 4885/* Implementation of recording::memento::write_reproducer for 4886 call_through_ptr. */ 4887 4888void 4889recording::call_through_ptr::write_reproducer (reproducer &r) 4890{ 4891 const char *id = r.make_identifier (this, "call"); 4892 const char *args_id = r.make_tmp_identifier ("args_for_", this); 4893 r.write (" gcc_jit_rvalue *%s[%i] = {\n", 4894 args_id, 4895 m_args.length ()); 4896 for (unsigned i = 0; i< m_args.length (); i++) 4897 r.write (" %s,\n", r.get_identifier_as_rvalue (m_args[i])); 4898 r.write (" };\n"); 4899 r.write (" gcc_jit_rvalue *%s =\n" 4900 " gcc_jit_context_new_call_through_ptr (%s, /* gcc_jit_context *ctxt */\n" 4901 " %s, /* gcc_jit_location *loc */\n" 4902 " %s, /* gcc_jit_rvalue *fn_ptr */\n" 4903 " %i, /* int numargs */ \n" 4904 " %s); /* gcc_jit_rvalue **args*/\n", 4905 id, 4906 r.get_identifier (get_context ()), 4907 r.get_identifier (m_loc), 4908 r.get_identifier_as_rvalue (m_fn_ptr), 4909 m_args.length (), 4910 args_id); 4911} 4912 4913/* The implementation of class gcc::jit::recording::array_access. */ 4914 4915/* Implementation of pure virtual hook recording::memento::replay_into 4916 for recording::array_access. */ 4917 4918void 4919recording::array_access::replay_into (replayer *r) 4920{ 4921 set_playback_obj ( 4922 r->new_array_access (playback_location (r, m_loc), 4923 m_ptr->playback_rvalue (), 4924 m_index->playback_rvalue ())); 4925} 4926 4927/* Implementation of pure virtual hook recording::rvalue::visit_children 4928 for recording::array_access. */ 4929 4930void 4931recording::array_access::visit_children (rvalue_visitor *v) 4932{ 4933 v->visit (m_ptr); 4934 v->visit (m_index); 4935} 4936 4937/* Implementation of recording::memento::make_debug_string for 4938 array accesses. */ 4939 4940recording::string * 4941recording::array_access::make_debug_string () 4942{ 4943 enum precedence prec = get_precedence (); 4944 return string::from_printf (m_ctxt, 4945 "%s[%s]", 4946 m_ptr->get_debug_string_parens (prec), 4947 m_index->get_debug_string_parens (prec)); 4948} 4949 4950/* Implementation of recording::memento::write_reproducer for 4951 array_access. */ 4952 4953void 4954recording::array_access::write_reproducer (reproducer &r) 4955{ 4956 const char *id = r.make_identifier (this, "lvalue"); 4957 r.write (" gcc_jit_lvalue *%s = \n" 4958 " gcc_jit_context_new_array_access (%s, /* gcc_jit_context *ctxt */\n" 4959 " %s, /*gcc_jit_location *loc */\n" 4960 " %s, /* gcc_jit_rvalue *ptr */\n" 4961 " %s); /* gcc_jit_rvalue *index */\n", 4962 id, 4963 r.get_identifier (get_context ()), 4964 r.get_identifier (m_loc), 4965 r.get_identifier_as_rvalue (m_ptr), 4966 r.get_identifier_as_rvalue (m_index)); 4967} 4968 4969/* The implementation of class gcc::jit::recording::access_field_of_lvalue. */ 4970 4971/* Implementation of pure virtual hook recording::memento::replay_into 4972 for recording::access_field_of_lvalue. */ 4973 4974void 4975recording::access_field_of_lvalue::replay_into (replayer *r) 4976{ 4977 set_playback_obj ( 4978 m_lvalue->playback_lvalue () 4979 ->access_field (playback_location (r, m_loc), 4980 m_field->playback_field ())); 4981 4982} 4983 4984/* Implementation of pure virtual hook recording::rvalue::visit_children 4985 for recording::access_field_of_lvalue. */ 4986 4987void 4988recording::access_field_of_lvalue::visit_children (rvalue_visitor *v) 4989{ 4990 v->visit (m_lvalue); 4991} 4992 4993/* Implementation of recording::memento::make_debug_string for 4994 accessing a field of an lvalue. */ 4995 4996recording::string * 4997recording::access_field_of_lvalue::make_debug_string () 4998{ 4999 enum precedence prec = get_precedence (); 5000 return string::from_printf (m_ctxt, 5001 "%s.%s", 5002 m_lvalue->get_debug_string_parens (prec), 5003 m_field->get_debug_string ()); 5004} 5005 5006/* Implementation of recording::memento::write_reproducer for 5007 access_field_of_lvalue. */ 5008 5009void 5010recording::access_field_of_lvalue::write_reproducer (reproducer &r) 5011{ 5012 const char *id = r.make_identifier (this, "lvalue"); 5013 r.write (" gcc_jit_lvalue *%s = \n" 5014 " gcc_jit_lvalue_access_field (%s, /*gcc_jit_lvalue *struct_or_union */\n" 5015 " %s, /*gcc_jit_location *loc */\n" 5016 " %s);\n", 5017 id, 5018 r.get_identifier_as_lvalue (m_lvalue), 5019 r.get_identifier (m_loc), 5020 r.get_identifier (m_field)); 5021} 5022 5023/* The implementation of class gcc::jit::recording::access_field_rvalue. */ 5024 5025/* Implementation of pure virtual hook recording::memento::replay_into 5026 for recording::access_field_rvalue. */ 5027 5028void 5029recording::access_field_rvalue::replay_into (replayer *r) 5030{ 5031 set_playback_obj ( 5032 m_rvalue->playback_rvalue () 5033 ->access_field (playback_location (r, m_loc), 5034 m_field->playback_field ())); 5035} 5036 5037/* Implementation of pure virtual hook recording::rvalue::visit_children 5038 for recording::access_field_rvalue. */ 5039 5040void 5041recording::access_field_rvalue::visit_children (rvalue_visitor *v) 5042{ 5043 v->visit (m_rvalue); 5044} 5045 5046/* Implementation of recording::memento::make_debug_string for 5047 accessing a field of an rvalue. */ 5048 5049recording::string * 5050recording::access_field_rvalue::make_debug_string () 5051{ 5052 enum precedence prec = get_precedence (); 5053 return string::from_printf (m_ctxt, 5054 "%s.%s", 5055 m_rvalue->get_debug_string_parens (prec), 5056 m_field->get_debug_string ()); 5057} 5058 5059/* Implementation of recording::memento::write_reproducer for 5060 access_field_rvalue. */ 5061 5062void 5063recording::access_field_rvalue::write_reproducer (reproducer &r) 5064{ 5065 const char *id = r.make_identifier (this, "rvalue"); 5066 r.write (" gcc_jit_rvalue *%s = \n" 5067 " gcc_jit_rvalue_access_field (%s, /*gcc_jit_rvalue *struct_or_union */\n" 5068 " %s, /*gcc_jit_location *loc */\n" 5069 " %s);\n", 5070 id, 5071 r.get_identifier_as_rvalue (m_rvalue), 5072 r.get_identifier (m_loc), 5073 r.get_identifier (m_field)); 5074} 5075 5076/* The implementation of class 5077 gcc::jit::recording::dereference_field_rvalue. */ 5078 5079/* Implementation of pure virtual hook recording::memento::replay_into 5080 for recording::dereference_field_rvalue. */ 5081 5082void 5083recording::dereference_field_rvalue::replay_into (replayer *r) 5084{ 5085 set_playback_obj ( 5086 m_rvalue->playback_rvalue ()-> 5087 dereference_field (playback_location (r, m_loc), 5088 m_field->playback_field ())); 5089} 5090 5091/* Implementation of pure virtual hook recording::rvalue::visit_children 5092 for recording::dereference_field_rvalue. */ 5093 5094void 5095recording::dereference_field_rvalue::visit_children (rvalue_visitor *v) 5096{ 5097 v->visit (m_rvalue); 5098} 5099 5100/* Implementation of recording::memento::make_debug_string for 5101 dereferencing a field of an rvalue. */ 5102 5103recording::string * 5104recording::dereference_field_rvalue::make_debug_string () 5105{ 5106 enum precedence prec = get_precedence (); 5107 return string::from_printf (m_ctxt, 5108 "%s->%s", 5109 m_rvalue->get_debug_string_parens (prec), 5110 m_field->get_debug_string ()); 5111} 5112 5113/* Implementation of recording::memento::write_reproducer for 5114 dereference_field_rvalue. */ 5115 5116void 5117recording::dereference_field_rvalue::write_reproducer (reproducer &r) 5118{ 5119 const char *id = r.make_identifier (this, "lvalue"); 5120 r.write (" gcc_jit_lvalue *%s=\n" 5121 " gcc_jit_rvalue_dereference_field (%s, /* gcc_jit_rvalue *ptr */\n" 5122 " %s, /* gcc_jit_location *loc */\n" 5123 " %s); /* gcc_jit_field *field */\n", 5124 id, 5125 r.get_identifier_as_rvalue (m_rvalue), 5126 r.get_identifier (m_loc), 5127 r.get_identifier (m_field)); 5128} 5129 5130/* The implementation of class gcc::jit::recording::dereference_rvalue. */ 5131 5132/* Implementation of pure virtual hook recording::memento::replay_into 5133 for recording::dereference_rvalue. */ 5134 5135void 5136recording::dereference_rvalue::replay_into (replayer *r) 5137{ 5138 set_playback_obj ( 5139 m_rvalue->playback_rvalue ()-> 5140 dereference (playback_location (r, m_loc))); 5141} 5142 5143/* Implementation of pure virtual hook recording::rvalue::visit_children 5144 for recording::dereference_rvalue. */ 5145 5146void 5147recording::dereference_rvalue::visit_children (rvalue_visitor *v) 5148{ 5149 v->visit (m_rvalue); 5150} 5151 5152/* Implementation of recording::memento::make_debug_string for 5153 dereferencing an rvalue. */ 5154 5155recording::string * 5156recording::dereference_rvalue::make_debug_string () 5157{ 5158 enum precedence prec = get_precedence (); 5159 return string::from_printf (m_ctxt, 5160 "*%s", 5161 m_rvalue->get_debug_string_parens (prec)); 5162} 5163 5164/* Implementation of recording::memento::write_reproducer for 5165 dereference_rvalue. */ 5166 5167void 5168recording::dereference_rvalue::write_reproducer (reproducer &r) 5169{ 5170 const char *id = r.make_identifier (this, "dereference"); 5171 r.write (" gcc_jit_lvalue *%s =\n" 5172 " gcc_jit_rvalue_dereference (%s, /* gcc_jit_rvalue *rvalue */\n" 5173 " %s); /* gcc_jit_location *loc */\n", 5174 id, 5175 r.get_identifier_as_rvalue (m_rvalue), 5176 r.get_identifier (m_loc)); 5177} 5178 5179/* The implementation of class gcc::jit::recording::get_address_of_lvalue. */ 5180 5181/* Implementation of pure virtual hook recording::memento::replay_into 5182 for recording::get_address_of_lvalue. */ 5183 5184void 5185recording::get_address_of_lvalue::replay_into (replayer *r) 5186{ 5187 set_playback_obj ( 5188 m_lvalue->playback_lvalue ()-> 5189 get_address (playback_location (r, m_loc))); 5190} 5191 5192/* Implementation of pure virtual hook recording::rvalue::visit_children 5193 for recording::get_address_of_lvalue. */ 5194 5195void 5196recording::get_address_of_lvalue::visit_children (rvalue_visitor *v) 5197{ 5198 v->visit (m_lvalue); 5199} 5200 5201/* Implementation of recording::memento::make_debug_string for 5202 getting the address of an lvalue. */ 5203 5204recording::string * 5205recording::get_address_of_lvalue::make_debug_string () 5206{ 5207 enum precedence prec = get_precedence (); 5208 return string::from_printf (m_ctxt, 5209 "&%s", 5210 m_lvalue->get_debug_string_parens (prec)); 5211} 5212 5213/* Implementation of recording::memento::write_reproducer for 5214 get_address_of_lvalue. */ 5215 5216void 5217recording::get_address_of_lvalue::write_reproducer (reproducer &r) 5218{ 5219 const char *id = r.make_identifier (this, "address_of"); 5220 r.write (" gcc_jit_rvalue *%s =\n" 5221 " gcc_jit_lvalue_get_address (%s, /* gcc_jit_lvalue *lvalue */\n" 5222 " %s); /* gcc_jit_location *loc */\n", 5223 id, 5224 r.get_identifier_as_lvalue (m_lvalue), 5225 r.get_identifier (m_loc)); 5226} 5227 5228/* The implementation of class gcc::jit::recording::local. */ 5229 5230/* Implementation of pure virtual hook recording::memento::replay_into 5231 for recording::local. */ 5232 5233void 5234recording::local::replay_into (replayer *r) 5235{ 5236 set_playback_obj ( 5237 m_func->playback_function () 5238 ->new_local (playback_location (r, m_loc), 5239 m_type->playback_type (), 5240 playback_string (m_name))); 5241} 5242 5243/* Override the default implementation of 5244 recording::memento::write_to_dump for locals by writing 5245 TYPE NAME; 5246 for use at the top of the function body as if it were a 5247 declaration. */ 5248 5249void 5250recording::local::write_to_dump (dump &d) 5251{ 5252 if (d.update_locations ()) 5253 m_loc = d.make_location (); 5254 d.write(" %s %s;\n", 5255 m_type->get_debug_string (), 5256 get_debug_string ()); 5257} 5258 5259void 5260recording::local::write_reproducer (reproducer &r) 5261{ 5262 const char *id = r.make_identifier (this, "local"); 5263 r.write (" gcc_jit_lvalue *%s =\n" 5264 " gcc_jit_function_new_local (%s, /* gcc_jit_function *func */\n" 5265 " %s, /* gcc_jit_location *loc */\n" 5266 " %s, /* gcc_jit_type *type */\n" 5267 " %s); /* const char *name */\n", 5268 id, 5269 r.get_identifier (m_func), 5270 r.get_identifier (m_loc), 5271 r.get_identifier_as_type (m_type), 5272 m_name->get_debug_string ()); 5273} 5274 5275/* The implementation of class gcc::jit::recording::statement. */ 5276 5277/* We poison the default implementation of 5278 gcc::jit::recording::statement::get_successor_blocks 5279 since this vfunc must only ever be called on terminator 5280 statements. */ 5281 5282vec <recording::block *> 5283recording::statement::get_successor_blocks () const 5284{ 5285 /* The base class implementation is for non-terminating statements, 5286 and thus should never be called. */ 5287 gcc_unreachable (); 5288 vec <block *> result; 5289 result.create (0); 5290 return result; 5291} 5292 5293/* Extend the default implementation of 5294 recording::memento::write_to_dump for statements by (if requested) 5295 updating the location of the statement to the current location in 5296 the dumpfile. */ 5297 5298void 5299recording::statement::write_to_dump (dump &d) 5300{ 5301 memento::write_to_dump (d); 5302 if (d.update_locations ()) 5303 m_loc = d.make_location (); 5304} 5305 5306/* The implementation of class gcc::jit::recording::eval. */ 5307 5308/* Implementation of pure virtual hook recording::memento::replay_into 5309 for recording::eval. */ 5310 5311void 5312recording::eval::replay_into (replayer *r) 5313{ 5314 playback_block (get_block ()) 5315 ->add_eval (playback_location (r), 5316 m_rvalue->playback_rvalue ()); 5317} 5318 5319/* Implementation of recording::memento::make_debug_string for 5320 an eval statement. */ 5321 5322recording::string * 5323recording::eval::make_debug_string () 5324{ 5325 return string::from_printf (m_ctxt, 5326 "(void)%s;", 5327 m_rvalue->get_debug_string ()); 5328} 5329 5330/* Implementation of recording::memento::write_reproducer for 5331 eval statements. */ 5332 5333void 5334recording::eval::write_reproducer (reproducer &r) 5335{ 5336 r.write (" gcc_jit_block_add_eval (%s, /*gcc_jit_block *block */\n" 5337 " %s, /* gcc_jit_location *loc */\n" 5338 " %s); /* gcc_jit_rvalue *rvalue */\n", 5339 r.get_identifier (get_block ()), 5340 r.get_identifier (get_loc ()), 5341 r.get_identifier_as_rvalue (m_rvalue)); 5342} 5343 5344/* The implementation of class gcc::jit::recording::assignment. */ 5345 5346/* Implementation of pure virtual hook recording::memento::replay_into 5347 for recording::assignment. */ 5348 5349void 5350recording::assignment::replay_into (replayer *r) 5351{ 5352 playback_block (get_block ()) 5353 ->add_assignment (playback_location (r), 5354 m_lvalue->playback_lvalue (), 5355 m_rvalue->playback_rvalue ()); 5356} 5357 5358/* Implementation of recording::memento::make_debug_string for 5359 an assignment statement. */ 5360 5361recording::string * 5362recording::assignment::make_debug_string () 5363{ 5364 return string::from_printf (m_ctxt, 5365 "%s = %s;", 5366 m_lvalue->get_debug_string (), 5367 m_rvalue->get_debug_string ()); 5368} 5369 5370/* Implementation of recording::memento::write_reproducer for 5371 assignment statements. */ 5372 5373void 5374recording::assignment::write_reproducer (reproducer &r) 5375{ 5376 r.write (" gcc_jit_block_add_assignment (%s, /*gcc_jit_block *block */\n" 5377 " %s, /* gcc_jit_location *loc */\n" 5378 " %s, /* gcc_jit_lvalue *lvalue */\n" 5379 " %s); /* gcc_jit_rvalue *rvalue */\n", 5380 r.get_identifier (get_block ()), 5381 r.get_identifier (get_loc ()), 5382 r.get_identifier_as_lvalue (m_lvalue), 5383 r.get_identifier_as_rvalue (m_rvalue)); 5384} 5385 5386/* The implementation of class gcc::jit::recording::assignment_op. */ 5387 5388/* Implementation of pure virtual hook recording::memento::replay_into 5389 for recording::assignment_op. */ 5390 5391void 5392recording::assignment_op::replay_into (replayer *r) 5393{ 5394 playback::type *result_type = 5395 m_lvalue->playback_lvalue ()->get_type (); 5396 5397 playback::rvalue *binary_op = 5398 r->new_binary_op (playback_location (r), 5399 m_op, 5400 result_type, 5401 m_lvalue->playback_rvalue (), 5402 m_rvalue->playback_rvalue ()); 5403 5404 playback_block (get_block ()) 5405 ->add_assignment (playback_location (r), 5406 m_lvalue->playback_lvalue (), 5407 binary_op); 5408} 5409 5410/* Implementation of recording::memento::make_debug_string for 5411 an assignment_op statement. */ 5412 5413recording::string * 5414recording::assignment_op::make_debug_string () 5415{ 5416 return string::from_printf (m_ctxt, 5417 "%s %s= %s;", 5418 m_lvalue->get_debug_string (), 5419 binary_op_strings[m_op], 5420 m_rvalue->get_debug_string ()); 5421} 5422 5423/* Implementation of recording::memento::write_reproducer for 5424 assignment_op statements. */ 5425 5426void 5427recording::assignment_op::write_reproducer (reproducer &r) 5428{ 5429 r.write (" gcc_jit_block_add_assignment_op (%s, /*gcc_jit_block *block */\n" 5430 " %s, /* gcc_jit_location *loc */\n" 5431 " %s, /* gcc_jit_lvalue *lvalue */\n" 5432 " %s, /* enum gcc_jit_binary_op op */\n" 5433 " %s); /* gcc_jit_rvalue *rvalue */\n", 5434 r.get_identifier (get_block ()), 5435 r.get_identifier (get_loc ()), 5436 r.get_identifier_as_lvalue (m_lvalue), 5437 binary_op_reproducer_strings[m_op], 5438 r.get_identifier_as_rvalue (m_rvalue)); 5439} 5440 5441/* The implementation of class gcc::jit::recording::comment. */ 5442 5443/* Implementation of pure virtual hook recording::memento::replay_into 5444 for recording::comment. */ 5445 5446void 5447recording::comment::replay_into (replayer *r) 5448{ 5449 playback_block (get_block ()) 5450 ->add_comment (playback_location (r), 5451 m_text->c_str ()); 5452} 5453 5454/* Implementation of recording::memento::make_debug_string for 5455 a comment "statement". */ 5456 5457recording::string * 5458recording::comment::make_debug_string () 5459{ 5460 return string::from_printf (m_ctxt, 5461 "/* %s */", 5462 m_text->c_str ()); 5463} 5464 5465/* Implementation of recording::memento::write_reproducer for 5466 comments. */ 5467 5468void 5469recording::comment::write_reproducer (reproducer &r) 5470{ 5471 r.write (" gcc_jit_block_add_comment (%s, /*gcc_jit_block *block */\n" 5472 " %s, /* gcc_jit_location *loc */\n" 5473 " %s); /* const char *text */\n", 5474 r.get_identifier (get_block ()), 5475 r.get_identifier (get_loc ()), 5476 m_text->get_debug_string ()); 5477} 5478 5479/* The implementation of class gcc::jit::recording::conditional. */ 5480 5481/* Implementation of pure virtual hook recording::memento::replay_into 5482 for recording::conditional. */ 5483 5484void 5485recording::conditional::replay_into (replayer *r) 5486{ 5487 playback_block (get_block ()) 5488 ->add_conditional (playback_location (r), 5489 m_boolval->playback_rvalue (), 5490 playback_block (m_on_true), 5491 playback_block (m_on_false)); 5492} 5493 5494/* Override the poisoned default implementation of 5495 gcc::jit::recording::statement::get_successor_blocks 5496 5497 A conditional jump has 2 successor blocks. */ 5498 5499vec <recording::block *> 5500recording::conditional::get_successor_blocks () const 5501{ 5502 vec <block *> result; 5503 result.create (2); 5504 result.quick_push (m_on_true); 5505 result.quick_push (m_on_false); 5506 return result; 5507} 5508 5509/* Implementation of recording::memento::make_debug_string for 5510 a conditional jump statement. */ 5511 5512recording::string * 5513recording::conditional::make_debug_string () 5514{ 5515 if (m_on_false) 5516 return string::from_printf (m_ctxt, 5517 "if (%s) goto %s; else goto %s;", 5518 m_boolval->get_debug_string (), 5519 m_on_true->get_debug_string (), 5520 m_on_false->get_debug_string ()); 5521 else 5522 return string::from_printf (m_ctxt, 5523 "if (%s) goto %s;", 5524 m_boolval->get_debug_string (), 5525 m_on_true->get_debug_string ()); 5526} 5527 5528/* Implementation of recording::memento::write_reproducer for 5529 conditional statements. */ 5530 5531void 5532recording::conditional::write_reproducer (reproducer &r) 5533{ 5534 r.write (" gcc_jit_block_end_with_conditional (%s, /*gcc_jit_block *block */\n" 5535 " %s, /* gcc_jit_location *loc */\n" 5536 " %s, /* gcc_jit_rvalue *boolval */\n" 5537 " %s, /* gcc_jit_block *on_true */\n" 5538 " %s); /* gcc_jit_block *on_false */\n", 5539 r.get_identifier (get_block ()), 5540 r.get_identifier (get_loc ()), 5541 r.get_identifier_as_rvalue (m_boolval), 5542 r.get_identifier (m_on_true), 5543 r.get_identifier (m_on_false)); 5544} 5545 5546/* The implementation of class gcc::jit::recording::jump. */ 5547 5548/* Implementation of pure virtual hook recording::memento::replay_into 5549 for recording::jump. */ 5550 5551void 5552recording::jump::replay_into (replayer *r) 5553{ 5554 playback_block (get_block ()) 5555 ->add_jump (playback_location (r), 5556 m_target->playback_block ()); 5557} 5558 5559/* Override the poisoned default implementation of 5560 gcc::jit::recording::statement::get_successor_blocks 5561 5562 An unconditional jump has 1 successor block. */ 5563 5564vec <recording::block *> 5565recording::jump::get_successor_blocks () const 5566{ 5567 vec <block *> result; 5568 result.create (1); 5569 result.quick_push (m_target); 5570 return result; 5571} 5572 5573/* Implementation of recording::memento::make_debug_string for 5574 a unconditional jump statement. */ 5575 5576recording::string * 5577recording::jump::make_debug_string () 5578{ 5579 return string::from_printf (m_ctxt, 5580 "goto %s;", 5581 m_target->get_debug_string ()); 5582} 5583 5584/* Implementation of recording::memento::write_reproducer for 5585 jump statements. */ 5586 5587void 5588recording::jump::write_reproducer (reproducer &r) 5589{ 5590 r.write (" gcc_jit_block_end_with_jump (%s, /*gcc_jit_block *block */\n" 5591 " %s, /* gcc_jit_location *loc */\n" 5592 " %s); /* gcc_jit_block *target */\n", 5593 r.get_identifier (get_block ()), 5594 r.get_identifier (get_loc ()), 5595 r.get_identifier (m_target)); 5596} 5597 5598/* The implementation of class gcc::jit::recording::return_. */ 5599 5600/* Implementation of pure virtual hook recording::memento::replay_into 5601 for recording::return_. */ 5602 5603void 5604recording::return_::replay_into (replayer *r) 5605{ 5606 playback_block (get_block ()) 5607 ->add_return (playback_location (r), 5608 m_rvalue ? m_rvalue->playback_rvalue () : NULL); 5609} 5610 5611/* Override the poisoned default implementation of 5612 gcc::jit::recording::statement::get_successor_blocks 5613 5614 A return statement has no successor block. */ 5615 5616vec <recording::block *> 5617recording::return_::get_successor_blocks () const 5618{ 5619 vec <block *> result; 5620 result.create (0); 5621 return result; 5622} 5623 5624/* Implementation of recording::memento::make_debug_string for 5625 a return statement (covers both those with and without rvalues). */ 5626 5627recording::string * 5628recording::return_::make_debug_string () 5629{ 5630 if (m_rvalue) 5631 return string::from_printf (m_ctxt, 5632 "return %s;", 5633 m_rvalue->get_debug_string ()); 5634 else 5635 return string::from_printf (m_ctxt, 5636 "return;"); 5637} 5638 5639/* Implementation of recording::memento::write_reproducer for 5640 return statements. */ 5641 5642void 5643recording::return_::write_reproducer (reproducer &r) 5644{ 5645 if (m_rvalue) 5646 r.write (" gcc_jit_block_end_with_return (%s, /*gcc_jit_block *block */\n" 5647 " %s, /* gcc_jit_location *loc */\n" 5648 " %s); /* gcc_jit_rvalue *rvalue */\n", 5649 r.get_identifier (get_block ()), 5650 r.get_identifier (get_loc ()), 5651 r.get_identifier_as_rvalue (m_rvalue)); 5652 else 5653 r.write (" gcc_jit_block_end_with_void_return (%s, /*gcc_jit_block *block */\n" 5654 " %s); /* gcc_jit_location *loc */\n", 5655 r.get_identifier (get_block ()), 5656 r.get_identifier (get_loc ())); 5657} 5658 5659/* The implementation of class gcc::jit::recording::case_. */ 5660 5661void 5662recording::case_::write_reproducer (reproducer &r) 5663{ 5664 const char *id = r.make_identifier (this, "case"); 5665 const char *fmt = 5666 " gcc_jit_case *%s = \n" 5667 " gcc_jit_context_new_case (%s, /*gcc_jit_context *ctxt */\n" 5668 " %s, /* gcc_jit_rvalue *min_value */\n" 5669 " %s, /* gcc_jit_rvalue *max_value */\n" 5670 " %s); /* gcc_jit_block *dest_block */\n"; 5671 r.write (fmt, 5672 id, 5673 r.get_identifier (get_context ()), 5674 r.get_identifier_as_rvalue (m_min_value), 5675 r.get_identifier_as_rvalue (m_max_value), 5676 r.get_identifier (m_dest_block)); 5677} 5678 5679recording::string * 5680recording::case_::make_debug_string () 5681{ 5682 return string::from_printf (get_context (), 5683 "case %s ... %s: goto %s;", 5684 m_min_value->get_debug_string (), 5685 m_max_value->get_debug_string (), 5686 m_dest_block->get_debug_string ()); 5687} 5688 5689/* The implementation of class gcc::jit::recording::switch_. */ 5690 5691/* gcc::jit::recording::switch_'s constructor. */ 5692 5693recording::switch_::switch_ (block *b, 5694 location *loc, 5695 rvalue *expr, 5696 block *default_block, 5697 int num_cases, 5698 case_ **cases) 5699: statement (b, loc), 5700 m_expr (expr), 5701 m_default_block (default_block) 5702{ 5703 m_cases.reserve_exact (num_cases); 5704 for (int i = 0; i< num_cases; i++) 5705 m_cases.quick_push (cases[i]); 5706} 5707 5708/* Implementation of pure virtual hook recording::memento::replay_into 5709 for recording::switch_. */ 5710 5711void 5712recording::switch_::replay_into (replayer *r) 5713{ 5714 auto_vec <playback::case_> pcases; 5715 int i; 5716 recording::case_ *rcase; 5717 pcases.reserve_exact (m_cases.length ()); 5718 FOR_EACH_VEC_ELT (m_cases, i, rcase) 5719 { 5720 playback::case_ pcase (rcase->get_min_value ()->playback_rvalue (), 5721 rcase->get_max_value ()->playback_rvalue (), 5722 rcase->get_dest_block ()->playback_block ()); 5723 pcases.safe_push (pcase); 5724 } 5725 playback_block (get_block ()) 5726 ->add_switch (playback_location (r), 5727 m_expr->playback_rvalue (), 5728 m_default_block->playback_block (), 5729 &pcases); 5730} 5731 5732/* Override the poisoned default implementation of 5733 gcc::jit::recording::statement::get_successor_blocks 5734 5735 A switch statement has (NUM_CASES + 1) successor blocks. */ 5736 5737vec <recording::block *> 5738recording::switch_::get_successor_blocks () const 5739{ 5740 vec <block *> result; 5741 result.create (m_cases.length () + 1); 5742 result.quick_push (m_default_block); 5743 int i; 5744 case_ *c; 5745 FOR_EACH_VEC_ELT (m_cases, i, c) 5746 result.quick_push (c->get_dest_block ()); 5747 return result; 5748} 5749 5750/* Implementation of recording::memento::make_debug_string for 5751 a switch statement. */ 5752 5753recording::string * 5754recording::switch_::make_debug_string () 5755{ 5756 auto_vec <char> cases_str; 5757 int i; 5758 case_ *c; 5759 FOR_EACH_VEC_ELT (m_cases, i, c) 5760 { 5761 size_t len = strlen (c->get_debug_string ()); 5762 unsigned idx = cases_str.length (); 5763 cases_str.safe_grow (idx + 1 + len); 5764 cases_str[idx] = ' '; 5765 memcpy (&(cases_str[idx + 1]), 5766 c->get_debug_string (), 5767 len); 5768 } 5769 cases_str.safe_push ('\0'); 5770 5771 return string::from_printf (m_ctxt, 5772 "switch (%s) {default: goto %s;%s}", 5773 m_expr->get_debug_string (), 5774 m_default_block->get_debug_string (), 5775 &cases_str[0]); 5776} 5777 5778/* Implementation of recording::memento::write_reproducer for 5779 switch statements. */ 5780 5781void 5782recording::switch_::write_reproducer (reproducer &r) 5783{ 5784 r.make_identifier (this, "switch"); 5785 int i; 5786 case_ *c; 5787 const char *cases_id = 5788 r.make_tmp_identifier ("cases_for", this); 5789 r.write (" gcc_jit_case *%s[%i] = {\n", 5790 cases_id, 5791 m_cases.length ()); 5792 FOR_EACH_VEC_ELT (m_cases, i, c) 5793 r.write (" %s,\n", r.get_identifier (c)); 5794 r.write (" };\n"); 5795 const char *fmt = 5796 " gcc_jit_block_end_with_switch (%s, /*gcc_jit_block *block */\n" 5797 " %s, /* gcc_jit_location *loc */\n" 5798 " %s, /* gcc_jit_rvalue *expr */\n" 5799 " %s, /* gcc_jit_block *default_block */\n" 5800 " %i, /* int num_cases */\n" 5801 " %s); /* gcc_jit_case **cases */\n"; 5802 r.write (fmt, 5803 r.get_identifier (get_block ()), 5804 r.get_identifier (get_loc ()), 5805 r.get_identifier_as_rvalue (m_expr), 5806 r.get_identifier (m_default_block), 5807 m_cases.length (), 5808 cases_id); 5809} 5810 5811} // namespace gcc::jit 5812 5813} // namespace gcc 5814