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