Mercurial > hg > CbC > CbC_gcc
annotate gcc/tree-mudflap.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
rev | line source |
---|---|
0 | 1 /* Mudflap: narrow-pointer bounds-checking by tree rewriting. |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
2 Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 |
0 | 3 Free Software Foundation, Inc. |
4 Contributed by Frank Ch. Eigler <fche@redhat.com> | |
5 and Graydon Hoare <graydon@redhat.com> | |
6 | |
7 This file is part of GCC. | |
8 | |
9 GCC is free software; you can redistribute it and/or modify it under | |
10 the terms of the GNU General Public License as published by the Free | |
11 Software Foundation; either version 3, or (at your option) any later | |
12 version. | |
13 | |
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with GCC; see the file COPYING3. If not see | |
21 <http://www.gnu.org/licenses/>. */ | |
22 | |
23 | |
24 #include "config.h" | |
25 #include "system.h" | |
26 #include "coretypes.h" | |
27 #include "tm.h" | |
28 #include "tree.h" | |
29 #include "tm_p.h" | |
30 #include "basic-block.h" | |
31 #include "flags.h" | |
32 #include "function.h" | |
33 #include "tree-inline.h" | |
34 #include "gimple.h" | |
35 #include "tree-iterator.h" | |
36 #include "tree-flow.h" | |
37 #include "tree-mudflap.h" | |
38 #include "tree-dump.h" | |
39 #include "tree-pass.h" | |
40 #include "hashtab.h" | |
41 #include "diagnostic.h" | |
42 #include <demangle.h> | |
43 #include "langhooks.h" | |
44 #include "ggc.h" | |
45 #include "cgraph.h" | |
46 #include "toplev.h" | |
47 #include "gimple.h" | |
48 | |
49 /* Internal function decls */ | |
50 | |
51 | |
52 /* Options. */ | |
53 #define flag_mudflap_threads (flag_mudflap == 2) | |
54 | |
55 /* Helpers. */ | |
56 static tree mf_build_string (const char *string); | |
57 static tree mf_varname_tree (tree); | |
58 static tree mf_file_function_line_tree (location_t); | |
59 | |
60 /* Indirection-related instrumentation. */ | |
61 static void mf_decl_cache_locals (void); | |
62 static void mf_decl_clear_locals (void); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
63 static void mf_xform_statements (void); |
0 | 64 static unsigned int execute_mudflap_function_ops (void); |
65 | |
66 /* Addressable variables instrumentation. */ | |
67 static void mf_xform_decls (gimple_seq, tree); | |
68 static tree mx_xfn_xform_decls (gimple_stmt_iterator *, bool *, | |
69 struct walk_stmt_info *); | |
70 static gimple_seq mx_register_decls (tree, gimple_seq, location_t); | |
71 static unsigned int execute_mudflap_function_decls (void); | |
72 | |
73 | |
74 /* ------------------------------------------------------------------------ */ | |
75 /* Some generally helpful functions for mudflap instrumentation. */ | |
76 | |
77 /* Build a reference to a literal string. */ | |
78 static tree | |
79 mf_build_string (const char *string) | |
80 { | |
81 size_t len = strlen (string); | |
82 tree result = mf_mark (build_string (len + 1, string)); | |
83 | |
84 TREE_TYPE (result) = build_array_type | |
85 (char_type_node, build_index_type (build_int_cst (NULL_TREE, len))); | |
86 TREE_CONSTANT (result) = 1; | |
87 TREE_READONLY (result) = 1; | |
88 TREE_STATIC (result) = 1; | |
89 | |
90 result = build1 (ADDR_EXPR, build_pointer_type (char_type_node), result); | |
91 | |
92 return mf_mark (result); | |
93 } | |
94 | |
95 /* Create a properly typed STRING_CST node that describes the given | |
96 declaration. It will be used as an argument for __mf_register(). | |
97 Try to construct a helpful string, including file/function/variable | |
98 name. */ | |
99 | |
100 static tree | |
101 mf_varname_tree (tree decl) | |
102 { | |
103 static pretty_printer buf_rec; | |
104 static int initialized = 0; | |
105 pretty_printer *buf = & buf_rec; | |
106 const char *buf_contents; | |
107 tree result; | |
108 | |
109 gcc_assert (decl); | |
110 | |
111 if (!initialized) | |
112 { | |
113 pp_construct (buf, /* prefix */ NULL, /* line-width */ 0); | |
114 initialized = 1; | |
115 } | |
116 pp_clear_output_area (buf); | |
117 | |
118 /* Add FILENAME[:LINENUMBER[:COLUMNNUMBER]]. */ | |
119 { | |
120 expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (decl)); | |
121 const char *sourcefile; | |
122 unsigned sourceline = xloc.line; | |
123 unsigned sourcecolumn = 0; | |
124 sourcecolumn = xloc.column; | |
125 sourcefile = xloc.file; | |
126 if (sourcefile == NULL && current_function_decl != NULL_TREE) | |
127 sourcefile = DECL_SOURCE_FILE (current_function_decl); | |
128 if (sourcefile == NULL) | |
129 sourcefile = "<unknown file>"; | |
130 | |
131 pp_string (buf, sourcefile); | |
132 | |
133 if (sourceline != 0) | |
134 { | |
135 pp_string (buf, ":"); | |
136 pp_decimal_int (buf, sourceline); | |
137 | |
138 if (sourcecolumn != 0) | |
139 { | |
140 pp_string (buf, ":"); | |
141 pp_decimal_int (buf, sourcecolumn); | |
142 } | |
143 } | |
144 } | |
145 | |
146 if (current_function_decl != NULL_TREE) | |
147 { | |
148 /* Add (FUNCTION) */ | |
149 pp_string (buf, " ("); | |
150 { | |
151 const char *funcname = NULL; | |
152 if (DECL_NAME (current_function_decl)) | |
153 funcname = lang_hooks.decl_printable_name (current_function_decl, 1); | |
154 if (funcname == NULL) | |
155 funcname = "anonymous fn"; | |
156 | |
157 pp_string (buf, funcname); | |
158 } | |
159 pp_string (buf, ") "); | |
160 } | |
161 else | |
162 pp_string (buf, " "); | |
163 | |
164 /* Add <variable-declaration>, possibly demangled. */ | |
165 { | |
166 const char *declname = NULL; | |
167 | |
168 if (DECL_NAME (decl) != NULL) | |
169 { | |
170 if (strcmp ("GNU C++", lang_hooks.name) == 0) | |
171 { | |
172 /* The gcc/cp decl_printable_name hook doesn't do as good a job as | |
173 the libiberty demangler. */ | |
174 declname = cplus_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)), | |
175 DMGL_AUTO | DMGL_VERBOSE); | |
176 } | |
177 if (declname == NULL) | |
178 declname = lang_hooks.decl_printable_name (decl, 3); | |
179 } | |
180 if (declname == NULL) | |
181 declname = "<unnamed variable>"; | |
182 | |
183 pp_string (buf, declname); | |
184 } | |
185 | |
186 /* Return the lot as a new STRING_CST. */ | |
187 buf_contents = pp_base_formatted_text (buf); | |
188 result = mf_build_string (buf_contents); | |
189 pp_clear_output_area (buf); | |
190 | |
191 return result; | |
192 } | |
193 | |
194 | |
195 /* And another friend, for producing a simpler message. */ | |
196 | |
197 static tree | |
198 mf_file_function_line_tree (location_t location) | |
199 { | |
200 expanded_location xloc = expand_location (location); | |
201 const char *file = NULL, *colon, *line, *op, *name, *cp; | |
202 char linecolbuf[30]; /* Enough for two decimal numbers plus a colon. */ | |
203 char *string; | |
204 tree result; | |
205 | |
206 /* Add FILENAME[:LINENUMBER[:COLUMNNUMBER]]. */ | |
207 file = xloc.file; | |
208 if (file == NULL && current_function_decl != NULL_TREE) | |
209 file = DECL_SOURCE_FILE (current_function_decl); | |
210 if (file == NULL) | |
211 file = "<unknown file>"; | |
212 | |
213 if (xloc.line > 0) | |
214 { | |
215 if (xloc.column > 0) | |
216 sprintf (linecolbuf, "%d:%d", xloc.line, xloc.column); | |
217 else | |
218 sprintf (linecolbuf, "%d", xloc.line); | |
219 colon = ":"; | |
220 line = linecolbuf; | |
221 } | |
222 else | |
223 colon = line = ""; | |
224 | |
225 /* Add (FUNCTION). */ | |
226 name = lang_hooks.decl_printable_name (current_function_decl, 1); | |
227 if (name) | |
228 { | |
229 op = " ("; | |
230 cp = ")"; | |
231 } | |
232 else | |
233 op = name = cp = ""; | |
234 | |
235 string = concat (file, colon, line, op, name, cp, NULL); | |
236 result = mf_build_string (string); | |
237 free (string); | |
238 | |
239 return result; | |
240 } | |
241 | |
242 | |
243 /* global tree nodes */ | |
244 | |
245 /* Global tree objects for global variables and functions exported by | |
246 mudflap runtime library. mf_init_extern_trees must be called | |
247 before using these. */ | |
248 | |
249 /* uintptr_t (usually "unsigned long") */ | |
250 static GTY (()) tree mf_uintptr_type; | |
251 | |
252 /* struct __mf_cache { uintptr_t low; uintptr_t high; }; */ | |
253 static GTY (()) tree mf_cache_struct_type; | |
254 | |
255 /* struct __mf_cache * const */ | |
256 static GTY (()) tree mf_cache_structptr_type; | |
257 | |
258 /* extern struct __mf_cache __mf_lookup_cache []; */ | |
259 static GTY (()) tree mf_cache_array_decl; | |
260 | |
261 /* extern unsigned char __mf_lc_shift; */ | |
262 static GTY (()) tree mf_cache_shift_decl; | |
263 | |
264 /* extern uintptr_t __mf_lc_mask; */ | |
265 static GTY (()) tree mf_cache_mask_decl; | |
266 | |
267 /* Their function-scope local shadows, used in single-threaded mode only. */ | |
268 | |
269 /* auto const unsigned char __mf_lc_shift_l; */ | |
270 static GTY (()) tree mf_cache_shift_decl_l; | |
271 | |
272 /* auto const uintptr_t __mf_lc_mask_l; */ | |
273 static GTY (()) tree mf_cache_mask_decl_l; | |
274 | |
275 /* extern void __mf_check (void *ptr, size_t sz, int type, const char *); */ | |
276 static GTY (()) tree mf_check_fndecl; | |
277 | |
278 /* extern void __mf_register (void *ptr, size_t sz, int type, const char *); */ | |
279 static GTY (()) tree mf_register_fndecl; | |
280 | |
281 /* extern void __mf_unregister (void *ptr, size_t sz, int type); */ | |
282 static GTY (()) tree mf_unregister_fndecl; | |
283 | |
284 /* extern void __mf_init (); */ | |
285 static GTY (()) tree mf_init_fndecl; | |
286 | |
287 /* extern int __mf_set_options (const char*); */ | |
288 static GTY (()) tree mf_set_options_fndecl; | |
289 | |
290 | |
291 /* Helper for mudflap_init: construct a decl with the given category, | |
292 name, and type, mark it an external reference, and pushdecl it. */ | |
293 static inline tree | |
294 mf_make_builtin (enum tree_code category, const char *name, tree type) | |
295 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
296 tree decl = mf_mark (build_decl (UNKNOWN_LOCATION, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
297 category, get_identifier (name), type)); |
0 | 298 TREE_PUBLIC (decl) = 1; |
299 DECL_EXTERNAL (decl) = 1; | |
300 lang_hooks.decls.pushdecl (decl); | |
301 /* The decl was declared by the compiler. */ | |
302 DECL_ARTIFICIAL (decl) = 1; | |
303 /* And we don't want debug info for it. */ | |
304 DECL_IGNORED_P (decl) = 1; | |
305 return decl; | |
306 } | |
307 | |
308 /* Helper for mudflap_init: construct a tree corresponding to the type | |
309 struct __mf_cache { uintptr_t low; uintptr_t high; }; | |
310 where uintptr_t is the FIELD_TYPE argument. */ | |
311 static inline tree | |
312 mf_make_mf_cache_struct_type (tree field_type) | |
313 { | |
314 /* There is, abominably, no language-independent way to construct a | |
315 RECORD_TYPE. So we have to call the basic type construction | |
316 primitives by hand. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
317 tree fieldlo = build_decl (UNKNOWN_LOCATION, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
318 FIELD_DECL, get_identifier ("low"), field_type); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
319 tree fieldhi = build_decl (UNKNOWN_LOCATION, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
320 FIELD_DECL, get_identifier ("high"), field_type); |
0 | 321 |
322 tree struct_type = make_node (RECORD_TYPE); | |
323 DECL_CONTEXT (fieldlo) = struct_type; | |
324 DECL_CONTEXT (fieldhi) = struct_type; | |
325 TREE_CHAIN (fieldlo) = fieldhi; | |
326 TYPE_FIELDS (struct_type) = fieldlo; | |
327 TYPE_NAME (struct_type) = get_identifier ("__mf_cache"); | |
328 layout_type (struct_type); | |
329 | |
330 return struct_type; | |
331 } | |
332 | |
333 /* Initialize the global tree nodes that correspond to mf-runtime.h | |
334 declarations. */ | |
335 void | |
336 mudflap_init (void) | |
337 { | |
338 static bool done = false; | |
339 tree mf_const_string_type; | |
340 tree mf_cache_array_type; | |
341 tree mf_check_register_fntype; | |
342 tree mf_unregister_fntype; | |
343 tree mf_init_fntype; | |
344 tree mf_set_options_fntype; | |
345 | |
346 if (done) | |
347 return; | |
348 done = true; | |
349 | |
350 mf_uintptr_type = lang_hooks.types.type_for_mode (ptr_mode, | |
351 /*unsignedp=*/true); | |
352 mf_const_string_type | |
353 = build_pointer_type (build_qualified_type | |
354 (char_type_node, TYPE_QUAL_CONST)); | |
355 | |
356 mf_cache_struct_type = mf_make_mf_cache_struct_type (mf_uintptr_type); | |
357 mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type); | |
358 mf_cache_array_type = build_array_type (mf_cache_struct_type, 0); | |
359 mf_check_register_fntype = | |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
360 build_function_type_list (void_type_node, ptr_type_node, size_type_node, |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
361 integer_type_node, mf_const_string_type, NULL_TREE); |
0 | 362 mf_unregister_fntype = |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
363 build_function_type_list (void_type_node, ptr_type_node, size_type_node, |
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
364 integer_type_node, NULL_TREE); |
0 | 365 mf_init_fntype = |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
366 build_function_type_list (void_type_node, NULL_TREE); |
0 | 367 mf_set_options_fntype = |
63
b7f97abdc517
update gcc from gcc-4.5.0 to gcc-4.6
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
368 build_function_type_list (integer_type_node, mf_const_string_type, NULL_TREE); |
0 | 369 |
370 mf_cache_array_decl = mf_make_builtin (VAR_DECL, "__mf_lookup_cache", | |
371 mf_cache_array_type); | |
372 mf_cache_shift_decl = mf_make_builtin (VAR_DECL, "__mf_lc_shift", | |
373 unsigned_char_type_node); | |
374 mf_cache_mask_decl = mf_make_builtin (VAR_DECL, "__mf_lc_mask", | |
375 mf_uintptr_type); | |
376 /* Don't process these in mudflap_enqueue_decl, should they come by | |
377 there for some reason. */ | |
378 mf_mark (mf_cache_array_decl); | |
379 mf_mark (mf_cache_shift_decl); | |
380 mf_mark (mf_cache_mask_decl); | |
381 mf_check_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_check", | |
382 mf_check_register_fntype); | |
383 mf_register_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_register", | |
384 mf_check_register_fntype); | |
385 mf_unregister_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_unregister", | |
386 mf_unregister_fntype); | |
387 mf_init_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_init", | |
388 mf_init_fntype); | |
389 mf_set_options_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_set_options", | |
390 mf_set_options_fntype); | |
391 } | |
392 | |
393 | |
394 /* ------------------------------------------------------------------------ */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
395 /* This is the second part of the mudflap instrumentation. It works on |
0 | 396 low-level GIMPLE using the CFG, because we want to run this pass after |
397 tree optimizations have been performed, but we have to preserve the CFG | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
398 for expansion from trees to RTL. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
399 Below is the list of transformations performed on statements in the |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
400 current function. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
401 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
402 1) Memory reference transforms: Perform the mudflap indirection-related |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
403 tree transforms on memory references. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
404 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
405 2) Mark BUILTIN_ALLOCA calls not inlineable. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
406 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
407 */ |
0 | 408 |
409 static unsigned int | |
410 execute_mudflap_function_ops (void) | |
411 { | |
412 struct gimplify_ctx gctx; | |
413 | |
414 /* Don't instrument functions such as the synthetic constructor | |
415 built during mudflap_finish_file. */ | |
416 if (mf_marked_p (current_function_decl) || | |
417 DECL_ARTIFICIAL (current_function_decl)) | |
418 return 0; | |
419 | |
420 push_gimplify_context (&gctx); | |
421 | |
422 /* In multithreaded mode, don't cache the lookup cache parameters. */ | |
423 if (! flag_mudflap_threads) | |
424 mf_decl_cache_locals (); | |
425 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
426 mf_xform_statements (); |
0 | 427 |
428 if (! flag_mudflap_threads) | |
429 mf_decl_clear_locals (); | |
430 | |
431 pop_gimplify_context (NULL); | |
432 return 0; | |
433 } | |
434 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
435 /* Insert a gimple_seq SEQ on all the outgoing edges out of BB. Note that |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
436 if BB has more than one edge, STMT will be replicated for each edge. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
437 Also, abnormal edges will be ignored. */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
438 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
439 static void |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
440 insert_edge_copies_seq (gimple_seq seq, basic_block bb) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
441 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
442 edge e; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
443 edge_iterator ei; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
444 unsigned n_copies = -1; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
445 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
446 FOR_EACH_EDGE (e, ei, bb->succs) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
447 if (!(e->flags & EDGE_ABNORMAL)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
448 n_copies++; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
449 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
450 FOR_EACH_EDGE (e, ei, bb->succs) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
451 if (!(e->flags & EDGE_ABNORMAL)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
452 gsi_insert_seq_on_edge (e, n_copies-- > 0 ? gimple_seq_copy (seq) : seq); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
453 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
454 |
0 | 455 /* Create and initialize local shadow variables for the lookup cache |
456 globals. Put their decls in the *_l globals for use by | |
457 mf_build_check_statement_for. */ | |
458 | |
459 static void | |
460 mf_decl_cache_locals (void) | |
461 { | |
462 gimple g; | |
463 gimple_seq seq = gimple_seq_alloc (); | |
464 | |
465 /* Build the cache vars. */ | |
466 mf_cache_shift_decl_l | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
467 = mf_mark (make_rename_temp (TREE_TYPE (mf_cache_shift_decl), |
0 | 468 "__mf_lookup_shift_l")); |
469 | |
470 mf_cache_mask_decl_l | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
471 = mf_mark (make_rename_temp (TREE_TYPE (mf_cache_mask_decl), |
0 | 472 "__mf_lookup_mask_l")); |
473 | |
474 /* Build initialization nodes for the cache vars. We just load the | |
475 globals into the cache variables. */ | |
476 g = gimple_build_assign (mf_cache_shift_decl_l, mf_cache_shift_decl); | |
477 gimple_set_location (g, DECL_SOURCE_LOCATION (current_function_decl)); | |
478 gimple_seq_add_stmt (&seq, g); | |
479 | |
480 g = gimple_build_assign (mf_cache_mask_decl_l, mf_cache_mask_decl); | |
481 gimple_set_location (g, DECL_SOURCE_LOCATION (current_function_decl)); | |
482 gimple_seq_add_stmt (&seq, g); | |
483 | |
484 insert_edge_copies_seq (seq, ENTRY_BLOCK_PTR); | |
485 | |
486 gsi_commit_edge_inserts (); | |
487 } | |
488 | |
489 | |
490 static void | |
491 mf_decl_clear_locals (void) | |
492 { | |
493 /* Unset local shadows. */ | |
494 mf_cache_shift_decl_l = NULL_TREE; | |
495 mf_cache_mask_decl_l = NULL_TREE; | |
496 } | |
497 | |
498 static void | |
499 mf_build_check_statement_for (tree base, tree limit, | |
500 gimple_stmt_iterator *instr_gsi, | |
501 location_t location, tree dirflag) | |
502 { | |
503 gimple_stmt_iterator gsi; | |
504 basic_block cond_bb, then_bb, join_bb; | |
505 edge e; | |
506 tree cond, t, u, v; | |
507 tree mf_base; | |
508 tree mf_elem; | |
509 tree mf_limit; | |
510 gimple g; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
511 gimple_seq seq, stmts; |
0 | 512 |
513 /* We first need to split the current basic block, and start altering | |
514 the CFG. This allows us to insert the statements we're about to | |
515 construct into the right basic blocks. */ | |
516 | |
517 cond_bb = gimple_bb (gsi_stmt (*instr_gsi)); | |
518 gsi = *instr_gsi; | |
519 gsi_prev (&gsi); | |
520 if (! gsi_end_p (gsi)) | |
521 e = split_block (cond_bb, gsi_stmt (gsi)); | |
522 else | |
523 e = split_block_after_labels (cond_bb); | |
524 cond_bb = e->src; | |
525 join_bb = e->dest; | |
526 | |
527 /* A recap at this point: join_bb is the basic block at whose head | |
528 is the gimple statement for which this check expression is being | |
529 built. cond_bb is the (possibly new, synthetic) basic block the | |
530 end of which will contain the cache-lookup code, and a | |
531 conditional that jumps to the cache-miss code or, much more | |
532 likely, over to join_bb. */ | |
533 | |
534 /* Create the bb that contains the cache-miss fallback block (mf_check). */ | |
535 then_bb = create_empty_bb (cond_bb); | |
536 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE); | |
537 make_single_succ_edge (then_bb, join_bb, EDGE_FALLTHRU); | |
538 | |
539 /* Mark the pseudo-fallthrough edge from cond_bb to join_bb. */ | |
540 e = find_edge (cond_bb, join_bb); | |
541 e->flags = EDGE_FALSE_VALUE; | |
542 e->count = cond_bb->count; | |
543 e->probability = REG_BR_PROB_BASE; | |
544 | |
545 /* Update dominance info. Note that bb_join's data was | |
546 updated by split_block. */ | |
547 if (dom_info_available_p (CDI_DOMINATORS)) | |
548 { | |
549 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb); | |
550 set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb); | |
551 } | |
552 | |
553 /* Build our local variables. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
554 mf_elem = make_rename_temp (mf_cache_structptr_type, "__mf_elem"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
555 mf_base = make_rename_temp (mf_uintptr_type, "__mf_base"); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
556 mf_limit = make_rename_temp (mf_uintptr_type, "__mf_limit"); |
0 | 557 |
558 /* Build: __mf_base = (uintptr_t) <base address expression>. */ | |
559 seq = gimple_seq_alloc (); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
560 t = fold_convert_loc (location, mf_uintptr_type, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
561 unshare_expr (base)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
562 t = force_gimple_operand (t, &stmts, false, NULL_TREE); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
563 gimple_seq_add_seq (&seq, stmts); |
0 | 564 g = gimple_build_assign (mf_base, t); |
565 gimple_set_location (g, location); | |
566 gimple_seq_add_stmt (&seq, g); | |
567 | |
568 /* Build: __mf_limit = (uintptr_t) <limit address expression>. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
569 t = fold_convert_loc (location, mf_uintptr_type, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
570 unshare_expr (limit)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
571 t = force_gimple_operand (t, &stmts, false, NULL_TREE); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
572 gimple_seq_add_seq (&seq, stmts); |
0 | 573 g = gimple_build_assign (mf_limit, t); |
574 gimple_set_location (g, location); | |
575 gimple_seq_add_stmt (&seq, g); | |
576 | |
577 /* Build: __mf_elem = &__mf_lookup_cache [(__mf_base >> __mf_shift) | |
578 & __mf_mask]. */ | |
579 t = build2 (RSHIFT_EXPR, mf_uintptr_type, mf_base, | |
580 flag_mudflap_threads ? mf_cache_shift_decl | |
581 : mf_cache_shift_decl_l); | |
582 t = build2 (BIT_AND_EXPR, mf_uintptr_type, t, | |
583 flag_mudflap_threads ? mf_cache_mask_decl | |
584 : mf_cache_mask_decl_l); | |
585 t = build4 (ARRAY_REF, | |
586 TREE_TYPE (TREE_TYPE (mf_cache_array_decl)), | |
587 mf_cache_array_decl, t, NULL_TREE, NULL_TREE); | |
588 t = build1 (ADDR_EXPR, mf_cache_structptr_type, t); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
589 t = force_gimple_operand (t, &stmts, false, NULL_TREE); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
590 gimple_seq_add_seq (&seq, stmts); |
0 | 591 g = gimple_build_assign (mf_elem, t); |
592 gimple_set_location (g, location); | |
593 gimple_seq_add_stmt (&seq, g); | |
594 | |
595 /* Quick validity check. | |
596 | |
597 if (__mf_elem->low > __mf_base | |
598 || (__mf_elem_high < __mf_limit)) | |
599 { | |
600 __mf_check (); | |
601 ... and only if single-threaded: | |
602 __mf_lookup_shift_1 = f...; | |
603 __mf_lookup_mask_l = ...; | |
604 } | |
605 | |
606 It is expected that this body of code is rarely executed so we mark | |
607 the edge to the THEN clause of the conditional jump as unlikely. */ | |
608 | |
609 /* Construct t <-- '__mf_elem->low > __mf_base'. */ | |
610 t = build3 (COMPONENT_REF, mf_uintptr_type, | |
611 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem), | |
612 TYPE_FIELDS (mf_cache_struct_type), NULL_TREE); | |
613 t = build2 (GT_EXPR, boolean_type_node, t, mf_base); | |
614 | |
615 /* Construct '__mf_elem->high < __mf_limit'. | |
616 | |
617 First build: | |
618 1) u <-- '__mf_elem->high' | |
619 2) v <-- '__mf_limit'. | |
620 | |
621 Then build 'u <-- (u < v). */ | |
622 | |
623 u = build3 (COMPONENT_REF, mf_uintptr_type, | |
624 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem), | |
625 TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE); | |
626 | |
627 v = mf_limit; | |
628 | |
629 u = build2 (LT_EXPR, boolean_type_node, u, v); | |
630 | |
631 /* Build the composed conditional: t <-- 't || u'. Then store the | |
632 result of the evaluation of 't' in a temporary variable which we | |
633 can use as the condition for the conditional jump. */ | |
634 t = build2 (TRUTH_OR_EXPR, boolean_type_node, t, u); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
635 t = force_gimple_operand (t, &stmts, false, NULL_TREE); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
636 gimple_seq_add_seq (&seq, stmts); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
637 cond = make_rename_temp (boolean_type_node, "__mf_unlikely_cond"); |
0 | 638 g = gimple_build_assign (cond, t); |
639 gimple_set_location (g, location); | |
640 gimple_seq_add_stmt (&seq, g); | |
641 | |
642 /* Build the conditional jump. 'cond' is just a temporary so we can | |
643 simply build a void COND_EXPR. We do need labels in both arms though. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
644 g = gimple_build_cond (NE_EXPR, cond, boolean_false_node, NULL_TREE, |
0 | 645 NULL_TREE); |
646 gimple_set_location (g, location); | |
647 gimple_seq_add_stmt (&seq, g); | |
648 | |
649 /* At this point, after so much hard work, we have only constructed | |
650 the conditional jump, | |
651 | |
652 if (__mf_elem->low > __mf_base | |
653 || (__mf_elem_high < __mf_limit)) | |
654 | |
655 The lowered GIMPLE tree representing this code is in the statement | |
656 list starting at 'head'. | |
657 | |
658 We can insert this now in the current basic block, i.e. the one that | |
659 the statement we're instrumenting was originally in. */ | |
660 gsi = gsi_last_bb (cond_bb); | |
661 gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING); | |
662 | |
663 /* Now build up the body of the cache-miss handling: | |
664 | |
665 __mf_check(); | |
666 refresh *_l vars. | |
667 | |
668 This is the body of the conditional. */ | |
669 | |
670 seq = gimple_seq_alloc (); | |
671 /* u is a string, so it is already a gimple value. */ | |
672 u = mf_file_function_line_tree (location); | |
673 /* NB: we pass the overall [base..limit] range to mf_check. */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
674 v = fold_build2_loc (location, PLUS_EXPR, mf_uintptr_type, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
675 fold_build2_loc (location, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
676 MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base), |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
677 build_int_cst (mf_uintptr_type, 1)); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
678 v = force_gimple_operand (v, &stmts, true, NULL_TREE); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
679 gimple_seq_add_seq (&seq, stmts); |
0 | 680 g = gimple_build_call (mf_check_fndecl, 4, mf_base, v, dirflag, u); |
681 gimple_seq_add_stmt (&seq, g); | |
682 | |
683 if (! flag_mudflap_threads) | |
684 { | |
685 if (stmt_ends_bb_p (g)) | |
686 { | |
687 gsi = gsi_start_bb (then_bb); | |
688 gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING); | |
689 e = split_block (then_bb, g); | |
690 then_bb = e->dest; | |
691 seq = gimple_seq_alloc (); | |
692 } | |
693 | |
694 g = gimple_build_assign (mf_cache_shift_decl_l, mf_cache_shift_decl); | |
695 gimple_seq_add_stmt (&seq, g); | |
696 | |
697 g = gimple_build_assign (mf_cache_mask_decl_l, mf_cache_mask_decl); | |
698 gimple_seq_add_stmt (&seq, g); | |
699 } | |
700 | |
701 /* Insert the check code in the THEN block. */ | |
702 gsi = gsi_start_bb (then_bb); | |
703 gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING); | |
704 | |
705 *instr_gsi = gsi_start_bb (join_bb); | |
706 } | |
707 | |
708 | |
709 /* Check whether the given decl, generally a VAR_DECL or PARM_DECL, is | |
710 eligible for instrumentation. For the mudflap1 pass, this implies | |
711 that it should be registered with the libmudflap runtime. For the | |
712 mudflap2 pass this means instrumenting an indirection operation with | |
713 respect to the object. | |
714 */ | |
715 static int | |
716 mf_decl_eligible_p (tree decl) | |
717 { | |
718 return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL) | |
719 /* The decl must have its address taken. In the case of | |
720 arrays, this flag is also set if the indexes are not | |
721 compile-time known valid constants. */ | |
722 /* XXX: not sufficient: return-by-value structs! */ | |
723 && TREE_ADDRESSABLE (decl) | |
724 /* The type of the variable must be complete. */ | |
725 && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl)) | |
726 /* The decl hasn't been decomposed somehow. */ | |
727 && !DECL_HAS_VALUE_EXPR_P (decl)); | |
728 } | |
729 | |
730 | |
731 static void | |
732 mf_xform_derefs_1 (gimple_stmt_iterator *iter, tree *tp, | |
733 location_t location, tree dirflag) | |
734 { | |
735 tree type, base, limit, addr, size, t; | |
736 | |
737 /* Don't instrument read operations. */ | |
738 if (dirflag == integer_zero_node && flag_mudflap_ignore_reads) | |
739 return; | |
740 | |
741 /* Don't instrument marked nodes. */ | |
742 if (mf_marked_p (*tp)) | |
743 return; | |
744 | |
745 t = *tp; | |
746 type = TREE_TYPE (t); | |
747 | |
748 if (type == error_mark_node) | |
749 return; | |
750 | |
751 size = TYPE_SIZE_UNIT (type); | |
752 | |
753 switch (TREE_CODE (t)) | |
754 { | |
755 case ARRAY_REF: | |
756 case COMPONENT_REF: | |
757 { | |
758 /* This is trickier than it may first appear. The reason is | |
759 that we are looking at expressions from the "inside out" at | |
760 this point. We may have a complex nested aggregate/array | |
761 expression (e.g. "a.b[i].c"), maybe with an indirection as | |
762 the leftmost operator ("p->a.b.d"), where instrumentation | |
763 is necessary. Or we may have an innocent "a.b.c" | |
764 expression that must not be instrumented. We need to | |
765 recurse all the way down the nesting structure to figure it | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
766 out: looking just at the outer node is not enough. */ |
0 | 767 tree var; |
768 int component_ref_only = (TREE_CODE (t) == COMPONENT_REF); | |
769 /* If we have a bitfield component reference, we must note the | |
770 innermost addressable object in ELT, from which we will | |
771 construct the byte-addressable bounds of the bitfield. */ | |
772 tree elt = NULL_TREE; | |
773 int bitfield_ref_p = (TREE_CODE (t) == COMPONENT_REF | |
774 && DECL_BIT_FIELD_TYPE (TREE_OPERAND (t, 1))); | |
775 | |
776 /* Iterate to the top of the ARRAY_REF/COMPONENT_REF | |
777 containment hierarchy to find the outermost VAR_DECL. */ | |
778 var = TREE_OPERAND (t, 0); | |
779 while (1) | |
780 { | |
781 if (bitfield_ref_p && elt == NULL_TREE | |
782 && (TREE_CODE (var) == ARRAY_REF | |
783 || TREE_CODE (var) == COMPONENT_REF)) | |
784 elt = var; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
785 |
0 | 786 if (TREE_CODE (var) == ARRAY_REF) |
787 { | |
788 component_ref_only = 0; | |
789 var = TREE_OPERAND (var, 0); | |
790 } | |
791 else if (TREE_CODE (var) == COMPONENT_REF) | |
792 var = TREE_OPERAND (var, 0); | |
793 else if (INDIRECT_REF_P (var)) | |
794 { | |
795 base = TREE_OPERAND (var, 0); | |
796 break; | |
797 } | |
798 else if (TREE_CODE (var) == VIEW_CONVERT_EXPR) | |
799 { | |
800 var = TREE_OPERAND (var, 0); | |
801 if (CONSTANT_CLASS_P (var) | |
802 && TREE_CODE (var) != STRING_CST) | |
803 return; | |
804 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
805 else |
0 | 806 { |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
807 gcc_assert (TREE_CODE (var) == VAR_DECL |
0 | 808 || TREE_CODE (var) == PARM_DECL |
809 || TREE_CODE (var) == RESULT_DECL | |
810 || TREE_CODE (var) == STRING_CST); | |
811 /* Don't instrument this access if the underlying | |
812 variable is not "eligible". This test matches | |
813 those arrays that have only known-valid indexes, | |
814 and thus are not labeled TREE_ADDRESSABLE. */ | |
815 if (! mf_decl_eligible_p (var) || component_ref_only) | |
816 return; | |
817 else | |
818 { | |
819 base = build1 (ADDR_EXPR, | |
820 build_pointer_type (TREE_TYPE (var)), var); | |
821 break; | |
822 } | |
823 } | |
824 } | |
825 | |
826 /* Handle the case of ordinary non-indirection structure | |
827 accesses. These have only nested COMPONENT_REF nodes (no | |
828 INDIRECT_REF), but pass through the above filter loop. | |
829 Note that it's possible for such a struct variable to match | |
830 the eligible_p test because someone else might take its | |
831 address sometime. */ | |
832 | |
833 /* We need special processing for bitfield components, because | |
834 their addresses cannot be taken. */ | |
835 if (bitfield_ref_p) | |
836 { | |
837 tree field = TREE_OPERAND (t, 1); | |
838 | |
839 if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST) | |
840 size = DECL_SIZE_UNIT (field); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
841 |
0 | 842 if (elt) |
843 elt = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (elt)), | |
844 elt); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
845 addr = fold_convert_loc (location, ptr_type_node, elt ? elt : base); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
846 addr = fold_build2_loc (location, POINTER_PLUS_EXPR, ptr_type_node, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
847 addr, fold_convert_loc (location, sizetype, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
848 byte_position (field))); |
0 | 849 } |
850 else | |
851 addr = build1 (ADDR_EXPR, build_pointer_type (type), t); | |
852 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
853 limit = fold_build2_loc (location, MINUS_EXPR, mf_uintptr_type, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
854 fold_build2_loc (location, PLUS_EXPR, mf_uintptr_type, |
0 | 855 convert (mf_uintptr_type, addr), |
856 size), | |
857 integer_one_node); | |
858 } | |
859 break; | |
860 | |
861 case INDIRECT_REF: | |
862 addr = TREE_OPERAND (t, 0); | |
863 base = addr; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
864 limit = fold_build2_loc (location, POINTER_PLUS_EXPR, ptr_type_node, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
865 fold_build2_loc (location, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
866 POINTER_PLUS_EXPR, ptr_type_node, base, |
0 | 867 size), |
868 size_int (-1)); | |
869 break; | |
870 | |
871 case TARGET_MEM_REF: | |
872 addr = tree_mem_ref_addr (ptr_type_node, t); | |
873 base = addr; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
874 limit = fold_build2_loc (location, POINTER_PLUS_EXPR, ptr_type_node, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
875 fold_build2_loc (location, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
876 POINTER_PLUS_EXPR, ptr_type_node, base, |
0 | 877 size), |
878 size_int (-1)); | |
879 break; | |
880 | |
881 case ARRAY_RANGE_REF: | |
882 warning (OPT_Wmudflap, | |
883 "mudflap checking not yet implemented for ARRAY_RANGE_REF"); | |
884 return; | |
885 | |
886 case BIT_FIELD_REF: | |
887 /* ??? merge with COMPONENT_REF code above? */ | |
888 { | |
889 tree ofs, rem, bpu; | |
890 | |
891 /* If we're not dereferencing something, then the access | |
892 must be ok. */ | |
893 if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF) | |
894 return; | |
895 | |
896 bpu = bitsize_int (BITS_PER_UNIT); | |
897 ofs = convert (bitsizetype, TREE_OPERAND (t, 2)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
898 rem = size_binop_loc (location, TRUNC_MOD_EXPR, ofs, bpu); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
899 ofs = fold_convert_loc (location, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
900 sizetype, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
901 size_binop_loc (location, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
902 TRUNC_DIV_EXPR, ofs, bpu)); |
0 | 903 |
904 size = convert (bitsizetype, TREE_OPERAND (t, 1)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
905 size = size_binop_loc (location, PLUS_EXPR, size, rem); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
906 size = size_binop_loc (location, CEIL_DIV_EXPR, size, bpu); |
0 | 907 size = convert (sizetype, size); |
908 | |
909 addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0); | |
910 addr = convert (ptr_type_node, addr); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
911 addr = fold_build2_loc (location, POINTER_PLUS_EXPR, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
912 ptr_type_node, addr, ofs); |
0 | 913 |
914 base = addr; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
915 limit = fold_build2_loc (location, POINTER_PLUS_EXPR, ptr_type_node, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
916 fold_build2_loc (location, |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
917 POINTER_PLUS_EXPR, ptr_type_node, |
0 | 918 base, size), |
919 size_int (-1)); | |
920 } | |
921 break; | |
922 | |
923 default: | |
924 return; | |
925 } | |
926 | |
927 mf_build_check_statement_for (base, limit, iter, location, dirflag); | |
928 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
929 /* Transform |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
930 1) Memory references. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
931 2) BUILTIN_ALLOCA calls. |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
932 */ |
0 | 933 static void |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
934 mf_xform_statements (void) |
0 | 935 { |
936 basic_block bb, next; | |
937 gimple_stmt_iterator i; | |
938 int saved_last_basic_block = last_basic_block; | |
939 enum gimple_rhs_class grhs_class; | |
940 | |
941 bb = ENTRY_BLOCK_PTR ->next_bb; | |
942 do | |
943 { | |
944 next = bb->next_bb; | |
945 for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) | |
946 { | |
947 gimple s = gsi_stmt (i); | |
948 | |
949 /* Only a few GIMPLE statements can reference memory. */ | |
950 switch (gimple_code (s)) | |
951 { | |
952 case GIMPLE_ASSIGN: | |
953 mf_xform_derefs_1 (&i, gimple_assign_lhs_ptr (s), | |
954 gimple_location (s), integer_one_node); | |
955 mf_xform_derefs_1 (&i, gimple_assign_rhs1_ptr (s), | |
956 gimple_location (s), integer_zero_node); | |
957 grhs_class = get_gimple_rhs_class (gimple_assign_rhs_code (s)); | |
958 if (grhs_class == GIMPLE_BINARY_RHS) | |
959 mf_xform_derefs_1 (&i, gimple_assign_rhs2_ptr (s), | |
960 gimple_location (s), integer_zero_node); | |
961 break; | |
962 | |
963 case GIMPLE_RETURN: | |
964 if (gimple_return_retval (s) != NULL_TREE) | |
965 { | |
966 mf_xform_derefs_1 (&i, gimple_return_retval_ptr (s), | |
967 gimple_location (s), | |
968 integer_zero_node); | |
969 } | |
970 break; | |
971 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
972 case GIMPLE_CALL: |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
973 { |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
974 tree fndecl = gimple_call_fndecl (s); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
975 if (fndecl && (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_ALLOCA)) |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
976 gimple_call_set_cannot_inline (s, true); |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
977 } |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
978 break; |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
979 |
0 | 980 default: |
981 ; | |
982 } | |
983 } | |
984 bb = next; | |
985 } | |
986 while (bb && bb->index <= saved_last_basic_block); | |
987 } | |
988 | |
989 /* ------------------------------------------------------------------------ */ | |
990 /* ADDR_EXPR transforms. Perform the declaration-related mudflap tree | |
991 transforms on the current function. | |
992 | |
993 This is the first part of the mudflap instrumentation. It works on | |
994 high-level GIMPLE because after lowering, all variables are moved out | |
995 of their BIND_EXPR binding context, and we lose liveness information | |
996 for the declarations we wish to instrument. */ | |
997 | |
998 static unsigned int | |
999 execute_mudflap_function_decls (void) | |
1000 { | |
1001 struct gimplify_ctx gctx; | |
1002 | |
1003 /* Don't instrument functions such as the synthetic constructor | |
1004 built during mudflap_finish_file. */ | |
1005 if (mf_marked_p (current_function_decl) || | |
1006 DECL_ARTIFICIAL (current_function_decl)) | |
1007 return 0; | |
1008 | |
1009 push_gimplify_context (&gctx); | |
1010 | |
1011 mf_xform_decls (gimple_body (current_function_decl), | |
1012 DECL_ARGUMENTS (current_function_decl)); | |
1013 | |
1014 pop_gimplify_context (NULL); | |
1015 return 0; | |
1016 } | |
1017 | |
1018 /* This struct is passed between mf_xform_decls to store state needed | |
1019 during the traversal searching for objects that have their | |
1020 addresses taken. */ | |
1021 struct mf_xform_decls_data | |
1022 { | |
1023 tree param_decls; | |
1024 }; | |
1025 | |
1026 | |
1027 /* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of | |
1028 _DECLs if appropriate. Arrange to call the __mf_register function | |
1029 now, and the __mf_unregister function later for each. Return the | |
1030 gimple sequence after synthesis. */ | |
1031 gimple_seq | |
1032 mx_register_decls (tree decl, gimple_seq seq, location_t location) | |
1033 { | |
1034 gimple_seq finally_stmts = NULL; | |
1035 gimple_stmt_iterator initially_stmts = gsi_start (seq); | |
1036 | |
1037 while (decl != NULL_TREE) | |
1038 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1039 if (mf_decl_eligible_p (decl) |
0 | 1040 /* Not already processed. */ |
1041 && ! mf_marked_p (decl) | |
1042 /* Automatic variable. */ | |
1043 && ! DECL_EXTERNAL (decl) | |
1044 && ! TREE_STATIC (decl)) | |
1045 { | |
1046 tree size = NULL_TREE, variable_name; | |
1047 gimple unregister_fncall, register_fncall; | |
1048 tree unregister_fncall_param, register_fncall_param; | |
1049 | |
1050 /* Variable-sized objects should have sizes already been | |
1051 gimplified when we got here. */ | |
1052 size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl))); | |
1053 gcc_assert (is_gimple_val (size)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1054 |
0 | 1055 |
1056 unregister_fncall_param = | |
1057 mf_mark (build1 (ADDR_EXPR, | |
1058 build_pointer_type (TREE_TYPE (decl)), | |
1059 decl)); | |
1060 /* __mf_unregister (&VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */ | |
1061 unregister_fncall = gimple_build_call (mf_unregister_fndecl, 3, | |
1062 unregister_fncall_param, | |
1063 size, | |
1064 build_int_cst (NULL_TREE, 3)); | |
1065 | |
1066 | |
1067 variable_name = mf_varname_tree (decl); | |
1068 register_fncall_param = | |
1069 mf_mark (build1 (ADDR_EXPR, | |
1070 build_pointer_type (TREE_TYPE (decl)), | |
1071 decl)); | |
1072 /* __mf_register (&VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, | |
1073 "name") */ | |
1074 register_fncall = gimple_build_call (mf_register_fndecl, 4, | |
1075 register_fncall_param, | |
1076 size, | |
1077 build_int_cst (NULL_TREE, 3), | |
1078 variable_name); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1079 |
0 | 1080 |
1081 /* Accumulate the two calls. */ | |
1082 gimple_set_location (register_fncall, location); | |
1083 gimple_set_location (unregister_fncall, location); | |
1084 | |
1085 /* Add the __mf_register call at the current appending point. */ | |
1086 if (gsi_end_p (initially_stmts)) | |
1087 { | |
1088 if (!DECL_ARTIFICIAL (decl)) | |
1089 warning (OPT_Wmudflap, | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1090 "mudflap cannot track %qE in stub function", |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1091 DECL_NAME (decl)); |
0 | 1092 } |
1093 else | |
1094 { | |
1095 gsi_insert_before (&initially_stmts, register_fncall, | |
1096 GSI_SAME_STMT); | |
1097 | |
1098 /* Accumulate the FINALLY piece. */ | |
1099 gimple_seq_add_stmt (&finally_stmts, unregister_fncall); | |
1100 } | |
1101 mf_mark (decl); | |
1102 } | |
1103 | |
1104 decl = TREE_CHAIN (decl); | |
1105 } | |
1106 | |
1107 /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */ | |
1108 if (finally_stmts != NULL) | |
1109 { | |
1110 gimple stmt = gimple_build_try (seq, finally_stmts, GIMPLE_TRY_FINALLY); | |
1111 gimple_seq new_seq = gimple_seq_alloc (); | |
1112 | |
1113 gimple_seq_add_stmt (&new_seq, stmt); | |
1114 return new_seq; | |
1115 } | |
1116 else | |
1117 return seq; | |
1118 } | |
1119 | |
1120 | |
1121 /* Process every variable mentioned in BIND_EXPRs. */ | |
1122 static tree | |
1123 mx_xfn_xform_decls (gimple_stmt_iterator *gsi, | |
1124 bool *handled_operands_p ATTRIBUTE_UNUSED, | |
1125 struct walk_stmt_info *wi) | |
1126 { | |
1127 struct mf_xform_decls_data *d = (struct mf_xform_decls_data *) wi->info; | |
1128 gimple stmt = gsi_stmt (*gsi); | |
1129 | |
1130 switch (gimple_code (stmt)) | |
1131 { | |
1132 case GIMPLE_BIND: | |
1133 { | |
1134 /* Process function parameters now (but only once). */ | |
1135 if (d->param_decls) | |
1136 { | |
1137 gimple_bind_set_body (stmt, | |
1138 mx_register_decls (d->param_decls, | |
1139 gimple_bind_body (stmt), | |
1140 gimple_location (stmt))); | |
1141 d->param_decls = NULL_TREE; | |
1142 } | |
1143 | |
1144 gimple_bind_set_body (stmt, | |
1145 mx_register_decls (gimple_bind_vars (stmt), | |
1146 gimple_bind_body (stmt), | |
1147 gimple_location (stmt))); | |
1148 } | |
1149 break; | |
1150 | |
1151 default: | |
1152 break; | |
1153 } | |
1154 | |
1155 return NULL_TREE; | |
1156 } | |
1157 | |
1158 /* Perform the object lifetime tracking mudflap transform on the given function | |
1159 tree. The tree is mutated in place, with possibly copied subtree nodes. | |
1160 | |
1161 For every auto variable declared, if its address is ever taken | |
1162 within the function, then supply its lifetime to the mudflap | |
1163 runtime with the __mf_register and __mf_unregister calls. | |
1164 */ | |
1165 | |
1166 static void | |
1167 mf_xform_decls (gimple_seq fnbody, tree fnparams) | |
1168 { | |
1169 struct mf_xform_decls_data d; | |
1170 struct walk_stmt_info wi; | |
1171 struct pointer_set_t *pset = pointer_set_create (); | |
1172 | |
1173 d.param_decls = fnparams; | |
1174 memset (&wi, 0, sizeof (wi)); | |
1175 wi.info = (void*) &d; | |
1176 wi.pset = pset; | |
1177 walk_gimple_seq (fnbody, mx_xfn_xform_decls, NULL, &wi); | |
1178 pointer_set_destroy (pset); | |
1179 } | |
1180 | |
1181 | |
1182 /* ------------------------------------------------------------------------ */ | |
1183 /* Externally visible mudflap functions. */ | |
1184 | |
1185 | |
1186 /* Mark and return the given tree node to prevent further mudflap | |
1187 transforms. */ | |
1188 static GTY ((param_is (union tree_node))) htab_t marked_trees = NULL; | |
1189 | |
1190 tree | |
1191 mf_mark (tree t) | |
1192 { | |
1193 void **slot; | |
1194 | |
1195 if (marked_trees == NULL) | |
1196 marked_trees = htab_create_ggc (31, htab_hash_pointer, htab_eq_pointer, | |
1197 NULL); | |
1198 | |
1199 slot = htab_find_slot (marked_trees, t, INSERT); | |
1200 *slot = t; | |
1201 return t; | |
1202 } | |
1203 | |
1204 int | |
1205 mf_marked_p (tree t) | |
1206 { | |
1207 void *entry; | |
1208 | |
1209 if (marked_trees == NULL) | |
1210 return 0; | |
1211 | |
1212 entry = htab_find (marked_trees, t); | |
1213 return (entry != NULL); | |
1214 } | |
1215 | |
1216 /* Remember given node as a static of some kind: global data, | |
1217 function-scope static, or an anonymous constant. Its assembler | |
1218 label is given. */ | |
1219 | |
1220 /* A list of globals whose incomplete declarations we encountered. | |
1221 Instead of emitting the __mf_register call for them here, it's | |
1222 delayed until program finish time. If they're still incomplete by | |
1223 then, warnings are emitted. */ | |
1224 | |
1225 static GTY (()) VEC(tree,gc) *deferred_static_decls; | |
1226 | |
1227 /* A list of statements for calling __mf_register() at startup time. */ | |
1228 static GTY (()) tree enqueued_call_stmt_chain; | |
1229 | |
1230 static void | |
1231 mudflap_register_call (tree obj, tree object_size, tree varname) | |
1232 { | |
1233 tree arg, call_stmt; | |
1234 | |
1235 arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj); | |
1236 arg = convert (ptr_type_node, arg); | |
1237 | |
1238 call_stmt = build_call_expr (mf_register_fndecl, 4, | |
1239 arg, | |
1240 convert (size_type_node, object_size), | |
1241 /* __MF_TYPE_STATIC */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1242 build_int_cst (NULL_TREE, 4), |
0 | 1243 varname); |
1244 | |
1245 append_to_statement_list (call_stmt, &enqueued_call_stmt_chain); | |
1246 } | |
1247 | |
1248 void | |
1249 mudflap_enqueue_decl (tree obj) | |
1250 { | |
1251 if (mf_marked_p (obj)) | |
1252 return; | |
1253 | |
1254 /* We don't need to process variable decls that are internally | |
1255 generated extern. If we did, we'd end up with warnings for them | |
1256 during mudflap_finish_file (). That would confuse the user, | |
1257 since the text would refer to variables that don't show up in the | |
1258 user's source code. */ | |
1259 if (DECL_P (obj) && DECL_EXTERNAL (obj) && DECL_ARTIFICIAL (obj)) | |
1260 return; | |
1261 | |
1262 VEC_safe_push (tree, gc, deferred_static_decls, obj); | |
1263 } | |
1264 | |
1265 | |
1266 void | |
1267 mudflap_enqueue_constant (tree obj) | |
1268 { | |
1269 tree object_size, varname; | |
1270 | |
1271 if (mf_marked_p (obj)) | |
1272 return; | |
1273 | |
1274 if (TREE_CODE (obj) == STRING_CST) | |
1275 object_size = build_int_cst (NULL_TREE, TREE_STRING_LENGTH (obj)); | |
1276 else | |
1277 object_size = size_in_bytes (TREE_TYPE (obj)); | |
1278 | |
1279 if (TREE_CODE (obj) == STRING_CST) | |
1280 varname = mf_build_string ("string literal"); | |
1281 else | |
1282 varname = mf_build_string ("constant"); | |
1283 | |
1284 mudflap_register_call (obj, object_size, varname); | |
1285 } | |
1286 | |
1287 | |
1288 /* Emit any file-wide instrumentation. */ | |
1289 void | |
1290 mudflap_finish_file (void) | |
1291 { | |
1292 tree ctor_statements = NULL_TREE; | |
1293 | |
1294 /* No need to continue when there were errors. */ | |
1295 if (errorcount != 0 || sorrycount != 0) | |
1296 return; | |
1297 | |
1298 /* Insert a call to __mf_init. */ | |
1299 { | |
1300 tree call2_stmt = build_call_expr (mf_init_fndecl, 0); | |
1301 append_to_statement_list (call2_stmt, &ctor_statements); | |
1302 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1303 |
0 | 1304 /* If appropriate, call __mf_set_options to pass along read-ignore mode. */ |
1305 if (flag_mudflap_ignore_reads) | |
1306 { | |
1307 tree arg = mf_build_string ("-ignore-reads"); | |
1308 tree call_stmt = build_call_expr (mf_set_options_fndecl, 1, arg); | |
1309 append_to_statement_list (call_stmt, &ctor_statements); | |
1310 } | |
1311 | |
1312 /* Process all enqueued object decls. */ | |
1313 if (deferred_static_decls) | |
1314 { | |
1315 size_t i; | |
1316 tree obj; | |
1317 for (i = 0; VEC_iterate (tree, deferred_static_decls, i, obj); i++) | |
1318 { | |
1319 gcc_assert (DECL_P (obj)); | |
1320 | |
1321 if (mf_marked_p (obj)) | |
1322 continue; | |
1323 | |
1324 /* Omit registration for static unaddressed objects. NB: | |
1325 Perform registration for non-static objects regardless of | |
1326 TREE_USED or TREE_ADDRESSABLE, because they may be used | |
1327 from other compilation units. */ | |
1328 if (! TREE_PUBLIC (obj) && ! TREE_ADDRESSABLE (obj)) | |
1329 continue; | |
1330 | |
1331 if (! COMPLETE_TYPE_P (TREE_TYPE (obj))) | |
1332 { | |
1333 warning (OPT_Wmudflap, | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1334 "mudflap cannot track unknown size extern %qE", |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1335 DECL_NAME (obj)); |
0 | 1336 continue; |
1337 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1338 |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1339 mudflap_register_call (obj, |
0 | 1340 size_in_bytes (TREE_TYPE (obj)), |
1341 mf_varname_tree (obj)); | |
1342 } | |
1343 | |
1344 VEC_truncate (tree, deferred_static_decls, 0); | |
1345 } | |
1346 | |
1347 /* Append all the enqueued registration calls. */ | |
1348 if (enqueued_call_stmt_chain) | |
1349 { | |
1350 append_to_statement_list (enqueued_call_stmt_chain, &ctor_statements); | |
1351 enqueued_call_stmt_chain = NULL_TREE; | |
1352 } | |
1353 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1354 cgraph_build_static_cdtor ('I', ctor_statements, |
0 | 1355 MAX_RESERVED_INIT_PRIORITY-1); |
1356 } | |
1357 | |
1358 | |
1359 static bool | |
1360 gate_mudflap (void) | |
1361 { | |
1362 return flag_mudflap != 0; | |
1363 } | |
1364 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1365 struct gimple_opt_pass pass_mudflap_1 = |
0 | 1366 { |
1367 { | |
1368 GIMPLE_PASS, | |
1369 "mudflap1", /* name */ | |
1370 gate_mudflap, /* gate */ | |
1371 execute_mudflap_function_decls, /* execute */ | |
1372 NULL, /* sub */ | |
1373 NULL, /* next */ | |
1374 0, /* static_pass_number */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1375 TV_NONE, /* tv_id */ |
0 | 1376 PROP_gimple_any, /* properties_required */ |
1377 0, /* properties_provided */ | |
1378 0, /* properties_destroyed */ | |
1379 0, /* todo_flags_start */ | |
1380 TODO_dump_func /* todo_flags_finish */ | |
1381 } | |
1382 }; | |
1383 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1384 struct gimple_opt_pass pass_mudflap_2 = |
0 | 1385 { |
1386 { | |
1387 GIMPLE_PASS, | |
1388 "mudflap2", /* name */ | |
1389 gate_mudflap, /* gate */ | |
1390 execute_mudflap_function_ops, /* execute */ | |
1391 NULL, /* sub */ | |
1392 NULL, /* next */ | |
1393 0, /* static_pass_number */ | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1394 TV_NONE, /* tv_id */ |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1395 PROP_ssa | PROP_cfg | PROP_gimple_leh,/* properties_required */ |
0 | 1396 0, /* properties_provided */ |
1397 0, /* properties_destroyed */ | |
1398 0, /* todo_flags_start */ | |
1399 TODO_verify_flow | TODO_verify_stmts | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
1400 | TODO_dump_func | TODO_update_ssa /* todo_flags_finish */ |
0 | 1401 } |
1402 }; | |
1403 | |
1404 #include "gt-tree-mudflap.h" |