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