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]. */
199 if (file == NULL && current_function_decl != NULL_TREE)
200 file = DECL_SOURCE_FILE (current_function_decl);
202 file = "<unknown file>";
206 sprintf (linebuf, "%d", xloc.line);
213 /* Add (FUNCTION). */
214 name = lang_hooks.decl_printable_name (current_function_decl, 1);
223 string = concat (file, colon, line, op, name, cp, NULL);
224 result = mf_build_string (string);
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 /* Helper for mudflap_init: construct a decl with the given category,
276 name, and type, mark it an external reference, and pushdecl it. */
278 mf_make_builtin (enum tree_code category, const char *name, tree type)
280 tree decl = mf_mark (build_decl (category, get_identifier (name), type));
281 TREE_PUBLIC (decl) = 1;
282 DECL_EXTERNAL (decl) = 1;
283 lang_hooks.decls.pushdecl (decl);
287 /* Helper for mudflap_init: construct a tree corresponding to the type
288 struct __mf_cache { uintptr_t low; uintptr_t high; };
289 where uintptr_t is the FIELD_TYPE argument. */
291 mf_make_mf_cache_struct_type (tree field_type)
293 /* There is, abominably, no language-independent way to construct a
294 RECORD_TYPE. So we have to call the basic type construction
295 primitives by hand. */
296 tree fieldlo = build_decl (FIELD_DECL, get_identifier ("low"), field_type);
297 tree fieldhi = build_decl (FIELD_DECL, get_identifier ("high"), field_type);
299 tree struct_type = make_node (RECORD_TYPE);
300 DECL_CONTEXT (fieldlo) = struct_type;
301 DECL_CONTEXT (fieldhi) = struct_type;
302 TREE_CHAIN (fieldlo) = fieldhi;
303 TYPE_FIELDS (struct_type) = fieldlo;
304 TYPE_NAME (struct_type) = get_identifier ("__mf_cache");
305 layout_type (struct_type);
310 #define build_function_type_0(rtype) \
311 build_function_type (rtype, void_list_node)
312 #define build_function_type_3(rtype, arg1, arg2, arg3) \
313 build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2, \
314 tree_cons (0, arg3, void_list_node))))
315 #define build_function_type_4(rtype, arg1, arg2, arg3, arg4) \
316 build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2, \
317 tree_cons (0, arg3, tree_cons (0, arg4, \
320 /* Initialize the global tree nodes that correspond to mf-runtime.h
325 static bool done = false;
326 tree mf_const_string_type;
327 tree mf_cache_array_type;
328 tree mf_check_register_fntype;
329 tree mf_unregister_fntype;
336 mf_uintptr_type = lang_hooks.types.type_for_mode (ptr_mode,
339 = build_pointer_type (build_qualified_type
340 (char_type_node, TYPE_QUAL_CONST));
342 mf_cache_struct_type = mf_make_mf_cache_struct_type (mf_uintptr_type);
343 mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type);
344 mf_cache_array_type = build_array_type (mf_cache_struct_type, 0);
345 mf_check_register_fntype =
346 build_function_type_4 (void_type_node, ptr_type_node, size_type_node,
347 integer_type_node, mf_const_string_type);
348 mf_unregister_fntype =
349 build_function_type_3 (void_type_node, ptr_type_node, size_type_node,
352 build_function_type_0 (void_type_node);
354 mf_cache_array_decl = mf_make_builtin (VAR_DECL, "__mf_lookup_cache",
355 mf_cache_array_type);
356 mf_cache_shift_decl = mf_make_builtin (VAR_DECL, "__mf_lc_shift",
357 unsigned_char_type_node);
358 mf_cache_mask_decl = mf_make_builtin (VAR_DECL, "__mf_lc_mask",
360 mf_check_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_check",
361 mf_check_register_fntype);
362 mf_register_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_register",
363 mf_check_register_fntype);
364 mf_unregister_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_unregister",
365 mf_unregister_fntype);
366 mf_init_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_init",
369 #undef build_function_type_4
370 #undef build_function_type_3
371 #undef build_function_type_0
374 /* ------------------------------------------------------------------------ */
375 /* Memory reference transforms. Perform the mudflap indirection-related
376 tree transforms on the current function.
378 This is the second part of the mudflap instrumentation. It works on
379 low-level GIMPLE using the CFG, because we want to run this pass after
380 tree optimizations have been performed, but we have to preserve the CFG
381 for expansion from trees to RTL. */
384 execute_mudflap_function_ops (void)
386 if (mf_marked_p (current_function_decl))
389 push_gimplify_context ();
391 /* In multithreaded mode, don't cache the lookup cache parameters. */
392 if (! flag_mudflap_threads)
393 mf_decl_cache_locals ();
397 if (! flag_mudflap_threads)
398 mf_decl_clear_locals ();
400 pop_gimplify_context (NULL);
403 /* Create and initialize local shadow variables for the lookup cache
404 globals. Put their decls in the *_l globals for use by
405 mf_build_check_statement_for. */
408 mf_decl_cache_locals (void)
410 tree t, shift_init_stmts, mask_init_stmts;
411 tree_stmt_iterator tsi;
413 /* Build the cache vars. */
414 mf_cache_shift_decl_l
415 = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_shift_decl),
416 "__mf_lookup_shift_l"));
419 = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_mask_decl),
420 "__mf_lookup_mask_l"));
422 /* Build initialization nodes for the cache vars. We just load the
423 globals into the cache variables. */
424 t = build (MODIFY_EXPR, TREE_TYPE (mf_cache_shift_decl_l),
425 mf_cache_shift_decl_l, mf_cache_shift_decl);
426 SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
427 gimplify_to_stmt_list (&t);
428 shift_init_stmts = t;
430 t = build (MODIFY_EXPR, TREE_TYPE (mf_cache_mask_decl_l),
431 mf_cache_mask_decl_l, mf_cache_mask_decl);
432 SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
433 gimplify_to_stmt_list (&t);
436 /* Anticipating multiple entry points, we insert the cache vars
437 initializers in each successor of the ENTRY_BLOCK_PTR. */
438 for (tsi = tsi_start (shift_init_stmts);
441 insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
443 for (tsi = tsi_start (mask_init_stmts);
446 insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
447 bsi_commit_edge_inserts (NULL);
452 mf_decl_clear_locals (void)
454 /* Unset local shadows. */
455 mf_cache_shift_decl_l = NULL_TREE;
456 mf_cache_mask_decl_l = NULL_TREE;
460 mf_build_check_statement_for (tree addr, tree size,
461 block_stmt_iterator *instr_bsi,
462 location_t *locus, tree dirflag)
464 tree_stmt_iterator head, tsi;
465 tree ptrtype = TREE_TYPE (addr);
466 block_stmt_iterator bsi;
467 basic_block cond_bb, then_bb, join_bb;
469 tree cond, t, u, v, l1, l2;
474 /* We first need to split the current basic block, and start altering
475 the CFG. This allows us to insert the statements we're about to
476 construct into the right basic blocks. The label l1 is the label
477 of the block for the THEN clause of the conditional jump we're
478 about to construct, and l2 is the ELSE clause, which is just the
479 continuation of the old statement stream. */
480 l1 = create_artificial_label ();
481 l2 = create_artificial_label ();
482 cond_bb = bb_for_stmt (bsi_stmt (*instr_bsi));
485 if (! bsi_end_p (bsi))
487 e = split_block (cond_bb, bsi_stmt (bsi));
494 cond_bb = create_empty_bb (join_bb->prev_bb);
495 e = make_edge (cond_bb, join_bb, 0);
497 e->flags = EDGE_FALSE_VALUE;
498 then_bb = create_empty_bb (cond_bb);
499 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
500 make_edge (then_bb, join_bb, EDGE_FALLTHRU);
502 /* We expect that the conditional jump we will construct will not
503 be taken very often as it basically is an exception condition. */
504 predict_edge_def (then_bb->pred, PRED_MUDFLAP, NOT_TAKEN);
506 /* Update dominance info. Note that bb_join's data was
507 updated by split_block. */
508 if (dom_computed[CDI_DOMINATORS] >= DOM_CONS_OK)
510 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
511 set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb);
514 /* Build our local variables. */
515 mf_value = create_tmp_var (ptrtype, "__mf_value");
516 mf_elem = create_tmp_var (mf_cache_structptr_type, "__mf_elem");
517 mf_base = create_tmp_var (mf_uintptr_type, "__mf_base");
519 /* Build: __mf_value = <address expression>. */
520 t = build (MODIFY_EXPR, void_type_node, mf_value, unshare_expr (addr));
521 SET_EXPR_LOCUS (t, locus);
522 gimplify_to_stmt_list (&t);
523 head = tsi_start (t);
526 /* Build: __mf_base = (uintptr_t)__mf_value. */
527 t = build (MODIFY_EXPR, void_type_node, mf_base,
528 build1 (NOP_EXPR, mf_uintptr_type, mf_value));
529 SET_EXPR_LOCUS (t, locus);
530 gimplify_to_stmt_list (&t);
531 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
533 /* Build: __mf_elem = &__mf_lookup_cache [(__mf_base >> __mf_shift)
535 t = build (RSHIFT_EXPR, mf_uintptr_type, mf_base,
536 (flag_mudflap_threads ? mf_cache_shift_decl : mf_cache_shift_decl_l));
537 t = build (BIT_AND_EXPR, mf_uintptr_type, t,
538 (flag_mudflap_threads ? mf_cache_mask_decl : mf_cache_mask_decl_l));
539 t = build (ARRAY_REF,
540 TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
541 mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
542 t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
543 t = build (MODIFY_EXPR, void_type_node, mf_elem, t);
544 SET_EXPR_LOCUS (t, locus);
545 gimplify_to_stmt_list (&t);
546 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
548 /* Quick validity check.
550 if (__mf_elem->low > __mf_base
551 || (__mf_elem_high < __mf_base + sizeof(T) - 1))
554 ... and only if single-threaded:
555 __mf_lookup_shift_1 = f...;
556 __mf_lookup_mask_l = ...;
559 It is expected that this body of code is rarely executed so we mark
560 the edge to the THEN clause of the conditional jump as unlikely. */
562 /* Construct t <-- '__mf_elem->low > __mf_base'. */
563 t = build (COMPONENT_REF, mf_uintptr_type,
564 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
565 TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
566 t = build (GT_EXPR, boolean_type_node, t, mf_base);
568 /* Construct '__mf_elem->high < __mf_base + sizeof(T) - 1'.
571 1) u <-- '__mf_elem->high'
572 2) v <-- '__mf_base + sizeof (T) - 1'.
574 Then build 'u <-- (u < v). */
577 u = build (COMPONENT_REF, mf_uintptr_type,
578 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
579 TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
581 v = convert (mf_uintptr_type,
582 size_binop (MINUS_EXPR, size, size_one_node));
583 v = fold (build (PLUS_EXPR, mf_uintptr_type, mf_base, v));
585 u = build (LT_EXPR, boolean_type_node, u, v);
587 /* Build the composed conditional: t <-- 't || u'. Then store the
588 result of the evaluation of 't' in a temporary variable which we
589 can use as the condition for the conditional jump. */
590 t = build (TRUTH_OR_EXPR, boolean_type_node, t, u);
591 cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
592 t = build (MODIFY_EXPR, boolean_type_node, cond, t);
593 gimplify_to_stmt_list (&t);
594 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
596 /* Build the conditional jump. 'cond' is just a temporary so we can
597 simply build a void COND_EXPR. We do need labels in both arms though. */
598 t = build (COND_EXPR, void_type_node, cond,
599 build (GOTO_EXPR, void_type_node, tree_block_label (then_bb)),
600 build (GOTO_EXPR, void_type_node, tree_block_label (join_bb)));
601 SET_EXPR_LOCUS (t, locus);
602 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
604 /* At this point, after so much hard work, we have only constructed
605 the conditional jump,
607 if (__mf_elem->low > __mf_base
608 || (__mf_elem_high < __mf_base + sizeof(T) - 1))
610 The lowered GIMPLE tree representing this code is in the statement
611 list starting at 'head'.
613 We can insert this now in the current basic block, ie. the one that
614 the statement we're instrumenting was originally in. */
615 bsi = bsi_last (cond_bb);
616 for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
617 bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
619 /* Now build up the body of the cache-miss handling:
624 This is the body of the conditional. */
626 u = tree_cons (NULL_TREE,
627 mf_file_function_line_tree (locus == NULL ? UNKNOWN_LOCATION
630 u = tree_cons (NULL_TREE, dirflag, u);
631 u = tree_cons (NULL_TREE, size, u);
632 u = tree_cons (NULL_TREE, mf_value, u);
633 t = build_function_call_expr (mf_check_fndecl, u);
634 gimplify_to_stmt_list (&t);
635 head = tsi_start (t);
638 if (! flag_mudflap_threads)
640 t = build (MODIFY_EXPR, void_type_node,
641 mf_cache_shift_decl_l, mf_cache_shift_decl);
642 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
644 t = build (MODIFY_EXPR, void_type_node,
645 mf_cache_mask_decl_l, mf_cache_mask_decl);
646 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
649 /* Insert the check code in the THEN block. */
650 bsi = bsi_start (then_bb);
651 for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
652 bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
654 *instr_bsi = bsi_start (join_bb);
655 bsi_next (instr_bsi);
659 mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
660 location_t *locus, tree dirflag)
662 tree type, ptr_type, addr, size, t;
664 /* Don't instrument read operations. */
665 if (dirflag == integer_zero_node && flag_mudflap_ignore_reads)
669 type = TREE_TYPE (t);
670 size = TYPE_SIZE_UNIT (type);
672 switch (TREE_CODE (t))
676 /* Omit checking if we can statically determine that the access is
677 valid. For non-addressable local arrays this is not optional,
678 since we won't have called __mf_register for the object. */
681 op0 = TREE_OPERAND (t, 0);
682 op1 = TREE_OPERAND (t, 1);
683 while (TREE_CODE (op1) == INTEGER_CST)
685 tree dom = TYPE_DOMAIN (TREE_TYPE (op0));
687 /* Test for index in range. Break if not. */
689 || (! TYPE_MIN_VALUE (dom)
690 || ! really_constant_p (TYPE_MIN_VALUE (dom)))
691 || (! TYPE_MAX_VALUE (dom)
692 || ! really_constant_p (TYPE_MAX_VALUE (dom)))
693 || (tree_int_cst_lt (op1, TYPE_MIN_VALUE (dom))
694 || tree_int_cst_lt (TYPE_MAX_VALUE (dom), op1)))
697 /* If we're looking at a non-external VAR_DECL, then the
698 access must be ok. */
699 if (TREE_CODE (op0) == VAR_DECL && !DECL_EXTERNAL (op0))
702 /* Only continue if we're still looking at an array. */
703 if (TREE_CODE (op0) != ARRAY_REF)
706 op1 = TREE_OPERAND (op0, 1);
707 op0 = TREE_OPERAND (op0, 0);
710 /* If we got here, we couldn't statically the check. */
711 ptr_type = build_pointer_type (type);
712 addr = build1 (ADDR_EXPR, ptr_type, t);
717 addr = TREE_OPERAND (t, 0);
718 ptr_type = TREE_TYPE (addr);
721 case ARRAY_RANGE_REF:
722 warning ("mudflap checking not yet implemented for ARRAY_RANGE_REF");
729 /* If we're not dereferencing something, then the access
731 if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
734 field = TREE_OPERAND (t, 1);
736 /* If we're looking at a bit field, then we can't take its address
737 with ADDR_EXPR -- lang_hooks.mark_addressable will error. Do
738 things the hard way with PLUS. */
739 if (DECL_BIT_FIELD_TYPE (field))
741 if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST)
742 size = DECL_SIZE_UNIT (field);
744 addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
745 addr = fold_convert (ptr_type_node, addr);
746 addr = fold (build (PLUS_EXPR, ptr_type_node,
747 addr, fold_convert (ptr_type_node,
748 byte_position (field))));
752 ptr_type = build_pointer_type (type);
753 addr = build1 (ADDR_EXPR, ptr_type, t);
762 /* If we're not dereferencing something, then the access
764 if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
767 bpu = bitsize_int (BITS_PER_UNIT);
768 ofs = convert (bitsizetype, TREE_OPERAND (t, 2));
769 rem = size_binop (TRUNC_MOD_EXPR, ofs, bpu);
770 ofs = size_binop (TRUNC_DIV_EXPR, ofs, bpu);
772 size = convert (bitsizetype, TREE_OPERAND (t, 1));
773 size = size_binop (PLUS_EXPR, size, rem);
774 size = size_binop (CEIL_DIV_EXPR, size, bpu);
775 size = convert (sizetype, size);
777 addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
778 addr = convert (ptr_type_node, addr);
779 addr = fold (build (PLUS_EXPR, ptr_type_node, addr, ofs));
787 mf_build_check_statement_for (addr, size, iter, locus, dirflag);
791 mf_xform_derefs (void)
793 basic_block bb, next;
794 block_stmt_iterator i;
795 int saved_last_basic_block = last_basic_block;
797 bb = ENTRY_BLOCK_PTR ->next_bb;
801 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
803 tree s = bsi_stmt (i);
805 /* Only a few GIMPLE statements can reference memory. */
806 switch (TREE_CODE (s))
809 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
811 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 1), EXPR_LOCUS (s),
816 if (TREE_OPERAND (s, 0) != NULL_TREE)
818 if (TREE_CODE (TREE_OPERAND (s, 0)) == MODIFY_EXPR)
819 mf_xform_derefs_1 (&i, &TREE_OPERAND (TREE_OPERAND (s, 0), 1),
820 EXPR_LOCUS (s), integer_zero_node);
822 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
833 while (bb && bb->index <= saved_last_basic_block);
836 /* ------------------------------------------------------------------------ */
837 /* ADDR_EXPR transforms. Perform the declaration-related mudflap tree
838 transforms on the current function.
840 This is the first part of the mudflap instrumentation. It works on
841 high-level GIMPLE because after lowering, all variables are moved out
842 of their BIND_EXPR binding context, and we lose liveness information
843 for the declarations we wish to instrument. */
846 execute_mudflap_function_decls (void)
848 if (mf_marked_p (current_function_decl))
851 push_gimplify_context ();
853 mf_xform_decls (DECL_SAVED_TREE (current_function_decl),
854 DECL_ARGUMENTS (current_function_decl));
856 pop_gimplify_context (NULL);
859 /* This struct is passed between mf_xform_decls to store state needed
860 during the traversal searching for objects that have their
862 struct mf_xform_decls_data
868 /* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of
869 _DECLs if appropriate. Arrange to call the __mf_register function
870 now, and the __mf_unregister function later for each. */
872 mx_register_decls (tree decl, tree *stmt_list)
874 tree finally_stmts = NULL_TREE;
875 tree_stmt_iterator initially_stmts = tsi_start (*stmt_list);
877 while (decl != NULL_TREE)
880 if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
881 /* It must be a non-external, automatic variable. */
882 && ! DECL_EXTERNAL (decl)
883 && ! TREE_STATIC (decl)
884 /* The decl must have its address taken. */
885 && TREE_ADDRESSABLE (decl)
886 /* The type of the variable must be complete. */
887 && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
888 /* Don't process the same decl twice. */
889 && ! mf_marked_p (decl))
891 tree size = NULL_TREE, variable_name;
892 tree unregister_fncall, unregister_fncall_params;
893 tree register_fncall, register_fncall_params;
895 if (DECL_DEFER_OUTPUT (decl))
897 /* Oh no ... it's probably a variable-length array (VLA).
898 The size and address cannot be computed by merely
899 looking at the DECL. See gimplify_decl_stmt for the
900 method by which VLA declarations turn into calls to
901 BUILT_IN_STACK_ALLOC. We assume that multiple
902 VLAs declared later in the same block get allocation
903 code later than the others. */
904 tree stack_alloc_call = NULL_TREE;
906 while(! tsi_end_p (initially_stmts))
908 tree t = tsi_stmt (initially_stmts);
910 tree call = NULL_TREE;
911 if (TREE_CODE (t) == CALL_EXPR)
913 else if (TREE_CODE (t) == MODIFY_EXPR &&
914 TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR)
915 call = TREE_OPERAND (t, 1);
916 else if (TREE_CODE (t) == TRY_FINALLY_EXPR)
918 /* We hope that this is the try/finally block sometimes
919 constructed by gimplify_bind_expr() for a BIND_EXPR
920 that contains VLAs. This very naive recursion
921 appears to be sufficient. */
922 initially_stmts = tsi_start (TREE_OPERAND (t, 0));
925 if (call != NULL_TREE)
927 if (TREE_CODE (TREE_OPERAND(call, 0)) == ADDR_EXPR &&
928 TREE_OPERAND (TREE_OPERAND (call, 0), 0) ==
929 implicit_built_in_decls [BUILT_IN_STACK_ALLOC])
931 tree stack_alloc_args = TREE_OPERAND (call, 1);
932 tree stack_alloc_op1 = TREE_VALUE (stack_alloc_args);
933 tree stack_alloc_op2 = TREE_VALUE (TREE_CHAIN (stack_alloc_args));
935 if (TREE_CODE (stack_alloc_op1) == ADDR_EXPR &&
936 TREE_OPERAND (stack_alloc_op1, 0) == decl)
939 size = stack_alloc_op2;
940 stack_alloc_call = call;
941 /* Advance iterator to point past this allocation call. */
942 tsi_next (&initially_stmts);
948 tsi_next (&initially_stmts);
951 if (stack_alloc_call == NULL_TREE)
953 warning ("mudflap cannot handle variable-sized declaration `%s'",
954 IDENTIFIER_POINTER (DECL_NAME (decl)));
960 size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
963 /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
964 unregister_fncall_params =
965 tree_cons (NULL_TREE,
966 convert (ptr_type_node,
967 mf_mark (build1 (ADDR_EXPR,
968 build_pointer_type (TREE_TYPE (decl)),
970 tree_cons (NULL_TREE,
972 tree_cons (NULL_TREE,
973 build_int_2 (3, 0), /* __MF_TYPE_STACK */
975 /* __mf_unregister (...) */
976 unregister_fncall = build_function_call_expr (mf_unregister_fndecl,
977 unregister_fncall_params);
979 /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, "name") */
980 variable_name = mf_varname_tree (decl);
981 register_fncall_params =
982 tree_cons (NULL_TREE,
983 convert (ptr_type_node,
984 mf_mark (build1 (ADDR_EXPR,
985 build_pointer_type (TREE_TYPE (decl)),
987 tree_cons (NULL_TREE,
989 tree_cons (NULL_TREE,
990 build_int_2 (3, 0), /* __MF_TYPE_STACK */
991 tree_cons (NULL_TREE,
995 /* __mf_register (...) */
996 register_fncall = build_function_call_expr (mf_register_fndecl,
997 register_fncall_params);
999 /* Accumulate the two calls. */
1000 /* ??? Set EXPR_LOCATION. */
1001 gimplify_stmt (®ister_fncall);
1002 gimplify_stmt (&unregister_fncall);
1004 /* Add the __mf_register call at the current appending point. */
1005 if (tsi_end_p (initially_stmts))
1006 internal_error ("mudflap ran off end of BIND_EXPR body");
1007 tsi_link_before (&initially_stmts, register_fncall, TSI_SAME_STMT);
1009 /* Accumulate the FINALLY piece. */
1010 append_to_statement_list (unregister_fncall, &finally_stmts);
1015 decl = TREE_CHAIN (decl);
1018 /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
1019 if (finally_stmts != NULL_TREE)
1021 tree t = build (TRY_FINALLY_EXPR, void_type_node,
1022 *stmt_list, finally_stmts);
1024 append_to_statement_list (t, stmt_list);
1029 /* Process every variable mentioned in BIND_EXPRs. */
1031 mx_xfn_xform_decls (tree *t, int *continue_p, void *data)
1033 struct mf_xform_decls_data* d = (struct mf_xform_decls_data*) data;
1035 if (*t == NULL_TREE || *t == error_mark_node)
1043 switch (TREE_CODE (*t))
1047 /* Process function parameters now (but only once). */
1048 mx_register_decls (d->param_decls, &BIND_EXPR_BODY (*t));
1049 d->param_decls = NULL_TREE;
1051 mx_register_decls (BIND_EXPR_VARS (*t), &BIND_EXPR_BODY (*t));
1062 /* Perform the object lifetime tracking mudflap transform on the given function
1063 tree. The tree is mutated in place, with possibly copied subtree nodes.
1065 For every auto variable declared, if its address is ever taken
1066 within the function, then supply its lifetime to the mudflap
1067 runtime with the __mf_register and __mf_unregister calls.
1071 mf_xform_decls (tree fnbody, tree fnparams)
1073 struct mf_xform_decls_data d;
1074 d.param_decls = fnparams;
1075 walk_tree_without_duplicates (&fnbody, mx_xfn_xform_decls, &d);
1079 /* ------------------------------------------------------------------------ */
1080 /* Externally visible mudflap functions. */
1083 /* Mark and return the given tree node to prevent further mudflap
1085 static GTY ((param_is (union tree_node))) htab_t marked_trees = NULL;
1092 if (marked_trees == NULL)
1093 marked_trees = htab_create_ggc (31, htab_hash_pointer, htab_eq_pointer, NULL);
1095 slot = htab_find_slot (marked_trees, t, INSERT);
1101 mf_marked_p (tree t)
1105 if (marked_trees == NULL)
1108 entry = htab_find (marked_trees, t);
1109 return (entry != NULL);
1112 /* Remember given node as a static of some kind: global data,
1113 function-scope static, or an anonymous constant. Its assembler
1116 /* A list of globals whose incomplete declarations we encountered.
1117 Instead of emitting the __mf_register call for them here, it's
1118 delayed until program finish time. If they're still incomplete by
1119 then, warnings are emitted. */
1121 static GTY (()) varray_type deferred_static_decls;
1123 /* A list of statements for calling __mf_register() at startup time. */
1124 static GTY (()) tree enqueued_call_stmt_chain;
1127 mudflap_register_call (tree obj, tree object_size, tree varname)
1129 tree arg, args, call_stmt;
1131 args = tree_cons (NULL_TREE, varname, NULL_TREE);
1133 arg = build_int_2 (4, 0); /* __MF_TYPE_STATIC */
1134 args = tree_cons (NULL_TREE, arg, args);
1136 arg = convert (size_type_node, object_size);
1137 args = tree_cons (NULL_TREE, arg, args);
1139 arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj);
1140 arg = convert (ptr_type_node, arg);
1141 args = tree_cons (NULL_TREE, arg, args);
1143 call_stmt = build_function_call_expr (mf_register_fndecl, args);
1145 /* Add an initial __mf_init() call to the list of registration calls. */
1146 if (enqueued_call_stmt_chain == NULL_TREE)
1148 tree call2_stmt = build_function_call_expr (mf_init_fndecl, NULL_TREE);
1149 append_to_statement_list (call2_stmt, &enqueued_call_stmt_chain);
1152 append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
1156 mudflap_enqueue_decl (tree obj)
1158 if (mf_marked_p (obj))
1161 /* We don't need to process variable decls that are internally
1162 generated extern. If we did, we'd end up with warnings for them
1163 during mudflap_finish_file (). That would confuse the user,
1164 since the text would refer to variables that don't show up in the
1165 user's source code. */
1166 if (DECL_P (obj) && DECL_EXTERNAL (obj) && DECL_ARTIFICIAL (obj))
1169 if (COMPLETE_TYPE_P (TREE_TYPE (obj)))
1175 object_size = size_in_bytes (TREE_TYPE (obj));
1179 fprintf (dump_file, "enqueue_decl obj=`");
1180 print_generic_expr (dump_file, obj, dump_flags);
1181 fprintf (dump_file, "' size=");
1182 print_generic_expr (dump_file, object_size, dump_flags);
1183 fprintf (dump_file, "\n");
1186 /* NB: the above condition doesn't require TREE_USED or
1187 TREE_ADDRESSABLE. That's because this object may be a global
1188 only used from other compilation units. XXX: Maybe static
1189 objects could require those attributes being set. */
1191 mudflap_register_call (obj, object_size, mf_varname_tree (obj));
1197 if (! deferred_static_decls)
1198 VARRAY_TREE_INIT (deferred_static_decls, 10, "deferred static list");
1200 /* Ugh, linear search... */
1201 for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
1202 if (VARRAY_TREE (deferred_static_decls, i) == obj)
1204 warning ("mudflap cannot track lifetime of `%s'",
1205 IDENTIFIER_POINTER (DECL_NAME (obj)));
1209 VARRAY_PUSH_TREE (deferred_static_decls, obj);
1214 mudflap_enqueue_constant (tree obj)
1216 tree object_size, varname;
1218 if (mf_marked_p (obj))
1221 if (TREE_CODE (obj) == STRING_CST)
1222 object_size = build_int_2 (TREE_STRING_LENGTH (obj), 0);
1224 object_size = size_in_bytes (TREE_TYPE (obj));
1228 fprintf (dump_file, "enqueue_constant obj=`");
1229 print_generic_expr (dump_file, obj, dump_flags);
1230 fprintf (dump_file, "' size=");
1231 print_generic_expr (dump_file, object_size, dump_flags);
1232 fprintf (dump_file, "\n");
1235 if (TREE_CODE (obj) == STRING_CST)
1236 varname = mf_build_string ("string literal");
1238 varname = mf_build_string ("constant");
1240 mudflap_register_call (obj, object_size, varname);
1244 /* Emit any file-wide instrumentation. */
1246 mudflap_finish_file (void)
1248 /* Try to give the deferred objects one final try. */
1249 if (deferred_static_decls)
1253 for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
1255 tree obj = VARRAY_TREE (deferred_static_decls, i);
1257 /* Call enqueue_decl again on the same object it has previously
1258 put into the table. (It won't modify the table this time, so
1259 infinite iteration is not a problem.) */
1260 mudflap_enqueue_decl (obj);
1263 VARRAY_CLEAR (deferred_static_decls);
1266 if (enqueued_call_stmt_chain)
1268 cgraph_build_static_cdtor ('I', enqueued_call_stmt_chain,
1269 MAX_RESERVED_INIT_PRIORITY-1);
1270 enqueued_call_stmt_chain = 0;
1278 return flag_mudflap != 0;
1281 struct tree_opt_pass pass_mudflap_1 =
1283 "mudflap1", /* name */
1284 gate_mudflap, /* gate */
1285 execute_mudflap_function_decls, /* execute */
1288 0, /* static_pass_number */
1290 PROP_gimple_any, /* properties_required */
1291 0, /* properties_provided */
1292 0, /* properties_destroyed */
1293 0, /* todo_flags_start */
1294 TODO_dump_func /* todo_flags_finish */
1297 struct tree_opt_pass pass_mudflap_2 =
1299 "mudflap2", /* name */
1300 gate_mudflap, /* gate */
1301 execute_mudflap_function_ops, /* execute */
1304 0, /* static_pass_number */
1306 PROP_gimple_leh, /* properties_required */
1307 0, /* properties_provided */
1308 0, /* properties_destroyed */
1309 0, /* todo_flags_start */
1310 TODO_verify_flow | TODO_verify_stmts
1311 | TODO_dump_func /* todo_flags_finish */
1314 #include "gt-tree-mudflap.h"