OSDN Git Service

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