OSDN Git Service

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