OSDN Git Service

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