1/* Internals of libgccjit: classes for recording calls made to the JIT API. 2 Copyright (C) 2013-2015 Free Software Foundation, Inc. 3 Contributed by David Malcolm <dmalcolm@redhat.com>. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify it 8under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3, or (at your option) 10any later version. 11 12GCC is distributed in the hope that it will be useful, but 13WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING3. If not see 19<http://www.gnu.org/licenses/>. */ 20 21#ifndef JIT_RECORDING_H 22#define JIT_RECORDING_H 23 24#include "jit-common.h" 25#include "jit-logging.h" 26 27namespace gcc { 28 29namespace jit { 30 31class result; 32class dump; 33class reproducer; 34 35/********************************************************************** 36 Recording. 37 **********************************************************************/ 38 39namespace recording { 40 41playback::location * 42playback_location (replayer *r, location *loc); 43 44const char * 45playback_string (string *str); 46 47playback::block * 48playback_block (block *b); 49 50/* A recording of a call to gcc_jit_context_enable_dump. */ 51struct requested_dump 52{ 53 const char *m_dumpname; 54 char **m_out_ptr; 55}; 56 57/* A JIT-compilation context. */ 58class context : public log_user 59{ 60public: 61 context (context *parent_ctxt); 62 ~context (); 63 64 builtins_manager * 65 get_builtins_manager (); 66 67 void record (memento *m); 68 void replay_into (replayer *r); 69 void disassociate_from_playback (); 70 71 string * 72 new_string (const char *text); 73 74 location * 75 new_location (const char *filename, 76 int line, 77 int column, 78 bool created_by_user); 79 80 type * 81 get_type (enum gcc_jit_types type); 82 83 type * 84 get_int_type (int num_bytes, int is_signed); 85 86 type * 87 new_array_type (location *loc, 88 type *element_type, 89 int num_elements); 90 91 field * 92 new_field (location *loc, 93 type *type, 94 const char *name); 95 96 struct_ * 97 new_struct_type (location *loc, 98 const char *name); 99 100 union_ * 101 new_union_type (location *loc, 102 const char *name); 103 104 function_type * 105 new_function_type (type *return_type, 106 int num_params, 107 type **param_types, 108 int is_variadic); 109 110 type * 111 new_function_ptr_type (location *loc, 112 type *return_type, 113 int num_params, 114 type **param_types, 115 int is_variadic); 116 117 param * 118 new_param (location *loc, 119 type *type, 120 const char *name); 121 122 function * 123 new_function (location *loc, 124 enum gcc_jit_function_kind kind, 125 type *return_type, 126 const char *name, 127 int num_params, 128 param **params, 129 int is_variadic, 130 enum built_in_function builtin_id); 131 132 function * 133 get_builtin_function (const char *name); 134 135 lvalue * 136 new_global (location *loc, 137 enum gcc_jit_global_kind kind, 138 type *type, 139 const char *name); 140 141 template <typename HOST_TYPE> 142 rvalue * 143 new_rvalue_from_const (type *type, 144 HOST_TYPE value); 145 146 rvalue * 147 new_string_literal (const char *value); 148 149 rvalue * 150 new_unary_op (location *loc, 151 enum gcc_jit_unary_op op, 152 type *result_type, 153 rvalue *a); 154 155 rvalue * 156 new_binary_op (location *loc, 157 enum gcc_jit_binary_op op, 158 type *result_type, 159 rvalue *a, rvalue *b); 160 161 rvalue * 162 new_comparison (location *loc, 163 enum gcc_jit_comparison op, 164 rvalue *a, rvalue *b); 165 166 rvalue * 167 new_call (location *loc, 168 function *func, 169 int numargs, rvalue **args); 170 171 rvalue * 172 new_call_through_ptr (location *loc, 173 rvalue *fn_ptr, 174 int numargs, rvalue **args); 175 176 rvalue * 177 new_cast (location *loc, 178 rvalue *expr, 179 type *type_); 180 181 lvalue * 182 new_array_access (location *loc, 183 rvalue *ptr, 184 rvalue *index); 185 186 case_ * 187 new_case (rvalue *min_value, 188 rvalue *max_value, 189 block *block); 190 191 void 192 set_str_option (enum gcc_jit_str_option opt, 193 const char *value); 194 195 void 196 set_int_option (enum gcc_jit_int_option opt, 197 int value); 198 199 void 200 set_bool_option (enum gcc_jit_bool_option opt, 201 int value); 202 203 void 204 set_inner_bool_option (enum inner_bool_option inner_opt, 205 int value); 206 207 void 208 add_command_line_option (const char *optname); 209 210 void 211 append_command_line_options (vec <char *> *argvec); 212 213 void 214 enable_dump (const char *dumpname, 215 char **out_ptr); 216 217 const char * 218 get_str_option (enum gcc_jit_str_option opt) const 219 { 220 return m_str_options[opt]; 221 } 222 223 int 224 get_int_option (enum gcc_jit_int_option opt) const 225 { 226 return m_int_options[opt]; 227 } 228 229 int 230 get_bool_option (enum gcc_jit_bool_option opt) const 231 { 232 return m_bool_options[opt]; 233 } 234 235 int 236 get_inner_bool_option (enum inner_bool_option opt) const 237 { 238 return m_inner_bool_options[opt]; 239 } 240 241 result * 242 compile (); 243 244 void 245 compile_to_file (enum gcc_jit_output_kind output_kind, 246 const char *output_path); 247 248 void 249 add_error (location *loc, const char *fmt, ...) 250 GNU_PRINTF(3, 4); 251 252 void 253 add_error_va (location *loc, const char *fmt, va_list ap) 254 GNU_PRINTF(3, 0); 255 256 const char * 257 get_first_error () const; 258 259 const char * 260 get_last_error () const; 261 262 bool errors_occurred () const 263 { 264 if (m_parent_ctxt) 265 if (m_parent_ctxt->errors_occurred ()) 266 return true; 267 return m_error_count; 268 } 269 270 type *get_opaque_FILE_type (); 271 272 void dump_to_file (const char *path, bool update_locations); 273 274 void dump_reproducer_to_file (const char *path); 275 276 void 277 get_all_requested_dumps (vec <recording::requested_dump> *out); 278 279private: 280 void log_all_options () const; 281 void log_str_option (enum gcc_jit_str_option opt) const; 282 void log_int_option (enum gcc_jit_int_option opt) const; 283 void log_bool_option (enum gcc_jit_bool_option opt) const; 284 void log_inner_bool_option (enum inner_bool_option opt) const; 285 286 void validate (); 287 288private: 289 context *m_parent_ctxt; 290 291 /* The ultimate ancestor of the contexts within a family tree of 292 contexts. This has itself as its own m_toplevel_ctxt. */ 293 context *m_toplevel_ctxt; 294 295 int m_error_count; 296 297 char *m_first_error_str; 298 bool m_owns_first_error_str; 299 300 char *m_last_error_str; 301 bool m_owns_last_error_str; 302 303 char *m_str_options[GCC_JIT_NUM_STR_OPTIONS]; 304 int m_int_options[GCC_JIT_NUM_INT_OPTIONS]; 305 bool m_bool_options[GCC_JIT_NUM_BOOL_OPTIONS]; 306 bool m_inner_bool_options[NUM_INNER_BOOL_OPTIONS]; 307 auto_vec <char *> m_command_line_options; 308 309 /* Dumpfiles that were requested via gcc_jit_context_enable_dump. */ 310 auto_vec<requested_dump> m_requested_dumps; 311 312 /* Recorded API usage. */ 313 auto_vec<memento *> m_mementos; 314 315 /* Specific recordings, for use by dump_to_file. */ 316 auto_vec<compound_type *> m_compound_types; 317 auto_vec<global *> m_globals; 318 auto_vec<function *> m_functions; 319 320 type *m_basic_types[NUM_GCC_JIT_TYPES]; 321 type *m_FILE_type; 322 323 builtins_manager *m_builtins_manager; // lazily created 324}; 325 326 327/* An object with lifetime managed by the context i.e. 328 it lives until the context is released, at which 329 point it itself is cleaned up. */ 330 331class memento 332{ 333public: 334 virtual ~memento () {} 335 336 /* Hook for replaying this. */ 337 virtual void replay_into (replayer *r) = 0; 338 339 void set_playback_obj (void *obj) { m_playback_obj = obj; } 340 341 342 /* Get the context that owns this object. 343 344 Implements the post-error-checking part of 345 gcc_jit_object_get_context. */ 346 context *get_context () { return m_ctxt; } 347 348 memento * 349 as_object () { return this; } 350 351 /* Debugging hook, for use in generating error messages etc. 352 Implements the post-error-checking part of 353 gcc_jit_object_get_debug_string. */ 354 const char * 355 get_debug_string (); 356 357 virtual void write_to_dump (dump &d); 358 virtual void write_reproducer (reproducer &r) = 0; 359 virtual location *dyn_cast_location () { return NULL; } 360 361protected: 362 memento (context *ctxt) 363 : m_ctxt (ctxt), 364 m_playback_obj (NULL), 365 m_debug_string (NULL) 366 { 367 gcc_assert (ctxt); 368 } 369 370 string *new_string (const char *text) { return m_ctxt->new_string (text); } 371 372private: 373 virtual string * make_debug_string () = 0; 374 375public: 376 context *m_ctxt; 377 378protected: 379 void *m_playback_obj; 380 381private: 382 string *m_debug_string; 383}; 384 385/* or just use std::string? */ 386class string : public memento 387{ 388public: 389 string (context *ctxt, const char *text); 390 ~string (); 391 392 const char *c_str () { return m_buffer; } 393 394 static string * from_printf (context *ctxt, const char *fmt, ...) 395 GNU_PRINTF(2, 3); 396 397 void replay_into (replayer *) {} 398 399private: 400 string * make_debug_string (); 401 void write_reproducer (reproducer &r); 402 403private: 404 size_t m_len; 405 char *m_buffer; 406}; 407 408class location : public memento 409{ 410public: 411 location (context *ctxt, string *filename, int line, int column, 412 bool created_by_user) 413 : memento (ctxt), 414 m_filename (filename), 415 m_line (line), 416 m_column (column), 417 m_created_by_user (created_by_user) 418 {} 419 420 void replay_into (replayer *r); 421 422 playback::location * 423 playback_location (replayer *r) 424 { 425 /* Normally during playback, we can walk forwards through the list of 426 recording objects, playing them back. The ordering of recording 427 ensures that everything that a recording object refers to has 428 already been played back, so we can simply look up the relevant 429 m_playback_obj. 430 431 Locations are an exception, due to the "write_to_dump" method of 432 recording::statement. This method can set a new location on a 433 statement after the statement is created, and thus the location 434 appears in the context's memento list *after* the statement that 435 refers to it. 436 437 In such circumstances, the statement is replayed *before* the location, 438 when the latter doesn't yet have a playback object. 439 440 Hence we need to ensure that locations have playback objects. */ 441 if (!m_playback_obj) 442 { 443 replay_into (r); 444 } 445 gcc_assert (m_playback_obj); 446 return static_cast <playback::location *> (m_playback_obj); 447 } 448 449 location *dyn_cast_location () { return this; } 450 bool created_by_user () const { return m_created_by_user; } 451 452private: 453 string * make_debug_string (); 454 void write_reproducer (reproducer &r); 455 456private: 457 string *m_filename; 458 int m_line; 459 int m_column; 460 bool m_created_by_user; 461}; 462 463class type : public memento 464{ 465public: 466 type *get_pointer (); 467 type *get_const (); 468 type *get_volatile (); 469 470 /* Get the type obtained when dereferencing this type. 471 472 This will return NULL if it's not valid to dereference this type. 473 The caller is responsible for setting an error. */ 474 virtual type *dereference () = 0; 475 476 /* Dynamic casts. */ 477 virtual function_type *dyn_cast_function_type () { return NULL; } 478 virtual function_type *as_a_function_type() { gcc_unreachable (); return NULL; } 479 virtual struct_ *dyn_cast_struct () { return NULL; } 480 481 /* Is it typesafe to copy to this type from rtype? */ 482 virtual bool accepts_writes_from (type *rtype) 483 { 484 gcc_assert (rtype); 485 return this == rtype->unqualified (); 486 } 487 488 /* Strip off "const" etc */ 489 virtual type *unqualified () 490 { 491 return this; 492 } 493 494 virtual bool is_int () const = 0; 495 virtual bool is_float () const = 0; 496 virtual bool is_bool () const = 0; 497 virtual type *is_pointer () = 0; 498 virtual type *is_array () = 0; 499 virtual bool is_void () const { return false; } 500 501 bool is_numeric () const 502 { 503 return is_int () || is_float () || is_bool (); 504 } 505 506 playback::type * 507 playback_type () 508 { 509 return static_cast <playback::type *> (m_playback_obj); 510 } 511 512 virtual const char *access_as_type (reproducer &r); 513 514protected: 515 type (context *ctxt) 516 : memento (ctxt), 517 m_pointer_to_this_type (NULL) 518 {} 519 520private: 521 type *m_pointer_to_this_type; 522}; 523 524/* Result of "gcc_jit_context_get_type". */ 525class memento_of_get_type : public type 526{ 527public: 528 memento_of_get_type (context *ctxt, 529 enum gcc_jit_types kind) 530 : type (ctxt), 531 m_kind (kind) {} 532 533 type *dereference (); 534 535 bool accepts_writes_from (type *rtype) 536 { 537 if (m_kind == GCC_JIT_TYPE_VOID_PTR) 538 if (rtype->is_pointer ()) 539 { 540 /* LHS (this) is type (void *), and the RHS is a pointer: 541 accept it: */ 542 return true; 543 } 544 545 return type::accepts_writes_from (rtype); 546 } 547 548 bool is_int () const; 549 bool is_float () const; 550 bool is_bool () const; 551 type *is_pointer () { return dereference (); } 552 type *is_array () { return NULL; } 553 bool is_void () const { return m_kind == GCC_JIT_TYPE_VOID; } 554 555public: 556 void replay_into (replayer *r); 557 558private: 559 string * make_debug_string (); 560 void write_reproducer (reproducer &r); 561 562private: 563 enum gcc_jit_types m_kind; 564}; 565 566/* Result of "gcc_jit_type_get_pointer". */ 567class memento_of_get_pointer : public type 568{ 569public: 570 memento_of_get_pointer (type *other_type) 571 : type (other_type->m_ctxt), 572 m_other_type (other_type) {} 573 574 type *dereference () { return m_other_type; } 575 576 bool accepts_writes_from (type *rtype); 577 578 void replay_into (replayer *r); 579 580 bool is_int () const { return false; } 581 bool is_float () const { return false; } 582 bool is_bool () const { return false; } 583 type *is_pointer () { return m_other_type; } 584 type *is_array () { return NULL; } 585 586private: 587 string * make_debug_string (); 588 void write_reproducer (reproducer &r); 589 590private: 591 type *m_other_type; 592}; 593 594/* Result of "gcc_jit_type_get_const". */ 595class memento_of_get_const : public type 596{ 597public: 598 memento_of_get_const (type *other_type) 599 : type (other_type->m_ctxt), 600 m_other_type (other_type) {} 601 602 type *dereference () { return m_other_type->dereference (); } 603 604 bool accepts_writes_from (type */*rtype*/) 605 { 606 /* Can't write to a "const". */ 607 return false; 608 } 609 610 /* Strip off the "const", giving the underlying type. */ 611 type *unqualified () { return m_other_type; } 612 613 bool is_int () const { return m_other_type->is_int (); } 614 bool is_float () const { return m_other_type->is_float (); } 615 bool is_bool () const { return m_other_type->is_bool (); } 616 type *is_pointer () { return m_other_type->is_pointer (); } 617 type *is_array () { return m_other_type->is_array (); } 618 619 void replay_into (replayer *); 620 621private: 622 string * make_debug_string (); 623 void write_reproducer (reproducer &r); 624 625private: 626 type *m_other_type; 627}; 628 629/* Result of "gcc_jit_type_get_volatile". */ 630class memento_of_get_volatile : public type 631{ 632public: 633 memento_of_get_volatile (type *other_type) 634 : type (other_type->m_ctxt), 635 m_other_type (other_type) {} 636 637 type *dereference () { return m_other_type->dereference (); } 638 639 /* Strip off the "volatile", giving the underlying type. */ 640 type *unqualified () { return m_other_type; } 641 642 bool is_int () const { return m_other_type->is_int (); } 643 bool is_float () const { return m_other_type->is_float (); } 644 bool is_bool () const { return m_other_type->is_bool (); } 645 type *is_pointer () { return m_other_type->is_pointer (); } 646 type *is_array () { return m_other_type->is_array (); } 647 648 void replay_into (replayer *); 649 650private: 651 string * make_debug_string (); 652 void write_reproducer (reproducer &r); 653 654private: 655 type *m_other_type; 656}; 657 658class array_type : public type 659{ 660 public: 661 array_type (context *ctxt, 662 location *loc, 663 type *element_type, 664 int num_elements) 665 : type (ctxt), 666 m_loc (loc), 667 m_element_type (element_type), 668 m_num_elements (num_elements) 669 {} 670 671 type *dereference (); 672 673 bool is_int () const { return false; } 674 bool is_float () const { return false; } 675 bool is_bool () const { return false; } 676 type *is_pointer () { return NULL; } 677 type *is_array () { return m_element_type; } 678 679 void replay_into (replayer *); 680 681 private: 682 string * make_debug_string (); 683 void write_reproducer (reproducer &r); 684 685 private: 686 location *m_loc; 687 type *m_element_type; 688 int m_num_elements; 689}; 690 691class function_type : public type 692{ 693public: 694 function_type (context *ctxt, 695 type *return_type, 696 int num_params, 697 type **param_types, 698 int is_variadic); 699 700 type *dereference (); 701 function_type *dyn_cast_function_type () { return this; } 702 function_type *as_a_function_type () { return this; } 703 704 bool is_int () const { return false; } 705 bool is_float () const { return false; } 706 bool is_bool () const { return false; } 707 type *is_pointer () { return NULL; } 708 type *is_array () { return NULL; } 709 710 void replay_into (replayer *); 711 712 type * get_return_type () const { return m_return_type; } 713 const vec<type *> &get_param_types () const { return m_param_types; } 714 int is_variadic () const { return m_is_variadic; } 715 716 string * make_debug_string_with_ptr (); 717 718 void 719 write_deferred_reproducer (reproducer &r, 720 memento *ptr_type); 721 722 private: 723 string * make_debug_string (); 724 string * make_debug_string_with (const char *); 725 void write_reproducer (reproducer &r); 726 727private: 728 type *m_return_type; 729 auto_vec<type *> m_param_types; 730 int m_is_variadic; 731}; 732 733class field : public memento 734{ 735public: 736 field (context *ctxt, 737 location *loc, 738 type *type, 739 string *name) 740 : memento (ctxt), 741 m_loc (loc), 742 m_type (type), 743 m_name (name), 744 m_container (NULL) 745 {} 746 747 type * get_type () const { return m_type; } 748 749 compound_type * get_container () const { return m_container; } 750 void set_container (compound_type *c) { m_container = c; } 751 752 void replay_into (replayer *); 753 754 void write_to_dump (dump &d); 755 756 playback::field * 757 playback_field () const 758 { 759 return static_cast <playback::field *> (m_playback_obj); 760 } 761 762private: 763 string * make_debug_string (); 764 void write_reproducer (reproducer &r); 765 766private: 767 location *m_loc; 768 type *m_type; 769 string *m_name; 770 compound_type *m_container; 771}; 772 773/* Base class for struct_ and union_ */ 774class compound_type : public type 775{ 776public: 777 compound_type (context *ctxt, 778 location *loc, 779 string *name); 780 781 string *get_name () const { return m_name; } 782 location *get_loc () const { return m_loc; } 783 fields * get_fields () { return m_fields; } 784 785 void 786 set_fields (location *loc, 787 int num_fields, 788 field **fields); 789 790 type *dereference (); 791 792 bool is_int () const { return false; } 793 bool is_float () const { return false; } 794 bool is_bool () const { return false; } 795 type *is_pointer () { return NULL; } 796 type *is_array () { return NULL; } 797 798 playback::compound_type * 799 playback_compound_type () 800 { 801 return static_cast <playback::compound_type *> (m_playback_obj); 802 } 803 804private: 805 location *m_loc; 806 string *m_name; 807 fields *m_fields; 808}; 809 810class struct_ : public compound_type 811{ 812public: 813 struct_ (context *ctxt, 814 location *loc, 815 string *name); 816 817 struct_ *dyn_cast_struct () { return this; } 818 819 type * 820 as_type () { return this; } 821 822 void replay_into (replayer *r); 823 824 const char *access_as_type (reproducer &r); 825 826private: 827 string * make_debug_string (); 828 void write_reproducer (reproducer &r); 829}; 830 831// memento of struct_::set_fields 832class fields : public memento 833{ 834public: 835 fields (compound_type *struct_or_union, 836 int num_fields, 837 field **fields); 838 839 void replay_into (replayer *r); 840 841 void write_to_dump (dump &d); 842 843 int length () const { return m_fields.length (); } 844 field *get_field (int i) const { return m_fields[i]; } 845 846private: 847 string * make_debug_string (); 848 void write_reproducer (reproducer &r); 849 850private: 851 compound_type *m_struct_or_union; 852 auto_vec<field *> m_fields; 853}; 854 855class union_ : public compound_type 856{ 857public: 858 union_ (context *ctxt, 859 location *loc, 860 string *name); 861 862 void replay_into (replayer *r); 863 864private: 865 string * make_debug_string (); 866 void write_reproducer (reproducer &r); 867 868private: 869 location *m_loc; 870 string *m_name; 871}; 872 873/* An abstract base class for operations that visit all rvalues within an 874 expression tree. 875 Currently the only implementation is class rvalue_usage_validator within 876 jit-recording.c. */ 877 878class rvalue_visitor 879{ 880 public: 881 virtual ~rvalue_visitor () {} 882 virtual void visit (rvalue *rvalue) = 0; 883}; 884 885/* When generating debug strings for rvalues we mimic C, so we need to 886 mimic C's precedence levels when handling compound expressions. 887 These are in order from strongest precedence to weakest. */ 888enum precedence 889{ 890 PRECEDENCE_PRIMARY, 891 PRECEDENCE_POSTFIX, 892 PRECEDENCE_UNARY, 893 PRECEDENCE_CAST, 894 PRECEDENCE_MULTIPLICATIVE, 895 PRECEDENCE_ADDITIVE, 896 PRECEDENCE_SHIFT, 897 PRECEDENCE_RELATIONAL, 898 PRECEDENCE_EQUALITY, 899 PRECEDENCE_BITWISE_AND, 900 PRECEDENCE_BITWISE_XOR, 901 PRECEDENCE_BITWISE_IOR, 902 PRECEDENCE_LOGICAL_AND, 903 PRECEDENCE_LOGICAL_OR 904}; 905 906class rvalue : public memento 907{ 908public: 909 rvalue (context *ctxt, 910 location *loc, 911 type *type_) 912 : memento (ctxt), 913 m_loc (loc), 914 m_type (type_), 915 m_scope (NULL), 916 m_parenthesized_string (NULL) 917 { 918 gcc_assert (type_); 919 } 920 921 location * get_loc () const { return m_loc; } 922 923 /* Get the recording::type of this rvalue. 924 925 Implements the post-error-checking part of 926 gcc_jit_rvalue_get_type. */ 927 type * get_type () const { return m_type; } 928 929 playback::rvalue * 930 playback_rvalue () const 931 { 932 return static_cast <playback::rvalue *> (m_playback_obj); 933 } 934 rvalue * 935 access_field (location *loc, 936 field *field); 937 938 lvalue * 939 dereference_field (location *loc, 940 field *field); 941 942 lvalue * 943 dereference (location *loc); 944 945 void 946 verify_valid_within_stmt (const char *api_funcname, statement *s); 947 948 virtual void visit_children (rvalue_visitor *v) = 0; 949 950 void set_scope (function *scope); 951 function *get_scope () const { return m_scope; } 952 953 /* Dynamic cast. */ 954 virtual param *dyn_cast_param () { return NULL; } 955 956 virtual const char *access_as_rvalue (reproducer &r); 957 958 /* Get the debug string, wrapped in parentheses. */ 959 const char * 960 get_debug_string_parens (enum precedence outer_prec); 961 962 virtual bool is_constant () const { return false; } 963 virtual bool get_wide_int (wide_int *) const { return false; } 964 965private: 966 virtual enum precedence get_precedence () const = 0; 967 968protected: 969 location *m_loc; 970 type *m_type; 971 972 private: 973 function *m_scope; /* NULL for globals, non-NULL for locals/params */ 974 string *m_parenthesized_string; 975}; 976 977class lvalue : public rvalue 978{ 979public: 980 lvalue (context *ctxt, 981 location *loc, 982 type *type_) 983 : rvalue (ctxt, loc, type_) 984 {} 985 986 playback::lvalue * 987 playback_lvalue () const 988 { 989 return static_cast <playback::lvalue *> (m_playback_obj); 990 } 991 992 lvalue * 993 access_field (location *loc, 994 field *field); 995 996 rvalue * 997 get_address (location *loc); 998 999 rvalue * 1000 as_rvalue () { return this; } 1001 1002 const char *access_as_rvalue (reproducer &r); 1003 virtual const char *access_as_lvalue (reproducer &r); 1004}; 1005 1006class param : public lvalue 1007{ 1008public: 1009 param (context *ctxt, 1010 location *loc, 1011 type *type, 1012 string *name) 1013 : lvalue (ctxt, loc, type), 1014 m_name (name) {} 1015 1016 lvalue * 1017 as_lvalue () { return this; } 1018 1019 void replay_into (replayer *r); 1020 1021 void visit_children (rvalue_visitor *) {} 1022 1023 playback::param * 1024 playback_param () const 1025 { 1026 return static_cast <playback::param *> (m_playback_obj); 1027 } 1028 1029 param *dyn_cast_param () { return this; } 1030 1031 const char *access_as_rvalue (reproducer &r); 1032 const char *access_as_lvalue (reproducer &r); 1033 1034private: 1035 string * make_debug_string () { return m_name; } 1036 void write_reproducer (reproducer &r); 1037 enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; } 1038 1039private: 1040 string *m_name; 1041}; 1042 1043class function : public memento 1044{ 1045public: 1046 function (context *ctxt, 1047 location *loc, 1048 enum gcc_jit_function_kind kind, 1049 type *return_type, 1050 string *name, 1051 int num_params, 1052 param **params, 1053 int is_variadic, 1054 enum built_in_function builtin_id); 1055 1056 void replay_into (replayer *r); 1057 1058 playback::function * 1059 playback_function () const 1060 { 1061 return static_cast <playback::function *> (m_playback_obj); 1062 } 1063 1064 enum gcc_jit_function_kind get_kind () const { return m_kind; } 1065 1066 lvalue * 1067 new_local (location *loc, 1068 type *type, 1069 const char *name); 1070 1071 block* 1072 new_block (const char *name); 1073 1074 location *get_loc () const { return m_loc; } 1075 type *get_return_type () const { return m_return_type; } 1076 string * get_name () const { return m_name; } 1077 const vec<param *> &get_params () const { return m_params; } 1078 1079 /* Get the given param by index. 1080 Implements the post-error-checking part of 1081 gcc_jit_function_get_param. */ 1082 param *get_param (int i) const { return m_params[i]; } 1083 1084 bool is_variadic () const { return m_is_variadic; } 1085 1086 void write_to_dump (dump &d); 1087 1088 void validate (); 1089 1090 void dump_to_dot (const char *path); 1091 1092private: 1093 string * make_debug_string (); 1094 void write_reproducer (reproducer &r); 1095 1096private: 1097 location *m_loc; 1098 enum gcc_jit_function_kind m_kind; 1099 type *m_return_type; 1100 string *m_name; 1101 auto_vec<param *> m_params; 1102 int m_is_variadic; 1103 enum built_in_function m_builtin_id; 1104 auto_vec<local *> m_locals; 1105 auto_vec<block *> m_blocks; 1106}; 1107 1108class block : public memento 1109{ 1110public: 1111 block (function *func, int index, string *name) 1112 : memento (func->m_ctxt), 1113 m_func (func), 1114 m_index (index), 1115 m_name (name), 1116 m_statements (), 1117 m_has_been_terminated (false), 1118 m_is_reachable (false) 1119 { 1120 } 1121 1122 /* Get the recording::function containing this block. 1123 Implements the post-error-checking part of 1124 gcc_jit_block_get_function. */ 1125 function *get_function () { return m_func; } 1126 1127 bool has_been_terminated () { return m_has_been_terminated; } 1128 bool is_reachable () { return m_is_reachable; } 1129 1130 statement * 1131 add_eval (location *loc, 1132 rvalue *rvalue); 1133 1134 statement * 1135 add_assignment (location *loc, 1136 lvalue *lvalue, 1137 rvalue *rvalue); 1138 1139 statement * 1140 add_assignment_op (location *loc, 1141 lvalue *lvalue, 1142 enum gcc_jit_binary_op op, 1143 rvalue *rvalue); 1144 1145 statement * 1146 add_comment (location *loc, 1147 const char *text); 1148 1149 statement * 1150 end_with_conditional (location *loc, 1151 rvalue *boolval, 1152 block *on_true, 1153 block *on_false); 1154 1155 statement * 1156 end_with_jump (location *loc, 1157 block *target); 1158 1159 statement * 1160 end_with_return (location *loc, 1161 rvalue *rvalue); 1162 1163 statement * 1164 end_with_switch (location *loc, 1165 rvalue *expr, 1166 block *default_block, 1167 int num_cases, 1168 case_ **cases); 1169 1170 playback::block * 1171 playback_block () const 1172 { 1173 return static_cast <playback::block *> (m_playback_obj); 1174 } 1175 1176 void write_to_dump (dump &d); 1177 1178 bool validate (); 1179 1180 location *get_loc () const; 1181 1182 statement *get_first_statement () const; 1183 statement *get_last_statement () const; 1184 1185 vec <block *> get_successor_blocks () const; 1186 1187private: 1188 string * make_debug_string (); 1189 void write_reproducer (reproducer &r); 1190 1191 void replay_into (replayer *r); 1192 1193 void dump_to_dot (pretty_printer *pp); 1194 void dump_edges_to_dot (pretty_printer *pp); 1195 1196private: 1197 function *m_func; 1198 int m_index; 1199 string *m_name; 1200 auto_vec<statement *> m_statements; 1201 bool m_has_been_terminated; 1202 bool m_is_reachable; 1203 1204 friend class function; 1205}; 1206 1207class global : public lvalue 1208{ 1209public: 1210 global (context *ctxt, 1211 location *loc, 1212 enum gcc_jit_global_kind kind, 1213 type *type, 1214 string *name) 1215 : lvalue (ctxt, loc, type), 1216 m_kind (kind), 1217 m_name (name) 1218 {} 1219 1220 void replay_into (replayer *); 1221 1222 void visit_children (rvalue_visitor *) {} 1223 1224 void write_to_dump (dump &d); 1225 1226private: 1227 string * make_debug_string () { return m_name; } 1228 void write_reproducer (reproducer &r); 1229 enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; } 1230 1231private: 1232 enum gcc_jit_global_kind m_kind; 1233 string *m_name; 1234}; 1235 1236template <typename HOST_TYPE> 1237class memento_of_new_rvalue_from_const : public rvalue 1238{ 1239public: 1240 memento_of_new_rvalue_from_const (context *ctxt, 1241 location *loc, 1242 type *type, 1243 HOST_TYPE value) 1244 : rvalue (ctxt, loc, type), 1245 m_value (value) {} 1246 1247 void replay_into (replayer *r); 1248 1249 void visit_children (rvalue_visitor *) {} 1250 1251 bool is_constant () const { return true; } 1252 1253 bool get_wide_int (wide_int *out) const; 1254 1255private: 1256 string * make_debug_string (); 1257 void write_reproducer (reproducer &r); 1258 enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; } 1259 1260private: 1261 HOST_TYPE m_value; 1262}; 1263 1264class memento_of_new_string_literal : public rvalue 1265{ 1266public: 1267 memento_of_new_string_literal (context *ctxt, 1268 location *loc, 1269 string *value) 1270 : rvalue (ctxt, loc, ctxt->get_type (GCC_JIT_TYPE_CONST_CHAR_PTR)), 1271 m_value (value) {} 1272 1273 void replay_into (replayer *r); 1274 1275 void visit_children (rvalue_visitor *) {} 1276 1277private: 1278 string * make_debug_string (); 1279 void write_reproducer (reproducer &r); 1280 enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; } 1281 1282private: 1283 string *m_value; 1284}; 1285 1286class unary_op : public rvalue 1287{ 1288public: 1289 unary_op (context *ctxt, 1290 location *loc, 1291 enum gcc_jit_unary_op op, 1292 type *result_type, 1293 rvalue *a) 1294 : rvalue (ctxt, loc, result_type), 1295 m_op (op), 1296 m_a (a) 1297 {} 1298 1299 void replay_into (replayer *r); 1300 1301 void visit_children (rvalue_visitor *v); 1302 1303private: 1304 string * make_debug_string (); 1305 void write_reproducer (reproducer &r); 1306 enum precedence get_precedence () const {return PRECEDENCE_UNARY;} 1307 1308private: 1309 enum gcc_jit_unary_op m_op; 1310 rvalue *m_a; 1311}; 1312 1313class binary_op : public rvalue 1314{ 1315public: 1316 binary_op (context *ctxt, 1317 location *loc, 1318 enum gcc_jit_binary_op op, 1319 type *result_type, 1320 rvalue *a, rvalue *b) 1321 : rvalue (ctxt, loc, result_type), 1322 m_op (op), 1323 m_a (a), 1324 m_b (b) {} 1325 1326 void replay_into (replayer *r); 1327 1328 void visit_children (rvalue_visitor *v); 1329 1330private: 1331 string * make_debug_string (); 1332 void write_reproducer (reproducer &r); 1333 enum precedence get_precedence () const; 1334 1335private: 1336 enum gcc_jit_binary_op m_op; 1337 rvalue *m_a; 1338 rvalue *m_b; 1339}; 1340 1341class comparison : public rvalue 1342{ 1343public: 1344 comparison (context *ctxt, 1345 location *loc, 1346 enum gcc_jit_comparison op, 1347 rvalue *a, rvalue *b) 1348 : rvalue (ctxt, loc, ctxt->get_type (GCC_JIT_TYPE_BOOL)), 1349 m_op (op), 1350 m_a (a), 1351 m_b (b) 1352 {} 1353 1354 void replay_into (replayer *r); 1355 1356 void visit_children (rvalue_visitor *v); 1357 1358private: 1359 string * make_debug_string (); 1360 void write_reproducer (reproducer &r); 1361 enum precedence get_precedence () const; 1362 1363private: 1364 enum gcc_jit_comparison m_op; 1365 rvalue *m_a; 1366 rvalue *m_b; 1367}; 1368 1369class cast : public rvalue 1370{ 1371public: 1372 cast (context *ctxt, 1373 location *loc, 1374 rvalue *a, 1375 type *type_) 1376 : rvalue (ctxt, loc, type_), 1377 m_rvalue (a) 1378 {} 1379 1380 void replay_into (replayer *r); 1381 1382 void visit_children (rvalue_visitor *v); 1383 1384private: 1385 string * make_debug_string (); 1386 void write_reproducer (reproducer &r); 1387 enum precedence get_precedence () const { return PRECEDENCE_CAST; } 1388 1389private: 1390 rvalue *m_rvalue; 1391}; 1392 1393class call : public rvalue 1394{ 1395public: 1396 call (context *ctxt, 1397 location *loc, 1398 function *func, 1399 int numargs, 1400 rvalue **args); 1401 1402 void replay_into (replayer *r); 1403 1404 void visit_children (rvalue_visitor *v); 1405 1406private: 1407 string * make_debug_string (); 1408 void write_reproducer (reproducer &r); 1409 enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; } 1410 1411private: 1412 function *m_func; 1413 auto_vec<rvalue *> m_args; 1414}; 1415 1416class call_through_ptr : public rvalue 1417{ 1418public: 1419 call_through_ptr (context *ctxt, 1420 location *loc, 1421 rvalue *fn_ptr, 1422 int numargs, 1423 rvalue **args); 1424 1425 void replay_into (replayer *r); 1426 1427 void visit_children (rvalue_visitor *v); 1428 1429private: 1430 string * make_debug_string (); 1431 void write_reproducer (reproducer &r); 1432 enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; } 1433 1434private: 1435 rvalue *m_fn_ptr; 1436 auto_vec<rvalue *> m_args; 1437}; 1438 1439class array_access : public lvalue 1440{ 1441public: 1442 array_access (context *ctxt, 1443 location *loc, 1444 rvalue *ptr, 1445 rvalue *index) 1446 : lvalue (ctxt, loc, ptr->get_type ()->dereference ()), 1447 m_ptr (ptr), 1448 m_index (index) 1449 {} 1450 1451 void replay_into (replayer *r); 1452 1453 void visit_children (rvalue_visitor *v); 1454 1455private: 1456 string * make_debug_string (); 1457 void write_reproducer (reproducer &r); 1458 enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; } 1459 1460private: 1461 rvalue *m_ptr; 1462 rvalue *m_index; 1463}; 1464 1465class access_field_of_lvalue : public lvalue 1466{ 1467public: 1468 access_field_of_lvalue (context *ctxt, 1469 location *loc, 1470 lvalue *val, 1471 field *field) 1472 : lvalue (ctxt, loc, field->get_type ()), 1473 m_lvalue (val), 1474 m_field (field) 1475 {} 1476 1477 void replay_into (replayer *r); 1478 1479 void visit_children (rvalue_visitor *v); 1480 1481private: 1482 string * make_debug_string (); 1483 void write_reproducer (reproducer &r); 1484 enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; } 1485 1486private: 1487 lvalue *m_lvalue; 1488 field *m_field; 1489}; 1490 1491class access_field_rvalue : public rvalue 1492{ 1493public: 1494 access_field_rvalue (context *ctxt, 1495 location *loc, 1496 rvalue *val, 1497 field *field) 1498 : rvalue (ctxt, loc, field->get_type ()), 1499 m_rvalue (val), 1500 m_field (field) 1501 {} 1502 1503 void replay_into (replayer *r); 1504 1505 void visit_children (rvalue_visitor *v); 1506 1507private: 1508 string * make_debug_string (); 1509 void write_reproducer (reproducer &r); 1510 enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; } 1511 1512private: 1513 rvalue *m_rvalue; 1514 field *m_field; 1515}; 1516 1517class dereference_field_rvalue : public lvalue 1518{ 1519public: 1520 dereference_field_rvalue (context *ctxt, 1521 location *loc, 1522 rvalue *val, 1523 field *field) 1524 : lvalue (ctxt, loc, field->get_type ()), 1525 m_rvalue (val), 1526 m_field (field) 1527 {} 1528 1529 void replay_into (replayer *r); 1530 1531 void visit_children (rvalue_visitor *v); 1532 1533private: 1534 string * make_debug_string (); 1535 void write_reproducer (reproducer &r); 1536 enum precedence get_precedence () const { return PRECEDENCE_POSTFIX; } 1537 1538private: 1539 rvalue *m_rvalue; 1540 field *m_field; 1541}; 1542 1543class dereference_rvalue : public lvalue 1544{ 1545public: 1546 dereference_rvalue (context *ctxt, 1547 location *loc, 1548 rvalue *val) 1549 : lvalue (ctxt, loc, val->get_type ()->dereference ()), 1550 m_rvalue (val) {} 1551 1552 void replay_into (replayer *r); 1553 1554 void visit_children (rvalue_visitor *v); 1555 1556private: 1557 string * make_debug_string (); 1558 void write_reproducer (reproducer &r); 1559 enum precedence get_precedence () const { return PRECEDENCE_UNARY; } 1560 1561private: 1562 rvalue *m_rvalue; 1563}; 1564 1565class get_address_of_lvalue : public rvalue 1566{ 1567public: 1568 get_address_of_lvalue (context *ctxt, 1569 location *loc, 1570 lvalue *val) 1571 : rvalue (ctxt, loc, val->get_type ()->get_pointer ()), 1572 m_lvalue (val) 1573 {} 1574 1575 void replay_into (replayer *r); 1576 1577 void visit_children (rvalue_visitor *v); 1578 1579private: 1580 string * make_debug_string (); 1581 void write_reproducer (reproducer &r); 1582 enum precedence get_precedence () const { return PRECEDENCE_UNARY; } 1583 1584private: 1585 lvalue *m_lvalue; 1586}; 1587 1588class local : public lvalue 1589{ 1590public: 1591 local (function *func, location *loc, type *type_, string *name) 1592 : lvalue (func->m_ctxt, loc, type_), 1593 m_func (func), 1594 m_name (name) 1595 { 1596 set_scope (func); 1597 } 1598 1599 void replay_into (replayer *r); 1600 1601 void visit_children (rvalue_visitor *) {} 1602 1603 void write_to_dump (dump &d); 1604 1605private: 1606 string * make_debug_string () { return m_name; } 1607 void write_reproducer (reproducer &r); 1608 enum precedence get_precedence () const { return PRECEDENCE_PRIMARY; } 1609 1610private: 1611 function *m_func; 1612 string *m_name; 1613}; 1614 1615class statement : public memento 1616{ 1617public: 1618 virtual vec <block *> get_successor_blocks () const; 1619 1620 void write_to_dump (dump &d); 1621 1622 block *get_block () const { return m_block; } 1623 location *get_loc () const { return m_loc; } 1624 1625protected: 1626 statement (block *b, location *loc) 1627 : memento (b->m_ctxt), 1628 m_block (b), 1629 m_loc (loc) {} 1630 1631 playback::location * 1632 playback_location (replayer *r) const 1633 { 1634 return ::gcc::jit::recording::playback_location (r, m_loc); 1635 } 1636 1637private: 1638 block *m_block; 1639 location *m_loc; 1640}; 1641 1642class eval : public statement 1643{ 1644public: 1645 eval (block *b, 1646 location *loc, 1647 rvalue *rvalue) 1648 : statement (b, loc), 1649 m_rvalue (rvalue) {} 1650 1651 void replay_into (replayer *r); 1652 1653private: 1654 string * make_debug_string (); 1655 void write_reproducer (reproducer &r); 1656 1657private: 1658 rvalue *m_rvalue; 1659}; 1660 1661class assignment : public statement 1662{ 1663public: 1664 assignment (block *b, 1665 location *loc, 1666 lvalue *lvalue, 1667 rvalue *rvalue) 1668 : statement (b, loc), 1669 m_lvalue (lvalue), 1670 m_rvalue (rvalue) {} 1671 1672 void replay_into (replayer *r); 1673 1674private: 1675 string * make_debug_string (); 1676 void write_reproducer (reproducer &r); 1677 1678private: 1679 lvalue *m_lvalue; 1680 rvalue *m_rvalue; 1681}; 1682 1683class assignment_op : public statement 1684{ 1685public: 1686 assignment_op (block *b, 1687 location *loc, 1688 lvalue *lvalue, 1689 enum gcc_jit_binary_op op, 1690 rvalue *rvalue) 1691 : statement (b, loc), 1692 m_lvalue (lvalue), 1693 m_op (op), 1694 m_rvalue (rvalue) {} 1695 1696 void replay_into (replayer *r); 1697 1698private: 1699 string * make_debug_string (); 1700 void write_reproducer (reproducer &r); 1701 1702private: 1703 lvalue *m_lvalue; 1704 enum gcc_jit_binary_op m_op; 1705 rvalue *m_rvalue; 1706}; 1707 1708class comment : public statement 1709{ 1710public: 1711 comment (block *b, 1712 location *loc, 1713 string *text) 1714 : statement (b, loc), 1715 m_text (text) {} 1716 1717 void replay_into (replayer *r); 1718 1719private: 1720 string * make_debug_string (); 1721 void write_reproducer (reproducer &r); 1722 1723private: 1724 string *m_text; 1725}; 1726 1727class conditional : public statement 1728{ 1729public: 1730 conditional (block *b, 1731 location *loc, 1732 rvalue *boolval, 1733 block *on_true, 1734 block *on_false) 1735 : statement (b, loc), 1736 m_boolval (boolval), 1737 m_on_true (on_true), 1738 m_on_false (on_false) {} 1739 1740 void replay_into (replayer *r); 1741 1742 vec <block *> get_successor_blocks () const; 1743 1744private: 1745 string * make_debug_string (); 1746 void write_reproducer (reproducer &r); 1747 1748private: 1749 rvalue *m_boolval; 1750 block *m_on_true; 1751 block *m_on_false; 1752}; 1753 1754class jump : public statement 1755{ 1756public: 1757 jump (block *b, 1758 location *loc, 1759 block *target) 1760 : statement (b, loc), 1761 m_target (target) {} 1762 1763 void replay_into (replayer *r); 1764 1765 vec <block *> get_successor_blocks () const; 1766 1767private: 1768 string * make_debug_string (); 1769 void write_reproducer (reproducer &r); 1770 1771private: 1772 block *m_target; 1773}; 1774 1775class return_ : public statement 1776{ 1777public: 1778 return_ (block *b, 1779 location *loc, 1780 rvalue *rvalue) 1781 : statement (b, loc), 1782 m_rvalue (rvalue) {} 1783 1784 void replay_into (replayer *r); 1785 1786 vec <block *> get_successor_blocks () const; 1787 1788private: 1789 string * make_debug_string (); 1790 void write_reproducer (reproducer &r); 1791 1792private: 1793 rvalue *m_rvalue; 1794}; 1795 1796class case_ : public memento 1797{ 1798 public: 1799 case_ (context *ctxt, 1800 rvalue *min_value, 1801 rvalue *max_value, 1802 block *dest_block) 1803 : memento (ctxt), 1804 m_min_value (min_value), 1805 m_max_value (max_value), 1806 m_dest_block (dest_block) 1807 {} 1808 1809 rvalue *get_min_value () const { return m_min_value; } 1810 rvalue *get_max_value () const { return m_max_value; } 1811 block *get_dest_block () const { return m_dest_block; } 1812 1813 void replay_into (replayer *) { /* empty */ } 1814 1815 void write_reproducer (reproducer &r); 1816 1817private: 1818 string * make_debug_string (); 1819 1820 private: 1821 rvalue *m_min_value; 1822 rvalue *m_max_value; 1823 block *m_dest_block; 1824}; 1825 1826class switch_ : public statement 1827{ 1828public: 1829 switch_ (block *b, 1830 location *loc, 1831 rvalue *expr, 1832 block *default_block, 1833 int num_cases, 1834 case_ **cases); 1835 1836 void replay_into (replayer *r); 1837 1838 vec <block *> get_successor_blocks () const; 1839 1840private: 1841 string * make_debug_string (); 1842 void write_reproducer (reproducer &r); 1843 1844private: 1845 rvalue *m_expr; 1846 block *m_default_block; 1847 auto_vec <case_ *> m_cases; 1848}; 1849 1850} // namespace gcc::jit::recording 1851 1852/* Create a recording::memento_of_new_rvalue_from_const instance and add 1853 it to this context's list of mementos. 1854 1855 Implements the post-error-checking part of 1856 gcc_jit_context_new_rvalue_from_{int|long|double|ptr}. */ 1857 1858template <typename HOST_TYPE> 1859recording::rvalue * 1860recording::context::new_rvalue_from_const (recording::type *type, 1861 HOST_TYPE value) 1862{ 1863 recording::rvalue *result = 1864 new memento_of_new_rvalue_from_const <HOST_TYPE> (this, NULL, type, value); 1865 record (result); 1866 return result; 1867} 1868 1869} // namespace gcc::jit 1870 1871} // namespace gcc 1872 1873#endif /* JIT_RECORDING_H */ 1874