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
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
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
27 #include "coretypes.h"
29 #include "hard-reg-set.h"
33 #include "basic-block.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"
43 #include "diagnostic.h"
45 #include "langhooks.h"
49 /* Internal function decls */
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. */
74 mf_build_string (const char *string)
76 size_t len = strlen (string);
77 tree result = mf_mark (build_string (len + 1, string));
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
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;
106 if (decl == NULL_TREE)
111 pp_construct (buf, /* prefix */ NULL, /* line-width */ 0);
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);
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, ") ");
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);
186 /* And another friend, for producing a simpler message. */
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;
197 /* Add FILENAME[:LINENUMBER]. */
198 if (xloc.file == NULL && current_function_decl != NULL_TREE)
199 xloc.file = DECL_SOURCE_FILE (current_function_decl);
200 if (xloc.file == NULL)
201 xloc.file = "<unknown file>";
205 sprintf (linebuf, "%d", xloc.line);
212 /* Add (FUNCTION). */
213 name = lang_hooks.decl_printable_name (current_function_decl, 1);
222 string = concat (file, colon, line, op, name, cp, NULL);
223 result = mf_build_string (string);
230 /* global tree nodes */
232 /* Global tree objects for global variables and functions exported by
233 mudflap runtime library. mf_init_extern_trees must be called
234 before using these. */
236 /* uintptr_t (usually "unsigned long") */
237 static GTY (()) tree mf_uintptr_type;
239 /* struct __mf_cache { uintptr_t low; uintptr_t high; }; */
240 static GTY (()) tree mf_cache_struct_type;
242 /* struct __mf_cache * const */
243 static GTY (()) tree mf_cache_structptr_type;
245 /* extern struct __mf_cache __mf_lookup_cache []; */
246 static GTY (()) tree mf_cache_array_decl;
248 /* extern unsigned char __mf_lc_shift; */
249 static GTY (()) tree mf_cache_shift_decl;
251 /* extern uintptr_t __mf_lc_mask; */
252 static GTY (()) tree mf_cache_mask_decl;
254 /* Their function-scope local shadows, used in single-threaded mode only. */
256 /* auto const unsigned char __mf_lc_shift_l; */
257 static GTY (()) tree mf_cache_shift_decl_l;
259 /* auto const uintptr_t __mf_lc_mask_l; */
260 static GTY (()) tree mf_cache_mask_decl_l;
262 /* extern void __mf_check (void *ptr, size_t sz, int type, const char *); */
263 static GTY (()) tree mf_check_fndecl;
265 /* extern void __mf_register (void *ptr, size_t sz, int type, const char *); */
266 static GTY (()) tree mf_register_fndecl;
268 /* extern void __mf_unregister (void *ptr, size_t sz, int type); */
269 static GTY (()) tree mf_unregister_fndecl;
271 /* extern void __mf_init (); */
272 static GTY (()) tree mf_init_fndecl;
274 /* Helper for mudflap_init: construct a decl with the given category,
275 name, and type, mark it an external reference, and pushdecl it. */
277 mf_make_builtin (enum tree_code category, const char *name, tree type)
279 tree decl = mf_mark (build_decl (category, get_identifier (name), type));
280 TREE_PUBLIC (decl) = 1;
281 DECL_EXTERNAL (decl) = 1;
282 lang_hooks.decls.pushdecl (decl);
286 /* Helper for mudflap_init: construct a tree corresponding to the type
287 struct __mf_cache { uintptr_t low; uintptr_t high; };
288 where uintptr_t is the FIELD_TYPE argument. */
290 mf_make_mf_cache_struct_type (tree field_type)
292 /* There is, abominably, no language-independent way to construct a
293 RECORD_TYPE. So we have to call the basic type construction
294 primitives by hand. */
295 tree fieldlo = build_decl (FIELD_DECL, get_identifier ("low"), field_type);
296 tree fieldhi = build_decl (FIELD_DECL, get_identifier ("high"), field_type);
298 tree struct_type = make_node (RECORD_TYPE);
299 DECL_CONTEXT (fieldlo) = struct_type;
300 DECL_CONTEXT (fieldhi) = struct_type;
301 TREE_CHAIN (fieldlo) = fieldhi;
302 TYPE_FIELDS (struct_type) = fieldlo;
303 TYPE_NAME (struct_type) = get_identifier ("__mf_cache");
304 layout_type (struct_type);
309 #define build_function_type_0(rtype) \
310 build_function_type (rtype, void_list_node)
311 #define build_function_type_3(rtype, arg1, arg2, arg3) \
312 build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2, \
313 tree_cons (0, arg3, void_list_node))))
314 #define build_function_type_4(rtype, arg1, arg2, arg3, arg4) \
315 build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2, \
316 tree_cons (0, arg3, tree_cons (0, arg4, \
319 /* Initialize the global tree nodes that correspond to mf-runtime.h
324 static bool done = false;
325 tree mf_const_string_type;
326 tree mf_cache_array_type;
327 tree mf_check_register_fntype;
328 tree mf_unregister_fntype;
335 mf_uintptr_type = lang_hooks.types.type_for_mode (ptr_mode,
338 = build_pointer_type (build_qualified_type
339 (char_type_node, TYPE_QUAL_CONST));
341 mf_cache_struct_type = mf_make_mf_cache_struct_type (mf_uintptr_type);
342 mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type);
343 mf_cache_array_type = build_array_type (mf_cache_struct_type, 0);
344 mf_check_register_fntype =
345 build_function_type_4 (void_type_node, ptr_type_node, size_type_node,
346 integer_type_node, mf_const_string_type);
347 mf_unregister_fntype =
348 build_function_type_3 (void_type_node, ptr_type_node, size_type_node,
351 build_function_type_0 (void_type_node);
353 mf_cache_array_decl = mf_make_builtin (VAR_DECL, "__mf_lookup_cache",
354 mf_cache_array_type);
355 mf_cache_shift_decl = mf_make_builtin (VAR_DECL, "__mf_lc_shift",
356 unsigned_char_type_node);
357 mf_cache_mask_decl = mf_make_builtin (VAR_DECL, "__mf_lc_mask",
359 mf_check_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_check",
360 mf_check_register_fntype);
361 mf_register_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_register",
362 mf_check_register_fntype);
363 mf_unregister_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_unregister",
364 mf_unregister_fntype);
365 mf_init_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_init",
368 #undef build_function_type_4
369 #undef build_function_type_3
370 #undef build_function_type_0
373 /* ------------------------------------------------------------------------ */
374 /* Memory reference transforms. Perform the mudflap indirection-related
375 tree transforms on the current function.
377 This is the second part of the mudflap instrumentation. It works on
378 low-level GIMPLE using the CFG, because we want to run this pass after
379 tree optimizations have been performed, but we have to preserve the CFG
380 for expansion from trees to RTL. */
383 execute_mudflap_function_ops (void)
385 if (mf_marked_p (current_function_decl))
388 push_gimplify_context ();
390 /* In multithreaded mode, don't cache the lookup cache parameters. */
391 if (! flag_mudflap_threads)
392 mf_decl_cache_locals ();
396 if (! flag_mudflap_threads)
397 mf_decl_clear_locals ();
399 pop_gimplify_context (NULL);
402 /* Create and initialize local shadow variables for the lookup cache
403 globals. Put their decls in the *_l globals for use by
404 mf_build_check_statement_for. */
407 mf_decl_cache_locals (void)
409 tree t, shift_init_stmts, mask_init_stmts;
410 tree_stmt_iterator tsi;
412 /* Build the cache vars. */
413 mf_cache_shift_decl_l
414 = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_shift_decl),
415 "__mf_lookup_shift_l"));
418 = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_mask_decl),
419 "__mf_lookup_mask_l"));
421 /* Build initialization nodes for the cache vars. We just load the
422 globals into the cache variables. */
423 t = build (MODIFY_EXPR, TREE_TYPE (mf_cache_shift_decl_l),
424 mf_cache_shift_decl_l, mf_cache_shift_decl);
425 SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
426 gimplify_to_stmt_list (&t);
427 shift_init_stmts = t;
429 t = build (MODIFY_EXPR, TREE_TYPE (mf_cache_mask_decl_l),
430 mf_cache_mask_decl_l, mf_cache_mask_decl);
431 SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
432 gimplify_to_stmt_list (&t);
435 /* Anticipating multiple entry points, we insert the cache vars
436 initializers in each successor of the ENTRY_BLOCK_PTR. */
437 for (tsi = tsi_start (shift_init_stmts);
440 insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
442 for (tsi = tsi_start (mask_init_stmts);
445 insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
446 bsi_commit_edge_inserts (NULL);
451 mf_decl_clear_locals (void)
453 /* Unset local shadows. */
454 mf_cache_shift_decl_l = NULL_TREE;
455 mf_cache_mask_decl_l = NULL_TREE;
459 mf_build_check_statement_for (tree addr, tree size,
460 block_stmt_iterator *instr_bsi,
461 location_t *locus, tree dirflag)
463 tree_stmt_iterator head, tsi;
464 tree ptrtype = TREE_TYPE (addr);
465 block_stmt_iterator bsi;
466 basic_block cond_bb, then_bb, join_bb;
468 tree cond, t, u, v, l1, l2;
473 /* We first need to split the current basic block, and start altering
474 the CFG. This allows us to insert the statements we're about to
475 construct into the right basic blocks. The label l1 is the label
476 of the block for the THEN clause of the conditional jump we're
477 about to construct, and l2 is the ELSE clause, which is just the
478 continuation of the old statement stream. */
479 l1 = create_artificial_label ();
480 l2 = create_artificial_label ();
481 cond_bb = bb_for_stmt (bsi_stmt (*instr_bsi));
484 if (! bsi_end_p (bsi))
486 e = split_block (cond_bb, bsi_stmt (bsi));
493 cond_bb = create_empty_bb (join_bb->prev_bb);
494 e = make_edge (cond_bb, join_bb, 0);
496 e->flags = EDGE_FALSE_VALUE;
497 then_bb = create_empty_bb (cond_bb);
498 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
499 make_edge (then_bb, join_bb, EDGE_FALLTHRU);
501 /* We expect that the conditional jump we will construct will not
502 be taken very often as it basically is an exception condition. */
503 predict_edge_def (then_bb->pred, PRED_MUDFLAP, NOT_TAKEN);
505 /* Update dominance info. Note that bb_join's data was
506 updated by split_block. */
507 if (dom_computed[CDI_DOMINATORS] >= DOM_CONS_OK)
509 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
510 set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb);
513 /* Build our local variables. */
514 mf_value = create_tmp_var (ptrtype, "__mf_value");
515 mf_elem = create_tmp_var (mf_cache_structptr_type, "__mf_elem");
516 mf_base = create_tmp_var (mf_uintptr_type, "__mf_base");
518 /* Build: __mf_value = <address expression>. */
519 t = build (MODIFY_EXPR, void_type_node, mf_value, unshare_expr (addr));
520 SET_EXPR_LOCUS (t, locus);
521 gimplify_to_stmt_list (&t);
522 head = tsi_start (t);
525 /* Build: __mf_base = (uintptr_t)__mf_value. */
526 t = build (MODIFY_EXPR, void_type_node, mf_base,
527 build1 (NOP_EXPR, mf_uintptr_type, mf_value));
528 SET_EXPR_LOCUS (t, locus);
529 gimplify_to_stmt_list (&t);
530 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
532 /* Build: __mf_elem = &__mf_lookup_cache [(__mf_base >> __mf_shift)
534 t = build (RSHIFT_EXPR, mf_uintptr_type, mf_base,
535 (flag_mudflap_threads ? mf_cache_shift_decl : mf_cache_shift_decl_l));
536 t = build (BIT_AND_EXPR, mf_uintptr_type, t,
537 (flag_mudflap_threads ? mf_cache_mask_decl : mf_cache_mask_decl_l));
538 t = build (ARRAY_REF,
539 TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
540 mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
541 t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
542 t = build (MODIFY_EXPR, void_type_node, mf_elem, t);
543 SET_EXPR_LOCUS (t, locus);
544 gimplify_to_stmt_list (&t);
545 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
547 /* Quick validity check.
549 if (__mf_elem->low > __mf_base
550 || (__mf_elem_high < __mf_base + sizeof(T) - 1))
553 ... and only if single-threaded:
554 __mf_lookup_shift_1 = f...;
555 __mf_lookup_mask_l = ...;
558 It is expected that this body of code is rarely executed so we mark
559 the edge to the THEN clause of the conditional jump as unlikely. */
561 /* Construct t <-- '__mf_elem->low > __mf_base'. */
562 t = build (COMPONENT_REF, mf_uintptr_type,
563 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
564 TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
565 t = build (GT_EXPR, boolean_type_node, t, mf_base);
567 /* Construct '__mf_elem->high < __mf_base + sizeof(T) - 1'.
570 1) u <-- '__mf_elem->high'
571 2) v <-- '__mf_base + sizeof (T) - 1'.
573 Then build 'u <-- (u < v). */
576 u = build (COMPONENT_REF, mf_uintptr_type,
577 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
578 TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
580 v = convert (mf_uintptr_type,
581 size_binop (MINUS_EXPR, size, size_one_node));
582 v = fold (build (PLUS_EXPR, mf_uintptr_type, mf_base, v));
584 u = build (LT_EXPR, boolean_type_node, u, v);
586 /* Build the composed conditional: t <-- 't || u'. Then store the
587 result of the evaluation of 't' in a temporary variable which we
588 can use as the condition for the conditional jump. */
589 t = build (TRUTH_OR_EXPR, boolean_type_node, t, u);
590 cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
591 t = build (MODIFY_EXPR, boolean_type_node, cond, t);
592 gimplify_to_stmt_list (&t);
593 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
595 /* Build the conditional jump. 'cond' is just a temporary so we can
596 simply build a void COND_EXPR. We do need labels in both arms though. */
597 t = build (COND_EXPR, void_type_node, cond,
598 build (GOTO_EXPR, void_type_node, tree_block_label (then_bb)),
599 build (GOTO_EXPR, void_type_node, tree_block_label (join_bb)));
600 SET_EXPR_LOCUS (t, locus);
601 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
603 /* At this point, after so much hard work, we have only constructed
604 the conditional jump,
606 if (__mf_elem->low > __mf_base
607 || (__mf_elem_high < __mf_base + sizeof(T) - 1))
609 The lowered GIMPLE tree representing this code is in the statement
610 list starting at 'head'.
612 We can insert this now in the current basic block, ie. the one that
613 the statement we're instrumenting was originally in. */
614 bsi = bsi_last (cond_bb);
615 for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
616 bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
618 /* Now build up the body of the cache-miss handling:
623 This is the body of the conditional. */
625 u = tree_cons (NULL_TREE,
626 mf_file_function_line_tree (locus == NULL ? UNKNOWN_LOCATION
629 u = tree_cons (NULL_TREE, dirflag, u);
630 u = tree_cons (NULL_TREE, size, u);
631 u = tree_cons (NULL_TREE, mf_value, u);
632 t = build_function_call_expr (mf_check_fndecl, u);
633 gimplify_to_stmt_list (&t);
634 head = tsi_start (t);
637 if (! flag_mudflap_threads)
639 t = build (MODIFY_EXPR, void_type_node,
640 mf_cache_shift_decl_l, mf_cache_shift_decl);
641 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
643 t = build (MODIFY_EXPR, void_type_node,
644 mf_cache_mask_decl_l, mf_cache_mask_decl);
645 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
648 /* Insert the check code in the THEN block. */
649 bsi = bsi_start (then_bb);
650 for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
651 bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
653 *instr_bsi = bsi_start (join_bb);
654 bsi_next (instr_bsi);
658 mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
659 location_t *locus, tree dirflag)
661 tree type, ptr_type, addr, size, t;
663 /* Don't instrument read operations. */
664 if (dirflag == integer_zero_node && flag_mudflap_ignore_reads)
668 type = TREE_TYPE (t);
669 size = TYPE_SIZE_UNIT (type);
671 switch (TREE_CODE (t))
675 /* Omit checking if we can statically determine that the access is
676 valid. For non-addressable local arrays this is not optional,
677 since we won't have called __mf_register for the object. */
680 op0 = TREE_OPERAND (t, 0);
681 op1 = TREE_OPERAND (t, 1);
682 while (TREE_CODE (op1) == INTEGER_CST)
684 tree dom = TYPE_DOMAIN (TREE_TYPE (op0));
686 /* Test for index in range. Break if not. */
688 || (! TYPE_MIN_VALUE (dom)
689 || ! really_constant_p (TYPE_MIN_VALUE (dom)))
690 || (! TYPE_MAX_VALUE (dom)
691 || ! really_constant_p (TYPE_MAX_VALUE (dom)))
692 || (tree_int_cst_lt (op1, TYPE_MIN_VALUE (dom))
693 || tree_int_cst_lt (TYPE_MAX_VALUE (dom), op1)))
696 /* If we're looking at a non-external VAR_DECL, then the
697 access must be ok. */
698 if (TREE_CODE (op0) == VAR_DECL && !DECL_EXTERNAL (op0))
701 /* Only continue if we're still looking at an array. */
702 if (TREE_CODE (op0) != ARRAY_REF)
705 op1 = TREE_OPERAND (op0, 1);
706 op0 = TREE_OPERAND (op0, 0);
709 /* If we got here, we couldn't statically the check. */
710 ptr_type = build_pointer_type (type);
711 addr = build1 (ADDR_EXPR, ptr_type, t);
716 addr = TREE_OPERAND (t, 0);
717 ptr_type = TREE_TYPE (addr);
720 case ARRAY_RANGE_REF:
721 warning ("mudflap checking not yet implemented for ARRAY_RANGE_REF");
728 /* If we're not dereferencing something, then the access
730 if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
733 field = TREE_OPERAND (t, 1);
735 /* If we're looking at a bit field, then we can't take its address
736 with ADDR_EXPR -- lang_hooks.mark_addressable will error. Do
737 things the hard way with PLUS. */
738 if (DECL_BIT_FIELD_TYPE (field))
740 if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST)
741 size = DECL_SIZE_UNIT (field);
743 addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
744 addr = fold_convert (ptr_type_node, addr);
745 addr = fold (build (PLUS_EXPR, ptr_type_node,
746 addr, fold_convert (ptr_type_node,
747 byte_position (field))));
751 ptr_type = build_pointer_type (type);
752 addr = build1 (ADDR_EXPR, ptr_type, t);
761 /* If we're not dereferencing something, then the access
763 if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
766 bpu = bitsize_int (BITS_PER_UNIT);
767 ofs = convert (bitsizetype, TREE_OPERAND (t, 2));
768 rem = size_binop (TRUNC_MOD_EXPR, ofs, bpu);
769 ofs = size_binop (TRUNC_DIV_EXPR, ofs, bpu);
771 size = convert (bitsizetype, TREE_OPERAND (t, 1));
772 size = size_binop (PLUS_EXPR, size, rem);
773 size = size_binop (CEIL_DIV_EXPR, size, bpu);
774 size = convert (sizetype, size);
776 addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
777 addr = convert (ptr_type_node, addr);
778 addr = fold (build (PLUS_EXPR, ptr_type_node, addr, ofs));
786 mf_build_check_statement_for (addr, size, iter, locus, dirflag);
790 mf_xform_derefs (void)
792 basic_block bb, next;
793 block_stmt_iterator i;
794 int saved_last_basic_block = last_basic_block;
796 bb = ENTRY_BLOCK_PTR ->next_bb;
800 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
802 tree s = bsi_stmt (i);
804 /* Only a few GIMPLE statements can reference memory. */
805 switch (TREE_CODE (s))
808 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
810 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 1), EXPR_LOCUS (s),
815 if (TREE_OPERAND (s, 0) != NULL_TREE)
817 if (TREE_CODE (TREE_OPERAND (s, 0)) == MODIFY_EXPR)
818 mf_xform_derefs_1 (&i, &TREE_OPERAND (TREE_OPERAND (s, 0), 1),
819 EXPR_LOCUS (s), integer_zero_node);
821 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
832 while (bb && bb->index <= saved_last_basic_block);
835 /* ------------------------------------------------------------------------ */
836 /* ADDR_EXPR transforms. Perform the declaration-related mudflap tree
837 transforms on the current function.
839 This is the first part of the mudflap instrumentation. It works on
840 high-level GIMPLE because after lowering, all variables are moved out
841 of their BIND_EXPR binding context, and we lose liveness information
842 for the declarations we wish to instrument. */
845 execute_mudflap_function_decls (void)
847 if (mf_marked_p (current_function_decl))
850 push_gimplify_context ();
852 mf_xform_decls (DECL_SAVED_TREE (current_function_decl),
853 DECL_ARGUMENTS (current_function_decl));
855 pop_gimplify_context (NULL);
858 /* This struct is passed between mf_xform_decls to store state needed
859 during the traversal searching for objects that have their
861 struct mf_xform_decls_data
867 /* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of
868 _DECLs if appropriate. Arrange to call the __mf_register function
869 now, and the __mf_unregister function later for each. */
871 mx_register_decls (tree decl, tree *stmt_list)
873 tree finally_stmts = NULL_TREE;
874 tree_stmt_iterator initially_stmts = tsi_start (*stmt_list);
876 while (decl != NULL_TREE)
879 if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
880 /* It must be a non-external, automatic variable. */
881 && ! DECL_EXTERNAL (decl)
882 && ! TREE_STATIC (decl)
883 /* The decl must have its address taken. */
884 && TREE_ADDRESSABLE (decl)
885 /* The type of the variable must be complete. */
886 && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
887 /* Don't process the same decl twice. */
888 && ! mf_marked_p (decl))
890 tree size = NULL_TREE, variable_name;
891 tree unregister_fncall, unregister_fncall_params;
892 tree register_fncall, register_fncall_params;
894 if (DECL_DEFER_OUTPUT (decl))
896 /* Oh no ... it's probably a variable-length array (VLA).
897 The size and address cannot be computed by merely
898 looking at the DECL. See gimplify_decl_stmt for the
899 method by which VLA declarations turn into calls to
900 BUILT_IN_STACK_ALLOC. We assume that multiple
901 VLAs declared later in the same block get allocation
902 code later than the others. */
903 tree stack_alloc_call = NULL_TREE;
905 while(! tsi_end_p (initially_stmts))
907 tree t = tsi_stmt (initially_stmts);
909 tree call = NULL_TREE;
910 if (TREE_CODE (t) == CALL_EXPR)
912 else if (TREE_CODE (t) == MODIFY_EXPR &&
913 TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR)
914 call = TREE_OPERAND (t, 1);
915 else if (TREE_CODE (t) == TRY_FINALLY_EXPR)
917 /* We hope that this is the try/finally block sometimes
918 constructed by gimplify_bind_expr() for a BIND_EXPR
919 that contains VLAs. This very naive recursion
920 appears to be sufficient. */
921 initially_stmts = tsi_start (TREE_OPERAND (t, 0));
924 if (call != NULL_TREE)
926 if (TREE_CODE (TREE_OPERAND(call, 0)) == ADDR_EXPR &&
927 TREE_OPERAND (TREE_OPERAND (call, 0), 0) ==
928 implicit_built_in_decls [BUILT_IN_STACK_ALLOC])
930 tree stack_alloc_args = TREE_OPERAND (call, 1);
931 tree stack_alloc_op1 = TREE_VALUE (stack_alloc_args);
932 tree stack_alloc_op2 = TREE_VALUE (TREE_CHAIN (stack_alloc_args));
934 if (TREE_CODE (stack_alloc_op1) == ADDR_EXPR &&
935 TREE_OPERAND (stack_alloc_op1, 0) == decl)
938 size = stack_alloc_op2;
939 stack_alloc_call = call;
940 /* Advance iterator to point past this allocation call. */
941 tsi_next (&initially_stmts);
947 tsi_next (&initially_stmts);
950 if (stack_alloc_call == NULL_TREE)
952 warning ("mudflap cannot handle variable-sized declaration `%s'",
953 IDENTIFIER_POINTER (DECL_NAME (decl)));
959 size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
962 /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
963 unregister_fncall_params =
964 tree_cons (NULL_TREE,
965 convert (ptr_type_node,
966 mf_mark (build1 (ADDR_EXPR,
967 build_pointer_type (TREE_TYPE (decl)),
969 tree_cons (NULL_TREE,
971 tree_cons (NULL_TREE,
972 build_int_2 (3, 0), /* __MF_TYPE_STACK */
974 /* __mf_unregister (...) */
975 unregister_fncall = build_function_call_expr (mf_unregister_fndecl,
976 unregister_fncall_params);
978 /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, "name") */
979 variable_name = mf_varname_tree (decl);
980 register_fncall_params =
981 tree_cons (NULL_TREE,
982 convert (ptr_type_node,
983 mf_mark (build1 (ADDR_EXPR,
984 build_pointer_type (TREE_TYPE (decl)),
986 tree_cons (NULL_TREE,
988 tree_cons (NULL_TREE,
989 build_int_2 (3, 0), /* __MF_TYPE_STACK */
990 tree_cons (NULL_TREE,
994 /* __mf_register (...) */
995 register_fncall = build_function_call_expr (mf_register_fndecl,
996 register_fncall_params);
998 /* Accumulate the two calls. */
999 /* ??? Set EXPR_LOCATION. */
1000 gimplify_stmt (®ister_fncall);
1001 gimplify_stmt (&unregister_fncall);
1003 /* Add the __mf_register call at the current appending point. */
1004 if (tsi_end_p (initially_stmts))
1005 internal_error ("mudflap ran off end of BIND_EXPR body");
1006 tsi_link_before (&initially_stmts, register_fncall, TSI_SAME_STMT);
1008 /* Accumulate the FINALLY piece. */
1009 append_to_statement_list (unregister_fncall, &finally_stmts);
1014 decl = TREE_CHAIN (decl);
1017 /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
1018 if (finally_stmts != NULL_TREE)
1020 tree t = build (TRY_FINALLY_EXPR, void_type_node,
1021 *stmt_list, finally_stmts);
1023 append_to_statement_list (t, stmt_list);
1028 /* Process every variable mentioned in BIND_EXPRs. */
1030 mx_xfn_xform_decls (tree *t, int *continue_p, void *data)
1032 struct mf_xform_decls_data* d = (struct mf_xform_decls_data*) data;
1034 if (*t == NULL_TREE || *t == error_mark_node)
1042 switch (TREE_CODE (*t))
1046 /* Process function parameters now (but only once). */
1047 mx_register_decls (d->param_decls, &BIND_EXPR_BODY (*t));
1048 d->param_decls = NULL_TREE;
1050 mx_register_decls (BIND_EXPR_VARS (*t), &BIND_EXPR_BODY (*t));
1061 /* Perform the object lifetime tracking mudflap transform on the given function
1062 tree. The tree is mutated in place, with possibly copied subtree nodes.
1064 For every auto variable declared, if its address is ever taken
1065 within the function, then supply its lifetime to the mudflap
1066 runtime with the __mf_register and __mf_unregister calls.
1070 mf_xform_decls (tree fnbody, tree fnparams)
1072 struct mf_xform_decls_data d;
1073 d.param_decls = fnparams;
1074 walk_tree_without_duplicates (&fnbody, mx_xfn_xform_decls, &d);
1078 /* ------------------------------------------------------------------------ */
1079 /* Externally visible mudflap functions. */
1082 /* Mark and return the given tree node to prevent further mudflap
1084 static GTY ((param_is (union tree_node))) htab_t marked_trees = NULL;
1091 if (marked_trees == NULL)
1092 marked_trees = htab_create_ggc (31, htab_hash_pointer, htab_eq_pointer, NULL);
1094 slot = htab_find_slot (marked_trees, t, INSERT);
1100 mf_marked_p (tree t)
1104 if (marked_trees == NULL)
1107 entry = htab_find (marked_trees, t);
1108 return (entry != NULL);
1111 /* Remember given node as a static of some kind: global data,
1112 function-scope static, or an anonymous constant. Its assembler
1115 /* A list of globals whose incomplete declarations we encountered.
1116 Instead of emitting the __mf_register call for them here, it's
1117 delayed until program finish time. If they're still incomplete by
1118 then, warnings are emitted. */
1120 static GTY (()) varray_type deferred_static_decls;
1122 /* A list of statements for calling __mf_register() at startup time. */
1123 static GTY (()) tree enqueued_call_stmt_chain;
1126 mudflap_register_call (tree obj, tree object_size, tree varname)
1128 tree arg, args, call_stmt;
1130 args = tree_cons (NULL_TREE, varname, NULL_TREE);
1132 arg = build_int_2 (4, 0); /* __MF_TYPE_STATIC */
1133 args = tree_cons (NULL_TREE, arg, args);
1135 arg = convert (size_type_node, object_size);
1136 args = tree_cons (NULL_TREE, arg, args);
1138 arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj);
1139 arg = convert (ptr_type_node, arg);
1140 args = tree_cons (NULL_TREE, arg, args);
1142 call_stmt = build_function_call_expr (mf_register_fndecl, args);
1144 /* Add an initial __mf_init() call to the list of registration calls. */
1145 if (enqueued_call_stmt_chain == NULL_TREE)
1147 tree call2_stmt = build_function_call_expr (mf_init_fndecl, NULL_TREE);
1148 append_to_statement_list (call2_stmt, &enqueued_call_stmt_chain);
1151 append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
1155 mudflap_enqueue_decl (tree obj)
1157 if (mf_marked_p (obj))
1160 /* We don't need to process variable decls that are internally
1161 generated extern. If we did, we'd end up with warnings for them
1162 during mudflap_finish_file (). That would confuse the user,
1163 since the text would refer to variables that don't show up in the
1164 user's source code. */
1165 if (DECL_P (obj) && DECL_EXTERNAL (obj) && DECL_ARTIFICIAL (obj))
1168 if (COMPLETE_TYPE_P (TREE_TYPE (obj)))
1174 object_size = size_in_bytes (TREE_TYPE (obj));
1178 fprintf (dump_file, "enqueue_decl obj=`");
1179 print_generic_expr (dump_file, obj, dump_flags);
1180 fprintf (dump_file, "' size=");
1181 print_generic_expr (dump_file, object_size, dump_flags);
1182 fprintf (dump_file, "\n");
1185 /* NB: the above condition doesn't require TREE_USED or
1186 TREE_ADDRESSABLE. That's because this object may be a global
1187 only used from other compilation units. XXX: Maybe static
1188 objects could require those attributes being set. */
1190 mudflap_register_call (obj, object_size, mf_varname_tree (obj));
1196 if (! deferred_static_decls)
1197 VARRAY_TREE_INIT (deferred_static_decls, 10, "deferred static list");
1199 /* Ugh, linear search... */
1200 for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
1201 if (VARRAY_TREE (deferred_static_decls, i) == obj)
1203 warning ("mudflap cannot track lifetime of `%s'",
1204 IDENTIFIER_POINTER (DECL_NAME (obj)));
1208 VARRAY_PUSH_TREE (deferred_static_decls, obj);
1213 mudflap_enqueue_constant (tree obj)
1215 tree object_size, varname;
1217 if (mf_marked_p (obj))
1220 if (TREE_CODE (obj) == STRING_CST)
1221 object_size = build_int_2 (TREE_STRING_LENGTH (obj), 0);
1223 object_size = size_in_bytes (TREE_TYPE (obj));
1227 fprintf (dump_file, "enqueue_constant obj=`");
1228 print_generic_expr (dump_file, obj, dump_flags);
1229 fprintf (dump_file, "' size=");
1230 print_generic_expr (dump_file, object_size, dump_flags);
1231 fprintf (dump_file, "\n");
1234 if (TREE_CODE (obj) == STRING_CST)
1235 varname = mf_build_string ("string literal");
1237 varname = mf_build_string ("constant");
1239 mudflap_register_call (obj, object_size, varname);
1243 /* Emit any file-wide instrumentation. */
1245 mudflap_finish_file (void)
1247 /* Try to give the deferred objects one final try. */
1248 if (deferred_static_decls)
1252 for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
1254 tree obj = VARRAY_TREE (deferred_static_decls, i);
1256 /* Call enqueue_decl again on the same object it has previously
1257 put into the table. (It won't modify the table this time, so
1258 infinite iteration is not a problem.) */
1259 mudflap_enqueue_decl (obj);
1262 VARRAY_CLEAR (deferred_static_decls);
1265 if (enqueued_call_stmt_chain)
1267 cgraph_build_static_cdtor ('I', enqueued_call_stmt_chain,
1268 MAX_RESERVED_INIT_PRIORITY-1);
1269 enqueued_call_stmt_chain = 0;
1277 return flag_mudflap != 0;
1280 struct tree_opt_pass pass_mudflap_1 =
1282 "mudflap1", /* name */
1283 gate_mudflap, /* gate */
1284 execute_mudflap_function_decls, /* execute */
1287 0, /* static_pass_number */
1289 PROP_gimple_any, /* properties_required */
1290 0, /* properties_provided */
1291 0, /* properties_destroyed */
1292 0, /* todo_flags_start */
1293 TODO_dump_func /* todo_flags_finish */
1296 struct tree_opt_pass pass_mudflap_2 =
1298 "mudflap2", /* name */
1299 gate_mudflap, /* gate */
1300 execute_mudflap_function_ops, /* execute */
1303 0, /* static_pass_number */
1305 PROP_gimple_leh, /* properties_required */
1306 0, /* properties_provided */
1307 0, /* properties_destroyed */
1308 0, /* todo_flags_start */
1309 TODO_verify_flow | TODO_verify_stmts
1310 | TODO_dump_func /* todo_flags_finish */
1313 #include "gt-tree-mudflap.h"