OSDN Git Service

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