OSDN Git Service

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