Home | History | Annotate | Line # | Download | only in gcc
gimple-streamer-out.cc revision 1.1.1.1
      1 /* Routines for emitting GIMPLE to a file stream.
      2 
      3    Copyright (C) 2011-2022 Free Software Foundation, Inc.
      4    Contributed by Diego Novillo <dnovillo (at) google.com>
      5 
      6 This file is part of GCC.
      7 
      8 GCC is free software; you can redistribute it and/or modify it under
      9 the terms of the GNU General Public License as published by the Free
     10 Software Foundation; either version 3, or (at your option) any later
     11 version.
     12 
     13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
     15 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     16 for more details.
     17 
     18 You should have received a copy of the GNU General Public License
     19 along with GCC; see the file COPYING3.  If not see
     20 <http://www.gnu.org/licenses/>.  */
     21 
     22 #include "config.h"
     23 #include "system.h"
     24 #include "coretypes.h"
     25 #include "backend.h"
     26 #include "tree.h"
     27 #include "gimple.h"
     28 #include "gimple-ssa.h"
     29 #include "gimple-streamer.h"
     30 #include "tree-eh.h"
     31 #include "gimple-iterator.h"
     32 #include "cgraph.h"
     33 #include "value-prof.h"
     34 #include "gimple-pretty-print.h"
     35 
     36 /* Output PHI function PHI to the main stream in OB.  */
     37 
     38 static void
     39 output_phi (struct output_block *ob, gphi *phi)
     40 {
     41   unsigned i, len = gimple_phi_num_args (phi);
     42 
     43   streamer_write_record_start (ob, lto_gimple_code_to_tag (GIMPLE_PHI));
     44   streamer_write_uhwi (ob, SSA_NAME_VERSION (PHI_RESULT (phi)));
     45 
     46   for (i = 0; i < len; i++)
     47     {
     48       stream_write_tree (ob, gimple_phi_arg_def (phi, i), true);
     49       streamer_write_uhwi (ob, gimple_phi_arg_edge (phi, i)->src->index);
     50       bitpack_d bp = bitpack_create (ob->main_stream);
     51       location_t loc = gimple_phi_arg_location (phi, i);
     52       stream_output_location_and_block (ob, &bp, loc);
     53     }
     54 }
     55 
     56 
     57 /* Emit statement STMT on the main stream of output block OB.  */
     58 
     59 static void
     60 output_gimple_stmt (struct output_block *ob, struct function *fn, gimple *stmt)
     61 {
     62   unsigned i;
     63   enum gimple_code code;
     64   enum LTO_tags tag;
     65   struct bitpack_d bp;
     66   histogram_value hist;
     67 
     68   /* Emit identifying tag.  */
     69   code = gimple_code (stmt);
     70   tag = lto_gimple_code_to_tag (code);
     71   streamer_write_record_start (ob, tag);
     72 
     73   /* Emit the tuple header.  */
     74   bp = bitpack_create (ob->main_stream);
     75   bp_pack_var_len_unsigned (&bp, gimple_num_ops (stmt));
     76   bp_pack_value (&bp, gimple_no_warning_p (stmt), 1);
     77   if (is_gimple_assign (stmt))
     78     bp_pack_value (&bp,
     79 		   gimple_assign_nontemporal_move_p (
     80 		     as_a <gassign *> (stmt)),
     81 		   1);
     82   bp_pack_value (&bp, gimple_has_volatile_ops (stmt), 1);
     83   hist = gimple_histogram_value (fn, stmt);
     84   bp_pack_value (&bp, hist != NULL, 1);
     85   bp_pack_var_len_unsigned (&bp, stmt->subcode);
     86 
     87   /* Emit location information for the statement, including gimple_block.  */
     88   stream_output_location_and_block (ob, &bp, gimple_location (stmt));
     89 
     90   /* Emit the operands.  */
     91   switch (gimple_code (stmt))
     92     {
     93     case GIMPLE_RESX:
     94       streamer_write_hwi (ob, gimple_resx_region (as_a <gresx *> (stmt)));
     95       break;
     96 
     97     case GIMPLE_EH_MUST_NOT_THROW:
     98       stream_write_tree (ob,
     99 			 gimple_eh_must_not_throw_fndecl (
    100 			   as_a <geh_mnt *> (stmt)),
    101 			 true);
    102       break;
    103 
    104     case GIMPLE_EH_DISPATCH:
    105       streamer_write_hwi (ob,
    106 			  gimple_eh_dispatch_region (
    107 			    as_a <geh_dispatch *> (stmt)));
    108       break;
    109 
    110     case GIMPLE_ASM:
    111       {
    112 	gasm *asm_stmt = as_a <gasm *> (stmt);
    113 	streamer_write_uhwi (ob, gimple_asm_ninputs (asm_stmt));
    114 	streamer_write_uhwi (ob, gimple_asm_noutputs (asm_stmt));
    115 	streamer_write_uhwi (ob, gimple_asm_nclobbers (asm_stmt));
    116 	streamer_write_uhwi (ob, gimple_asm_nlabels (asm_stmt));
    117 	streamer_write_string (ob, ob->main_stream,
    118 			       gimple_asm_string (asm_stmt), true);
    119       }
    120       /* Fallthru  */
    121 
    122     case GIMPLE_ASSIGN:
    123     case GIMPLE_CALL:
    124     case GIMPLE_RETURN:
    125     case GIMPLE_SWITCH:
    126     case GIMPLE_LABEL:
    127     case GIMPLE_COND:
    128     case GIMPLE_GOTO:
    129     case GIMPLE_DEBUG:
    130       for (i = 0; i < gimple_num_ops (stmt); i++)
    131 	{
    132 	  tree op = gimple_op (stmt, i);
    133 	  tree *basep = NULL;
    134 	  /* Wrap all uses of non-automatic variables inside MEM_REFs
    135 	     so that we do not have to deal with type mismatches on
    136 	     merged symbols during IL read in.  The first operand
    137 	     of GIMPLE_DEBUG must be a decl, not MEM_REF, though.  */
    138 	  if (!flag_wpa && op && (i || !is_gimple_debug (stmt)))
    139 	    {
    140 	      basep = &op;
    141 	      if (TREE_CODE (*basep) == ADDR_EXPR)
    142 		basep = &TREE_OPERAND (*basep, 0);
    143 	      while (handled_component_p (*basep))
    144 		basep = &TREE_OPERAND (*basep, 0);
    145 	      if (VAR_P (*basep)
    146 		  && !auto_var_in_fn_p (*basep, fn->decl)
    147 		  && !DECL_REGISTER (*basep))
    148 		{
    149 		  bool volatilep = TREE_THIS_VOLATILE (*basep);
    150 		  tree ptrtype = build_pointer_type (TREE_TYPE (*basep));
    151 		  *basep = build2 (MEM_REF, TREE_TYPE (*basep),
    152 				   build1 (ADDR_EXPR, ptrtype, *basep),
    153 				   build_int_cst (ptrtype, 0));
    154 		  TREE_THIS_VOLATILE (*basep) = volatilep;
    155 		}
    156 	      else
    157 		basep = NULL;
    158 	    }
    159 	  stream_write_tree (ob, op, true);
    160 	  /* Restore the original base if we wrapped it inside a MEM_REF.  */
    161 	  if (basep)
    162 	    *basep = TREE_OPERAND (TREE_OPERAND (*basep, 0), 0);
    163 	}
    164       if (is_gimple_call (stmt))
    165 	{
    166 	  if (gimple_call_internal_p (stmt))
    167 	    streamer_write_enum (ob->main_stream, internal_fn,
    168 				 IFN_LAST, gimple_call_internal_fn (stmt));
    169 	  else
    170 	    stream_write_tree (ob, gimple_call_fntype (stmt), true);
    171 	}
    172       break;
    173 
    174     case GIMPLE_NOP:
    175     case GIMPLE_PREDICT:
    176       break;
    177 
    178     case GIMPLE_TRANSACTION:
    179       {
    180 	gtransaction *txn = as_a <gtransaction *> (stmt);
    181 	gcc_assert (gimple_transaction_body (txn) == NULL);
    182 	stream_write_tree (ob, gimple_transaction_label_norm (txn), true);
    183 	stream_write_tree (ob, gimple_transaction_label_uninst (txn), true);
    184 	stream_write_tree (ob, gimple_transaction_label_over (txn), true);
    185       }
    186       break;
    187 
    188     default:
    189       gcc_unreachable ();
    190     }
    191   if (hist)
    192     stream_out_histogram_value (ob, hist);
    193 }
    194 
    195 
    196 /* Output a basic block BB to the main stream in OB for this FN.  */
    197 
    198 void
    199 output_bb (struct output_block *ob, basic_block bb, struct function *fn)
    200 {
    201   gimple_stmt_iterator bsi = gsi_start_bb (bb);
    202 
    203   streamer_write_record_start (ob,
    204 			       (!gsi_end_p (bsi)) || phi_nodes (bb)
    205 			        ? LTO_bb1
    206 				: LTO_bb0);
    207 
    208   streamer_write_uhwi (ob, bb->index);
    209   bb->count.stream_out (ob);
    210   streamer_write_hwi (ob, bb->flags);
    211   streamer_write_hwi (ob, bb->discriminator);
    212 
    213   if (!gsi_end_p (bsi) || phi_nodes (bb))
    214     {
    215       /* Output the statements.  The list of statements is terminated
    216 	 with a zero.  */
    217       for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
    218 	{
    219 	  int region;
    220 	  gimple *stmt = gsi_stmt (bsi);
    221 	  if (streamer_dump_file)
    222 	    {
    223 	      fprintf (streamer_dump_file, "  Streaming gimple stmt ");
    224 	      print_gimple_stmt (streamer_dump_file, stmt, 0, TDF_SLIM);
    225 	    }
    226 
    227 	  output_gimple_stmt (ob, fn, stmt);
    228 
    229 	  /* Emit the EH region holding STMT.  */
    230 	  region = lookup_stmt_eh_lp_fn (fn, stmt);
    231 	  if (region != 0)
    232 	    {
    233 	      streamer_write_record_start (ob, LTO_eh_region);
    234 	      streamer_write_hwi (ob, region);
    235 	    }
    236 	  else
    237 	    streamer_write_record_start (ob, LTO_null);
    238 	}
    239 
    240       streamer_write_record_start (ob, LTO_null);
    241 
    242       for (gphi_iterator psi = gsi_start_phis (bb);
    243 	   !gsi_end_p (psi);
    244 	   gsi_next (&psi))
    245 	{
    246 	  gphi *phi = psi.phi ();
    247 
    248 	  /* Only emit PHIs for gimple registers.  PHI nodes for .MEM
    249 	     will be filled in on reading when the SSA form is
    250 	     updated.  */
    251 	  if (!virtual_operand_p (gimple_phi_result (phi)))
    252 	    output_phi (ob, phi);
    253 	}
    254 
    255       streamer_write_record_start (ob, LTO_null);
    256     }
    257 }
    258