OSDN Git Service

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