xref: /dflybsd-src/contrib/gcc-4.7/gcc/gimple-streamer-in.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Routines for reading GIMPLE from a file stream.
2*e4b17023SJohn Marino 
3*e4b17023SJohn Marino    Copyright 2011 Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Diego Novillo <dnovillo@google.com>
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "coretypes.h"
25*e4b17023SJohn Marino #include "diagnostic.h"
26*e4b17023SJohn Marino #include "tree.h"
27*e4b17023SJohn Marino #include "tree-flow.h"
28*e4b17023SJohn Marino #include "data-streamer.h"
29*e4b17023SJohn Marino #include "tree-streamer.h"
30*e4b17023SJohn Marino #include "gimple-streamer.h"
31*e4b17023SJohn Marino 
32*e4b17023SJohn Marino /* Read a PHI function for basic block BB in function FN.  DATA_IN is
33*e4b17023SJohn Marino    the file being read.  IB is the input block to use for reading.  */
34*e4b17023SJohn Marino 
35*e4b17023SJohn Marino static gimple
input_phi(struct lto_input_block * ib,basic_block bb,struct data_in * data_in,struct function * fn)36*e4b17023SJohn Marino input_phi (struct lto_input_block *ib, basic_block bb, struct data_in *data_in,
37*e4b17023SJohn Marino 	   struct function *fn)
38*e4b17023SJohn Marino {
39*e4b17023SJohn Marino   unsigned HOST_WIDE_INT ix;
40*e4b17023SJohn Marino   tree phi_result;
41*e4b17023SJohn Marino   int i, len;
42*e4b17023SJohn Marino   gimple result;
43*e4b17023SJohn Marino 
44*e4b17023SJohn Marino   ix = streamer_read_uhwi (ib);
45*e4b17023SJohn Marino   phi_result = VEC_index (tree, SSANAMES (fn), ix);
46*e4b17023SJohn Marino   len = EDGE_COUNT (bb->preds);
47*e4b17023SJohn Marino   result = create_phi_node (phi_result, bb);
48*e4b17023SJohn Marino   SSA_NAME_DEF_STMT (phi_result) = result;
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino   /* We have to go through a lookup process here because the preds in the
51*e4b17023SJohn Marino      reconstructed graph are generally in a different order than they
52*e4b17023SJohn Marino      were in the original program.  */
53*e4b17023SJohn Marino   for (i = 0; i < len; i++)
54*e4b17023SJohn Marino     {
55*e4b17023SJohn Marino       tree def = stream_read_tree (ib, data_in);
56*e4b17023SJohn Marino       int src_index = streamer_read_uhwi (ib);
57*e4b17023SJohn Marino       location_t arg_loc = lto_input_location (ib, data_in);
58*e4b17023SJohn Marino       basic_block sbb = BASIC_BLOCK_FOR_FUNCTION (fn, src_index);
59*e4b17023SJohn Marino 
60*e4b17023SJohn Marino       edge e = NULL;
61*e4b17023SJohn Marino       int j;
62*e4b17023SJohn Marino 
63*e4b17023SJohn Marino       for (j = 0; j < len; j++)
64*e4b17023SJohn Marino 	if (EDGE_PRED (bb, j)->src == sbb)
65*e4b17023SJohn Marino 	  {
66*e4b17023SJohn Marino 	    e = EDGE_PRED (bb, j);
67*e4b17023SJohn Marino 	    break;
68*e4b17023SJohn Marino 	  }
69*e4b17023SJohn Marino 
70*e4b17023SJohn Marino       add_phi_arg (result, def, e, arg_loc);
71*e4b17023SJohn Marino     }
72*e4b17023SJohn Marino 
73*e4b17023SJohn Marino   return result;
74*e4b17023SJohn Marino }
75*e4b17023SJohn Marino 
76*e4b17023SJohn Marino 
77*e4b17023SJohn Marino /* Read a statement with tag TAG in function FN from block IB using
78*e4b17023SJohn Marino    descriptors in DATA_IN.  */
79*e4b17023SJohn Marino 
80*e4b17023SJohn Marino static gimple
input_gimple_stmt(struct lto_input_block * ib,struct data_in * data_in,struct function * fn,enum LTO_tags tag)81*e4b17023SJohn Marino input_gimple_stmt (struct lto_input_block *ib, struct data_in *data_in,
82*e4b17023SJohn Marino 		   struct function *fn, enum LTO_tags tag)
83*e4b17023SJohn Marino {
84*e4b17023SJohn Marino   gimple stmt;
85*e4b17023SJohn Marino   enum gimple_code code;
86*e4b17023SJohn Marino   unsigned HOST_WIDE_INT num_ops;
87*e4b17023SJohn Marino   size_t i;
88*e4b17023SJohn Marino   struct bitpack_d bp;
89*e4b17023SJohn Marino 
90*e4b17023SJohn Marino   code = lto_tag_to_gimple_code (tag);
91*e4b17023SJohn Marino 
92*e4b17023SJohn Marino   /* Read the tuple header.  */
93*e4b17023SJohn Marino   bp = streamer_read_bitpack (ib);
94*e4b17023SJohn Marino   num_ops = bp_unpack_var_len_unsigned (&bp);
95*e4b17023SJohn Marino   stmt = gimple_alloc (code, num_ops);
96*e4b17023SJohn Marino   stmt->gsbase.no_warning = bp_unpack_value (&bp, 1);
97*e4b17023SJohn Marino   if (is_gimple_assign (stmt))
98*e4b17023SJohn Marino     stmt->gsbase.nontemporal_move = bp_unpack_value (&bp, 1);
99*e4b17023SJohn Marino   stmt->gsbase.has_volatile_ops = bp_unpack_value (&bp, 1);
100*e4b17023SJohn Marino   stmt->gsbase.subcode = bp_unpack_var_len_unsigned (&bp);
101*e4b17023SJohn Marino 
102*e4b17023SJohn Marino   /* Read location information.  */
103*e4b17023SJohn Marino   gimple_set_location (stmt, lto_input_location (ib, data_in));
104*e4b17023SJohn Marino 
105*e4b17023SJohn Marino   /* Read lexical block reference.  */
106*e4b17023SJohn Marino   gimple_set_block (stmt, stream_read_tree (ib, data_in));
107*e4b17023SJohn Marino 
108*e4b17023SJohn Marino   /* Read in all the operands.  */
109*e4b17023SJohn Marino   switch (code)
110*e4b17023SJohn Marino     {
111*e4b17023SJohn Marino     case GIMPLE_RESX:
112*e4b17023SJohn Marino       gimple_resx_set_region (stmt, streamer_read_hwi (ib));
113*e4b17023SJohn Marino       break;
114*e4b17023SJohn Marino 
115*e4b17023SJohn Marino     case GIMPLE_EH_MUST_NOT_THROW:
116*e4b17023SJohn Marino       gimple_eh_must_not_throw_set_fndecl (stmt, stream_read_tree (ib, data_in));
117*e4b17023SJohn Marino       break;
118*e4b17023SJohn Marino 
119*e4b17023SJohn Marino     case GIMPLE_EH_DISPATCH:
120*e4b17023SJohn Marino       gimple_eh_dispatch_set_region (stmt, streamer_read_hwi (ib));
121*e4b17023SJohn Marino       break;
122*e4b17023SJohn Marino 
123*e4b17023SJohn Marino     case GIMPLE_ASM:
124*e4b17023SJohn Marino       {
125*e4b17023SJohn Marino 	/* FIXME lto.  Move most of this into a new gimple_asm_set_string().  */
126*e4b17023SJohn Marino 	tree str;
127*e4b17023SJohn Marino 	stmt->gimple_asm.ni = streamer_read_uhwi (ib);
128*e4b17023SJohn Marino 	stmt->gimple_asm.no = streamer_read_uhwi (ib);
129*e4b17023SJohn Marino 	stmt->gimple_asm.nc = streamer_read_uhwi (ib);
130*e4b17023SJohn Marino 	stmt->gimple_asm.nl = streamer_read_uhwi (ib);
131*e4b17023SJohn Marino 	str = streamer_read_string_cst (data_in, ib);
132*e4b17023SJohn Marino 	stmt->gimple_asm.string = TREE_STRING_POINTER (str);
133*e4b17023SJohn Marino       }
134*e4b17023SJohn Marino       /* Fallthru  */
135*e4b17023SJohn Marino 
136*e4b17023SJohn Marino     case GIMPLE_ASSIGN:
137*e4b17023SJohn Marino     case GIMPLE_CALL:
138*e4b17023SJohn Marino     case GIMPLE_RETURN:
139*e4b17023SJohn Marino     case GIMPLE_SWITCH:
140*e4b17023SJohn Marino     case GIMPLE_LABEL:
141*e4b17023SJohn Marino     case GIMPLE_COND:
142*e4b17023SJohn Marino     case GIMPLE_GOTO:
143*e4b17023SJohn Marino     case GIMPLE_DEBUG:
144*e4b17023SJohn Marino       for (i = 0; i < num_ops; i++)
145*e4b17023SJohn Marino 	{
146*e4b17023SJohn Marino 	  tree op = stream_read_tree (ib, data_in);
147*e4b17023SJohn Marino 	  gimple_set_op (stmt, i, op);
148*e4b17023SJohn Marino 	  if (!op)
149*e4b17023SJohn Marino 	    continue;
150*e4b17023SJohn Marino 
151*e4b17023SJohn Marino 	  /* Fixup FIELD_DECLs in COMPONENT_REFs, they are not handled
152*e4b17023SJohn Marino 	     by decl merging.  */
153*e4b17023SJohn Marino 	  if (TREE_CODE (op) == ADDR_EXPR)
154*e4b17023SJohn Marino 	    op = TREE_OPERAND (op, 0);
155*e4b17023SJohn Marino 	  while (handled_component_p (op))
156*e4b17023SJohn Marino 	    {
157*e4b17023SJohn Marino 	      if (TREE_CODE (op) == COMPONENT_REF)
158*e4b17023SJohn Marino 		{
159*e4b17023SJohn Marino 		  tree field, type, tem;
160*e4b17023SJohn Marino 		  tree closest_match = NULL_TREE;
161*e4b17023SJohn Marino 		  field = TREE_OPERAND (op, 1);
162*e4b17023SJohn Marino 		  type = DECL_CONTEXT (field);
163*e4b17023SJohn Marino 		  for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
164*e4b17023SJohn Marino 		    {
165*e4b17023SJohn Marino 		      if (TREE_CODE (tem) != FIELD_DECL)
166*e4b17023SJohn Marino 			continue;
167*e4b17023SJohn Marino 		      if (tem == field)
168*e4b17023SJohn Marino 			break;
169*e4b17023SJohn Marino 		      if (DECL_NONADDRESSABLE_P (tem)
170*e4b17023SJohn Marino 			  == DECL_NONADDRESSABLE_P (field)
171*e4b17023SJohn Marino 			  && gimple_compare_field_offset (tem, field))
172*e4b17023SJohn Marino 			{
173*e4b17023SJohn Marino 			  if (types_compatible_p (TREE_TYPE (tem),
174*e4b17023SJohn Marino 						  TREE_TYPE (field)))
175*e4b17023SJohn Marino 			    break;
176*e4b17023SJohn Marino 			  else
177*e4b17023SJohn Marino 			    closest_match = tem;
178*e4b17023SJohn Marino 			}
179*e4b17023SJohn Marino 		    }
180*e4b17023SJohn Marino 		  /* In case of type mismatches across units we can fail
181*e4b17023SJohn Marino 		     to unify some types and thus not find a proper
182*e4b17023SJohn Marino 		     field-decl here.  */
183*e4b17023SJohn Marino 		  if (tem == NULL_TREE)
184*e4b17023SJohn Marino 		    {
185*e4b17023SJohn Marino 		      /* Thus, emit a ODR violation warning.  */
186*e4b17023SJohn Marino 		      if (warning_at (gimple_location (stmt), 0,
187*e4b17023SJohn Marino 				      "use of type %<%E%> with two mismatching "
188*e4b17023SJohn Marino 				      "declarations at field %<%E%>",
189*e4b17023SJohn Marino 				      type, TREE_OPERAND (op, 1)))
190*e4b17023SJohn Marino 			{
191*e4b17023SJohn Marino 			  if (TYPE_FIELDS (type))
192*e4b17023SJohn Marino 			    inform (DECL_SOURCE_LOCATION (TYPE_FIELDS (type)),
193*e4b17023SJohn Marino 				    "original type declared here");
194*e4b17023SJohn Marino 			  inform (DECL_SOURCE_LOCATION (TREE_OPERAND (op, 1)),
195*e4b17023SJohn Marino 				  "field in mismatching type declared here");
196*e4b17023SJohn Marino 			  if (TYPE_NAME (TREE_TYPE (field))
197*e4b17023SJohn Marino 			      && (TREE_CODE (TYPE_NAME (TREE_TYPE (field)))
198*e4b17023SJohn Marino 				  == TYPE_DECL))
199*e4b17023SJohn Marino 			    inform (DECL_SOURCE_LOCATION
200*e4b17023SJohn Marino 				      (TYPE_NAME (TREE_TYPE (field))),
201*e4b17023SJohn Marino 				    "type of field declared here");
202*e4b17023SJohn Marino 			  if (closest_match
203*e4b17023SJohn Marino 			      && TYPE_NAME (TREE_TYPE (closest_match))
204*e4b17023SJohn Marino 			      && (TREE_CODE (TYPE_NAME
205*e4b17023SJohn Marino 				   (TREE_TYPE (closest_match))) == TYPE_DECL))
206*e4b17023SJohn Marino 			    inform (DECL_SOURCE_LOCATION
207*e4b17023SJohn Marino 				      (TYPE_NAME (TREE_TYPE (closest_match))),
208*e4b17023SJohn Marino 				    "type of mismatching field declared here");
209*e4b17023SJohn Marino 			}
210*e4b17023SJohn Marino 		      /* And finally fixup the types.  */
211*e4b17023SJohn Marino 		      TREE_OPERAND (op, 0)
212*e4b17023SJohn Marino 			= build1 (VIEW_CONVERT_EXPR, type,
213*e4b17023SJohn Marino 				  TREE_OPERAND (op, 0));
214*e4b17023SJohn Marino 		    }
215*e4b17023SJohn Marino 		  else
216*e4b17023SJohn Marino 		    TREE_OPERAND (op, 1) = tem;
217*e4b17023SJohn Marino 		}
218*e4b17023SJohn Marino 
219*e4b17023SJohn Marino 	      op = TREE_OPERAND (op, 0);
220*e4b17023SJohn Marino 	    }
221*e4b17023SJohn Marino 	}
222*e4b17023SJohn Marino       if (is_gimple_call (stmt))
223*e4b17023SJohn Marino 	{
224*e4b17023SJohn Marino 	  if (gimple_call_internal_p (stmt))
225*e4b17023SJohn Marino 	    gimple_call_set_internal_fn
226*e4b17023SJohn Marino 	      (stmt, streamer_read_enum (ib, internal_fn, IFN_LAST));
227*e4b17023SJohn Marino 	  else
228*e4b17023SJohn Marino 	    gimple_call_set_fntype (stmt, stream_read_tree (ib, data_in));
229*e4b17023SJohn Marino 	}
230*e4b17023SJohn Marino       break;
231*e4b17023SJohn Marino 
232*e4b17023SJohn Marino     case GIMPLE_NOP:
233*e4b17023SJohn Marino     case GIMPLE_PREDICT:
234*e4b17023SJohn Marino       break;
235*e4b17023SJohn Marino 
236*e4b17023SJohn Marino     case GIMPLE_TRANSACTION:
237*e4b17023SJohn Marino       gimple_transaction_set_label (stmt, stream_read_tree (ib, data_in));
238*e4b17023SJohn Marino       break;
239*e4b17023SJohn Marino 
240*e4b17023SJohn Marino     default:
241*e4b17023SJohn Marino       internal_error ("bytecode stream: unknown GIMPLE statement tag %s",
242*e4b17023SJohn Marino 		      lto_tag_name (tag));
243*e4b17023SJohn Marino     }
244*e4b17023SJohn Marino 
245*e4b17023SJohn Marino   /* Update the properties of symbols, SSA names and labels associated
246*e4b17023SJohn Marino      with STMT.  */
247*e4b17023SJohn Marino   if (code == GIMPLE_ASSIGN || code == GIMPLE_CALL)
248*e4b17023SJohn Marino     {
249*e4b17023SJohn Marino       tree lhs = gimple_get_lhs (stmt);
250*e4b17023SJohn Marino       if (lhs && TREE_CODE (lhs) == SSA_NAME)
251*e4b17023SJohn Marino 	SSA_NAME_DEF_STMT (lhs) = stmt;
252*e4b17023SJohn Marino     }
253*e4b17023SJohn Marino   else if (code == GIMPLE_LABEL)
254*e4b17023SJohn Marino     gcc_assert (emit_label_in_global_context_p (gimple_label_label (stmt))
255*e4b17023SJohn Marino 	        || DECL_CONTEXT (gimple_label_label (stmt)) == fn->decl);
256*e4b17023SJohn Marino   else if (code == GIMPLE_ASM)
257*e4b17023SJohn Marino     {
258*e4b17023SJohn Marino       unsigned i;
259*e4b17023SJohn Marino 
260*e4b17023SJohn Marino       for (i = 0; i < gimple_asm_noutputs (stmt); i++)
261*e4b17023SJohn Marino 	{
262*e4b17023SJohn Marino 	  tree op = TREE_VALUE (gimple_asm_output_op (stmt, i));
263*e4b17023SJohn Marino 	  if (TREE_CODE (op) == SSA_NAME)
264*e4b17023SJohn Marino 	    SSA_NAME_DEF_STMT (op) = stmt;
265*e4b17023SJohn Marino 	}
266*e4b17023SJohn Marino     }
267*e4b17023SJohn Marino 
268*e4b17023SJohn Marino   /* Reset alias information.  */
269*e4b17023SJohn Marino   if (code == GIMPLE_CALL)
270*e4b17023SJohn Marino     gimple_call_reset_alias_info (stmt);
271*e4b17023SJohn Marino 
272*e4b17023SJohn Marino   /* Mark the statement modified so its operand vectors can be filled in.  */
273*e4b17023SJohn Marino   gimple_set_modified (stmt, true);
274*e4b17023SJohn Marino 
275*e4b17023SJohn Marino   return stmt;
276*e4b17023SJohn Marino }
277*e4b17023SJohn Marino 
278*e4b17023SJohn Marino 
279*e4b17023SJohn Marino /* Read a basic block with tag TAG from DATA_IN using input block IB.
280*e4b17023SJohn Marino    FN is the function being processed.  */
281*e4b17023SJohn Marino 
282*e4b17023SJohn Marino void
input_bb(struct lto_input_block * ib,enum LTO_tags tag,struct data_in * data_in,struct function * fn,int count_materialization_scale)283*e4b17023SJohn Marino input_bb (struct lto_input_block *ib, enum LTO_tags tag,
284*e4b17023SJohn Marino 	  struct data_in *data_in, struct function *fn,
285*e4b17023SJohn Marino 	  int count_materialization_scale)
286*e4b17023SJohn Marino {
287*e4b17023SJohn Marino   unsigned int index;
288*e4b17023SJohn Marino   basic_block bb;
289*e4b17023SJohn Marino   gimple_stmt_iterator bsi;
290*e4b17023SJohn Marino 
291*e4b17023SJohn Marino   /* This routine assumes that CFUN is set to FN, as it needs to call
292*e4b17023SJohn Marino      basic GIMPLE routines that use CFUN.  */
293*e4b17023SJohn Marino   gcc_assert (cfun == fn);
294*e4b17023SJohn Marino 
295*e4b17023SJohn Marino   index = streamer_read_uhwi (ib);
296*e4b17023SJohn Marino   bb = BASIC_BLOCK_FOR_FUNCTION (fn, index);
297*e4b17023SJohn Marino 
298*e4b17023SJohn Marino   bb->count = (streamer_read_hwi (ib) * count_materialization_scale
299*e4b17023SJohn Marino 	       + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE;
300*e4b17023SJohn Marino   bb->loop_depth = streamer_read_hwi (ib);
301*e4b17023SJohn Marino   bb->frequency = streamer_read_hwi (ib);
302*e4b17023SJohn Marino   bb->flags = streamer_read_hwi (ib);
303*e4b17023SJohn Marino 
304*e4b17023SJohn Marino   /* LTO_bb1 has statements.  LTO_bb0 does not.  */
305*e4b17023SJohn Marino   if (tag == LTO_bb0)
306*e4b17023SJohn Marino     return;
307*e4b17023SJohn Marino 
308*e4b17023SJohn Marino   bsi = gsi_start_bb (bb);
309*e4b17023SJohn Marino   tag = streamer_read_record_start (ib);
310*e4b17023SJohn Marino   while (tag)
311*e4b17023SJohn Marino     {
312*e4b17023SJohn Marino       gimple stmt = input_gimple_stmt (ib, data_in, fn, tag);
313*e4b17023SJohn Marino       if (!is_gimple_debug (stmt))
314*e4b17023SJohn Marino 	find_referenced_vars_in (stmt);
315*e4b17023SJohn Marino       gsi_insert_after (&bsi, stmt, GSI_NEW_STMT);
316*e4b17023SJohn Marino 
317*e4b17023SJohn Marino       /* After the statement, expect a 0 delimiter or the EH region
318*e4b17023SJohn Marino 	 that the previous statement belongs to.  */
319*e4b17023SJohn Marino       tag = streamer_read_record_start (ib);
320*e4b17023SJohn Marino       lto_tag_check_set (tag, 2, LTO_eh_region, LTO_null);
321*e4b17023SJohn Marino 
322*e4b17023SJohn Marino       if (tag == LTO_eh_region)
323*e4b17023SJohn Marino 	{
324*e4b17023SJohn Marino 	  HOST_WIDE_INT region = streamer_read_hwi (ib);
325*e4b17023SJohn Marino 	  gcc_assert (region == (int) region);
326*e4b17023SJohn Marino 	  add_stmt_to_eh_lp (stmt, region);
327*e4b17023SJohn Marino 	}
328*e4b17023SJohn Marino 
329*e4b17023SJohn Marino       tag = streamer_read_record_start (ib);
330*e4b17023SJohn Marino     }
331*e4b17023SJohn Marino 
332*e4b17023SJohn Marino   tag = streamer_read_record_start (ib);
333*e4b17023SJohn Marino   while (tag)
334*e4b17023SJohn Marino     {
335*e4b17023SJohn Marino       gimple phi = input_phi (ib, bb, data_in, fn);
336*e4b17023SJohn Marino       find_referenced_vars_in (phi);
337*e4b17023SJohn Marino       tag = streamer_read_record_start (ib);
338*e4b17023SJohn Marino     }
339*e4b17023SJohn Marino }
340