xref: /openbsd-src/gnu/gcc/gcc/tree-mudflap.c (revision 404b540a9034ac75a6199ad1a32d1bbc7a0d4210)
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 (&register_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