OSDN Git Service

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