OSDN Git Service

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