1169689Skan/* Mudflap: narrow-pointer bounds-checking by tree rewriting.
2169689Skan   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3169689Skan   Contributed by Frank Ch. Eigler <fche@redhat.com>
4169689Skan   and Graydon Hoare <graydon@redhat.com>
5169689Skan
6169689SkanThis file is part of GCC.
7169689Skan
8169689SkanGCC is free software; you can redistribute it and/or modify it under
9169689Skanthe terms of the GNU General Public License as published by the Free
10169689SkanSoftware Foundation; either version 2, or (at your option) any later
11169689Skanversion.
12169689Skan
13169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY
14169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or
15169689SkanFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16169689Skanfor more details.
17169689Skan
18169689SkanYou should have received a copy of the GNU General Public License
19169689Skanalong with GCC; see the file COPYING.  If not, write to the Free
20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
21169689Skan02110-1301, USA.  */
22169689Skan
23169689Skan
24169689Skan#include "config.h"
25169689Skan#include "system.h"
26169689Skan#include "coretypes.h"
27169689Skan#include "tm.h"
28169689Skan#include "hard-reg-set.h"
29169689Skan#include "rtl.h"
30169689Skan#include "tree.h"
31169689Skan#include "tm_p.h"
32169689Skan#include "basic-block.h"
33169689Skan#include "flags.h"
34169689Skan#include "function.h"
35169689Skan#include "tree-inline.h"
36169689Skan#include "tree-gimple.h"
37169689Skan#include "tree-flow.h"
38169689Skan#include "tree-mudflap.h"
39169689Skan#include "tree-dump.h"
40169689Skan#include "tree-pass.h"
41169689Skan#include "hashtab.h"
42169689Skan#include "diagnostic.h"
43169689Skan#include <demangle.h>
44169689Skan#include "langhooks.h"
45169689Skan#include "ggc.h"
46169689Skan#include "cgraph.h"
47169689Skan#include "toplev.h"
48169689Skan
49169689Skan/* Internal function decls */
50169689Skan
51169689Skan
52169689Skan/* Options.  */
53169689Skan#define flag_mudflap_threads (flag_mudflap == 2)
54169689Skan
55169689Skan/* Helpers.  */
56169689Skanstatic tree mf_build_string (const char *string);
57169689Skanstatic tree mf_varname_tree (tree);
58169689Skanstatic tree mf_file_function_line_tree (location_t);
59169689Skan
60169689Skan/* Indirection-related instrumentation.  */
61169689Skanstatic void mf_decl_cache_locals (void);
62169689Skanstatic void mf_decl_clear_locals (void);
63169689Skanstatic void mf_xform_derefs (void);
64169689Skanstatic unsigned int execute_mudflap_function_ops (void);
65169689Skan
66169689Skan/* Addressable variables instrumentation.  */
67169689Skanstatic void mf_xform_decls (tree, tree);
68169689Skanstatic tree mx_xfn_xform_decls (tree *, int *, void *);
69169689Skanstatic void mx_register_decls (tree, tree *);
70169689Skanstatic unsigned int execute_mudflap_function_decls (void);
71169689Skan
72169689Skan
73169689Skan/* ------------------------------------------------------------------------ */
74169689Skan/* Some generally helpful functions for mudflap instrumentation.  */
75169689Skan
76169689Skan/* Build a reference to a literal string.  */
77169689Skanstatic tree
78169689Skanmf_build_string (const char *string)
79169689Skan{
80169689Skan  size_t len = strlen (string);
81169689Skan  tree result = mf_mark (build_string (len + 1, string));
82169689Skan
83169689Skan  TREE_TYPE (result) = build_array_type
84169689Skan    (char_type_node, build_index_type (build_int_cst (NULL_TREE, len)));
85169689Skan  TREE_CONSTANT (result) = 1;
86169689Skan  TREE_INVARIANT (result) = 1;
87169689Skan  TREE_READONLY (result) = 1;
88169689Skan  TREE_STATIC (result) = 1;
89169689Skan
90169689Skan  result = build1 (ADDR_EXPR, build_pointer_type (char_type_node), result);
91169689Skan
92169689Skan  return mf_mark (result);
93169689Skan}
94169689Skan
95169689Skan/* Create a properly typed STRING_CST node that describes the given
96169689Skan   declaration.  It will be used as an argument for __mf_register().
97169689Skan   Try to construct a helpful string, including file/function/variable
98169689Skan   name.  */
99169689Skan
100169689Skanstatic tree
101169689Skanmf_varname_tree (tree decl)
102169689Skan{
103169689Skan  static pretty_printer buf_rec;
104169689Skan  static int initialized = 0;
105169689Skan  pretty_printer *buf = & buf_rec;
106169689Skan  const char *buf_contents;
107169689Skan  tree result;
108169689Skan
109169689Skan  gcc_assert (decl);
110169689Skan
111169689Skan  if (!initialized)
112169689Skan    {
113169689Skan      pp_construct (buf, /* prefix */ NULL, /* line-width */ 0);
114169689Skan      initialized = 1;
115169689Skan    }
116169689Skan  pp_clear_output_area (buf);
117169689Skan
118169689Skan  /* Add FILENAME[:LINENUMBER[:COLUMNNUMBER]].  */
119169689Skan  {
120169689Skan    expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (decl));
121169689Skan    const char *sourcefile;
122169689Skan    unsigned sourceline = xloc.line;
123169689Skan    unsigned sourcecolumn = 0;
124169689Skan#ifdef USE_MAPPED_LOCATION
125169689Skan    sourcecolumn = xloc.column;
126169689Skan#endif
127169689Skan    sourcefile = xloc.file;
128169689Skan    if (sourcefile == NULL && current_function_decl != NULL_TREE)
129169689Skan      sourcefile = DECL_SOURCE_FILE (current_function_decl);
130169689Skan    if (sourcefile == NULL)
131169689Skan      sourcefile = "<unknown file>";
132169689Skan
133169689Skan    pp_string (buf, sourcefile);
134169689Skan
135169689Skan    if (sourceline != 0)
136169689Skan      {
137169689Skan        pp_string (buf, ":");
138169689Skan        pp_decimal_int (buf, sourceline);
139169689Skan
140169689Skan        if (sourcecolumn != 0)
141169689Skan          {
142169689Skan            pp_string (buf, ":");
143169689Skan            pp_decimal_int (buf, sourcecolumn);
144169689Skan          }
145169689Skan      }
146169689Skan  }
147169689Skan
148169689Skan  if (current_function_decl != NULL_TREE)
149169689Skan    {
150169689Skan      /* Add (FUNCTION) */
151169689Skan      pp_string (buf, " (");
152169689Skan      {
153169689Skan        const char *funcname = NULL;
154169689Skan        if (DECL_NAME (current_function_decl))
155169689Skan          funcname = lang_hooks.decl_printable_name (current_function_decl, 1);
156169689Skan        if (funcname == NULL)
157169689Skan          funcname = "anonymous fn";
158169689Skan
159169689Skan        pp_string (buf, funcname);
160169689Skan      }
161169689Skan      pp_string (buf, ") ");
162169689Skan    }
163169689Skan  else
164169689Skan    pp_string (buf, " ");
165169689Skan
166169689Skan  /* Add <variable-declaration>, possibly demangled.  */
167169689Skan  {
168169689Skan    const char *declname = NULL;
169169689Skan
170169689Skan    if (DECL_NAME (decl) != NULL)
171169689Skan      {
172169689Skan	if (strcmp ("GNU C++", lang_hooks.name) == 0)
173169689Skan	  {
174169689Skan	    /* The gcc/cp decl_printable_name hook doesn't do as good a job as
175169689Skan	       the libiberty demangler.  */
176169689Skan	    declname = cplus_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)),
177169689Skan				       DMGL_AUTO | DMGL_VERBOSE);
178169689Skan	  }
179169689Skan	if (declname == NULL)
180169689Skan	  declname = lang_hooks.decl_printable_name (decl, 3);
181169689Skan      }
182169689Skan    if (declname == NULL)
183169689Skan      declname = "<unnamed variable>";
184169689Skan
185169689Skan    pp_string (buf, declname);
186169689Skan  }
187169689Skan
188169689Skan  /* Return the lot as a new STRING_CST.  */
189169689Skan  buf_contents = pp_base_formatted_text (buf);
190169689Skan  result = mf_build_string (buf_contents);
191169689Skan  pp_clear_output_area (buf);
192169689Skan
193169689Skan  return result;
194169689Skan}
195169689Skan
196169689Skan
197169689Skan/* And another friend, for producing a simpler message.  */
198169689Skan
199169689Skanstatic tree
200169689Skanmf_file_function_line_tree (location_t location)
201169689Skan{
202169689Skan  expanded_location xloc = expand_location (location);
203169689Skan  const char *file = NULL, *colon, *line, *op, *name, *cp;
204169689Skan  char linecolbuf[30]; /* Enough for two decimal numbers plus a colon.  */
205169689Skan  char *string;
206169689Skan  tree result;
207169689Skan
208169689Skan  /* Add FILENAME[:LINENUMBER[:COLUMNNUMBER]].  */
209169689Skan  file = xloc.file;
210169689Skan  if (file == NULL && current_function_decl != NULL_TREE)
211169689Skan    file = DECL_SOURCE_FILE (current_function_decl);
212169689Skan  if (file == NULL)
213169689Skan    file = "<unknown file>";
214169689Skan
215169689Skan  if (xloc.line > 0)
216169689Skan    {
217169689Skan#ifdef USE_MAPPED_LOCATION
218169689Skan      if (xloc.column > 0)
219169689Skan        sprintf (linecolbuf, "%d:%d", xloc.line, xloc.column);
220169689Skan      else
221169689Skan#endif
222169689Skan        sprintf (linecolbuf, "%d", xloc.line);
223169689Skan      colon = ":";
224169689Skan      line = linecolbuf;
225169689Skan    }
226169689Skan  else
227169689Skan    colon = line = "";
228169689Skan
229169689Skan  /* Add (FUNCTION).  */
230169689Skan  name = lang_hooks.decl_printable_name (current_function_decl, 1);
231169689Skan  if (name)
232169689Skan    {
233169689Skan      op = " (";
234169689Skan      cp = ")";
235169689Skan    }
236169689Skan  else
237169689Skan    op = name = cp = "";
238169689Skan
239169689Skan  string = concat (file, colon, line, op, name, cp, NULL);
240169689Skan  result = mf_build_string (string);
241169689Skan  free (string);
242169689Skan
243169689Skan  return result;
244169689Skan}
245169689Skan
246169689Skan
247169689Skan/* global tree nodes */
248169689Skan
249169689Skan/* Global tree objects for global variables and functions exported by
250169689Skan   mudflap runtime library.  mf_init_extern_trees must be called
251169689Skan   before using these.  */
252169689Skan
253169689Skan/* uintptr_t (usually "unsigned long") */
254169689Skanstatic GTY (()) tree mf_uintptr_type;
255169689Skan
256169689Skan/* struct __mf_cache { uintptr_t low; uintptr_t high; }; */
257169689Skanstatic GTY (()) tree mf_cache_struct_type;
258169689Skan
259169689Skan/* struct __mf_cache * const */
260169689Skanstatic GTY (()) tree mf_cache_structptr_type;
261169689Skan
262169689Skan/* extern struct __mf_cache __mf_lookup_cache []; */
263169689Skanstatic GTY (()) tree mf_cache_array_decl;
264169689Skan
265169689Skan/* extern unsigned char __mf_lc_shift; */
266169689Skanstatic GTY (()) tree mf_cache_shift_decl;
267169689Skan
268169689Skan/* extern uintptr_t __mf_lc_mask; */
269169689Skanstatic GTY (()) tree mf_cache_mask_decl;
270169689Skan
271169689Skan/* Their function-scope local shadows, used in single-threaded mode only.  */
272169689Skan
273169689Skan/* auto const unsigned char __mf_lc_shift_l; */
274169689Skanstatic GTY (()) tree mf_cache_shift_decl_l;
275169689Skan
276169689Skan/* auto const uintptr_t __mf_lc_mask_l; */
277169689Skanstatic GTY (()) tree mf_cache_mask_decl_l;
278169689Skan
279169689Skan/* extern void __mf_check (void *ptr, size_t sz, int type, const char *); */
280169689Skanstatic GTY (()) tree mf_check_fndecl;
281169689Skan
282169689Skan/* extern void __mf_register (void *ptr, size_t sz, int type, const char *); */
283169689Skanstatic GTY (()) tree mf_register_fndecl;
284169689Skan
285169689Skan/* extern void __mf_unregister (void *ptr, size_t sz, int type); */
286169689Skanstatic GTY (()) tree mf_unregister_fndecl;
287169689Skan
288169689Skan/* extern void __mf_init (); */
289169689Skanstatic GTY (()) tree mf_init_fndecl;
290169689Skan
291169689Skan/* extern int __mf_set_options (const char*); */
292169689Skanstatic GTY (()) tree mf_set_options_fndecl;
293169689Skan
294169689Skan
295169689Skan/* Helper for mudflap_init: construct a decl with the given category,
296169689Skan   name, and type, mark it an external reference, and pushdecl it.  */
297169689Skanstatic inline tree
298169689Skanmf_make_builtin (enum tree_code category, const char *name, tree type)
299169689Skan{
300169689Skan  tree decl = mf_mark (build_decl (category, get_identifier (name), type));
301169689Skan  TREE_PUBLIC (decl) = 1;
302169689Skan  DECL_EXTERNAL (decl) = 1;
303169689Skan  lang_hooks.decls.pushdecl (decl);
304169689Skan  return decl;
305169689Skan}
306169689Skan
307169689Skan/* Helper for mudflap_init: construct a tree corresponding to the type
308169689Skan     struct __mf_cache { uintptr_t low; uintptr_t high; };
309169689Skan     where uintptr_t is the FIELD_TYPE argument.  */
310169689Skanstatic inline tree
311169689Skanmf_make_mf_cache_struct_type (tree field_type)
312169689Skan{
313169689Skan  /* There is, abominably, no language-independent way to construct a
314169689Skan     RECORD_TYPE.  So we have to call the basic type construction
315169689Skan     primitives by hand.  */
316169689Skan  tree fieldlo = build_decl (FIELD_DECL, get_identifier ("low"), field_type);
317169689Skan  tree fieldhi = build_decl (FIELD_DECL, get_identifier ("high"), field_type);
318169689Skan
319169689Skan  tree struct_type = make_node (RECORD_TYPE);
320169689Skan  DECL_CONTEXT (fieldlo) = struct_type;
321169689Skan  DECL_CONTEXT (fieldhi) = struct_type;
322169689Skan  TREE_CHAIN (fieldlo) = fieldhi;
323169689Skan  TYPE_FIELDS (struct_type) = fieldlo;
324169689Skan  TYPE_NAME (struct_type) = get_identifier ("__mf_cache");
325169689Skan  layout_type (struct_type);
326169689Skan
327169689Skan  return struct_type;
328169689Skan}
329169689Skan
330169689Skan#define build_function_type_0(rtype)            \
331169689Skan  build_function_type (rtype, void_list_node)
332169689Skan#define build_function_type_1(rtype, arg1)                 \
333169689Skan  build_function_type (rtype, tree_cons (0, arg1, void_list_node))
334169689Skan#define build_function_type_3(rtype, arg1, arg2, arg3)                  \
335169689Skan  build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2,   \
336169689Skan                                                             tree_cons (0, arg3, void_list_node))))
337169689Skan#define build_function_type_4(rtype, arg1, arg2, arg3, arg4)            \
338169689Skan  build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2,   \
339169689Skan                                                             tree_cons (0, arg3, tree_cons (0, arg4, \
340169689Skan                                                                                            void_list_node)))))
341169689Skan
342169689Skan/* Initialize the global tree nodes that correspond to mf-runtime.h
343169689Skan   declarations.  */
344169689Skanvoid
345169689Skanmudflap_init (void)
346169689Skan{
347169689Skan  static bool done = false;
348169689Skan  tree mf_const_string_type;
349169689Skan  tree mf_cache_array_type;
350169689Skan  tree mf_check_register_fntype;
351169689Skan  tree mf_unregister_fntype;
352169689Skan  tree mf_init_fntype;
353169689Skan  tree mf_set_options_fntype;
354169689Skan
355169689Skan  if (done)
356169689Skan    return;
357169689Skan  done = true;
358169689Skan
359169689Skan  mf_uintptr_type = lang_hooks.types.type_for_mode (ptr_mode,
360169689Skan                                                    /*unsignedp=*/true);
361169689Skan  mf_const_string_type
362169689Skan    = build_pointer_type (build_qualified_type
363169689Skan                          (char_type_node, TYPE_QUAL_CONST));
364169689Skan
365169689Skan  mf_cache_struct_type = mf_make_mf_cache_struct_type (mf_uintptr_type);
366169689Skan  mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type);
367169689Skan  mf_cache_array_type = build_array_type (mf_cache_struct_type, 0);
368169689Skan  mf_check_register_fntype =
369169689Skan    build_function_type_4 (void_type_node, ptr_type_node, size_type_node,
370169689Skan                           integer_type_node, mf_const_string_type);
371169689Skan  mf_unregister_fntype =
372169689Skan    build_function_type_3 (void_type_node, ptr_type_node, size_type_node,
373169689Skan                           integer_type_node);
374169689Skan  mf_init_fntype =
375169689Skan    build_function_type_0 (void_type_node);
376169689Skan  mf_set_options_fntype =
377169689Skan    build_function_type_1 (integer_type_node, mf_const_string_type);
378169689Skan
379169689Skan  mf_cache_array_decl = mf_make_builtin (VAR_DECL, "__mf_lookup_cache",
380169689Skan                                         mf_cache_array_type);
381169689Skan  mf_cache_shift_decl = mf_make_builtin (VAR_DECL, "__mf_lc_shift",
382169689Skan                                         unsigned_char_type_node);
383169689Skan  mf_cache_mask_decl = mf_make_builtin (VAR_DECL, "__mf_lc_mask",
384169689Skan                                        mf_uintptr_type);
385169689Skan  /* Don't process these in mudflap_enqueue_decl, should they come by
386169689Skan     there for some reason.  */
387169689Skan  mf_mark (mf_cache_array_decl);
388169689Skan  mf_mark (mf_cache_shift_decl);
389169689Skan  mf_mark (mf_cache_mask_decl);
390169689Skan  mf_check_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_check",
391169689Skan                                     mf_check_register_fntype);
392169689Skan  mf_register_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_register",
393169689Skan                                        mf_check_register_fntype);
394169689Skan  mf_unregister_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_unregister",
395169689Skan                                          mf_unregister_fntype);
396169689Skan  mf_init_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_init",
397169689Skan                                    mf_init_fntype);
398169689Skan  mf_set_options_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_set_options",
399169689Skan                                           mf_set_options_fntype);
400169689Skan}
401169689Skan#undef build_function_type_4
402169689Skan#undef build_function_type_3
403169689Skan#undef build_function_type_1
404169689Skan#undef build_function_type_0
405169689Skan
406169689Skan
407169689Skan/* ------------------------------------------------------------------------ */
408169689Skan/* Memory reference transforms. Perform the mudflap indirection-related
409169689Skan   tree transforms on the current function.
410169689Skan
411169689Skan   This is the second part of the mudflap instrumentation.  It works on
412169689Skan   low-level GIMPLE using the CFG, because we want to run this pass after
413169689Skan   tree optimizations have been performed, but we have to preserve the CFG
414169689Skan   for expansion from trees to RTL.  */
415169689Skan
416169689Skanstatic unsigned int
417169689Skanexecute_mudflap_function_ops (void)
418169689Skan{
419169689Skan  /* Don't instrument functions such as the synthetic constructor
420169689Skan     built during mudflap_finish_file.  */
421169689Skan  if (mf_marked_p (current_function_decl) ||
422169689Skan      DECL_ARTIFICIAL (current_function_decl))
423169689Skan    return 0;
424169689Skan
425169689Skan  push_gimplify_context ();
426169689Skan
427169689Skan  /* In multithreaded mode, don't cache the lookup cache parameters.  */
428169689Skan  if (! flag_mudflap_threads)
429169689Skan    mf_decl_cache_locals ();
430169689Skan
431169689Skan  mf_xform_derefs ();
432169689Skan
433169689Skan  if (! flag_mudflap_threads)
434169689Skan    mf_decl_clear_locals ();
435169689Skan
436169689Skan  pop_gimplify_context (NULL);
437169689Skan  return 0;
438169689Skan}
439169689Skan
440169689Skan/* Create and initialize local shadow variables for the lookup cache
441169689Skan   globals.  Put their decls in the *_l globals for use by
442169689Skan   mf_build_check_statement_for.  */
443169689Skan
444169689Skanstatic void
445169689Skanmf_decl_cache_locals (void)
446169689Skan{
447169689Skan  tree t, shift_init_stmts, mask_init_stmts;
448169689Skan  tree_stmt_iterator tsi;
449169689Skan
450169689Skan  /* Build the cache vars.  */
451169689Skan  mf_cache_shift_decl_l
452169689Skan    = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_shift_decl),
453169689Skan                               "__mf_lookup_shift_l"));
454169689Skan
455169689Skan  mf_cache_mask_decl_l
456169689Skan    = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_mask_decl),
457169689Skan                               "__mf_lookup_mask_l"));
458169689Skan
459169689Skan  /* Build initialization nodes for the cache vars.  We just load the
460169689Skan     globals into the cache variables.  */
461169689Skan  t = build2 (MODIFY_EXPR, TREE_TYPE (mf_cache_shift_decl_l),
462169689Skan              mf_cache_shift_decl_l, mf_cache_shift_decl);
463169689Skan  SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
464169689Skan  gimplify_to_stmt_list (&t);
465169689Skan  shift_init_stmts = t;
466169689Skan
467169689Skan  t = build2 (MODIFY_EXPR, TREE_TYPE (mf_cache_mask_decl_l),
468169689Skan              mf_cache_mask_decl_l, mf_cache_mask_decl);
469169689Skan  SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
470169689Skan  gimplify_to_stmt_list (&t);
471169689Skan  mask_init_stmts = t;
472169689Skan
473169689Skan  /* Anticipating multiple entry points, we insert the cache vars
474169689Skan     initializers in each successor of the ENTRY_BLOCK_PTR.  */
475169689Skan  for (tsi = tsi_start (shift_init_stmts);
476169689Skan       ! tsi_end_p (tsi);
477169689Skan       tsi_next (&tsi))
478169689Skan    insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
479169689Skan
480169689Skan  for (tsi = tsi_start (mask_init_stmts);
481169689Skan       ! tsi_end_p (tsi);
482169689Skan       tsi_next (&tsi))
483169689Skan    insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
484169689Skan  bsi_commit_edge_inserts ();
485169689Skan}
486169689Skan
487169689Skan
488169689Skanstatic void
489169689Skanmf_decl_clear_locals (void)
490169689Skan{
491169689Skan  /* Unset local shadows.  */
492169689Skan  mf_cache_shift_decl_l = NULL_TREE;
493169689Skan  mf_cache_mask_decl_l = NULL_TREE;
494169689Skan}
495169689Skan
496169689Skanstatic void
497169689Skanmf_build_check_statement_for (tree base, tree limit,
498169689Skan                              block_stmt_iterator *instr_bsi,
499169689Skan                              location_t *locus, tree dirflag)
500169689Skan{
501169689Skan  tree_stmt_iterator head, tsi;
502169689Skan  block_stmt_iterator bsi;
503169689Skan  basic_block cond_bb, then_bb, join_bb;
504169689Skan  edge e;
505169689Skan  tree cond, t, u, v;
506169689Skan  tree mf_base;
507169689Skan  tree mf_elem;
508169689Skan  tree mf_limit;
509169689Skan
510169689Skan  /* We first need to split the current basic block, and start altering
511169689Skan     the CFG.  This allows us to insert the statements we're about to
512169689Skan     construct into the right basic blocks.  */
513169689Skan
514169689Skan  cond_bb = bb_for_stmt (bsi_stmt (*instr_bsi));
515169689Skan  bsi = *instr_bsi;
516169689Skan  bsi_prev (&bsi);
517169689Skan  if (! bsi_end_p (bsi))
518169689Skan    e = split_block (cond_bb, bsi_stmt (bsi));
519169689Skan  else
520169689Skan    e = split_block_after_labels (cond_bb);
521169689Skan  cond_bb = e->src;
522169689Skan  join_bb = e->dest;
523169689Skan
524169689Skan  /* A recap at this point: join_bb is the basic block at whose head
525169689Skan     is the gimple statement for which this check expression is being
526169689Skan     built.  cond_bb is the (possibly new, synthetic) basic block the
527169689Skan     end of which will contain the cache-lookup code, and a
528169689Skan     conditional that jumps to the cache-miss code or, much more
529169689Skan     likely, over to join_bb.  */
530169689Skan
531169689Skan  /* Create the bb that contains the cache-miss fallback block (mf_check).  */
532169689Skan  then_bb = create_empty_bb (cond_bb);
533169689Skan  make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
534169689Skan  make_single_succ_edge (then_bb, join_bb, EDGE_FALLTHRU);
535169689Skan
536169689Skan  /* Mark the pseudo-fallthrough edge from cond_bb to join_bb.  */
537169689Skan  e = find_edge (cond_bb, join_bb);
538169689Skan  e->flags = EDGE_FALSE_VALUE;
539169689Skan  e->count = cond_bb->count;
540169689Skan  e->probability = REG_BR_PROB_BASE;
541169689Skan
542169689Skan  /* Update dominance info.  Note that bb_join's data was
543169689Skan     updated by split_block.  */
544169689Skan  if (dom_info_available_p (CDI_DOMINATORS))
545169689Skan    {
546169689Skan      set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
547169689Skan      set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb);
548169689Skan    }
549169689Skan
550169689Skan  /* Build our local variables.  */
551169689Skan  mf_elem = create_tmp_var (mf_cache_structptr_type, "__mf_elem");
552169689Skan  mf_base = create_tmp_var (mf_uintptr_type, "__mf_base");
553169689Skan  mf_limit = create_tmp_var (mf_uintptr_type, "__mf_limit");
554169689Skan
555169689Skan  /* Build: __mf_base = (uintptr_t) <base address expression>.  */
556169689Skan  t = build2 (MODIFY_EXPR, void_type_node, mf_base,
557169689Skan              convert (mf_uintptr_type, unshare_expr (base)));
558169689Skan  SET_EXPR_LOCUS (t, locus);
559169689Skan  gimplify_to_stmt_list (&t);
560169689Skan  head = tsi_start (t);
561169689Skan  tsi = tsi_last (t);
562169689Skan
563169689Skan  /* Build: __mf_limit = (uintptr_t) <limit address expression>.  */
564169689Skan  t = build2 (MODIFY_EXPR, void_type_node, mf_limit,
565169689Skan              convert (mf_uintptr_type, unshare_expr (limit)));
566169689Skan  SET_EXPR_LOCUS (t, locus);
567169689Skan  gimplify_to_stmt_list (&t);
568169689Skan  tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
569169689Skan
570169689Skan  /* Build: __mf_elem = &__mf_lookup_cache [(__mf_base >> __mf_shift)
571169689Skan                                            & __mf_mask].  */
572169689Skan  t = build2 (RSHIFT_EXPR, mf_uintptr_type, mf_base,
573169689Skan              (flag_mudflap_threads ? mf_cache_shift_decl : mf_cache_shift_decl_l));
574169689Skan  t = build2 (BIT_AND_EXPR, mf_uintptr_type, t,
575169689Skan              (flag_mudflap_threads ? mf_cache_mask_decl : mf_cache_mask_decl_l));
576169689Skan  t = build4 (ARRAY_REF,
577169689Skan              TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
578169689Skan              mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
579169689Skan  t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
580169689Skan  t = build2 (MODIFY_EXPR, void_type_node, mf_elem, t);
581169689Skan  SET_EXPR_LOCUS (t, locus);
582169689Skan  gimplify_to_stmt_list (&t);
583169689Skan  tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
584169689Skan
585169689Skan  /* Quick validity check.
586169689Skan
587169689Skan     if (__mf_elem->low > __mf_base
588169689Skan         || (__mf_elem_high < __mf_limit))
589169689Skan        {
590169689Skan          __mf_check ();
591169689Skan          ... and only if single-threaded:
592169689Skan          __mf_lookup_shift_1 = f...;
593169689Skan          __mf_lookup_mask_l = ...;
594169689Skan        }
595169689Skan
596169689Skan     It is expected that this body of code is rarely executed so we mark
597169689Skan     the edge to the THEN clause of the conditional jump as unlikely.  */
598169689Skan
599169689Skan  /* Construct t <-- '__mf_elem->low  > __mf_base'.  */
600169689Skan  t = build3 (COMPONENT_REF, mf_uintptr_type,
601169689Skan              build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
602169689Skan              TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
603169689Skan  t = build2 (GT_EXPR, boolean_type_node, t, mf_base);
604169689Skan
605169689Skan  /* Construct '__mf_elem->high < __mf_limit'.
606169689Skan
607169689Skan     First build:
608169689Skan        1) u <--  '__mf_elem->high'
609169689Skan        2) v <--  '__mf_limit'.
610169689Skan
611169689Skan     Then build 'u <-- (u < v).  */
612169689Skan
613169689Skan  u = build3 (COMPONENT_REF, mf_uintptr_type,
614169689Skan              build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
615169689Skan              TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
616169689Skan
617169689Skan  v = mf_limit;
618169689Skan
619169689Skan  u = build2 (LT_EXPR, boolean_type_node, u, v);
620169689Skan
621169689Skan  /* Build the composed conditional: t <-- 't || u'.  Then store the
622169689Skan     result of the evaluation of 't' in a temporary variable which we
623169689Skan     can use as the condition for the conditional jump.  */
624169689Skan  t = build2 (TRUTH_OR_EXPR, boolean_type_node, t, u);
625169689Skan  cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
626169689Skan  t = build2 (MODIFY_EXPR, boolean_type_node, cond, t);
627169689Skan  gimplify_to_stmt_list (&t);
628169689Skan  tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
629169689Skan
630169689Skan  /* Build the conditional jump.  'cond' is just a temporary so we can
631169689Skan     simply build a void COND_EXPR.  We do need labels in both arms though.  */
632169689Skan  t = build3 (COND_EXPR, void_type_node, cond,
633169689Skan              build1 (GOTO_EXPR, void_type_node, tree_block_label (then_bb)),
634169689Skan              build1 (GOTO_EXPR, void_type_node, tree_block_label (join_bb)));
635169689Skan  SET_EXPR_LOCUS (t, locus);
636169689Skan  tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
637169689Skan
638169689Skan  /* At this point, after so much hard work, we have only constructed
639169689Skan     the conditional jump,
640169689Skan
641169689Skan     if (__mf_elem->low > __mf_base
642169689Skan         || (__mf_elem_high < __mf_limit))
643169689Skan
644169689Skan     The lowered GIMPLE tree representing this code is in the statement
645169689Skan     list starting at 'head'.
646169689Skan
647169689Skan     We can insert this now in the current basic block, i.e. the one that
648169689Skan     the statement we're instrumenting was originally in.  */
649169689Skan  bsi = bsi_last (cond_bb);
650169689Skan  for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
651169689Skan    bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
652169689Skan
653169689Skan  /*  Now build up the body of the cache-miss handling:
654169689Skan
655169689Skan     __mf_check();
656169689Skan     refresh *_l vars.
657169689Skan
658169689Skan     This is the body of the conditional.  */
659169689Skan
660169689Skan  u = tree_cons (NULL_TREE,
661169689Skan                 mf_file_function_line_tree (locus == NULL ? UNKNOWN_LOCATION
662169689Skan                                             : *locus),
663169689Skan                 NULL_TREE);
664169689Skan  u = tree_cons (NULL_TREE, dirflag, u);
665169689Skan  /* NB: we pass the overall [base..limit] range to mf_check.  */
666169689Skan  u = tree_cons (NULL_TREE,
667169689Skan                 fold_build2 (PLUS_EXPR, integer_type_node,
668169689Skan			      fold_build2 (MINUS_EXPR, mf_uintptr_type, mf_limit, mf_base),
669169689Skan			      integer_one_node),
670169689Skan                 u);
671169689Skan  u = tree_cons (NULL_TREE, mf_base, u);
672169689Skan  t = build_function_call_expr (mf_check_fndecl, u);
673169689Skan  gimplify_to_stmt_list (&t);
674169689Skan  head = tsi_start (t);
675169689Skan  tsi = tsi_last (t);
676169689Skan
677169689Skan  if (! flag_mudflap_threads)
678169689Skan    {
679169689Skan      t = build2 (MODIFY_EXPR, void_type_node,
680169689Skan                  mf_cache_shift_decl_l, mf_cache_shift_decl);
681169689Skan      tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
682169689Skan
683169689Skan      t = build2 (MODIFY_EXPR, void_type_node,
684169689Skan                  mf_cache_mask_decl_l, mf_cache_mask_decl);
685169689Skan      tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
686169689Skan    }
687169689Skan
688169689Skan  /* Insert the check code in the THEN block.  */
689169689Skan  bsi = bsi_start (then_bb);
690169689Skan  for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
691169689Skan    bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
692169689Skan
693169689Skan  *instr_bsi = bsi_start (join_bb);
694169689Skan  bsi_next (instr_bsi);
695169689Skan}
696169689Skan
697169689Skan
698169689Skan/* Check whether the given decl, generally a VAR_DECL or PARM_DECL, is
699169689Skan   eligible for instrumentation.  For the mudflap1 pass, this implies
700169689Skan   that it should be registered with the libmudflap runtime.  For the
701169689Skan   mudflap2 pass this means instrumenting an indirection operation with
702169689Skan   respect to the object.
703169689Skan*/
704169689Skanstatic int
705169689Skanmf_decl_eligible_p (tree decl)
706169689Skan{
707169689Skan  return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
708169689Skan          /* The decl must have its address taken.  In the case of
709169689Skan             arrays, this flag is also set if the indexes are not
710169689Skan             compile-time known valid constants.  */
711169689Skan          && TREE_ADDRESSABLE (decl)    /* XXX: not sufficient: return-by-value structs! */
712169689Skan          /* The type of the variable must be complete.  */
713169689Skan          && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
714169689Skan	  /* The decl hasn't been decomposed somehow.  */
715169689Skan	  && !DECL_HAS_VALUE_EXPR_P (decl));
716169689Skan}
717169689Skan
718169689Skan
719169689Skanstatic void
720169689Skanmf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
721169689Skan                   location_t *locus, tree dirflag)
722169689Skan{
723169689Skan  tree type, base, limit, addr, size, t;
724169689Skan
725169689Skan  /* Don't instrument read operations.  */
726169689Skan  if (dirflag == integer_zero_node && flag_mudflap_ignore_reads)
727169689Skan    return;
728169689Skan
729169689Skan  /* Don't instrument marked nodes.  */
730169689Skan  if (mf_marked_p (*tp))
731169689Skan    return;
732169689Skan
733169689Skan  t = *tp;
734169689Skan  type = TREE_TYPE (t);
735169689Skan
736169689Skan  if (type == error_mark_node)
737169689Skan    return;
738169689Skan
739169689Skan  size = TYPE_SIZE_UNIT (type);
740169689Skan
741169689Skan  switch (TREE_CODE (t))
742169689Skan    {
743169689Skan    case ARRAY_REF:
744169689Skan    case COMPONENT_REF:
745169689Skan      {
746169689Skan        /* This is trickier than it may first appear.  The reason is
747169689Skan           that we are looking at expressions from the "inside out" at
748169689Skan           this point.  We may have a complex nested aggregate/array
749169689Skan           expression (e.g. "a.b[i].c"), maybe with an indirection as
750169689Skan           the leftmost operator ("p->a.b.d"), where instrumentation
751169689Skan           is necessary.  Or we may have an innocent "a.b.c"
752169689Skan           expression that must not be instrumented.  We need to
753169689Skan           recurse all the way down the nesting structure to figure it
754169689Skan           out: looking just at the outer node is not enough.  */
755169689Skan        tree var;
756169689Skan        int component_ref_only = (TREE_CODE (t) == COMPONENT_REF);
757169689Skan	/* If we have a bitfield component reference, we must note the
758169689Skan	   innermost addressable object in ELT, from which we will
759169689Skan	   construct the byte-addressable bounds of the bitfield.  */
760169689Skan	tree elt = NULL_TREE;
761169689Skan	int bitfield_ref_p = (TREE_CODE (t) == COMPONENT_REF
762169689Skan			      && DECL_BIT_FIELD_TYPE (TREE_OPERAND (t, 1)));
763169689Skan
764169689Skan        /* Iterate to the top of the ARRAY_REF/COMPONENT_REF
765169689Skan           containment hierarchy to find the outermost VAR_DECL.  */
766169689Skan        var = TREE_OPERAND (t, 0);
767169689Skan        while (1)
768169689Skan          {
769169689Skan	    if (bitfield_ref_p && elt == NULL_TREE
770169689Skan		&& (TREE_CODE (var) == ARRAY_REF || TREE_CODE (var) == COMPONENT_REF))
771169689Skan	      elt = var;
772169689Skan
773169689Skan            if (TREE_CODE (var) == ARRAY_REF)
774169689Skan              {
775169689Skan                component_ref_only = 0;
776169689Skan                var = TREE_OPERAND (var, 0);
777169689Skan              }
778169689Skan            else if (TREE_CODE (var) == COMPONENT_REF)
779169689Skan              var = TREE_OPERAND (var, 0);
780169689Skan            else if (INDIRECT_REF_P (var))
781169689Skan              {
782169689Skan		base = TREE_OPERAND (var, 0);
783169689Skan                break;
784169689Skan              }
785169689Skan            else
786169689Skan              {
787169689Skan                gcc_assert (TREE_CODE (var) == VAR_DECL
788169689Skan                            || TREE_CODE (var) == PARM_DECL
789169689Skan                            || TREE_CODE (var) == RESULT_DECL
790169689Skan                            || TREE_CODE (var) == STRING_CST);
791169689Skan                /* Don't instrument this access if the underlying
792169689Skan                   variable is not "eligible".  This test matches
793169689Skan                   those arrays that have only known-valid indexes,
794169689Skan                   and thus are not labeled TREE_ADDRESSABLE.  */
795169689Skan                if (! mf_decl_eligible_p (var) || component_ref_only)
796169689Skan                  return;
797169689Skan                else
798169689Skan		  {
799169689Skan		    base = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (var)), var);
800169689Skan		    break;
801169689Skan		  }
802169689Skan              }
803169689Skan          }
804169689Skan
805169689Skan        /* Handle the case of ordinary non-indirection structure
806169689Skan           accesses.  These have only nested COMPONENT_REF nodes (no
807169689Skan           INDIRECT_REF), but pass through the above filter loop.
808169689Skan           Note that it's possible for such a struct variable to match
809169689Skan           the eligible_p test because someone else might take its
810169689Skan           address sometime.  */
811169689Skan
812169689Skan        /* We need special processing for bitfield components, because
813169689Skan           their addresses cannot be taken.  */
814169689Skan        if (bitfield_ref_p)
815169689Skan          {
816169689Skan            tree field = TREE_OPERAND (t, 1);
817169689Skan
818169689Skan            if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST)
819169689Skan              size = DECL_SIZE_UNIT (field);
820169689Skan
821169689Skan	    if (elt)
822169689Skan	      elt = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (elt)), elt);
823169689Skan            addr = fold_convert (ptr_type_node, elt ? elt : base);
824169689Skan            addr = fold_build2 (PLUS_EXPR, ptr_type_node,
825169689Skan				addr, fold_convert (ptr_type_node,
826169689Skan						    byte_position (field)));
827169689Skan          }
828169689Skan        else
829169689Skan          addr = build1 (ADDR_EXPR, build_pointer_type (type), t);
830169689Skan
831169689Skan        limit = fold_build2 (MINUS_EXPR, mf_uintptr_type,
832169689Skan                             fold_build2 (PLUS_EXPR, mf_uintptr_type,
833169689Skan					  convert (mf_uintptr_type, addr),
834169689Skan					  size),
835169689Skan                             integer_one_node);
836169689Skan      }
837169689Skan      break;
838169689Skan
839169689Skan    case INDIRECT_REF:
840169689Skan      addr = TREE_OPERAND (t, 0);
841169689Skan      base = addr;
842169689Skan      limit = fold_build2 (MINUS_EXPR, ptr_type_node,
843169689Skan                           fold_build2 (PLUS_EXPR, ptr_type_node, base, size),
844169689Skan                           integer_one_node);
845169689Skan      break;
846169689Skan
847169689Skan    case TARGET_MEM_REF:
848169689Skan      addr = tree_mem_ref_addr (ptr_type_node, t);
849169689Skan      base = addr;
850169689Skan      limit = fold_build2 (MINUS_EXPR, ptr_type_node,
851169689Skan			   fold_build2 (PLUS_EXPR, ptr_type_node, base, size),
852169689Skan			   build_int_cst (ptr_type_node, 1));
853169689Skan      break;
854169689Skan
855169689Skan    case ARRAY_RANGE_REF:
856169689Skan      warning (0, "mudflap checking not yet implemented for ARRAY_RANGE_REF");
857169689Skan      return;
858169689Skan
859169689Skan    case BIT_FIELD_REF:
860169689Skan      /* ??? merge with COMPONENT_REF code above? */
861169689Skan      {
862169689Skan        tree ofs, rem, bpu;
863169689Skan
864169689Skan        /* If we're not dereferencing something, then the access
865169689Skan           must be ok.  */
866169689Skan        if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
867169689Skan          return;
868169689Skan
869169689Skan        bpu = bitsize_int (BITS_PER_UNIT);
870169689Skan        ofs = convert (bitsizetype, TREE_OPERAND (t, 2));
871169689Skan        rem = size_binop (TRUNC_MOD_EXPR, ofs, bpu);
872169689Skan        ofs = size_binop (TRUNC_DIV_EXPR, ofs, bpu);
873169689Skan
874169689Skan        size = convert (bitsizetype, TREE_OPERAND (t, 1));
875169689Skan        size = size_binop (PLUS_EXPR, size, rem);
876169689Skan        size = size_binop (CEIL_DIV_EXPR, size, bpu);
877169689Skan        size = convert (sizetype, size);
878169689Skan
879169689Skan        addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
880169689Skan        addr = convert (ptr_type_node, addr);
881169689Skan        addr = fold_build2 (PLUS_EXPR, ptr_type_node, addr, ofs);
882169689Skan
883169689Skan        base = addr;
884169689Skan        limit = fold_build2 (MINUS_EXPR, ptr_type_node,
885169689Skan                             fold_build2 (PLUS_EXPR, ptr_type_node, base, size),
886169689Skan                             integer_one_node);
887169689Skan      }
888169689Skan      break;
889169689Skan
890169689Skan    default:
891169689Skan      return;
892169689Skan    }
893169689Skan
894169689Skan  mf_build_check_statement_for (base, limit, iter, locus, dirflag);
895169689Skan}
896169689Skan
897169689Skanstatic void
898169689Skanmf_xform_derefs (void)
899169689Skan{
900169689Skan  basic_block bb, next;
901169689Skan  block_stmt_iterator i;
902169689Skan  int saved_last_basic_block = last_basic_block;
903169689Skan
904169689Skan  bb = ENTRY_BLOCK_PTR ->next_bb;
905169689Skan  do
906169689Skan    {
907169689Skan      next = bb->next_bb;
908169689Skan      for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
909169689Skan        {
910169689Skan          tree s = bsi_stmt (i);
911169689Skan
912169689Skan          /* Only a few GIMPLE statements can reference memory.  */
913169689Skan          switch (TREE_CODE (s))
914169689Skan            {
915169689Skan            case MODIFY_EXPR:
916169689Skan              mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
917169689Skan                                 integer_one_node);
918169689Skan              mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 1), EXPR_LOCUS (s),
919169689Skan                                 integer_zero_node);
920169689Skan              break;
921169689Skan
922169689Skan            case RETURN_EXPR:
923169689Skan              if (TREE_OPERAND (s, 0) != NULL_TREE)
924169689Skan                {
925169689Skan                  if (TREE_CODE (TREE_OPERAND (s, 0)) == MODIFY_EXPR)
926169689Skan                    mf_xform_derefs_1 (&i, &TREE_OPERAND (TREE_OPERAND (s, 0), 1),
927169689Skan                                       EXPR_LOCUS (s), integer_zero_node);
928169689Skan                  else
929169689Skan                    mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
930169689Skan                                       integer_zero_node);
931169689Skan                }
932169689Skan              break;
933169689Skan
934169689Skan            default:
935169689Skan              ;
936169689Skan            }
937169689Skan        }
938169689Skan      bb = next;
939169689Skan    }
940169689Skan  while (bb && bb->index <= saved_last_basic_block);
941169689Skan}
942169689Skan
943169689Skan/* ------------------------------------------------------------------------ */
944169689Skan/* ADDR_EXPR transforms.  Perform the declaration-related mudflap tree
945169689Skan   transforms on the current function.
946169689Skan
947169689Skan   This is the first part of the mudflap instrumentation.  It works on
948169689Skan   high-level GIMPLE because after lowering, all variables are moved out
949169689Skan   of their BIND_EXPR binding context, and we lose liveness information
950169689Skan   for the declarations we wish to instrument.  */
951169689Skan
952169689Skanstatic unsigned int
953169689Skanexecute_mudflap_function_decls (void)
954169689Skan{
955169689Skan  /* Don't instrument functions such as the synthetic constructor
956169689Skan     built during mudflap_finish_file.  */
957169689Skan  if (mf_marked_p (current_function_decl) ||
958169689Skan      DECL_ARTIFICIAL (current_function_decl))
959169689Skan    return 0;
960169689Skan
961169689Skan  push_gimplify_context ();
962169689Skan
963169689Skan  mf_xform_decls (DECL_SAVED_TREE (current_function_decl),
964169689Skan                  DECL_ARGUMENTS (current_function_decl));
965169689Skan
966169689Skan  pop_gimplify_context (NULL);
967169689Skan  return 0;
968169689Skan}
969169689Skan
970169689Skan/* This struct is passed between mf_xform_decls to store state needed
971169689Skan   during the traversal searching for objects that have their
972169689Skan   addresses taken.  */
973169689Skanstruct mf_xform_decls_data
974169689Skan{
975169689Skan  tree param_decls;
976169689Skan};
977169689Skan
978169689Skan
979169689Skan/* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of
980169689Skan   _DECLs if appropriate.  Arrange to call the __mf_register function
981169689Skan   now, and the __mf_unregister function later for each.  */
982169689Skanstatic void
983169689Skanmx_register_decls (tree decl, tree *stmt_list)
984169689Skan{
985169689Skan  tree finally_stmts = NULL_TREE;
986169689Skan  tree_stmt_iterator initially_stmts = tsi_start (*stmt_list);
987169689Skan
988169689Skan  while (decl != NULL_TREE)
989169689Skan    {
990169689Skan      if (mf_decl_eligible_p (decl)
991169689Skan          /* Not already processed.  */
992169689Skan          && ! mf_marked_p (decl)
993169689Skan          /* Automatic variable.  */
994169689Skan          && ! DECL_EXTERNAL (decl)
995169689Skan          && ! TREE_STATIC (decl))
996169689Skan        {
997169689Skan          tree size = NULL_TREE, variable_name;
998169689Skan          tree unregister_fncall, unregister_fncall_params;
999169689Skan          tree register_fncall, register_fncall_params;
1000169689Skan
1001169689Skan	  size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
1002169689Skan
1003169689Skan          /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
1004169689Skan          unregister_fncall_params =
1005169689Skan            tree_cons (NULL_TREE,
1006169689Skan                       convert (ptr_type_node,
1007169689Skan                                mf_mark (build1 (ADDR_EXPR,
1008169689Skan                                                 build_pointer_type (TREE_TYPE (decl)),
1009169689Skan                                                 decl))),
1010169689Skan                       tree_cons (NULL_TREE,
1011169689Skan                                  size,
1012169689Skan                                  tree_cons (NULL_TREE,
1013169689Skan					     /* __MF_TYPE_STACK */
1014169689Skan                                             build_int_cst (NULL_TREE, 3),
1015169689Skan                                             NULL_TREE)));
1016169689Skan          /* __mf_unregister (...) */
1017169689Skan          unregister_fncall = build_function_call_expr (mf_unregister_fndecl,
1018169689Skan                                                        unregister_fncall_params);
1019169689Skan
1020169689Skan          /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, "name") */
1021169689Skan          variable_name = mf_varname_tree (decl);
1022169689Skan          register_fncall_params =
1023169689Skan            tree_cons (NULL_TREE,
1024169689Skan                   convert (ptr_type_node,
1025169689Skan                            mf_mark (build1 (ADDR_EXPR,
1026169689Skan                                             build_pointer_type (TREE_TYPE (decl)),
1027169689Skan                                             decl))),
1028169689Skan                       tree_cons (NULL_TREE,
1029169689Skan                                  size,
1030169689Skan                                  tree_cons (NULL_TREE,
1031169689Skan					     /* __MF_TYPE_STACK */
1032169689Skan                                             build_int_cst (NULL_TREE, 3),
1033169689Skan                                             tree_cons (NULL_TREE,
1034169689Skan                                                        variable_name,
1035169689Skan                                                        NULL_TREE))));
1036169689Skan
1037169689Skan          /* __mf_register (...) */
1038169689Skan          register_fncall = build_function_call_expr (mf_register_fndecl,
1039169689Skan                                                      register_fncall_params);
1040169689Skan
1041169689Skan          /* Accumulate the two calls.  */
1042169689Skan          /* ??? Set EXPR_LOCATION.  */
1043169689Skan          gimplify_stmt (&register_fncall);
1044169689Skan          gimplify_stmt (&unregister_fncall);
1045169689Skan
1046169689Skan          /* Add the __mf_register call at the current appending point.  */
1047169689Skan          if (tsi_end_p (initially_stmts))
1048169689Skan	    warning (0, "mudflap cannot track %qs in stub function",
1049169689Skan		     IDENTIFIER_POINTER (DECL_NAME (decl)));
1050169689Skan	  else
1051169689Skan	    {
1052169689Skan	      tsi_link_before (&initially_stmts, register_fncall, TSI_SAME_STMT);
1053169689Skan
1054169689Skan	      /* Accumulate the FINALLY piece.  */
1055169689Skan	      append_to_statement_list (unregister_fncall, &finally_stmts);
1056169689Skan	    }
1057169689Skan          mf_mark (decl);
1058169689Skan        }
1059169689Skan
1060169689Skan      decl = TREE_CHAIN (decl);
1061169689Skan    }
1062169689Skan
1063169689Skan  /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
1064169689Skan  if (finally_stmts != NULL_TREE)
1065169689Skan    {
1066169689Skan      tree t = build2 (TRY_FINALLY_EXPR, void_type_node,
1067169689Skan                       *stmt_list, finally_stmts);
1068169689Skan      *stmt_list = NULL;
1069169689Skan      append_to_statement_list (t, stmt_list);
1070169689Skan    }
1071169689Skan}
1072169689Skan
1073169689Skan
1074169689Skan/* Process every variable mentioned in BIND_EXPRs.  */
1075169689Skanstatic tree
1076169689Skanmx_xfn_xform_decls (tree *t, int *continue_p, void *data)
1077169689Skan{
1078169689Skan  struct mf_xform_decls_data* d = (struct mf_xform_decls_data*) data;
1079169689Skan
1080169689Skan  if (*t == NULL_TREE || *t == error_mark_node)
1081169689Skan    {
1082169689Skan      *continue_p = 0;
1083169689Skan      return NULL_TREE;
1084169689Skan    }
1085169689Skan
1086169689Skan  *continue_p = 1;
1087169689Skan
1088169689Skan  switch (TREE_CODE (*t))
1089169689Skan    {
1090169689Skan    case BIND_EXPR:
1091169689Skan      {
1092169689Skan        /* Process function parameters now (but only once).  */
1093169689Skan        mx_register_decls (d->param_decls, &BIND_EXPR_BODY (*t));
1094169689Skan        d->param_decls = NULL_TREE;
1095169689Skan
1096169689Skan        mx_register_decls (BIND_EXPR_VARS (*t), &BIND_EXPR_BODY (*t));
1097169689Skan      }
1098169689Skan      break;
1099169689Skan
1100169689Skan    default:
1101169689Skan      break;
1102169689Skan    }
1103169689Skan
1104169689Skan  return NULL_TREE;
1105169689Skan}
1106169689Skan
1107169689Skan/* Perform the object lifetime tracking mudflap transform on the given function
1108169689Skan   tree.  The tree is mutated in place, with possibly copied subtree nodes.
1109169689Skan
1110169689Skan   For every auto variable declared, if its address is ever taken
1111169689Skan   within the function, then supply its lifetime to the mudflap
1112169689Skan   runtime with the __mf_register and __mf_unregister calls.
1113169689Skan*/
1114169689Skan
1115169689Skanstatic void
1116169689Skanmf_xform_decls (tree fnbody, tree fnparams)
1117169689Skan{
1118169689Skan  struct mf_xform_decls_data d;
1119169689Skan  d.param_decls = fnparams;
1120169689Skan  walk_tree_without_duplicates (&fnbody, mx_xfn_xform_decls, &d);
1121169689Skan}
1122169689Skan
1123169689Skan
1124169689Skan/* ------------------------------------------------------------------------ */
1125169689Skan/* Externally visible mudflap functions.  */
1126169689Skan
1127169689Skan
1128169689Skan/* Mark and return the given tree node to prevent further mudflap
1129169689Skan   transforms.  */
1130169689Skanstatic GTY ((param_is (union tree_node))) htab_t marked_trees = NULL;
1131169689Skan
1132169689Skantree
1133169689Skanmf_mark (tree t)
1134169689Skan{
1135169689Skan  void **slot;
1136169689Skan
1137169689Skan  if (marked_trees == NULL)
1138169689Skan    marked_trees = htab_create_ggc (31, htab_hash_pointer, htab_eq_pointer, NULL);
1139169689Skan
1140169689Skan  slot = htab_find_slot (marked_trees, t, INSERT);
1141169689Skan  *slot = t;
1142169689Skan  return t;
1143169689Skan}
1144169689Skan
1145169689Skanint
1146169689Skanmf_marked_p (tree t)
1147169689Skan{
1148169689Skan  void *entry;
1149169689Skan
1150169689Skan  if (marked_trees == NULL)
1151169689Skan    return 0;
1152169689Skan
1153169689Skan  entry = htab_find (marked_trees, t);
1154169689Skan  return (entry != NULL);
1155169689Skan}
1156169689Skan
1157169689Skan/* Remember given node as a static of some kind: global data,
1158169689Skan   function-scope static, or an anonymous constant.  Its assembler
1159169689Skan   label is given.  */
1160169689Skan
1161169689Skan/* A list of globals whose incomplete declarations we encountered.
1162169689Skan   Instead of emitting the __mf_register call for them here, it's
1163169689Skan   delayed until program finish time.  If they're still incomplete by
1164169689Skan   then, warnings are emitted.  */
1165169689Skan
1166169689Skanstatic GTY (()) VEC(tree,gc) *deferred_static_decls;
1167169689Skan
1168169689Skan/* A list of statements for calling __mf_register() at startup time.  */
1169169689Skanstatic GTY (()) tree enqueued_call_stmt_chain;
1170169689Skan
1171169689Skanstatic void
1172169689Skanmudflap_register_call (tree obj, tree object_size, tree varname)
1173169689Skan{
1174169689Skan  tree arg, args, call_stmt;
1175169689Skan
1176169689Skan  args = tree_cons (NULL_TREE, varname, NULL_TREE);
1177169689Skan
1178169689Skan  arg = build_int_cst (NULL_TREE, 4); /* __MF_TYPE_STATIC */
1179169689Skan  args = tree_cons (NULL_TREE, arg, args);
1180169689Skan
1181169689Skan  arg = convert (size_type_node, object_size);
1182169689Skan  args = tree_cons (NULL_TREE, arg, args);
1183169689Skan
1184169689Skan  arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj);
1185169689Skan  arg = convert (ptr_type_node, arg);
1186169689Skan  args = tree_cons (NULL_TREE, arg, args);
1187169689Skan
1188169689Skan  call_stmt = build_function_call_expr (mf_register_fndecl, args);
1189169689Skan
1190169689Skan  append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
1191169689Skan}
1192169689Skan
1193169689Skanvoid
1194169689Skanmudflap_enqueue_decl (tree obj)
1195169689Skan{
1196169689Skan  if (mf_marked_p (obj))
1197169689Skan    return;
1198169689Skan
1199169689Skan  /* We don't need to process variable decls that are internally
1200169689Skan     generated extern.  If we did, we'd end up with warnings for them
1201169689Skan     during mudflap_finish_file ().  That would confuse the user,
1202169689Skan     since the text would refer to variables that don't show up in the
1203169689Skan     user's source code.  */
1204169689Skan  if (DECL_P (obj) && DECL_EXTERNAL (obj) && DECL_ARTIFICIAL (obj))
1205169689Skan    return;
1206169689Skan
1207169689Skan  VEC_safe_push (tree, gc, deferred_static_decls, obj);
1208169689Skan}
1209169689Skan
1210169689Skan
1211169689Skanvoid
1212169689Skanmudflap_enqueue_constant (tree obj)
1213169689Skan{
1214169689Skan  tree object_size, varname;
1215169689Skan
1216169689Skan  if (mf_marked_p (obj))
1217169689Skan    return;
1218169689Skan
1219169689Skan  if (TREE_CODE (obj) == STRING_CST)
1220169689Skan    object_size = build_int_cst (NULL_TREE, TREE_STRING_LENGTH (obj));
1221169689Skan  else
1222169689Skan    object_size = size_in_bytes (TREE_TYPE (obj));
1223169689Skan
1224169689Skan  if (TREE_CODE (obj) == STRING_CST)
1225169689Skan    varname = mf_build_string ("string literal");
1226169689Skan  else
1227169689Skan    varname = mf_build_string ("constant");
1228169689Skan
1229169689Skan  mudflap_register_call (obj, object_size, varname);
1230169689Skan}
1231169689Skan
1232169689Skan
1233169689Skan/* Emit any file-wide instrumentation.  */
1234169689Skanvoid
1235169689Skanmudflap_finish_file (void)
1236169689Skan{
1237169689Skan  tree ctor_statements = NULL_TREE;
1238169689Skan
1239169689Skan  /* No need to continue when there were errors.  */
1240169689Skan  if (errorcount != 0 || sorrycount != 0)
1241169689Skan    return;
1242169689Skan
1243169689Skan  /* Insert a call to __mf_init.  */
1244169689Skan  {
1245169689Skan    tree call2_stmt = build_function_call_expr (mf_init_fndecl, NULL_TREE);
1246169689Skan    append_to_statement_list (call2_stmt, &ctor_statements);
1247169689Skan  }
1248169689Skan
1249169689Skan  /* If appropriate, call __mf_set_options to pass along read-ignore mode.  */
1250169689Skan  if (flag_mudflap_ignore_reads)
1251169689Skan    {
1252169689Skan      tree arg = tree_cons (NULL_TREE,
1253169689Skan                            mf_build_string ("-ignore-reads"), NULL_TREE);
1254169689Skan      tree call_stmt = build_function_call_expr (mf_set_options_fndecl, arg);
1255169689Skan      append_to_statement_list (call_stmt, &ctor_statements);
1256169689Skan    }
1257169689Skan
1258169689Skan  /* Process all enqueued object decls.  */
1259169689Skan  if (deferred_static_decls)
1260169689Skan    {
1261169689Skan      size_t i;
1262169689Skan      tree obj;
1263169689Skan      for (i = 0; VEC_iterate (tree, deferred_static_decls, i, obj); i++)
1264169689Skan        {
1265169689Skan          gcc_assert (DECL_P (obj));
1266169689Skan
1267169689Skan          if (mf_marked_p (obj))
1268169689Skan            continue;
1269169689Skan
1270169689Skan          /* Omit registration for static unaddressed objects.  NB:
1271169689Skan             Perform registration for non-static objects regardless of
1272169689Skan             TREE_USED or TREE_ADDRESSABLE, because they may be used
1273169689Skan             from other compilation units.  */
1274169689Skan          if (! TREE_PUBLIC (obj) && ! TREE_ADDRESSABLE (obj))
1275169689Skan            continue;
1276169689Skan
1277169689Skan          if (! COMPLETE_TYPE_P (TREE_TYPE (obj)))
1278169689Skan            {
1279169689Skan              warning (0, "mudflap cannot track unknown size extern %qs",
1280169689Skan                       IDENTIFIER_POINTER (DECL_NAME (obj)));
1281169689Skan              continue;
1282169689Skan            }
1283169689Skan
1284169689Skan          mudflap_register_call (obj,
1285169689Skan                                 size_in_bytes (TREE_TYPE (obj)),
1286169689Skan                                 mf_varname_tree (obj));
1287169689Skan        }
1288169689Skan
1289169689Skan      VEC_truncate (tree, deferred_static_decls, 0);
1290169689Skan    }
1291169689Skan
1292169689Skan  /* Append all the enqueued registration calls.  */
1293169689Skan  if (enqueued_call_stmt_chain)
1294169689Skan    {
1295169689Skan      append_to_statement_list (enqueued_call_stmt_chain, &ctor_statements);
1296169689Skan      enqueued_call_stmt_chain = NULL_TREE;
1297169689Skan    }
1298169689Skan
1299169689Skan  cgraph_build_static_cdtor ('I', ctor_statements,
1300169689Skan                             MAX_RESERVED_INIT_PRIORITY-1);
1301169689Skan}
1302169689Skan
1303169689Skan
1304169689Skanstatic bool
1305169689Skangate_mudflap (void)
1306169689Skan{
1307169689Skan  return flag_mudflap != 0;
1308169689Skan}
1309169689Skan
1310169689Skanstruct tree_opt_pass pass_mudflap_1 =
1311169689Skan{
1312169689Skan  "mudflap1",                           /* name */
1313169689Skan  gate_mudflap,                         /* gate */
1314169689Skan  execute_mudflap_function_decls,       /* execute */
1315169689Skan  NULL,                                 /* sub */
1316169689Skan  NULL,                                 /* next */
1317169689Skan  0,                                    /* static_pass_number */
1318169689Skan  0,                                    /* tv_id */
1319169689Skan  PROP_gimple_any,                      /* properties_required */
1320169689Skan  0,                                    /* properties_provided */
1321169689Skan  0,                                    /* properties_destroyed */
1322169689Skan  0,                                    /* todo_flags_start */
1323169689Skan  TODO_dump_func,                       /* todo_flags_finish */
1324169689Skan  0					/* letter */
1325169689Skan};
1326169689Skan
1327169689Skanstruct tree_opt_pass pass_mudflap_2 =
1328169689Skan{
1329169689Skan  "mudflap2",                           /* name */
1330169689Skan  gate_mudflap,                         /* gate */
1331169689Skan  execute_mudflap_function_ops,         /* execute */
1332169689Skan  NULL,                                 /* sub */
1333169689Skan  NULL,                                 /* next */
1334169689Skan  0,                                    /* static_pass_number */
1335169689Skan  0,                                    /* tv_id */
1336169689Skan  PROP_gimple_leh,                      /* properties_required */
1337169689Skan  0,                                    /* properties_provided */
1338169689Skan  0,                                    /* properties_destroyed */
1339169689Skan  0,                                    /* todo_flags_start */
1340169689Skan  TODO_verify_flow | TODO_verify_stmts
1341169689Skan  | TODO_dump_func,                     /* todo_flags_finish */
1342169689Skan  0					/* letter */
1343169689Skan};
1344169689Skan
1345169689Skan#include "gt-tree-mudflap.h"
1346