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