1 /* Internals of libgccjit: classes for playing back recorded API calls. 2 Copyright (C) 2013-2020 Free Software Foundation, Inc. 3 Contributed by David Malcolm <dmalcolm@redhat.com>. 4 5 This file is part of GCC. 6 7 GCC is free software; you can redistribute it and/or modify it 8 under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3, or (at your option) 10 any later version. 11 12 GCC is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GCC; see the file COPYING3. If not see 19 <http://www.gnu.org/licenses/>. */ 20 21 #ifndef JIT_PLAYBACK_H 22 #define JIT_PLAYBACK_H 23 24 #include <utility> // for std::pair 25 26 #include "timevar.h" 27 28 #include "jit-recording.h" 29 30 struct diagnostic_context; 31 struct diagnostic_info; 32 33 namespace gcc { 34 35 namespace jit { 36 37 /********************************************************************** 38 Playback. 39 **********************************************************************/ 40 41 namespace playback { 42 43 /* playback::context is an abstract base class. 44 45 The two concrete subclasses are: 46 - playback::compile_to_memory 47 - playback::compile_to_file. */ 48 49 class context : public log_user 50 { 51 public: 52 context (::gcc::jit::recording::context *ctxt); 53 ~context (); 54 55 void gt_ggc_mx (); 56 57 void replay (); 58 59 location * 60 new_location (recording::location *rloc, 61 const char *filename, 62 int line, 63 int column); 64 65 type * 66 get_type (enum gcc_jit_types type); 67 68 type * 69 new_array_type (location *loc, 70 type *element_type, 71 int num_elements); 72 73 field * 74 new_field (location *loc, 75 type *type, 76 const char *name); 77 78 field * 79 new_bitfield (location *loc, 80 type *type, 81 int width, 82 const char *name); 83 84 compound_type * 85 new_compound_type (location *loc, 86 const char *name, 87 bool is_struct); /* else is union */ 88 89 type * 90 new_function_type (type *return_type, 91 const auto_vec<type *> *param_types, 92 int is_variadic); 93 94 param * 95 new_param (location *loc, 96 type *type, 97 const char *name); 98 99 function * 100 new_function (location *loc, 101 enum gcc_jit_function_kind kind, 102 type *return_type, 103 const char *name, 104 const auto_vec<param *> *params, 105 int is_variadic, 106 enum built_in_function builtin_id); 107 108 lvalue * 109 new_global (location *loc, 110 enum gcc_jit_global_kind kind, 111 type *type, 112 const char *name); 113 114 template <typename HOST_TYPE> 115 rvalue * 116 new_rvalue_from_const (type *type, 117 HOST_TYPE value); 118 119 rvalue * 120 new_string_literal (const char *value); 121 122 rvalue * 123 new_rvalue_from_vector (location *loc, 124 type *type, 125 const auto_vec<rvalue *> &elements); 126 127 rvalue * 128 new_unary_op (location *loc, 129 enum gcc_jit_unary_op op, 130 type *result_type, 131 rvalue *a); 132 133 rvalue * 134 new_binary_op (location *loc, 135 enum gcc_jit_binary_op op, 136 type *result_type, 137 rvalue *a, rvalue *b); 138 139 rvalue * 140 new_comparison (location *loc, 141 enum gcc_jit_comparison op, 142 rvalue *a, rvalue *b); 143 144 rvalue * 145 new_call (location *loc, 146 function *func, 147 const auto_vec<rvalue *> *args, 148 bool require_tail_call); 149 150 rvalue * 151 new_call_through_ptr (location *loc, 152 rvalue *fn_ptr, 153 const auto_vec<rvalue *> *args, 154 bool require_tail_call); 155 156 rvalue * 157 new_cast (location *loc, 158 rvalue *expr, 159 type *type_); 160 161 lvalue * 162 new_array_access (location *loc, 163 rvalue *ptr, 164 rvalue *index); 165 166 void 167 set_str_option (enum gcc_jit_str_option opt, 168 const char *value); 169 170 void 171 set_int_option (enum gcc_jit_int_option opt, 172 int value); 173 174 void 175 set_bool_option (enum gcc_jit_bool_option opt, 176 int value); 177 178 const char * get_str_option(enum gcc_jit_str_option opt)179 get_str_option (enum gcc_jit_str_option opt) const 180 { 181 return m_recording_ctxt->get_str_option (opt); 182 } 183 184 int get_int_option(enum gcc_jit_int_option opt)185 get_int_option (enum gcc_jit_int_option opt) const 186 { 187 return m_recording_ctxt->get_int_option (opt); 188 } 189 190 int get_bool_option(enum gcc_jit_bool_option opt)191 get_bool_option (enum gcc_jit_bool_option opt) const 192 { 193 return m_recording_ctxt->get_bool_option (opt); 194 } 195 196 int get_inner_bool_option(enum inner_bool_option opt)197 get_inner_bool_option (enum inner_bool_option opt) const 198 { 199 return m_recording_ctxt->get_inner_bool_option (opt); 200 } 201 get_builtins_manager()202 builtins_manager *get_builtins_manager () const 203 { 204 return m_recording_ctxt->get_builtins_manager (); 205 } 206 207 void 208 compile (); 209 210 void 211 add_error (location *loc, const char *fmt, ...) 212 GNU_PRINTF(3, 4); 213 214 void 215 add_error_va (location *loc, const char *fmt, va_list ap) 216 GNU_PRINTF(3, 0); 217 218 const char * 219 get_first_error () const; 220 221 void 222 add_diagnostic (struct diagnostic_context *context, 223 struct diagnostic_info *diagnostic); 224 225 void 226 set_tree_location (tree t, location *loc); 227 228 tree 229 new_field_access (location *loc, 230 tree datum, 231 field *field); 232 233 tree 234 new_dereference (tree ptr, location *loc); 235 236 tree 237 as_truth_value (tree expr, location *loc); 238 errors_occurred()239 bool errors_occurred () const 240 { 241 return m_recording_ctxt->errors_occurred (); 242 } 243 get_timer()244 timer *get_timer () const { return m_recording_ctxt->get_timer (); } 245 246 private: 247 void dump_generated_code (); 248 249 rvalue * 250 build_call (location *loc, 251 tree fn_ptr, 252 const auto_vec<rvalue *> *args, 253 bool require_tail_call); 254 255 tree 256 build_cast (location *loc, 257 rvalue *expr, 258 type *type_); 259 260 source_file * 261 get_source_file (const char *filename); 262 263 void handle_locations (); 264 265 const char * get_path_c_file () const; 266 const char * get_path_s_file () const; 267 const char * get_path_so_file () const; 268 269 private: 270 271 /* Functions for implementing "compile". */ 272 273 void acquire_mutex (); 274 void release_mutex (); 275 276 void 277 make_fake_args (vec <char *> *argvec, 278 const char *ctxt_progname, 279 vec <recording::requested_dump> *requested_dumps); 280 281 void 282 extract_any_requested_dumps 283 (vec <recording::requested_dump> *requested_dumps); 284 285 char * 286 read_dump_file (const char *path); 287 288 virtual void postprocess (const char *ctxt_progname) = 0; 289 290 protected: get_tempdir()291 tempdir *get_tempdir () { return m_tempdir; } 292 293 void 294 convert_to_dso (const char *ctxt_progname); 295 296 void 297 invoke_driver (const char *ctxt_progname, 298 const char *input_file, 299 const char *output_file, 300 timevar_id_t tv_id, 301 bool shared, 302 bool run_linker); 303 304 void 305 add_multilib_driver_arguments (vec <char *> *argvec); 306 307 result * 308 dlopen_built_dso (); 309 310 private: 311 void 312 invoke_embedded_driver (const vec <char *> *argvec); 313 314 void 315 invoke_external_driver (const char *ctxt_progname, 316 vec <char *> *argvec); 317 318 private: 319 ::gcc::jit::recording::context *m_recording_ctxt; 320 321 tempdir *m_tempdir; 322 323 auto_vec<function *> m_functions; 324 auto_vec<tree> m_globals; 325 tree m_const_char_ptr; 326 327 /* Source location handling. */ 328 auto_vec<source_file *> m_source_files; 329 330 auto_vec<std::pair<tree, location *> > m_cached_locations; 331 }; 332 333 class compile_to_memory : public context 334 { 335 public: 336 compile_to_memory (recording::context *ctxt); 337 void postprocess (const char *ctxt_progname) FINAL OVERRIDE; 338 get_result_obj()339 result *get_result_obj () const { return m_result; } 340 341 private: 342 result *m_result; 343 }; 344 345 class compile_to_file : public context 346 { 347 public: 348 compile_to_file (recording::context *ctxt, 349 enum gcc_jit_output_kind output_kind, 350 const char *output_path); 351 void postprocess (const char *ctxt_progname) FINAL OVERRIDE; 352 353 private: 354 void 355 copy_file (const char *src_path, 356 const char *dst_path); 357 358 private: 359 enum gcc_jit_output_kind m_output_kind; 360 const char *m_output_path; 361 }; 362 363 364 /* A temporary wrapper object. 365 These objects are (mostly) only valid during replay. 366 We allocate them on the GC heap, so that they will be cleaned 367 the next time the GC collects. 368 The exception is the "function" class, which is tracked and marked by 369 the jit::context, since it needs to stay alive during post-processing 370 (when the GC could run). */ 371 class wrapper 372 { 373 public: 374 /* Allocate in the GC heap. */ 375 void *operator new (size_t sz); 376 377 /* Some wrapper subclasses contain vec<> and so need to 378 release them when they are GC-ed. */ finalizer()379 virtual void finalizer () { } 380 381 }; 382 383 class type : public wrapper 384 { 385 public: type(tree inner)386 type (tree inner) 387 : m_inner(inner) 388 {} 389 as_tree()390 tree as_tree () const { return m_inner; } 391 get_pointer()392 type *get_pointer () const { return new type (build_pointer_type (m_inner)); } 393 get_const()394 type *get_const () const 395 { 396 return new type (build_qualified_type (m_inner, TYPE_QUAL_CONST)); 397 } 398 get_volatile()399 type *get_volatile () const 400 { 401 return new type (build_qualified_type (m_inner, TYPE_QUAL_VOLATILE)); 402 } 403 404 type *get_aligned (size_t alignment_in_bytes) const; 405 type *get_vector (size_t num_units) const; 406 407 private: 408 tree m_inner; 409 }; 410 411 class compound_type : public type 412 { 413 public: compound_type(tree inner)414 compound_type (tree inner) 415 : type (inner) 416 {} 417 418 void set_fields (const auto_vec<field *> *fields); 419 }; 420 421 class field : public wrapper 422 { 423 public: field(tree inner)424 field (tree inner) 425 : m_inner(inner) 426 {} 427 as_tree()428 tree as_tree () const { return m_inner; } 429 430 private: 431 tree m_inner; 432 }; 433 434 class bitfield : public field {}; 435 436 class function : public wrapper 437 { 438 public: 439 function(context *ctxt, tree fndecl, enum gcc_jit_function_kind kind); 440 441 void gt_ggc_mx (); 442 void finalizer () FINAL OVERRIDE; 443 444 tree get_return_type_as_tree () const; 445 as_fndecl()446 tree as_fndecl () const { return m_inner_fndecl; } 447 get_kind()448 enum gcc_jit_function_kind get_kind () const { return m_kind; } 449 450 lvalue * 451 new_local (location *loc, 452 type *type, 453 const char *name); 454 455 block* 456 new_block (const char *name); 457 458 rvalue * 459 get_address (location *loc); 460 461 void 462 build_stmt_list (); 463 464 void 465 postprocess (); 466 467 public: 468 context *m_ctxt; 469 470 public: 471 void set_tree_location(tree t,location * loc)472 set_tree_location (tree t, location *loc) 473 { 474 m_ctxt->set_tree_location (t, loc); 475 } 476 477 private: 478 tree m_inner_fndecl; 479 tree m_inner_block; 480 tree m_inner_bind_expr; 481 enum gcc_jit_function_kind m_kind; 482 tree m_stmt_list; 483 tree_stmt_iterator m_stmt_iter; 484 vec<block *> m_blocks; 485 }; 486 487 struct case_ 488 { case_case_489 case_ (rvalue *min_value, rvalue *max_value, block *dest_block) 490 : m_min_value (min_value), 491 m_max_value (max_value), 492 m_dest_block (dest_block) 493 {} 494 495 rvalue *m_min_value; 496 rvalue *m_max_value; 497 block *m_dest_block; 498 }; 499 500 class block : public wrapper 501 { 502 public: 503 block (function *func, 504 const char *name); 505 506 void finalizer () FINAL OVERRIDE; 507 as_label_decl()508 tree as_label_decl () const { return m_label_decl; } 509 get_function()510 function *get_function () const { return m_func; } 511 512 void 513 add_eval (location *loc, 514 rvalue *rvalue); 515 516 void 517 add_assignment (location *loc, 518 lvalue *lvalue, 519 rvalue *rvalue); 520 521 void 522 add_comment (location *loc, 523 const char *text); 524 525 void 526 add_conditional (location *loc, 527 rvalue *boolval, 528 block *on_true, 529 block *on_false); 530 531 block * 532 add_block (location *loc, 533 const char *name); 534 535 void 536 add_jump (location *loc, 537 block *target); 538 539 void 540 add_return (location *loc, 541 rvalue *rvalue); 542 543 void 544 add_switch (location *loc, 545 rvalue *expr, 546 block *default_block, 547 const auto_vec <case_> *cases); 548 549 private: 550 void set_tree_location(tree t,location * loc)551 set_tree_location (tree t, location *loc) 552 { 553 m_func->set_tree_location (t, loc); 554 } 555 add_stmt(tree stmt)556 void add_stmt (tree stmt) 557 { 558 /* TODO: use one stmt_list per block. */ 559 m_stmts.safe_push (stmt); 560 } 561 562 private: 563 function *m_func; 564 tree m_label_decl; 565 vec<tree> m_stmts; 566 567 public: // for now 568 tree m_label_expr; 569 570 friend class function; 571 }; 572 573 class rvalue : public wrapper 574 { 575 public: rvalue(context * ctxt,tree inner)576 rvalue (context *ctxt, tree inner) 577 : m_ctxt (ctxt), 578 m_inner (inner) 579 {} 580 581 rvalue * as_rvalue()582 as_rvalue () { return this; } 583 as_tree()584 tree as_tree () const { return m_inner; } 585 get_context()586 context *get_context () const { return m_ctxt; } 587 588 type * get_type()589 get_type () { return new type (TREE_TYPE (m_inner)); } 590 591 rvalue * 592 access_field (location *loc, 593 field *field); 594 595 lvalue * 596 dereference_field (location *loc, 597 field *field); 598 599 lvalue * 600 dereference (location *loc); 601 602 private: 603 context *m_ctxt; 604 tree m_inner; 605 }; 606 607 class lvalue : public rvalue 608 { 609 public: lvalue(context * ctxt,tree inner)610 lvalue (context *ctxt, tree inner) 611 : rvalue(ctxt, inner) 612 {} 613 614 lvalue * as_lvalue()615 as_lvalue () { return this; } 616 617 lvalue * 618 access_field (location *loc, 619 field *field); 620 621 rvalue * 622 get_address (location *loc); 623 624 private: 625 bool mark_addressable (location *loc); 626 }; 627 628 class param : public lvalue 629 { 630 public: param(context * ctxt,tree inner)631 param (context *ctxt, tree inner) 632 : lvalue(ctxt, inner) 633 {} 634 }; 635 636 /* Dealing with the linemap API. 637 638 It appears that libcpp requires locations to be created as if by 639 a tokenizer, creating them by filename, in ascending order of 640 line/column, whereas our API doesn't impose any such constraints: 641 we allow client code to create locations in arbitrary orders. 642 643 To square this circle, we need to cache all location creation, 644 grouping things up by filename/line, and then creating the linemap 645 entries in a post-processing phase. */ 646 647 /* A set of locations, all sharing a filename */ 648 class source_file : public wrapper 649 { 650 public: 651 source_file (tree filename); 652 void finalizer () FINAL OVERRIDE; 653 654 source_line * 655 get_source_line (int line_num); 656 filename_as_tree()657 tree filename_as_tree () const { return m_filename; } 658 659 const char* get_filename()660 get_filename () const { return IDENTIFIER_POINTER (m_filename); } 661 662 vec<source_line *> m_source_lines; 663 664 private: 665 tree m_filename; 666 }; 667 668 /* A source line, with one or more locations of interest. */ 669 class source_line : public wrapper 670 { 671 public: 672 source_line (source_file *file, int line_num); 673 void finalizer () FINAL OVERRIDE; 674 675 location * 676 get_location (recording::location *rloc, int column_num); 677 get_line_num()678 int get_line_num () const { return m_line_num; } 679 680 vec<location *> m_locations; 681 682 private: 683 source_file *m_source_file; 684 int m_line_num; 685 }; 686 687 /* A specific location on a source line. This is what we expose 688 to the client API. */ 689 class location : public wrapper 690 { 691 public: 692 location (recording::location *loc, source_line *line, int column_num); 693 get_column_num()694 int get_column_num () const { return m_column_num; } 695 get_recording_loc()696 recording::location *get_recording_loc () const { return m_recording_loc; } 697 698 location_t m_srcloc; 699 700 private: 701 recording::location *m_recording_loc; 702 source_line *m_line; 703 int m_column_num; 704 }; 705 706 } // namespace gcc::jit::playback 707 708 extern playback::context *active_playback_ctxt; 709 710 } // namespace gcc::jit 711 712 } // namespace gcc 713 714 #endif /* JIT_PLAYBACK_H */ 715