OSDN Git Service

PR middle-end/40815
[pf3gnuchains/gcc-fork.git] / gcc / lto-wpa-fixup.c
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
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 "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. */
50 static 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
90 void
91 lto_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
120 void
121 lto_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
134 static void
135 lto_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
204 static void
205 lto_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
222 static void
223 lto_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
250 static bool
251 gate_wpa_fixup (void)
252 {
253   return (flag_wpa || flag_ltrans) && gate_lto_out ();
254 }
255
256 struct 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