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