1/* Write and read any fix-up information generated by the WPA mode.
2
3   Copyright 2009 Free Software Foundation, Inc.
4   Contributed by Doug Kwan <dougkwan@google.com>
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along 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 "tm.h"
26#include "toplev.h"
27#include "tree.h"
28#include "expr.h"
29#include "flags.h"
30#include "cgraph.h"
31#include "function.h"
32#include "diagnostic.h"
33#include "vec.h"
34#include "bitmap.h"
35#include "timevar.h"
36#include "tree-flow.h"
37#include "tree-pass.h"
38#include "lto-streamer.h"
39
40/* LTO fix-up.
41
42   In WPA mode, LTO cannot access function bodies.  Some modifications in
43   IR require additional updates in function bodies,  which are not possible
44   in WPA mode.  So we write out information about these modifications for
45   LTRANS to fix up the function bodies accordingly.  */
46
47/* The vectors records function DECLs having multiple copies with different
48   exception throwing attributes.  We do not mark a DECL if all copies of it
49   have the same exception throwing attribute. */
50static bitmap lto_nothrow_fndecls;
51
52/* We need to fix up GIMPLE bodies due to changes in exception setting.
53   Consider this example:
54
55   a.h:
56   class a {
57   public:
58     a();
59     ~a();
60   };
61
62   main.cc:
63   #include "a.h"
64
65   int
66   main (int argc, char **argv)
67   {
68     a x;
69     return 0;
70   }
71
72   a.cc:
73   #include "a.h"
74   a::a() {}
75   a::~a() {}
76
77   When main.cc is compiled, gcc only sees the constructor declaration, so
78   the constructor and hence the call to it are marked as exception throwing.
79   When a.cc is compiled, the body of the constructor is available and is
80   obviously not exception throwing. Thus DECL of a::a in a.o has the NOTHROW
81   attribute.  When LTO runs, two DECLs of a::a with different exception
82   attributes are merged.  We want the merged DECL to be not exception
83   throwing for better generated code.  To do that, we need to fix up any
84   function calls that have been marked as exception throwing.  */
85
86/* Fix up all the call statements whose target fndecls might have changed
87   to NOTHROW.   Note that this problem is not WPA specific.  We can also
88   run into this problem in normal LTO with multiple input files.  */
89
90void
91lto_fixup_nothrow_decls (void)
92{
93  struct cgraph_node *node;
94  struct cgraph_edge *edge;
95  struct function *caller_function;
96  gimple call_stmt;
97
98  /* Quit if we are in WPA mode or have not marked any DECLs.  */
99  if (flag_wpa || !lto_nothrow_fndecls)
100    return;
101
102  /* For each node that has been marked, go over all call edges to it.  */
103  for (node = cgraph_nodes; node; node = node->next)
104    if (bitmap_bit_p (lto_nothrow_fndecls, DECL_UID (node->decl)))
105      {
106	gcc_assert (TREE_NOTHROW (node->decl));
107	for (edge = node->callers; edge; edge = edge->next_caller)
108	  {
109	    caller_function = DECL_STRUCT_FUNCTION (edge->caller->decl);
110	    call_stmt = edge->call_stmt;
111	    gcc_assert (call_stmt);
112	    if (lookup_stmt_eh_lp_fn (caller_function, call_stmt) != 0)
113	      remove_stmt_from_eh_lp_fn (caller_function, call_stmt);
114	  }
115      }
116}
117
118/* Mark FNDECL as becoming not exception throwing.  */
119
120void
121lto_mark_nothrow_fndecl (tree fndecl)
122{
123  gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
124  if (!lto_nothrow_fndecls)
125    lto_nothrow_fndecls = lto_bitmap_alloc ();
126
127  bitmap_set_bit (lto_nothrow_fndecls, DECL_UID (fndecl));
128}
129
130/* Write out fix-up information.  Currently the only WPA fix-up
131   information is the list of DECLs marked as not exception throwing. SET
132   is a cgraph node set whose fix-up information is to be written.  */
133
134static void
135lto_output_wpa_fixup (cgraph_node_set set)
136{
137  struct lto_simple_output_block *ob;
138  cgraph_node_set_iterator csi;
139  tree fndecl;
140  bitmap seen_decls;
141  VEC(tree, heap) *decls = NULL;
142  unsigned HOST_WIDE_INT i, count;
143
144  ob = lto_create_simple_output_block (LTO_section_wpa_fixup);
145
146  /* Accumulate the DECLs to be written out.  Since we do not want
147     duplicates, we need to use a bitmap and a vector to save the
148     DECLs we want.  Note that we need to check if lto_nothrow_fndecls
149     is NULL.  This happens when no DECL has been marked.  */
150  seen_decls = lto_bitmap_alloc ();
151  if (lto_nothrow_fndecls)
152    for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
153      {
154	struct cgraph_edge *e;
155	struct cgraph_node *n;
156
157	n = csi_node (csi);
158	fndecl = n->decl;
159
160	/* Check if the N's function is in the set of nothrow functions.  */
161	if (!bitmap_bit_p (seen_decls, DECL_UID (fndecl)))
162	  {
163	    bitmap_set_bit (seen_decls, (DECL_UID (fndecl)));
164	    if (bitmap_bit_p (lto_nothrow_fndecls, DECL_UID (fndecl)))
165	      VEC_safe_push (tree, heap, decls, fndecl);
166	  }
167
168	/* Now check the callees and also add them if they are nothrow.  This
169	   is needed because node N may end up in a different partition than
170	   its callees.  In which case, when the file holding N is compiled,
171	   the calls it makes to nothrow functions will not be fixed up,
172	   causing verification issues.  */
173	for (e = n->callees; e; e = e->next_callee)
174	  {
175	    fndecl = e->callee->decl;
176	    if (!bitmap_bit_p (seen_decls, DECL_UID (fndecl)))
177	      {
178		bitmap_set_bit (seen_decls, (DECL_UID (fndecl)));
179		if (bitmap_bit_p (lto_nothrow_fndecls, DECL_UID (fndecl)))
180		  VEC_safe_push (tree, heap, decls, fndecl);
181	      }
182	  }
183      }
184
185  /* Write out number of DECLs, followed by the DECLs.  */
186  count = VEC_length (tree, decls);
187  lto_output_uleb128_stream (ob->main_stream, count);
188  for (i = 0; i < count; i++)
189    {
190      fndecl = VEC_index (tree, decls, i);
191      lto_output_fn_decl_index (ob->decl_state, ob->main_stream, fndecl);
192    }
193
194  /* Release resources.  */
195  lto_destroy_simple_output_block (ob);
196  VEC_free(tree, heap, decls);
197  lto_bitmap_free (seen_decls);
198}
199
200/* Read in WPA fix-up information from one file. FILE_DATA points to
201   DECL information of the file where as IB is the input block for the
202   WPA fix-up section.  */
203
204static void
205lto_input_wpa_fixup_1 (struct lto_file_decl_data *file_data,
206		   struct lto_input_block *ib)
207{
208  unsigned HOST_WIDE_INT i, count, decl_index;
209  tree fndecl;
210
211  count = lto_input_uleb128 (ib);
212  for (i = 0; i < count; i++)
213    {
214      decl_index = lto_input_uleb128 (ib);
215      fndecl = lto_file_decl_data_get_fn_decl (file_data, decl_index);
216      lto_mark_nothrow_fndecl (fndecl);
217    }
218}
219
220/* Read in WPA fix-up information. */
221
222static void
223lto_input_wpa_fixup (void)
224{
225  struct lto_file_decl_data ** file_data_vec
226    = lto_get_file_decl_data ();
227  struct lto_file_decl_data * file_data;
228  int i = 0;
229
230  /* Fix up information is only used in LTRANS mode.  */
231  if (!flag_ltrans)
232    return;
233
234  while ((file_data = file_data_vec[i++]))
235    {
236      const char *data;
237      size_t len;
238      struct lto_input_block *ib
239	= lto_create_simple_input_block (file_data, LTO_section_wpa_fixup,
240					 &data, &len);
241
242      lto_input_wpa_fixup_1 (file_data, ib);
243      lto_destroy_simple_input_block (file_data, LTO_section_wpa_fixup, ib,
244				      data, len);
245    }
246}
247
248/* Gate function for all lto streaming passes.  */
249
250static bool
251gate_wpa_fixup (void)
252{
253  return (flag_wpa || flag_ltrans) && gate_lto_out ();
254}
255
256struct ipa_opt_pass_d pass_ipa_lto_wpa_fixup =
257{
258 {
259  IPA_PASS,
260  "lto_wpa_fixup",			/* name */
261  gate_wpa_fixup,		        /* gate */
262  NULL,		                        /* execute */
263  NULL,					/* sub */
264  NULL,					/* next */
265  0,					/* static_pass_number */
266  TV_WHOPR_WPA_FIXUP,		        /* tv_id */
267  0,	                                /* properties_required */
268  0,					/* properties_provided */
269  0,					/* properties_destroyed */
270  0,            			/* todo_flags_start */
271  TODO_dump_func                        /* todo_flags_finish */
272 },
273 NULL,		                        /* generate_summary */
274 lto_output_wpa_fixup,			/* write_summary */
275 lto_input_wpa_fixup,			/* read_summary */
276 NULL,					/* function_read_summary */
277 NULL,					/* stmt_fixup */
278 0,					/* TODOs */
279 NULL,			                /* function_transform */
280 NULL					/* variable_transform */
281};
282
283