/* Routines for emitting GIMPLE to a file stream.

   Copyright (C) 2011-2021 Free Software Foundation, Inc.
   Contributed by Diego Novillo <dnovillo@google.com>

This file is part of GCC.

GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.

GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
for more details.

You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "backend.h"
#include "tree.h"
#include "gimple.h"
#include "gimple-ssa.h"
#include "gimple-streamer.h"
#include "tree-eh.h"
#include "gimple-iterator.h"
#include "cgraph.h"
#include "value-prof.h"
#include "gimple-pretty-print.h"

/* Output PHI function PHI to the main stream in OB.  */

static void
output_phi (struct output_block *ob, gphi *phi)
{
  unsigned i, len = gimple_phi_num_args (phi);

  streamer_write_record_start (ob, lto_gimple_code_to_tag (GIMPLE_PHI));
  streamer_write_uhwi (ob, SSA_NAME_VERSION (PHI_RESULT (phi)));

  for (i = 0; i < len; i++)
    {
      stream_write_tree (ob, gimple_phi_arg_def (phi, i), true);
      streamer_write_uhwi (ob, gimple_phi_arg_edge (phi, i)->src->index);
      bitpack_d bp = bitpack_create (ob->main_stream);
      location_t loc = gimple_phi_arg_location (phi, i);
      stream_output_location_and_block (ob, &bp, loc);
    }
}


/* Emit statement STMT on the main stream of output block OB.  */

static void
output_gimple_stmt (struct output_block *ob, struct function *fn, gimple *stmt)
{
  unsigned i;
  enum gimple_code code;
  enum LTO_tags tag;
  struct bitpack_d bp;
  histogram_value hist;

  /* Emit identifying tag.  */
  code = gimple_code (stmt);
  tag = lto_gimple_code_to_tag (code);
  streamer_write_record_start (ob, tag);

  /* Emit the tuple header.  */
  bp = bitpack_create (ob->main_stream);
  bp_pack_var_len_unsigned (&bp, gimple_num_ops (stmt));
  bp_pack_value (&bp, gimple_no_warning_p (stmt), 1);
  if (is_gimple_assign (stmt))
    bp_pack_value (&bp,
		   gimple_assign_nontemporal_move_p (
		     as_a <gassign *> (stmt)),
		   1);
  bp_pack_value (&bp, gimple_has_volatile_ops (stmt), 1);
  hist = gimple_histogram_value (fn, stmt);
  bp_pack_value (&bp, hist != NULL, 1);
  bp_pack_var_len_unsigned (&bp, stmt->subcode);

  /* Emit location information for the statement, including gimple_block.  */
  stream_output_location_and_block (ob, &bp, gimple_location (stmt));

  /* Emit the operands.  */
  switch (gimple_code (stmt))
    {
    case GIMPLE_RESX:
      streamer_write_hwi (ob, gimple_resx_region (as_a <gresx *> (stmt)));
      break;

    case GIMPLE_EH_MUST_NOT_THROW:
      stream_write_tree (ob,
			 gimple_eh_must_not_throw_fndecl (
			   as_a <geh_mnt *> (stmt)),
			 true);
      break;

    case GIMPLE_EH_DISPATCH:
      streamer_write_hwi (ob,
			  gimple_eh_dispatch_region (
			    as_a <geh_dispatch *> (stmt)));
      break;

    case GIMPLE_ASM:
      {
	gasm *asm_stmt = as_a <gasm *> (stmt);
	streamer_write_uhwi (ob, gimple_asm_ninputs (asm_stmt));
	streamer_write_uhwi (ob, gimple_asm_noutputs (asm_stmt));
	streamer_write_uhwi (ob, gimple_asm_nclobbers (asm_stmt));
	streamer_write_uhwi (ob, gimple_asm_nlabels (asm_stmt));
	streamer_write_string (ob, ob->main_stream,
			       gimple_asm_string (asm_stmt), true);
      }
      /* Fallthru  */

    case GIMPLE_ASSIGN:
    case GIMPLE_CALL:
    case GIMPLE_RETURN:
    case GIMPLE_SWITCH:
    case GIMPLE_LABEL:
    case GIMPLE_COND:
    case GIMPLE_GOTO:
    case GIMPLE_DEBUG:
      for (i = 0; i < gimple_num_ops (stmt); i++)
	{
	  tree op = gimple_op (stmt, i);
	  tree *basep = NULL;
	  /* Wrap all uses of non-automatic variables inside MEM_REFs
	     so that we do not have to deal with type mismatches on
	     merged symbols during IL read in.  The first operand
	     of GIMPLE_DEBUG must be a decl, not MEM_REF, though.  */
	  if (!flag_wpa && op && (i || !is_gimple_debug (stmt)))
	    {
	      basep = &op;
	      if (TREE_CODE (*basep) == ADDR_EXPR)
		basep = &TREE_OPERAND (*basep, 0);
	      while (handled_component_p (*basep))
		basep = &TREE_OPERAND (*basep, 0);
	      if (VAR_P (*basep)
		  && !auto_var_in_fn_p (*basep, fn->decl)
		  && !DECL_REGISTER (*basep))
		{
		  bool volatilep = TREE_THIS_VOLATILE (*basep);
		  tree ptrtype = build_pointer_type (TREE_TYPE (*basep));
		  *basep = build2 (MEM_REF, TREE_TYPE (*basep),
				   build1 (ADDR_EXPR, ptrtype, *basep),
				   build_int_cst (ptrtype, 0));
		  TREE_THIS_VOLATILE (*basep) = volatilep;
		}
	      else
		basep = NULL;
	    }
	  stream_write_tree (ob, op, true);
	  /* Restore the original base if we wrapped it inside a MEM_REF.  */
	  if (basep)
	    *basep = TREE_OPERAND (TREE_OPERAND (*basep, 0), 0);
	}
      if (is_gimple_call (stmt))
	{
	  if (gimple_call_internal_p (stmt))
	    streamer_write_enum (ob->main_stream, internal_fn,
				 IFN_LAST, gimple_call_internal_fn (stmt));
	  else
	    stream_write_tree (ob, gimple_call_fntype (stmt), true);
	}
      break;

    case GIMPLE_NOP:
    case GIMPLE_PREDICT:
      break;

    case GIMPLE_TRANSACTION:
      {
	gtransaction *txn = as_a <gtransaction *> (stmt);
	gcc_assert (gimple_transaction_body (txn) == NULL);
	stream_write_tree (ob, gimple_transaction_label_norm (txn), true);
	stream_write_tree (ob, gimple_transaction_label_uninst (txn), true);
	stream_write_tree (ob, gimple_transaction_label_over (txn), true);
      }
      break;

    default:
      gcc_unreachable ();
    }
  if (hist)
    stream_out_histogram_value (ob, hist);
}


/* Output a basic block BB to the main stream in OB for this FN.  */

void
output_bb (struct output_block *ob, basic_block bb, struct function *fn)
{
  gimple_stmt_iterator bsi = gsi_start_bb (bb);

  streamer_write_record_start (ob,
			       (!gsi_end_p (bsi)) || phi_nodes (bb)
			        ? LTO_bb1
				: LTO_bb0);

  streamer_write_uhwi (ob, bb->index);
  bb->count.stream_out (ob);
  streamer_write_hwi (ob, bb->flags);
  streamer_write_hwi (ob, bb->discriminator);

  if (!gsi_end_p (bsi) || phi_nodes (bb))
    {
      /* Output the statements.  The list of statements is terminated
	 with a zero.  */
      for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
	{
	  int region;
	  gimple *stmt = gsi_stmt (bsi);
	  if (streamer_dump_file)
	    {
	      fprintf (streamer_dump_file, "  Streaming gimple stmt ");
	      print_gimple_stmt (streamer_dump_file, stmt, 0, TDF_SLIM);
	    }

	  output_gimple_stmt (ob, fn, stmt);

	  /* Emit the EH region holding STMT.  */
	  region = lookup_stmt_eh_lp_fn (fn, stmt);
	  if (region != 0)
	    {
	      streamer_write_record_start (ob, LTO_eh_region);
	      streamer_write_hwi (ob, region);
	    }
	  else
	    streamer_write_record_start (ob, LTO_null);
	}

      streamer_write_record_start (ob, LTO_null);

      for (gphi_iterator psi = gsi_start_phis (bb);
	   !gsi_end_p (psi);
	   gsi_next (&psi))
	{
	  gphi *phi = psi.phi ();

	  /* Only emit PHIs for gimple registers.  PHI nodes for .MEM
	     will be filled in on reading when the SSA form is
	     updated.  */
	  if (!virtual_operand_p (gimple_phi_result (phi)))
	    output_phi (ob, phi);
	}

      streamer_write_record_start (ob, LTO_null);
    }
}
