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