OSDN Git Service

gcc/fortran:
[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,                                           \
337                        tree_cons (0, arg1,                              \
338                                   tree_cons (0, arg2,                   \
339                                               tree_cons (0, arg3,       \
340                                                          void_list_node))))
341 #define build_function_type_4(rtype, arg1, arg2, arg3, arg4)            \
342   build_function_type (rtype,                                           \
343                        tree_cons (0, arg1,                              \
344                                   tree_cons (0, arg2,                   \
345                                              tree_cons (0, arg3,        \
346                                                         tree_cons (0, arg4, \
347                                                                    void_list_node)))))
348
349 /* Initialize the global tree nodes that correspond to mf-runtime.h
350    declarations.  */
351 void
352 mudflap_init (void)
353 {
354   static bool done = false;
355   tree mf_const_string_type;
356   tree mf_cache_array_type;
357   tree mf_check_register_fntype;
358   tree mf_unregister_fntype;
359   tree mf_init_fntype;
360   tree mf_set_options_fntype;
361
362   if (done)
363     return;
364   done = true;
365
366   mf_uintptr_type = lang_hooks.types.type_for_mode (ptr_mode,
367                                                     /*unsignedp=*/true);
368   mf_const_string_type
369     = build_pointer_type (build_qualified_type
370                           (char_type_node, TYPE_QUAL_CONST));
371
372   mf_cache_struct_type = mf_make_mf_cache_struct_type (mf_uintptr_type);
373   mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type);
374   mf_cache_array_type = build_array_type (mf_cache_struct_type, 0);
375   mf_check_register_fntype =
376     build_function_type_4 (void_type_node, ptr_type_node, size_type_node,
377                            integer_type_node, mf_const_string_type);
378   mf_unregister_fntype =
379     build_function_type_3 (void_type_node, ptr_type_node, size_type_node,
380                            integer_type_node);
381   mf_init_fntype =
382     build_function_type_0 (void_type_node);
383   mf_set_options_fntype =
384     build_function_type_1 (integer_type_node, mf_const_string_type);
385
386   mf_cache_array_decl = mf_make_builtin (VAR_DECL, "__mf_lookup_cache",
387                                          mf_cache_array_type);
388   mf_cache_shift_decl = mf_make_builtin (VAR_DECL, "__mf_lc_shift",
389                                          unsigned_char_type_node);
390   mf_cache_mask_decl = mf_make_builtin (VAR_DECL, "__mf_lc_mask",
391                                         mf_uintptr_type);
392   /* Don't process these in mudflap_enqueue_decl, should they come by
393      there for some reason.  */
394   mf_mark (mf_cache_array_decl);
395   mf_mark (mf_cache_shift_decl);
396   mf_mark (mf_cache_mask_decl);
397   mf_check_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_check",
398                                      mf_check_register_fntype);
399   mf_register_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_register",
400                                         mf_check_register_fntype);
401   mf_unregister_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_unregister",
402                                           mf_unregister_fntype);
403   mf_init_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_init",
404                                     mf_init_fntype);
405   mf_set_options_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_set_options",
406                                            mf_set_options_fntype);
407 }
408 #undef build_function_type_4
409 #undef build_function_type_3
410 #undef build_function_type_1
411 #undef build_function_type_0
412
413
414 /* ------------------------------------------------------------------------ */
415 /* Memory reference transforms. Perform the mudflap indirection-related
416    tree transforms on the current function.
417
418    This is the second part of the mudflap instrumentation.  It works on
419    low-level GIMPLE using the CFG, because we want to run this pass after
420    tree optimizations have been performed, but we have to preserve the CFG
421    for expansion from trees to RTL.  */
422
423 static unsigned int
424 execute_mudflap_function_ops (void)
425 {
426   /* Don't instrument functions such as the synthetic constructor
427      built during mudflap_finish_file.  */
428   if (mf_marked_p (current_function_decl) ||
429       DECL_ARTIFICIAL (current_function_decl))
430     return 0;
431
432   push_gimplify_context ();
433
434   /* In multithreaded mode, don't cache the lookup cache parameters.  */
435   if (! flag_mudflap_threads)
436     mf_decl_cache_locals ();
437
438   mf_xform_derefs ();
439
440   if (! flag_mudflap_threads)
441     mf_decl_clear_locals ();
442
443   pop_gimplify_context (NULL);
444   return 0;
445 }
446
447 /* Create and initialize local shadow variables for the lookup cache
448    globals.  Put their decls in the *_l globals for use by
449    mf_build_check_statement_for.  */
450
451 static void
452 mf_decl_cache_locals (void)
453 {
454   tree t, shift_init_stmts, mask_init_stmts;
455   tree_stmt_iterator tsi;
456
457   /* Build the cache vars.  */
458   mf_cache_shift_decl_l
459     = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_shift_decl),
460                                "__mf_lookup_shift_l"));
461
462   mf_cache_mask_decl_l
463     = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_mask_decl),
464                                "__mf_lookup_mask_l"));
465
466   /* Build initialization nodes for the cache vars.  We just load the
467      globals into the cache variables.  */
468   t = build_gimple_modify_stmt (mf_cache_shift_decl_l, mf_cache_shift_decl);
469   SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
470   gimplify_to_stmt_list (&t);
471   shift_init_stmts = t;
472
473   t = build_gimple_modify_stmt (mf_cache_mask_decl_l, mf_cache_mask_decl);
474   SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
475   gimplify_to_stmt_list (&t);
476   mask_init_stmts = t;
477
478   /* Anticipating multiple entry points, we insert the cache vars
479      initializers in each successor of the ENTRY_BLOCK_PTR.  */
480   for (tsi = tsi_start (shift_init_stmts);
481        ! tsi_end_p (tsi);
482        tsi_next (&tsi))
483     insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
484
485   for (tsi = tsi_start (mask_init_stmts);
486        ! tsi_end_p (tsi);
487        tsi_next (&tsi))
488     insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
489   bsi_commit_edge_inserts ();
490 }
491
492
493 static void
494 mf_decl_clear_locals (void)
495 {
496   /* Unset local shadows.  */
497   mf_cache_shift_decl_l = NULL_TREE;
498   mf_cache_mask_decl_l = NULL_TREE;
499 }
500
501 static void
502 mf_build_check_statement_for (tree base, tree limit,
503                               block_stmt_iterator *instr_bsi,
504                               location_t *locus, tree dirflag)
505 {
506   tree_stmt_iterator head, tsi;
507   block_stmt_iterator bsi;
508   basic_block cond_bb, then_bb, join_bb;
509   edge e;
510   tree cond, t, u, v;
511   tree mf_base;
512   tree mf_elem;
513   tree mf_limit;
514
515   /* We first need to split the current basic block, and start altering
516      the CFG.  This allows us to insert the statements we're about to
517      construct into the right basic blocks.  */
518
519   cond_bb = bb_for_stmt (bsi_stmt (*instr_bsi));
520   bsi = *instr_bsi;
521   bsi_prev (&bsi);
522   if (! bsi_end_p (bsi))
523     e = split_block (cond_bb, bsi_stmt (bsi));
524   else
525     e = split_block_after_labels (cond_bb);
526   cond_bb = e->src;
527   join_bb = e->dest;
528
529   /* A recap at this point: join_bb is the basic block at whose head
530      is the gimple statement for which this check expression is being
531      built.  cond_bb is the (possibly new, synthetic) basic block the
532      end of which will contain the cache-lookup code, and a
533      conditional that jumps to the cache-miss code or, much more
534      likely, over to join_bb.  */
535
536   /* Create the bb that contains the cache-miss fallback block (mf_check).  */
537   then_bb = create_empty_bb (cond_bb);
538   make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
539   make_single_succ_edge (then_bb, join_bb, EDGE_FALLTHRU);
540
541   /* Mark the pseudo-fallthrough edge from cond_bb to join_bb.  */
542   e = find_edge (cond_bb, join_bb);
543   e->flags = EDGE_FALSE_VALUE;
544   e->count = cond_bb->count;
545   e->probability = REG_BR_PROB_BASE;
546
547   /* Update dominance info.  Note that bb_join's data was
548      updated by split_block.  */
549   if (dom_info_available_p (CDI_DOMINATORS))
550     {
551       set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
552       set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb);
553     }
554
555   /* Build our local variables.  */
556   mf_elem = create_tmp_var (mf_cache_structptr_type, "__mf_elem");
557   mf_base = create_tmp_var (mf_uintptr_type, "__mf_base");
558   mf_limit = create_tmp_var (mf_uintptr_type, "__mf_limit");
559
560   /* Build: __mf_base = (uintptr_t) <base address expression>.  */
561   t = build_gimple_modify_stmt (mf_base,
562                                 fold_convert (mf_uintptr_type,
563                                               unshare_expr (base)));
564   SET_EXPR_LOCUS (t, locus);
565   gimplify_to_stmt_list (&t);
566   head = tsi_start (t);
567   tsi = tsi_last (t);
568
569   /* Build: __mf_limit = (uintptr_t) <limit address expression>.  */
570   t = build_gimple_modify_stmt (mf_limit,
571                                 fold_convert (mf_uintptr_type,
572                                               unshare_expr (limit)));
573   SET_EXPR_LOCUS (t, locus);
574   gimplify_to_stmt_list (&t);
575   tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
576
577   /* Build: __mf_elem = &__mf_lookup_cache [(__mf_base >> __mf_shift)
578                                             & __mf_mask].  */
579   t = build2 (RSHIFT_EXPR, mf_uintptr_type, mf_base,
580               flag_mudflap_threads ? mf_cache_shift_decl
581                : mf_cache_shift_decl_l);
582   t = build2 (BIT_AND_EXPR, mf_uintptr_type, t,
583               flag_mudflap_threads ? mf_cache_mask_decl
584                : mf_cache_mask_decl_l);
585   t = build4 (ARRAY_REF,
586               TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
587               mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
588   t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
589   t = build_gimple_modify_stmt (mf_elem, t);
590   SET_EXPR_LOCUS (t, locus);
591   gimplify_to_stmt_list (&t);
592   tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
593
594   /* Quick validity check.
595
596      if (__mf_elem->low > __mf_base
597          || (__mf_elem_high < __mf_limit))
598         {
599           __mf_check ();
600           ... and only if single-threaded:
601           __mf_lookup_shift_1 = f...;
602           __mf_lookup_mask_l = ...;
603         }
604
605      It is expected that this body of code is rarely executed so we mark
606      the edge to the THEN clause of the conditional jump as unlikely.  */
607
608   /* Construct t <-- '__mf_elem->low  > __mf_base'.  */
609   t = build3 (COMPONENT_REF, mf_uintptr_type,
610               build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
611               TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
612   t = build2 (GT_EXPR, boolean_type_node, t, mf_base);
613
614   /* Construct '__mf_elem->high < __mf_limit'.
615
616      First build:
617         1) u <--  '__mf_elem->high'
618         2) v <--  '__mf_limit'.
619
620      Then build 'u <-- (u < v).  */
621
622   u = build3 (COMPONENT_REF, mf_uintptr_type,
623               build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
624               TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
625
626   v = mf_limit;
627
628   u = build2 (LT_EXPR, boolean_type_node, u, v);
629
630   /* Build the composed conditional: t <-- 't || u'.  Then store the
631      result of the evaluation of 't' in a temporary variable which we
632      can use as the condition for the conditional jump.  */
633   t = build2 (TRUTH_OR_EXPR, boolean_type_node, t, u);
634   cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
635   t = build_gimple_modify_stmt (cond, t);
636   gimplify_to_stmt_list (&t);
637   tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
638
639   /* Build the conditional jump.  'cond' is just a temporary so we can
640      simply build a void COND_EXPR.  We do need labels in both arms though.  */
641   t = build3 (COND_EXPR, void_type_node, cond, NULL_TREE, NULL_TREE);
642   SET_EXPR_LOCUS (t, locus);
643   tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
644
645   /* At this point, after so much hard work, we have only constructed
646      the conditional jump,
647
648      if (__mf_elem->low > __mf_base
649          || (__mf_elem_high < __mf_limit))
650
651      The lowered GIMPLE tree representing this code is in the statement
652      list starting at 'head'.
653
654      We can insert this now in the current basic block, i.e. the one that
655      the statement we're instrumenting was originally in.  */
656   bsi = bsi_last (cond_bb);
657   for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
658     bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
659
660   /*  Now build up the body of the cache-miss handling:
661
662      __mf_check();
663      refresh *_l vars.
664
665      This is the body of the conditional.  */
666
667   u = mf_file_function_line_tree (locus == NULL ? UNKNOWN_LOCATION : *locus);
668   /* NB: we pass the overall [base..limit] range to mf_check.  */
669   v = fold_build2 (PLUS_EXPR, integer_type_node,
670                    fold_build2 (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base),
671                    integer_one_node);
672   t = build_call_expr (mf_check_fndecl, 4, mf_base, v, dirflag, u);
673   gimplify_to_stmt_list (&t);
674   head = tsi_start (t);
675   tsi = tsi_last (t);
676
677   if (! flag_mudflap_threads)
678     {
679       t = build_gimple_modify_stmt (mf_cache_shift_decl_l,
680                                     mf_cache_shift_decl);
681       tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
682
683       t = build_gimple_modify_stmt (mf_cache_mask_decl_l,
684                                     mf_cache_mask_decl);
685       tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
686     }
687
688   /* Insert the check code in the THEN block.  */
689   bsi = bsi_start (then_bb);
690   for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
691     bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
692
693   *instr_bsi = bsi_start (join_bb);
694 }
695
696
697 /* Check whether the given decl, generally a VAR_DECL or PARM_DECL, is
698    eligible for instrumentation.  For the mudflap1 pass, this implies
699    that it should be registered with the libmudflap runtime.  For the
700    mudflap2 pass this means instrumenting an indirection operation with
701    respect to the object.
702 */
703 static int
704 mf_decl_eligible_p (tree decl)
705 {
706   return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
707           /* The decl must have its address taken.  In the case of
708              arrays, this flag is also set if the indexes are not
709              compile-time known valid constants.  */
710           /* XXX: not sufficient: return-by-value structs! */
711           && TREE_ADDRESSABLE (decl)
712           /* The type of the variable must be complete.  */
713           && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
714           /* The decl hasn't been decomposed somehow.  */
715           && !DECL_HAS_VALUE_EXPR_P (decl));
716 }
717
718
719 static void
720 mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
721                    location_t *locus, tree dirflag)
722 {
723   tree type, base, limit, addr, size, t;
724
725   /* Don't instrument read operations.  */
726   if (dirflag == integer_zero_node && flag_mudflap_ignore_reads)
727     return;
728
729   /* Don't instrument marked nodes.  */
730   if (mf_marked_p (*tp))
731     return;
732
733   t = *tp;
734   type = TREE_TYPE (t);
735
736   if (type == error_mark_node)
737     return;
738
739   size = TYPE_SIZE_UNIT (type);
740
741   switch (TREE_CODE (t))
742     {
743     case ARRAY_REF:
744     case COMPONENT_REF:
745       {
746         /* This is trickier than it may first appear.  The reason is
747            that we are looking at expressions from the "inside out" at
748            this point.  We may have a complex nested aggregate/array
749            expression (e.g. "a.b[i].c"), maybe with an indirection as
750            the leftmost operator ("p->a.b.d"), where instrumentation
751            is necessary.  Or we may have an innocent "a.b.c"
752            expression that must not be instrumented.  We need to
753            recurse all the way down the nesting structure to figure it
754            out: looking just at the outer node is not enough.  */          
755         tree var;
756         int component_ref_only = (TREE_CODE (t) == COMPONENT_REF);
757         /* If we have a bitfield component reference, we must note the
758            innermost addressable object in ELT, from which we will
759            construct the byte-addressable bounds of the bitfield.  */
760         tree elt = NULL_TREE;
761         int bitfield_ref_p = (TREE_CODE (t) == COMPONENT_REF
762                               && DECL_BIT_FIELD_TYPE (TREE_OPERAND (t, 1)));
763
764         /* Iterate to the top of the ARRAY_REF/COMPONENT_REF
765            containment hierarchy to find the outermost VAR_DECL.  */
766         var = TREE_OPERAND (t, 0);
767         while (1)
768           {
769             if (bitfield_ref_p && elt == NULL_TREE
770                 && (TREE_CODE (var) == ARRAY_REF
771                     || TREE_CODE (var) == COMPONENT_REF))
772               elt = var;
773         
774             if (TREE_CODE (var) == ARRAY_REF)
775               {
776                 component_ref_only = 0;
777                 var = TREE_OPERAND (var, 0);
778               }
779             else if (TREE_CODE (var) == COMPONENT_REF)
780               var = TREE_OPERAND (var, 0);
781             else if (INDIRECT_REF_P (var))
782               {
783                 base = TREE_OPERAND (var, 0);
784                 break;
785               }
786             else 
787               {
788                 gcc_assert (TREE_CODE (var) == VAR_DECL 
789                             || TREE_CODE (var) == PARM_DECL
790                             || TREE_CODE (var) == RESULT_DECL
791                             || TREE_CODE (var) == STRING_CST);
792                 /* Don't instrument this access if the underlying
793                    variable is not "eligible".  This test matches
794                    those arrays that have only known-valid indexes,
795                    and thus are not labeled TREE_ADDRESSABLE.  */
796                 if (! mf_decl_eligible_p (var) || component_ref_only)
797                   return;
798                 else
799                   {
800                     base = build1 (ADDR_EXPR,
801                                    build_pointer_type (TREE_TYPE (var)), var);
802                     break;
803                   }
804               }
805           }
806
807         /* Handle the case of ordinary non-indirection structure
808            accesses.  These have only nested COMPONENT_REF nodes (no
809            INDIRECT_REF), but pass through the above filter loop.
810            Note that it's possible for such a struct variable to match
811            the eligible_p test because someone else might take its
812            address sometime.  */
813
814         /* We need special processing for bitfield components, because
815            their addresses cannot be taken.  */
816         if (bitfield_ref_p)
817           {
818             tree field = TREE_OPERAND (t, 1);
819
820             if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST)
821               size = DECL_SIZE_UNIT (field);
822             
823             if (elt)
824               elt = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (elt)),
825                             elt);
826             addr = fold_convert (ptr_type_node, elt ? elt : base);
827             addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
828                                 addr, fold_convert (sizetype,
829                                                     byte_position (field)));
830           }
831         else
832           addr = build1 (ADDR_EXPR, build_pointer_type (type), t);
833
834         limit = fold_build2 (MINUS_EXPR, mf_uintptr_type,
835                              fold_build2 (PLUS_EXPR, mf_uintptr_type,
836                                           convert (mf_uintptr_type, addr),
837                                           size),
838                              integer_one_node);
839       }
840       break;
841
842     case INDIRECT_REF:
843       addr = TREE_OPERAND (t, 0);
844       base = addr;
845       limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
846                            fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, base,
847                                         size),
848                            size_int (-1));
849       break;
850
851     case TARGET_MEM_REF:
852       addr = tree_mem_ref_addr (ptr_type_node, t);
853       base = addr;
854       limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
855                            fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, base,
856                                         size),
857                            size_int (-1));
858       break;
859
860     case ARRAY_RANGE_REF:
861       warning (0, "mudflap checking not yet implemented for ARRAY_RANGE_REF");
862       return;
863
864     case BIT_FIELD_REF:
865       /* ??? merge with COMPONENT_REF code above? */
866       {
867         tree ofs, rem, bpu;
868
869         /* If we're not dereferencing something, then the access
870            must be ok.  */
871         if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
872           return;
873
874         bpu = bitsize_int (BITS_PER_UNIT);
875         ofs = convert (bitsizetype, TREE_OPERAND (t, 2));
876         rem = size_binop (TRUNC_MOD_EXPR, ofs, bpu);
877         ofs = fold_convert (sizetype, size_binop (TRUNC_DIV_EXPR, ofs, bpu));
878
879         size = convert (bitsizetype, TREE_OPERAND (t, 1));
880         size = size_binop (PLUS_EXPR, size, rem);
881         size = size_binop (CEIL_DIV_EXPR, size, bpu);
882         size = convert (sizetype, size);
883
884         addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
885         addr = convert (ptr_type_node, addr);
886         addr = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node, addr, ofs);
887
888         base = addr;
889         limit = fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
890                              fold_build2 (POINTER_PLUS_EXPR, ptr_type_node,
891                                            base, size),
892                              size_int (-1));
893       }
894       break;
895
896     default:
897       return;
898     }
899
900   mf_build_check_statement_for (base, limit, iter, locus, dirflag);
901 }
902
903 static void
904 mf_xform_derefs (void)
905 {
906   basic_block bb, next;
907   block_stmt_iterator i;
908   int saved_last_basic_block = last_basic_block;
909
910   bb = ENTRY_BLOCK_PTR ->next_bb;
911   do
912     {
913       next = bb->next_bb;
914       for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
915         {
916           tree s = bsi_stmt (i);
917
918           /* Only a few GIMPLE statements can reference memory.  */
919           switch (TREE_CODE (s))
920             {
921             case GIMPLE_MODIFY_STMT:
922               mf_xform_derefs_1 (&i, &GIMPLE_STMT_OPERAND (s, 0),
923                                  EXPR_LOCUS (s), integer_one_node);
924               mf_xform_derefs_1 (&i, &GIMPLE_STMT_OPERAND (s, 1),
925                                  EXPR_LOCUS (s), integer_zero_node);
926               break;
927
928             case RETURN_EXPR:
929               if (TREE_OPERAND (s, 0) != NULL_TREE)
930                 {
931                   if (TREE_CODE (TREE_OPERAND (s, 0)) == GIMPLE_MODIFY_STMT)
932                     mf_xform_derefs_1 (&i, &GIMPLE_STMT_OPERAND
933                                              (TREE_OPERAND (s, 0), 1),
934                                        EXPR_LOCUS (s), integer_zero_node);
935                   else
936                     mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
937                                        integer_zero_node);
938                 }
939               break;
940
941             default:
942               ;
943             }
944         }
945       bb = next;
946     }
947   while (bb && bb->index <= saved_last_basic_block);
948 }
949
950 /* ------------------------------------------------------------------------ */
951 /* ADDR_EXPR transforms.  Perform the declaration-related mudflap tree
952    transforms on the current function.
953
954    This is the first part of the mudflap instrumentation.  It works on
955    high-level GIMPLE because after lowering, all variables are moved out
956    of their BIND_EXPR binding context, and we lose liveness information
957    for the declarations we wish to instrument.  */
958
959 static unsigned int
960 execute_mudflap_function_decls (void)
961 {
962   /* Don't instrument functions such as the synthetic constructor
963      built during mudflap_finish_file.  */
964   if (mf_marked_p (current_function_decl) ||
965       DECL_ARTIFICIAL (current_function_decl))
966     return 0;
967
968   push_gimplify_context ();
969
970   mf_xform_decls (DECL_SAVED_TREE (current_function_decl),
971                   DECL_ARGUMENTS (current_function_decl));
972
973   pop_gimplify_context (NULL);
974   return 0;
975 }
976
977 /* This struct is passed between mf_xform_decls to store state needed
978    during the traversal searching for objects that have their
979    addresses taken.  */
980 struct mf_xform_decls_data
981 {
982   tree param_decls;
983 };
984
985
986 /* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of
987    _DECLs if appropriate.  Arrange to call the __mf_register function
988    now, and the __mf_unregister function later for each.  */
989 static void
990 mx_register_decls (tree decl, tree *stmt_list)
991 {
992   tree finally_stmts = NULL_TREE;
993   tree_stmt_iterator initially_stmts = tsi_start (*stmt_list);
994
995   while (decl != NULL_TREE)
996     {
997       if (mf_decl_eligible_p (decl) 
998           /* Not already processed.  */
999           && ! mf_marked_p (decl)
1000           /* Automatic variable.  */
1001           && ! DECL_EXTERNAL (decl)
1002           && ! TREE_STATIC (decl))
1003         {
1004           tree size = NULL_TREE, variable_name;
1005           tree unregister_fncall, unregister_fncall_param;
1006           tree register_fncall, register_fncall_param;
1007
1008           size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
1009
1010
1011           unregister_fncall_param =
1012             convert (ptr_type_node,
1013                      mf_mark (build1 (ADDR_EXPR,
1014                                       build_pointer_type (TREE_TYPE (decl)),
1015                                       decl)));
1016           /* __mf_unregister (&VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
1017           unregister_fncall = build_call_expr (mf_unregister_fndecl, 3,
1018                                                unregister_fncall_param,
1019                                                size,
1020                                                build_int_cst (NULL_TREE, 3));
1021
1022
1023           variable_name = mf_varname_tree (decl);
1024           register_fncall_param =
1025             convert (ptr_type_node,
1026                      mf_mark (build1 (ADDR_EXPR,
1027                                       build_pointer_type (TREE_TYPE (decl)),
1028                                       decl)));
1029           /* __mf_register (&VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK,
1030                             "name") */
1031           register_fncall = build_call_expr (mf_register_fndecl, 4,
1032                                              register_fncall_param,
1033                                              size,
1034                                              build_int_cst (NULL_TREE, 3),
1035                                              variable_name);
1036
1037
1038           /* Accumulate the two calls.  */
1039           /* ??? Set EXPR_LOCATION.  */
1040           gimplify_stmt (&register_fncall);
1041           gimplify_stmt (&unregister_fncall);
1042
1043           /* Add the __mf_register call at the current appending point.  */
1044           if (tsi_end_p (initially_stmts))
1045             warning (0, "mudflap cannot track %qs in stub function",
1046                      IDENTIFIER_POINTER (DECL_NAME (decl)));
1047           else
1048             {
1049               tsi_link_before (&initially_stmts, register_fncall,
1050                                TSI_SAME_STMT);
1051
1052               /* Accumulate the FINALLY piece.  */
1053               append_to_statement_list (unregister_fncall, &finally_stmts);
1054             }
1055           mf_mark (decl);
1056         }
1057
1058       decl = TREE_CHAIN (decl);
1059     }
1060
1061   /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
1062   if (finally_stmts != NULL_TREE)
1063     {
1064       tree t = build2 (TRY_FINALLY_EXPR, void_type_node,
1065                        *stmt_list, finally_stmts);
1066       *stmt_list = NULL;
1067       append_to_statement_list (t, stmt_list);
1068     }
1069 }
1070
1071
1072 /* Process every variable mentioned in BIND_EXPRs.  */
1073 static tree
1074 mx_xfn_xform_decls (tree *t, int *continue_p, void *data)
1075 {
1076   struct mf_xform_decls_data* d = (struct mf_xform_decls_data*) data;
1077
1078   if (*t == NULL_TREE || *t == error_mark_node)
1079     {
1080       *continue_p = 0;
1081       return NULL_TREE;
1082     }
1083
1084   *continue_p = 1;
1085
1086   switch (TREE_CODE (*t))
1087     {
1088     case BIND_EXPR:
1089       {
1090         /* Process function parameters now (but only once).  */
1091         mx_register_decls (d->param_decls, &BIND_EXPR_BODY (*t));
1092         d->param_decls = NULL_TREE;
1093
1094         mx_register_decls (BIND_EXPR_VARS (*t), &BIND_EXPR_BODY (*t));
1095       }
1096       break;
1097
1098     default:
1099       break;
1100     }
1101
1102   return NULL_TREE;
1103 }
1104
1105 /* Perform the object lifetime tracking mudflap transform on the given function
1106    tree.  The tree is mutated in place, with possibly copied subtree nodes.
1107
1108    For every auto variable declared, if its address is ever taken
1109    within the function, then supply its lifetime to the mudflap
1110    runtime with the __mf_register and __mf_unregister calls.
1111 */
1112
1113 static void
1114 mf_xform_decls (tree fnbody, tree fnparams)
1115 {
1116   struct mf_xform_decls_data d;
1117   d.param_decls = fnparams;
1118   walk_tree_without_duplicates (&fnbody, mx_xfn_xform_decls, &d);
1119 }
1120
1121
1122 /* ------------------------------------------------------------------------ */
1123 /* Externally visible mudflap functions.  */
1124
1125
1126 /* Mark and return the given tree node to prevent further mudflap
1127    transforms.  */
1128 static GTY ((param_is (union tree_node))) htab_t marked_trees = NULL;
1129
1130 tree
1131 mf_mark (tree t)
1132 {
1133   void **slot;
1134
1135   if (marked_trees == NULL)
1136     marked_trees = htab_create_ggc (31, htab_hash_pointer, htab_eq_pointer,
1137                                     NULL);
1138
1139   slot = htab_find_slot (marked_trees, t, INSERT);
1140   *slot = t;
1141   return t;
1142 }
1143
1144 int
1145 mf_marked_p (tree t)
1146 {
1147   void *entry;
1148
1149   if (marked_trees == NULL)
1150     return 0;
1151
1152   entry = htab_find (marked_trees, t);
1153   return (entry != NULL);
1154 }
1155
1156 /* Remember given node as a static of some kind: global data,
1157    function-scope static, or an anonymous constant.  Its assembler
1158    label is given.  */
1159
1160 /* A list of globals whose incomplete declarations we encountered.
1161    Instead of emitting the __mf_register call for them here, it's
1162    delayed until program finish time.  If they're still incomplete by
1163    then, warnings are emitted.  */
1164
1165 static GTY (()) VEC(tree,gc) *deferred_static_decls;
1166
1167 /* A list of statements for calling __mf_register() at startup time.  */
1168 static GTY (()) tree enqueued_call_stmt_chain;
1169
1170 static void
1171 mudflap_register_call (tree obj, tree object_size, tree varname)
1172 {
1173   tree arg, call_stmt;
1174
1175   arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj);
1176   arg = convert (ptr_type_node, arg);
1177
1178   call_stmt = build_call_expr (mf_register_fndecl, 4,
1179                                arg,
1180                                convert (size_type_node, object_size),
1181                                /* __MF_TYPE_STATIC */
1182                                build_int_cst (NULL_TREE, 4), 
1183                                varname);
1184
1185   append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
1186 }
1187
1188 void
1189 mudflap_enqueue_decl (tree obj)
1190 {
1191   if (mf_marked_p (obj))
1192     return;
1193
1194   /* We don't need to process variable decls that are internally
1195      generated extern.  If we did, we'd end up with warnings for them
1196      during mudflap_finish_file ().  That would confuse the user,
1197      since the text would refer to variables that don't show up in the
1198      user's source code.  */
1199   if (DECL_P (obj) && DECL_EXTERNAL (obj) && DECL_ARTIFICIAL (obj))
1200     return;
1201
1202   VEC_safe_push (tree, gc, deferred_static_decls, obj);
1203 }
1204
1205
1206 void
1207 mudflap_enqueue_constant (tree obj)
1208 {
1209   tree object_size, varname;
1210
1211   if (mf_marked_p (obj))
1212     return;
1213
1214   if (TREE_CODE (obj) == STRING_CST)
1215     object_size = build_int_cst (NULL_TREE, TREE_STRING_LENGTH (obj));
1216   else
1217     object_size = size_in_bytes (TREE_TYPE (obj));
1218
1219   if (TREE_CODE (obj) == STRING_CST)
1220     varname = mf_build_string ("string literal");
1221   else
1222     varname = mf_build_string ("constant");
1223
1224   mudflap_register_call (obj, object_size, varname);
1225 }
1226
1227
1228 /* Emit any file-wide instrumentation.  */
1229 void
1230 mudflap_finish_file (void)
1231 {
1232   tree ctor_statements = NULL_TREE;
1233
1234   /* No need to continue when there were errors.  */
1235   if (errorcount != 0 || sorrycount != 0)
1236     return;
1237
1238   /* Insert a call to __mf_init.  */
1239   {
1240     tree call2_stmt = build_call_expr (mf_init_fndecl, 0);
1241     append_to_statement_list (call2_stmt, &ctor_statements);
1242   }
1243   
1244   /* If appropriate, call __mf_set_options to pass along read-ignore mode.  */
1245   if (flag_mudflap_ignore_reads)
1246     {
1247       tree arg = mf_build_string ("-ignore-reads");
1248       tree call_stmt = build_call_expr (mf_set_options_fndecl, 1, arg);
1249       append_to_statement_list (call_stmt, &ctor_statements);
1250     }
1251
1252   /* Process all enqueued object decls.  */
1253   if (deferred_static_decls)
1254     {
1255       size_t i;
1256       tree obj;
1257       for (i = 0; VEC_iterate (tree, deferred_static_decls, i, obj); i++)
1258         {
1259           gcc_assert (DECL_P (obj));
1260
1261           if (mf_marked_p (obj))
1262             continue;
1263
1264           /* Omit registration for static unaddressed objects.  NB:
1265              Perform registration for non-static objects regardless of
1266              TREE_USED or TREE_ADDRESSABLE, because they may be used
1267              from other compilation units.  */
1268           if (! TREE_PUBLIC (obj) && ! TREE_ADDRESSABLE (obj))
1269             continue;
1270
1271           if (! COMPLETE_TYPE_P (TREE_TYPE (obj)))
1272             {
1273               warning (0, "mudflap cannot track unknown size extern %qs",
1274                        IDENTIFIER_POINTER (DECL_NAME (obj)));
1275               continue;
1276             }
1277           
1278           mudflap_register_call (obj, 
1279                                  size_in_bytes (TREE_TYPE (obj)),
1280                                  mf_varname_tree (obj));
1281         }
1282
1283       VEC_truncate (tree, deferred_static_decls, 0);
1284     }
1285
1286   /* Append all the enqueued registration calls.  */
1287   if (enqueued_call_stmt_chain)
1288     {
1289       append_to_statement_list (enqueued_call_stmt_chain, &ctor_statements);
1290       enqueued_call_stmt_chain = NULL_TREE;
1291     }
1292
1293   cgraph_build_static_cdtor ('I', ctor_statements, 
1294                              MAX_RESERVED_INIT_PRIORITY-1);
1295 }
1296
1297
1298 static bool
1299 gate_mudflap (void)
1300 {
1301   return flag_mudflap != 0;
1302 }
1303
1304 struct tree_opt_pass pass_mudflap_1 = 
1305 {
1306   "mudflap1",                           /* name */
1307   gate_mudflap,                         /* gate */
1308   execute_mudflap_function_decls,       /* execute */
1309   NULL,                                 /* sub */
1310   NULL,                                 /* next */
1311   0,                                    /* static_pass_number */
1312   0,                                    /* tv_id */
1313   PROP_gimple_any,                      /* properties_required */
1314   0,                                    /* properties_provided */
1315   0,                                    /* properties_destroyed */
1316   0,                                    /* todo_flags_start */
1317   TODO_dump_func,                       /* todo_flags_finish */
1318   0                                     /* letter */
1319 };
1320
1321 struct tree_opt_pass pass_mudflap_2 = 
1322 {
1323   "mudflap2",                           /* name */
1324   gate_mudflap,                         /* gate */
1325   execute_mudflap_function_ops,         /* execute */
1326   NULL,                                 /* sub */
1327   NULL,                                 /* next */
1328   0,                                    /* static_pass_number */
1329   0,                                    /* tv_id */
1330   PROP_gimple_leh,                      /* properties_required */
1331   0,                                    /* properties_provided */
1332   0,                                    /* properties_destroyed */
1333   0,                                    /* todo_flags_start */
1334   TODO_verify_flow | TODO_verify_stmts
1335   | TODO_dump_func,                     /* todo_flags_finish */
1336   0                                     /* letter */
1337 };
1338
1339 #include "gt-tree-mudflap.h"