* rtl.h (insn_note): Remove NOTE_INSN_PREDICTION.
[official-gcc.git] / gcc / tree-mudflap.c
blobbd1762005302ebd0e2210b051bd288b8058f8301
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>
6 This file is part of GCC.
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.
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.
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. */
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"
49 /* Internal function decls */
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);
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);
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);
69 /* ------------------------------------------------------------------------ */
70 /* Some generally helpful functions for mudflap instrumentation. */
72 /* Build a reference to a literal string. */
73 static tree
74 mf_build_string (const char *string)
76 size_t len = strlen (string);
77 tree result = mf_mark (build_string (len + 1, string));
79 TREE_TYPE (result)
80 = build_array_type (char_type_node,
81 build_index_type (build_int_2 (len, 0)));
82 TREE_CONSTANT (result) = 1;
83 TREE_INVARIANT (result) = 1;
84 TREE_READONLY (result) = 1;
85 TREE_STATIC (result) = 1;
87 result = build1 (ADDR_EXPR, build_pointer_type (char_type_node), result);
89 return mf_mark (result);
92 /* Create a properly typed STRING_CST node that describes the given
93 declaration. It will be used as an argument for __mf_register().
94 Try to construct a helpful string, including file/function/variable
95 name. */
97 static tree
98 mf_varname_tree (tree decl)
100 static pretty_printer buf_rec;
101 static int initialized = 0;
102 pretty_printer *buf = & buf_rec;
103 const char *buf_contents;
104 tree result;
106 if (decl == NULL_TREE)
107 abort ();
109 if (!initialized)
111 pp_construct (buf, /* prefix */ NULL, /* line-width */ 0);
112 initialized = 1;
114 pp_clear_output_area (buf);
116 /* Add FILENAME[:LINENUMBER]. */
118 expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (decl));
119 const char *sourcefile;
120 unsigned sourceline = xloc.line;
122 sourcefile = xloc.file;
123 if (sourcefile == NULL && current_function_decl != NULL_TREE)
124 sourcefile = DECL_SOURCE_FILE (current_function_decl);
125 if (sourcefile == NULL)
126 sourcefile = "<unknown file>";
128 pp_string (buf, sourcefile);
130 if (sourceline != 0)
132 pp_string (buf, ":");
133 pp_decimal_int (buf, sourceline);
137 if (current_function_decl != NULL_TREE)
139 /* Add (FUNCTION): */
140 pp_string (buf, " (");
142 const char *funcname = NULL;
143 if (DECL_NAME (current_function_decl))
144 funcname = lang_hooks.decl_printable_name (current_function_decl, 1);
145 if (funcname == NULL)
146 funcname = "anonymous fn";
148 pp_string (buf, funcname);
150 pp_string (buf, ") ");
152 else
153 pp_string (buf, " ");
155 /* Add <variable-declaration>, possibly demangled. */
157 const char *declname = NULL;
159 if (strcmp ("GNU C++", lang_hooks.name) == 0 &&
160 DECL_NAME (decl) != NULL)
162 /* The gcc/cp decl_printable_name hook doesn't do as good a job as
163 the libiberty demangler. */
164 declname = cplus_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)),
165 DMGL_AUTO | DMGL_VERBOSE);
168 if (declname == NULL)
169 declname = lang_hooks.decl_printable_name (decl, 3);
171 if (declname == NULL)
172 declname = "<unnamed variable>";
174 pp_string (buf, declname);
177 /* Return the lot as a new STRING_CST. */
178 buf_contents = pp_base_formatted_text (buf);
179 result = mf_build_string (buf_contents);
180 pp_clear_output_area (buf);
182 return result;
186 /* And another friend, for producing a simpler message. */
188 static tree
189 mf_file_function_line_tree (location_t location)
191 expanded_location xloc = expand_location (location);
192 const char *file = NULL, *colon, *line, *op, *name, *cp;
193 char linebuf[18];
194 char *string;
195 tree result;
197 /* Add FILENAME[:LINENUMBER]. */
198 file = xloc.file;
199 if (file == NULL && current_function_decl != NULL_TREE)
200 file = DECL_SOURCE_FILE (current_function_decl);
201 if (file == NULL)
202 file = "<unknown file>";
204 if (xloc.line > 0)
206 sprintf (linebuf, "%d", xloc.line);
207 colon = ":";
208 line = linebuf;
210 else
211 colon = line = "";
213 /* Add (FUNCTION). */
214 name = lang_hooks.decl_printable_name (current_function_decl, 1);
215 if (name)
217 op = " (";
218 cp = ")";
220 else
221 op = name = cp = "";
223 string = concat (file, colon, line, op, name, cp, NULL);
224 result = mf_build_string (string);
225 free (string);
227 return result;
231 /* global tree nodes */
233 /* Global tree objects for global variables and functions exported by
234 mudflap runtime library. mf_init_extern_trees must be called
235 before using these. */
237 /* uintptr_t (usually "unsigned long") */
238 static GTY (()) tree mf_uintptr_type;
240 /* struct __mf_cache { uintptr_t low; uintptr_t high; }; */
241 static GTY (()) tree mf_cache_struct_type;
243 /* struct __mf_cache * const */
244 static GTY (()) tree mf_cache_structptr_type;
246 /* extern struct __mf_cache __mf_lookup_cache []; */
247 static GTY (()) tree mf_cache_array_decl;
249 /* extern unsigned char __mf_lc_shift; */
250 static GTY (()) tree mf_cache_shift_decl;
252 /* extern uintptr_t __mf_lc_mask; */
253 static GTY (()) tree mf_cache_mask_decl;
255 /* Their function-scope local shadows, used in single-threaded mode only. */
257 /* auto const unsigned char __mf_lc_shift_l; */
258 static GTY (()) tree mf_cache_shift_decl_l;
260 /* auto const uintptr_t __mf_lc_mask_l; */
261 static GTY (()) tree mf_cache_mask_decl_l;
263 /* extern void __mf_check (void *ptr, size_t sz, int type, const char *); */
264 static GTY (()) tree mf_check_fndecl;
266 /* extern void __mf_register (void *ptr, size_t sz, int type, const char *); */
267 static GTY (()) tree mf_register_fndecl;
269 /* extern void __mf_unregister (void *ptr, size_t sz, int type); */
270 static GTY (()) tree mf_unregister_fndecl;
272 /* extern void __mf_init (); */
273 static GTY (()) tree mf_init_fndecl;
275 /* extern int __mf_set_options (const char*); */
276 static GTY (()) tree mf_set_options_fndecl;
279 /* Helper for mudflap_init: construct a decl with the given category,
280 name, and type, mark it an external reference, and pushdecl it. */
281 static inline tree
282 mf_make_builtin (enum tree_code category, const char *name, tree type)
284 tree decl = mf_mark (build_decl (category, get_identifier (name), type));
285 TREE_PUBLIC (decl) = 1;
286 DECL_EXTERNAL (decl) = 1;
287 lang_hooks.decls.pushdecl (decl);
288 return decl;
291 /* Helper for mudflap_init: construct a tree corresponding to the type
292 struct __mf_cache { uintptr_t low; uintptr_t high; };
293 where uintptr_t is the FIELD_TYPE argument. */
294 static inline tree
295 mf_make_mf_cache_struct_type (tree field_type)
297 /* There is, abominably, no language-independent way to construct a
298 RECORD_TYPE. So we have to call the basic type construction
299 primitives by hand. */
300 tree fieldlo = build_decl (FIELD_DECL, get_identifier ("low"), field_type);
301 tree fieldhi = build_decl (FIELD_DECL, get_identifier ("high"), field_type);
303 tree struct_type = make_node (RECORD_TYPE);
304 DECL_CONTEXT (fieldlo) = struct_type;
305 DECL_CONTEXT (fieldhi) = struct_type;
306 TREE_CHAIN (fieldlo) = fieldhi;
307 TYPE_FIELDS (struct_type) = fieldlo;
308 TYPE_NAME (struct_type) = get_identifier ("__mf_cache");
309 layout_type (struct_type);
311 return struct_type;
314 #define build_function_type_0(rtype) \
315 build_function_type (rtype, void_list_node)
316 #define build_function_type_1(rtype, arg1) \
317 build_function_type (rtype, tree_cons (0, arg1, void_list_node))
318 #define build_function_type_3(rtype, arg1, arg2, arg3) \
319 build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2, \
320 tree_cons (0, arg3, void_list_node))))
321 #define build_function_type_4(rtype, arg1, arg2, arg3, arg4) \
322 build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2, \
323 tree_cons (0, arg3, tree_cons (0, arg4, \
324 void_list_node)))))
326 /* Initialize the global tree nodes that correspond to mf-runtime.h
327 declarations. */
328 void
329 mudflap_init (void)
331 static bool done = false;
332 tree mf_const_string_type;
333 tree mf_cache_array_type;
334 tree mf_check_register_fntype;
335 tree mf_unregister_fntype;
336 tree mf_init_fntype;
337 tree mf_set_options_fntype;
339 if (done)
340 return;
341 done = true;
343 mf_uintptr_type = lang_hooks.types.type_for_mode (ptr_mode,
344 /*unsignedp=*/true);
345 mf_const_string_type
346 = build_pointer_type (build_qualified_type
347 (char_type_node, TYPE_QUAL_CONST));
349 mf_cache_struct_type = mf_make_mf_cache_struct_type (mf_uintptr_type);
350 mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type);
351 mf_cache_array_type = build_array_type (mf_cache_struct_type, 0);
352 mf_check_register_fntype =
353 build_function_type_4 (void_type_node, ptr_type_node, size_type_node,
354 integer_type_node, mf_const_string_type);
355 mf_unregister_fntype =
356 build_function_type_3 (void_type_node, ptr_type_node, size_type_node,
357 integer_type_node);
358 mf_init_fntype =
359 build_function_type_0 (void_type_node);
360 mf_set_options_fntype =
361 build_function_type_1 (integer_type_node, mf_const_string_type);
363 mf_cache_array_decl = mf_make_builtin (VAR_DECL, "__mf_lookup_cache",
364 mf_cache_array_type);
365 mf_cache_shift_decl = mf_make_builtin (VAR_DECL, "__mf_lc_shift",
366 unsigned_char_type_node);
367 mf_cache_mask_decl = mf_make_builtin (VAR_DECL, "__mf_lc_mask",
368 mf_uintptr_type);
369 mf_check_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_check",
370 mf_check_register_fntype);
371 mf_register_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_register",
372 mf_check_register_fntype);
373 mf_unregister_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_unregister",
374 mf_unregister_fntype);
375 mf_init_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_init",
376 mf_init_fntype);
377 mf_set_options_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_set_options",
378 mf_set_options_fntype);
380 #undef build_function_type_4
381 #undef build_function_type_3
382 #undef build_function_type_1
383 #undef build_function_type_0
386 /* ------------------------------------------------------------------------ */
387 /* Memory reference transforms. Perform the mudflap indirection-related
388 tree transforms on the current function.
390 This is the second part of the mudflap instrumentation. It works on
391 low-level GIMPLE using the CFG, because we want to run this pass after
392 tree optimizations have been performed, but we have to preserve the CFG
393 for expansion from trees to RTL. */
395 static void
396 execute_mudflap_function_ops (void)
398 if (mf_marked_p (current_function_decl))
399 return;
401 push_gimplify_context ();
403 /* In multithreaded mode, don't cache the lookup cache parameters. */
404 if (! flag_mudflap_threads)
405 mf_decl_cache_locals ();
407 mf_xform_derefs ();
409 if (! flag_mudflap_threads)
410 mf_decl_clear_locals ();
412 pop_gimplify_context (NULL);
415 /* Create and initialize local shadow variables for the lookup cache
416 globals. Put their decls in the *_l globals for use by
417 mf_build_check_statement_for. */
419 static void
420 mf_decl_cache_locals (void)
422 tree t, shift_init_stmts, mask_init_stmts;
423 tree_stmt_iterator tsi;
425 /* Build the cache vars. */
426 mf_cache_shift_decl_l
427 = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_shift_decl),
428 "__mf_lookup_shift_l"));
430 mf_cache_mask_decl_l
431 = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_mask_decl),
432 "__mf_lookup_mask_l"));
434 /* Build initialization nodes for the cache vars. We just load the
435 globals into the cache variables. */
436 t = build (MODIFY_EXPR, TREE_TYPE (mf_cache_shift_decl_l),
437 mf_cache_shift_decl_l, mf_cache_shift_decl);
438 SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
439 gimplify_to_stmt_list (&t);
440 shift_init_stmts = t;
442 t = build (MODIFY_EXPR, TREE_TYPE (mf_cache_mask_decl_l),
443 mf_cache_mask_decl_l, mf_cache_mask_decl);
444 SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
445 gimplify_to_stmt_list (&t);
446 mask_init_stmts = t;
448 /* Anticipating multiple entry points, we insert the cache vars
449 initializers in each successor of the ENTRY_BLOCK_PTR. */
450 for (tsi = tsi_start (shift_init_stmts);
451 ! tsi_end_p (tsi);
452 tsi_next (&tsi))
453 insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
455 for (tsi = tsi_start (mask_init_stmts);
456 ! tsi_end_p (tsi);
457 tsi_next (&tsi))
458 insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
459 bsi_commit_edge_inserts (NULL);
463 static void
464 mf_decl_clear_locals (void)
466 /* Unset local shadows. */
467 mf_cache_shift_decl_l = NULL_TREE;
468 mf_cache_mask_decl_l = NULL_TREE;
471 static void
472 mf_build_check_statement_for (tree addr, tree size,
473 block_stmt_iterator *instr_bsi,
474 location_t *locus, tree dirflag)
476 tree_stmt_iterator head, tsi;
477 tree ptrtype = TREE_TYPE (addr);
478 block_stmt_iterator bsi;
479 basic_block cond_bb, then_bb, join_bb;
480 edge e;
481 tree cond, t, u, v, l1, l2;
482 tree mf_value;
483 tree mf_base;
484 tree mf_elem;
486 /* We first need to split the current basic block, and start altering
487 the CFG. This allows us to insert the statements we're about to
488 construct into the right basic blocks. The label l1 is the label
489 of the block for the THEN clause of the conditional jump we're
490 about to construct, and l2 is the ELSE clause, which is just the
491 continuation of the old statement stream. */
492 l1 = create_artificial_label ();
493 l2 = create_artificial_label ();
494 cond_bb = bb_for_stmt (bsi_stmt (*instr_bsi));
495 bsi = *instr_bsi;
496 bsi_prev (&bsi);
497 if (! bsi_end_p (bsi))
499 e = split_block (cond_bb, bsi_stmt (bsi));
500 cond_bb = e->src;
501 join_bb = e->dest;
503 else
505 join_bb = cond_bb;
506 cond_bb = create_empty_bb (join_bb->prev_bb);
507 e = make_edge (cond_bb, join_bb, 0);
509 e->flags = EDGE_FALSE_VALUE;
510 then_bb = create_empty_bb (cond_bb);
511 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
512 make_edge (then_bb, join_bb, EDGE_FALLTHRU);
514 /* We expect that the conditional jump we will construct will not
515 be taken very often as it basically is an exception condition. */
516 predict_edge_def (then_bb->pred, PRED_MUDFLAP, NOT_TAKEN);
518 /* Update dominance info. Note that bb_join's data was
519 updated by split_block. */
520 if (dom_computed[CDI_DOMINATORS] >= DOM_CONS_OK)
522 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
523 set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb);
526 /* Build our local variables. */
527 mf_value = create_tmp_var (ptrtype, "__mf_value");
528 mf_elem = create_tmp_var (mf_cache_structptr_type, "__mf_elem");
529 mf_base = create_tmp_var (mf_uintptr_type, "__mf_base");
531 /* Build: __mf_value = <address expression>. */
532 t = build (MODIFY_EXPR, void_type_node, mf_value, unshare_expr (addr));
533 SET_EXPR_LOCUS (t, locus);
534 gimplify_to_stmt_list (&t);
535 head = tsi_start (t);
536 tsi = tsi_last (t);
538 /* Build: __mf_base = (uintptr_t)__mf_value. */
539 t = build (MODIFY_EXPR, void_type_node, mf_base,
540 build1 (NOP_EXPR, mf_uintptr_type, mf_value));
541 SET_EXPR_LOCUS (t, locus);
542 gimplify_to_stmt_list (&t);
543 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
545 /* Build: __mf_elem = &__mf_lookup_cache [(__mf_base >> __mf_shift)
546 & __mf_mask]. */
547 t = build (RSHIFT_EXPR, mf_uintptr_type, mf_base,
548 (flag_mudflap_threads ? mf_cache_shift_decl : mf_cache_shift_decl_l));
549 t = build (BIT_AND_EXPR, mf_uintptr_type, t,
550 (flag_mudflap_threads ? mf_cache_mask_decl : mf_cache_mask_decl_l));
551 t = build (ARRAY_REF,
552 TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
553 mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
554 t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
555 t = build (MODIFY_EXPR, void_type_node, mf_elem, t);
556 SET_EXPR_LOCUS (t, locus);
557 gimplify_to_stmt_list (&t);
558 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
560 /* Quick validity check.
562 if (__mf_elem->low > __mf_base
563 || (__mf_elem_high < __mf_base + sizeof(T) - 1))
565 __mf_check ();
566 ... and only if single-threaded:
567 __mf_lookup_shift_1 = f...;
568 __mf_lookup_mask_l = ...;
571 It is expected that this body of code is rarely executed so we mark
572 the edge to the THEN clause of the conditional jump as unlikely. */
574 /* Construct t <-- '__mf_elem->low > __mf_base'. */
575 t = build (COMPONENT_REF, mf_uintptr_type,
576 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
577 TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
578 t = build (GT_EXPR, boolean_type_node, t, mf_base);
580 /* Construct '__mf_elem->high < __mf_base + sizeof(T) - 1'.
582 First build:
583 1) u <-- '__mf_elem->high'
584 2) v <-- '__mf_base + sizeof (T) - 1'.
586 Then build 'u <-- (u < v). */
589 u = build (COMPONENT_REF, mf_uintptr_type,
590 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
591 TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
593 v = convert (mf_uintptr_type,
594 size_binop (MINUS_EXPR, size, size_one_node));
595 v = fold (build (PLUS_EXPR, mf_uintptr_type, mf_base, v));
597 u = build (LT_EXPR, boolean_type_node, u, v);
599 /* Build the composed conditional: t <-- 't || u'. Then store the
600 result of the evaluation of 't' in a temporary variable which we
601 can use as the condition for the conditional jump. */
602 t = build (TRUTH_OR_EXPR, boolean_type_node, t, u);
603 cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
604 t = build (MODIFY_EXPR, boolean_type_node, cond, t);
605 gimplify_to_stmt_list (&t);
606 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
608 /* Build the conditional jump. 'cond' is just a temporary so we can
609 simply build a void COND_EXPR. We do need labels in both arms though. */
610 t = build (COND_EXPR, void_type_node, cond,
611 build (GOTO_EXPR, void_type_node, tree_block_label (then_bb)),
612 build (GOTO_EXPR, void_type_node, tree_block_label (join_bb)));
613 SET_EXPR_LOCUS (t, locus);
614 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
616 /* At this point, after so much hard work, we have only constructed
617 the conditional jump,
619 if (__mf_elem->low > __mf_base
620 || (__mf_elem_high < __mf_base + sizeof(T) - 1))
622 The lowered GIMPLE tree representing this code is in the statement
623 list starting at 'head'.
625 We can insert this now in the current basic block, ie. the one that
626 the statement we're instrumenting was originally in. */
627 bsi = bsi_last (cond_bb);
628 for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
629 bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
631 /* Now build up the body of the cache-miss handling:
633 __mf_check();
634 refresh *_l vars.
636 This is the body of the conditional. */
638 u = tree_cons (NULL_TREE,
639 mf_file_function_line_tree (locus == NULL ? UNKNOWN_LOCATION
640 : *locus),
641 NULL_TREE);
642 u = tree_cons (NULL_TREE, dirflag, u);
643 u = tree_cons (NULL_TREE, size, u);
644 u = tree_cons (NULL_TREE, mf_value, u);
645 t = build_function_call_expr (mf_check_fndecl, u);
646 gimplify_to_stmt_list (&t);
647 head = tsi_start (t);
648 tsi = tsi_last (t);
650 if (! flag_mudflap_threads)
652 t = build (MODIFY_EXPR, void_type_node,
653 mf_cache_shift_decl_l, mf_cache_shift_decl);
654 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
656 t = build (MODIFY_EXPR, void_type_node,
657 mf_cache_mask_decl_l, mf_cache_mask_decl);
658 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
661 /* Insert the check code in the THEN block. */
662 bsi = bsi_start (then_bb);
663 for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
664 bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
666 *instr_bsi = bsi_start (join_bb);
667 bsi_next (instr_bsi);
670 static void
671 mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
672 location_t *locus, tree dirflag)
674 tree type, ptr_type, addr, size, t;
676 /* Don't instrument read operations. */
677 if (dirflag == integer_zero_node && flag_mudflap_ignore_reads)
678 return;
680 t = *tp;
681 type = TREE_TYPE (t);
682 size = TYPE_SIZE_UNIT (type);
684 switch (TREE_CODE (t))
686 case ARRAY_REF:
688 /* Omit checking if we can statically determine that the access is
689 valid. For non-addressable local arrays this is not optional,
690 since we won't have called __mf_register for the object. */
691 tree op0, op1;
693 op0 = TREE_OPERAND (t, 0);
694 op1 = TREE_OPERAND (t, 1);
695 while (TREE_CODE (op1) == INTEGER_CST)
697 tree dom = TYPE_DOMAIN (TREE_TYPE (op0));
699 /* Test for index in range. Break if not. */
700 if (!dom
701 || (! TYPE_MIN_VALUE (dom)
702 || ! really_constant_p (TYPE_MIN_VALUE (dom)))
703 || (! TYPE_MAX_VALUE (dom)
704 || ! really_constant_p (TYPE_MAX_VALUE (dom)))
705 || (tree_int_cst_lt (op1, TYPE_MIN_VALUE (dom))
706 || tree_int_cst_lt (TYPE_MAX_VALUE (dom), op1)))
707 break;
709 /* If we're looking at a non-external VAR_DECL, then the
710 access must be ok. */
711 if (TREE_CODE (op0) == VAR_DECL && !DECL_EXTERNAL (op0))
712 return;
714 /* Only continue if we're still looking at an array. */
715 if (TREE_CODE (op0) != ARRAY_REF)
716 break;
718 op1 = TREE_OPERAND (op0, 1);
719 op0 = TREE_OPERAND (op0, 0);
722 /* If we got here, we couldn't statically the check. */
723 ptr_type = build_pointer_type (type);
724 addr = build1 (ADDR_EXPR, ptr_type, t);
726 break;
728 case INDIRECT_REF:
729 addr = TREE_OPERAND (t, 0);
730 ptr_type = TREE_TYPE (addr);
731 break;
733 case ARRAY_RANGE_REF:
734 warning ("mudflap checking not yet implemented for ARRAY_RANGE_REF");
735 return;
737 case COMPONENT_REF:
739 tree field;
741 /* If we're not dereferencing something, then the access
742 must be ok. */
743 if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
744 return;
746 field = TREE_OPERAND (t, 1);
748 /* If we're looking at a bit field, then we can't take its address
749 with ADDR_EXPR -- lang_hooks.mark_addressable will error. Do
750 things the hard way with PLUS. */
751 if (DECL_BIT_FIELD_TYPE (field))
753 if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST)
754 size = DECL_SIZE_UNIT (field);
756 addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
757 addr = fold_convert (ptr_type_node, addr);
758 addr = fold (build (PLUS_EXPR, ptr_type_node,
759 addr, fold_convert (ptr_type_node,
760 byte_position (field))));
762 else
764 ptr_type = build_pointer_type (type);
765 addr = build1 (ADDR_EXPR, ptr_type, t);
768 break;
770 case BIT_FIELD_REF:
772 tree ofs, rem, bpu;
774 /* If we're not dereferencing something, then the access
775 must be ok. */
776 if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
777 return;
779 bpu = bitsize_int (BITS_PER_UNIT);
780 ofs = convert (bitsizetype, TREE_OPERAND (t, 2));
781 rem = size_binop (TRUNC_MOD_EXPR, ofs, bpu);
782 ofs = size_binop (TRUNC_DIV_EXPR, ofs, bpu);
784 size = convert (bitsizetype, TREE_OPERAND (t, 1));
785 size = size_binop (PLUS_EXPR, size, rem);
786 size = size_binop (CEIL_DIV_EXPR, size, bpu);
787 size = convert (sizetype, size);
789 addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
790 addr = convert (ptr_type_node, addr);
791 addr = fold (build (PLUS_EXPR, ptr_type_node, addr, ofs));
793 break;
795 default:
796 return;
799 mf_build_check_statement_for (addr, size, iter, locus, dirflag);
802 static void
803 mf_xform_derefs (void)
805 basic_block bb, next;
806 block_stmt_iterator i;
807 int saved_last_basic_block = last_basic_block;
809 bb = ENTRY_BLOCK_PTR ->next_bb;
812 next = bb->next_bb;
813 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
815 tree s = bsi_stmt (i);
817 /* Only a few GIMPLE statements can reference memory. */
818 switch (TREE_CODE (s))
820 case MODIFY_EXPR:
821 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
822 integer_one_node);
823 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 1), EXPR_LOCUS (s),
824 integer_zero_node);
825 break;
827 case RETURN_EXPR:
828 if (TREE_OPERAND (s, 0) != NULL_TREE)
830 if (TREE_CODE (TREE_OPERAND (s, 0)) == MODIFY_EXPR)
831 mf_xform_derefs_1 (&i, &TREE_OPERAND (TREE_OPERAND (s, 0), 1),
832 EXPR_LOCUS (s), integer_zero_node);
833 else
834 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
835 integer_zero_node);
837 break;
839 default:
843 bb = next;
845 while (bb && bb->index <= saved_last_basic_block);
848 /* ------------------------------------------------------------------------ */
849 /* ADDR_EXPR transforms. Perform the declaration-related mudflap tree
850 transforms on the current function.
852 This is the first part of the mudflap instrumentation. It works on
853 high-level GIMPLE because after lowering, all variables are moved out
854 of their BIND_EXPR binding context, and we lose liveness information
855 for the declarations we wish to instrument. */
857 static void
858 execute_mudflap_function_decls (void)
860 if (mf_marked_p (current_function_decl))
861 return;
863 push_gimplify_context ();
865 mf_xform_decls (DECL_SAVED_TREE (current_function_decl),
866 DECL_ARGUMENTS (current_function_decl));
868 pop_gimplify_context (NULL);
871 /* This struct is passed between mf_xform_decls to store state needed
872 during the traversal searching for objects that have their
873 addresses taken. */
874 struct mf_xform_decls_data
876 tree param_decls;
880 /* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of
881 _DECLs if appropriate. Arrange to call the __mf_register function
882 now, and the __mf_unregister function later for each. */
883 static void
884 mx_register_decls (tree decl, tree *stmt_list)
886 tree finally_stmts = NULL_TREE;
887 tree_stmt_iterator initially_stmts = tsi_start (*stmt_list);
889 while (decl != NULL_TREE)
891 /* Eligible decl? */
892 if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
893 /* It must be a non-external, automatic variable. */
894 && ! DECL_EXTERNAL (decl)
895 && ! TREE_STATIC (decl)
896 /* The decl must have its address taken. */
897 && TREE_ADDRESSABLE (decl)
898 /* The type of the variable must be complete. */
899 && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
900 /* Don't process the same decl twice. */
901 && ! mf_marked_p (decl))
903 tree size = NULL_TREE, variable_name;
904 tree unregister_fncall, unregister_fncall_params;
905 tree register_fncall, register_fncall_params;
907 if (DECL_DEFER_OUTPUT (decl))
909 /* Oh no ... it's probably a variable-length array (VLA).
910 The size and address cannot be computed by merely
911 looking at the DECL. See gimplify_decl_stmt for the
912 method by which VLA declarations turn into calls to
913 BUILT_IN_STACK_ALLOC. We assume that multiple
914 VLAs declared later in the same block get allocation
915 code later than the others. */
916 tree stack_alloc_call = NULL_TREE;
918 while(! tsi_end_p (initially_stmts))
920 tree t = tsi_stmt (initially_stmts);
922 tree call = NULL_TREE;
923 if (TREE_CODE (t) == CALL_EXPR)
924 call = t;
925 else if (TREE_CODE (t) == MODIFY_EXPR &&
926 TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR)
927 call = TREE_OPERAND (t, 1);
928 else if (TREE_CODE (t) == TRY_FINALLY_EXPR)
930 /* We hope that this is the try/finally block sometimes
931 constructed by gimplify_bind_expr() for a BIND_EXPR
932 that contains VLAs. This very naive recursion
933 appears to be sufficient. */
934 initially_stmts = tsi_start (TREE_OPERAND (t, 0));
937 if (call != NULL_TREE)
939 if (TREE_CODE (TREE_OPERAND(call, 0)) == ADDR_EXPR &&
940 TREE_OPERAND (TREE_OPERAND (call, 0), 0) ==
941 implicit_built_in_decls [BUILT_IN_STACK_ALLOC])
943 tree stack_alloc_args = TREE_OPERAND (call, 1);
944 tree stack_alloc_op1 = TREE_VALUE (stack_alloc_args);
945 tree stack_alloc_op2 = TREE_VALUE (TREE_CHAIN (stack_alloc_args));
947 if (TREE_CODE (stack_alloc_op1) == ADDR_EXPR &&
948 TREE_OPERAND (stack_alloc_op1, 0) == decl)
950 /* Got it! */
951 size = stack_alloc_op2;
952 stack_alloc_call = call;
953 /* Advance iterator to point past this allocation call. */
954 tsi_next (&initially_stmts);
955 break;
960 tsi_next (&initially_stmts);
963 if (stack_alloc_call == NULL_TREE)
965 warning ("mudflap cannot handle variable-sized declaration `%s'",
966 IDENTIFIER_POINTER (DECL_NAME (decl)));
967 break;
970 else
972 size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
975 /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
976 unregister_fncall_params =
977 tree_cons (NULL_TREE,
978 convert (ptr_type_node,
979 mf_mark (build1 (ADDR_EXPR,
980 build_pointer_type (TREE_TYPE (decl)),
981 decl))),
982 tree_cons (NULL_TREE,
983 size,
984 tree_cons (NULL_TREE,
985 build_int_2 (3, 0), /* __MF_TYPE_STACK */
986 NULL_TREE)));
987 /* __mf_unregister (...) */
988 unregister_fncall = build_function_call_expr (mf_unregister_fndecl,
989 unregister_fncall_params);
991 /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, "name") */
992 variable_name = mf_varname_tree (decl);
993 register_fncall_params =
994 tree_cons (NULL_TREE,
995 convert (ptr_type_node,
996 mf_mark (build1 (ADDR_EXPR,
997 build_pointer_type (TREE_TYPE (decl)),
998 decl))),
999 tree_cons (NULL_TREE,
1000 size,
1001 tree_cons (NULL_TREE,
1002 build_int_2 (3, 0), /* __MF_TYPE_STACK */
1003 tree_cons (NULL_TREE,
1004 variable_name,
1005 NULL_TREE))));
1007 /* __mf_register (...) */
1008 register_fncall = build_function_call_expr (mf_register_fndecl,
1009 register_fncall_params);
1011 /* Accumulate the two calls. */
1012 /* ??? Set EXPR_LOCATION. */
1013 gimplify_stmt (&register_fncall);
1014 gimplify_stmt (&unregister_fncall);
1016 /* Add the __mf_register call at the current appending point. */
1017 if (tsi_end_p (initially_stmts))
1018 internal_error ("mudflap ran off end of BIND_EXPR body");
1019 tsi_link_before (&initially_stmts, register_fncall, TSI_SAME_STMT);
1021 /* Accumulate the FINALLY piece. */
1022 append_to_statement_list (unregister_fncall, &finally_stmts);
1024 mf_mark (decl);
1027 decl = TREE_CHAIN (decl);
1030 /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
1031 if (finally_stmts != NULL_TREE)
1033 tree t = build (TRY_FINALLY_EXPR, void_type_node,
1034 *stmt_list, finally_stmts);
1035 *stmt_list = NULL;
1036 append_to_statement_list (t, stmt_list);
1041 /* Process every variable mentioned in BIND_EXPRs. */
1042 static tree
1043 mx_xfn_xform_decls (tree *t, int *continue_p, void *data)
1045 struct mf_xform_decls_data* d = (struct mf_xform_decls_data*) data;
1047 if (*t == NULL_TREE || *t == error_mark_node)
1049 *continue_p = 0;
1050 return NULL_TREE;
1053 *continue_p = 1;
1055 switch (TREE_CODE (*t))
1057 case BIND_EXPR:
1059 /* Process function parameters now (but only once). */
1060 mx_register_decls (d->param_decls, &BIND_EXPR_BODY (*t));
1061 d->param_decls = NULL_TREE;
1063 mx_register_decls (BIND_EXPR_VARS (*t), &BIND_EXPR_BODY (*t));
1065 break;
1067 default:
1068 break;
1071 return NULL;
1074 /* Perform the object lifetime tracking mudflap transform on the given function
1075 tree. The tree is mutated in place, with possibly copied subtree nodes.
1077 For every auto variable declared, if its address is ever taken
1078 within the function, then supply its lifetime to the mudflap
1079 runtime with the __mf_register and __mf_unregister calls.
1082 static void
1083 mf_xform_decls (tree fnbody, tree fnparams)
1085 struct mf_xform_decls_data d;
1086 d.param_decls = fnparams;
1087 walk_tree_without_duplicates (&fnbody, mx_xfn_xform_decls, &d);
1091 /* ------------------------------------------------------------------------ */
1092 /* Externally visible mudflap functions. */
1095 /* Mark and return the given tree node to prevent further mudflap
1096 transforms. */
1097 static GTY ((param_is (union tree_node))) htab_t marked_trees = NULL;
1099 tree
1100 mf_mark (tree t)
1102 void **slot;
1104 if (marked_trees == NULL)
1105 marked_trees = htab_create_ggc (31, htab_hash_pointer, htab_eq_pointer, NULL);
1107 slot = htab_find_slot (marked_trees, t, INSERT);
1108 *slot = t;
1109 return t;
1113 mf_marked_p (tree t)
1115 void *entry;
1117 if (marked_trees == NULL)
1118 return 0;
1120 entry = htab_find (marked_trees, t);
1121 return (entry != NULL);
1124 /* Remember given node as a static of some kind: global data,
1125 function-scope static, or an anonymous constant. Its assembler
1126 label is given. */
1128 /* A list of globals whose incomplete declarations we encountered.
1129 Instead of emitting the __mf_register call for them here, it's
1130 delayed until program finish time. If they're still incomplete by
1131 then, warnings are emitted. */
1133 static GTY (()) varray_type deferred_static_decls;
1135 /* A list of statements for calling __mf_register() at startup time. */
1136 static GTY (()) tree enqueued_call_stmt_chain;
1138 static void
1139 mudflap_register_call (tree obj, tree object_size, tree varname)
1141 tree arg, args, call_stmt;
1143 args = tree_cons (NULL_TREE, varname, NULL_TREE);
1145 arg = build_int_2 (4, 0); /* __MF_TYPE_STATIC */
1146 args = tree_cons (NULL_TREE, arg, args);
1148 arg = convert (size_type_node, object_size);
1149 args = tree_cons (NULL_TREE, arg, args);
1151 arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj);
1152 arg = convert (ptr_type_node, arg);
1153 args = tree_cons (NULL_TREE, arg, args);
1155 call_stmt = build_function_call_expr (mf_register_fndecl, args);
1157 append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
1160 void
1161 mudflap_enqueue_decl (tree obj)
1163 if (mf_marked_p (obj))
1164 return;
1166 /* We don't need to process variable decls that are internally
1167 generated extern. If we did, we'd end up with warnings for them
1168 during mudflap_finish_file (). That would confuse the user,
1169 since the text would refer to variables that don't show up in the
1170 user's source code. */
1171 if (DECL_P (obj) && DECL_EXTERNAL (obj) && DECL_ARTIFICIAL (obj))
1172 return;
1174 if (COMPLETE_TYPE_P (TREE_TYPE (obj)))
1176 tree object_size;
1178 mf_mark (obj);
1180 object_size = size_in_bytes (TREE_TYPE (obj));
1182 if (dump_file)
1184 fprintf (dump_file, "enqueue_decl obj=`");
1185 print_generic_expr (dump_file, obj, dump_flags);
1186 fprintf (dump_file, "' size=");
1187 print_generic_expr (dump_file, object_size, dump_flags);
1188 fprintf (dump_file, "\n");
1191 /* NB: the above condition doesn't require TREE_USED or
1192 TREE_ADDRESSABLE. That's because this object may be a global
1193 only used from other compilation units. XXX: Maybe static
1194 objects could require those attributes being set. */
1196 mudflap_register_call (obj, object_size, mf_varname_tree (obj));
1198 else
1200 size_t i;
1202 if (! deferred_static_decls)
1203 VARRAY_TREE_INIT (deferred_static_decls, 10, "deferred static list");
1205 /* Ugh, linear search... */
1206 for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
1207 if (VARRAY_TREE (deferred_static_decls, i) == obj)
1209 warning ("mudflap cannot track lifetime of `%s'",
1210 IDENTIFIER_POINTER (DECL_NAME (obj)));
1211 return;
1214 VARRAY_PUSH_TREE (deferred_static_decls, obj);
1218 void
1219 mudflap_enqueue_constant (tree obj)
1221 tree object_size, varname;
1223 if (mf_marked_p (obj))
1224 return;
1226 if (TREE_CODE (obj) == STRING_CST)
1227 object_size = build_int_2 (TREE_STRING_LENGTH (obj), 0);
1228 else
1229 object_size = size_in_bytes (TREE_TYPE (obj));
1231 if (dump_file)
1233 fprintf (dump_file, "enqueue_constant obj=`");
1234 print_generic_expr (dump_file, obj, dump_flags);
1235 fprintf (dump_file, "' size=");
1236 print_generic_expr (dump_file, object_size, dump_flags);
1237 fprintf (dump_file, "\n");
1240 if (TREE_CODE (obj) == STRING_CST)
1241 varname = mf_build_string ("string literal");
1242 else
1243 varname = mf_build_string ("constant");
1245 mudflap_register_call (obj, object_size, varname);
1249 /* Emit any file-wide instrumentation. */
1250 void
1251 mudflap_finish_file (void)
1253 tree ctor_statements = NULL_TREE;
1255 /* Try to give the deferred objects one final try. */
1256 if (deferred_static_decls)
1258 size_t i;
1260 for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
1262 tree obj = VARRAY_TREE (deferred_static_decls, i);
1264 /* Call enqueue_decl again on the same object it has previously
1265 put into the table. (It won't modify the table this time, so
1266 infinite iteration is not a problem.) */
1267 mudflap_enqueue_decl (obj);
1270 VARRAY_CLEAR (deferred_static_decls);
1273 /* Insert a call to __mf_init. */
1275 tree call2_stmt = build_function_call_expr (mf_init_fndecl, NULL_TREE);
1276 append_to_statement_list (call2_stmt, &ctor_statements);
1279 /* If appropriate, call __mf_set_options to pass along read-ignore mode. */
1280 if (flag_mudflap_ignore_reads)
1282 tree arg = tree_cons (NULL_TREE,
1283 mf_build_string ("-ignore-reads"), NULL_TREE);
1284 tree call_stmt = build_function_call_expr (mf_set_options_fndecl, arg);
1285 append_to_statement_list (call_stmt, &ctor_statements);
1288 /* Append all the enqueued registration calls. */
1289 if (enqueued_call_stmt_chain)
1291 append_to_statement_list (enqueued_call_stmt_chain, &ctor_statements);
1292 enqueued_call_stmt_chain = NULL_TREE;
1295 cgraph_build_static_cdtor ('I', ctor_statements,
1296 MAX_RESERVED_INIT_PRIORITY-1);
1300 static bool
1301 gate_mudflap (void)
1303 return flag_mudflap != 0;
1306 struct tree_opt_pass pass_mudflap_1 =
1308 "mudflap1", /* name */
1309 gate_mudflap, /* gate */
1310 execute_mudflap_function_decls, /* execute */
1311 NULL, /* sub */
1312 NULL, /* next */
1313 0, /* static_pass_number */
1314 0, /* tv_id */
1315 PROP_gimple_any, /* properties_required */
1316 0, /* properties_provided */
1317 0, /* properties_destroyed */
1318 0, /* todo_flags_start */
1319 TODO_dump_func /* todo_flags_finish */
1322 struct tree_opt_pass pass_mudflap_2 =
1324 "mudflap2", /* name */
1325 gate_mudflap, /* gate */
1326 execute_mudflap_function_ops, /* execute */
1327 NULL, /* sub */
1328 NULL, /* next */
1329 0, /* static_pass_number */
1330 0, /* tv_id */
1331 PROP_gimple_leh, /* properties_required */
1332 0, /* properties_provided */
1333 0, /* properties_destroyed */
1334 0, /* todo_flags_start */
1335 TODO_verify_flow | TODO_verify_stmts
1336 | TODO_dump_func /* todo_flags_finish */
1339 #include "gt-tree-mudflap.h"