OSDN Git Service

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