* tree-inline.c (optimize_inline_calls): Set DECL_INLINED_FNS
[official-gcc.git] / gcc / tree-mudflap.c
blob2320bc9f2d98c722a85f01d67f840f987b360fcd
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 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>";
203 if (xloc.line > 0)
205 sprintf (linebuf, "%d", xloc.line);
206 colon = ":";
207 line = linebuf;
209 else
210 colon = line = "";
212 /* Add (FUNCTION). */
213 name = lang_hooks.decl_printable_name (current_function_decl, 1);
214 if (name)
216 op = " (";
217 cp = ")";
219 else
220 op = name = cp = "";
222 string = concat (file, colon, line, op, name, cp, NULL);
223 result = mf_build_string (string);
224 free (string);
226 return result;
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 /* Helper for mudflap_init: construct a decl with the given category,
272 name, and type, mark it an external reference, and pushdecl it. */
273 static inline tree
274 mf_make_builtin (enum tree_code category, const char *name, tree type)
276 tree decl = mf_mark (build_decl (category, get_identifier (name), type));
277 TREE_PUBLIC (decl) = 1;
278 DECL_EXTERNAL (decl) = 1;
279 lang_hooks.decls.pushdecl (decl);
280 return decl;
283 /* Helper for mudflap_init: construct a tree corresponding to the type
284 struct __mf_cache { uintptr_t low; uintptr_t high; };
285 where uintptr_t is the FIELD_TYPE argument. */
286 static inline tree
287 mf_make_mf_cache_struct_type (tree field_type)
289 /* There is, abominably, no language-independent way to construct a
290 RECORD_TYPE. So we have to call the basic type construction
291 primitives by hand. */
292 tree fieldlo = build_decl (FIELD_DECL, get_identifier ("low"), field_type);
293 tree fieldhi = build_decl (FIELD_DECL, get_identifier ("high"), field_type);
295 tree struct_type = make_node (RECORD_TYPE);
296 DECL_CONTEXT (fieldlo) = struct_type;
297 DECL_CONTEXT (fieldhi) = struct_type;
298 TREE_CHAIN (fieldlo) = fieldhi;
299 TYPE_FIELDS (struct_type) = fieldlo;
300 TYPE_NAME (struct_type) = get_identifier ("__mf_cache");
301 layout_type (struct_type);
303 return struct_type;
306 #define build_function_type_3(rtype, arg1, arg2, arg3) \
307 build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2, \
308 tree_cons (0, arg3, void_list_node))))
309 #define build_function_type_4(rtype, arg1, arg2, arg3, arg4) \
310 build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2, \
311 tree_cons (0, arg3, tree_cons (0, arg4, \
312 void_list_node)))))
314 /* Initialize the global tree nodes that correspond to mf-runtime.h
315 declarations. */
316 void
317 mudflap_init (void)
319 static bool done = false;
320 tree mf_const_string_type;
321 tree mf_cache_array_type;
322 tree mf_check_register_fntype;
323 tree mf_unregister_fntype;
325 if (done)
326 return;
327 done = true;
329 mf_uintptr_type = lang_hooks.types.type_for_mode (ptr_mode,
330 /*unsignedp=*/true);
331 mf_const_string_type
332 = build_pointer_type (build_qualified_type
333 (char_type_node, TYPE_QUAL_CONST));
335 mf_cache_struct_type = mf_make_mf_cache_struct_type (mf_uintptr_type);
336 mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type);
337 mf_cache_array_type = build_array_type (mf_cache_struct_type, 0);
338 mf_check_register_fntype =
339 build_function_type_4 (void_type_node, ptr_type_node, size_type_node,
340 integer_type_node, mf_const_string_type);
341 mf_unregister_fntype =
342 build_function_type_3 (void_type_node, ptr_type_node, size_type_node,
343 integer_type_node);
345 mf_cache_array_decl = mf_make_builtin (VAR_DECL, "__mf_lookup_cache",
346 mf_cache_array_type);
347 mf_cache_shift_decl = mf_make_builtin (VAR_DECL, "__mf_lc_shift",
348 unsigned_char_type_node);
349 mf_cache_mask_decl = mf_make_builtin (VAR_DECL, "__mf_lc_mask",
350 mf_uintptr_type);
351 mf_check_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_check",
352 mf_check_register_fntype);
353 mf_register_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_register",
354 mf_check_register_fntype);
355 mf_unregister_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_unregister",
356 mf_unregister_fntype);
358 #undef build_function_type_4
359 #undef build_function_type_3
362 /* ------------------------------------------------------------------------ */
363 /* Memory reference transforms. Perform the mudflap indirection-related
364 tree transforms on the current function.
366 This is the second part of the mudflap instrumentation. It works on
367 low-level GIMPLE using the CFG, because we want to run this pass after
368 tree optimizations have been performed, but we have to preserve the CFG
369 for expansion from trees to RTL. */
371 static void
372 execute_mudflap_function_ops (void)
374 if (mf_marked_p (current_function_decl))
375 return;
377 push_gimplify_context ();
379 /* In multithreaded mode, don't cache the lookup cache parameters. */
380 if (! flag_mudflap_threads)
381 mf_decl_cache_locals ();
383 mf_xform_derefs ();
385 if (! flag_mudflap_threads)
386 mf_decl_clear_locals ();
388 pop_gimplify_context (NULL);
391 /* Create and initialize local shadow variables for the lookup cache
392 globals. Put their decls in the *_l globals for use by
393 mf_build_check_statement_for. */
395 static void
396 mf_decl_cache_locals (void)
398 tree t, shift_init_stmts, mask_init_stmts;
399 tree_stmt_iterator tsi;
401 /* Build the cache vars. */
402 mf_cache_shift_decl_l
403 = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_shift_decl),
404 "__mf_lookup_shift_l"));
406 mf_cache_mask_decl_l
407 = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_mask_decl),
408 "__mf_lookup_mask_l"));
410 /* Build initialization nodes for the cache vars. We just load the
411 globals into the cache variables. */
412 t = build (MODIFY_EXPR, TREE_TYPE (mf_cache_shift_decl_l),
413 mf_cache_shift_decl_l, mf_cache_shift_decl);
414 SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
415 gimplify_to_stmt_list (&t);
416 shift_init_stmts = t;
418 t = build (MODIFY_EXPR, TREE_TYPE (mf_cache_mask_decl_l),
419 mf_cache_mask_decl_l, mf_cache_mask_decl);
420 SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
421 gimplify_to_stmt_list (&t);
422 mask_init_stmts = t;
424 /* Anticipating multiple entry points, we insert the cache vars
425 initializers in each successor of the ENTRY_BLOCK_PTR. */
426 for (tsi = tsi_start (shift_init_stmts);
427 ! tsi_end_p (tsi);
428 tsi_next (&tsi))
429 insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
431 for (tsi = tsi_start (mask_init_stmts);
432 ! tsi_end_p (tsi);
433 tsi_next (&tsi))
434 insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
435 bsi_commit_edge_inserts (NULL);
439 static void
440 mf_decl_clear_locals (void)
442 /* Unset local shadows. */
443 mf_cache_shift_decl_l = NULL_TREE;
444 mf_cache_mask_decl_l = NULL_TREE;
447 static void
448 mf_build_check_statement_for (tree addr, tree size,
449 block_stmt_iterator *instr_bsi,
450 location_t *locus, tree dirflag)
452 tree_stmt_iterator head, tsi;
453 tree ptrtype = TREE_TYPE (addr);
454 block_stmt_iterator bsi;
455 basic_block cond_bb, then_bb, join_bb;
456 edge e;
457 tree cond, t, u, v, l1, l2;
458 tree mf_value;
459 tree mf_base;
460 tree mf_elem;
462 /* We first need to split the current basic block, and start altering
463 the CFG. This allows us to insert the statements we're about to
464 construct into the right basic blocks. The label l1 is the label
465 of the block for the THEN clause of the conditional jump we're
466 about to construct, and l2 is the ELSE clause, which is just the
467 continuation of the old statement stream. */
468 l1 = create_artificial_label ();
469 l2 = create_artificial_label ();
470 cond_bb = bb_for_stmt (bsi_stmt (*instr_bsi));
471 bsi = *instr_bsi;
472 bsi_prev (&bsi);
473 if (! bsi_end_p (bsi))
475 e = split_block (cond_bb, bsi_stmt (bsi));
476 cond_bb = e->src;
477 join_bb = e->dest;
479 else
481 join_bb = cond_bb;
482 cond_bb = create_empty_bb (join_bb->prev_bb);
483 e = make_edge (cond_bb, join_bb, 0);
485 e->flags = EDGE_FALSE_VALUE;
486 then_bb = create_empty_bb (cond_bb);
487 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
488 make_edge (then_bb, join_bb, EDGE_FALLTHRU);
490 /* We expect that the conditional jump we will construct will not
491 be taken very often as it basically is an exception condition. */
492 predict_edge_def (then_bb->pred, PRED_MUDFLAP, NOT_TAKEN);
494 /* Update dominance info. Note that bb_join's data was
495 updated by split_block. */
496 if (dom_computed[CDI_DOMINATORS] >= DOM_CONS_OK)
498 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
499 set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb);
502 /* Build our local variables. */
503 mf_value = create_tmp_var (ptrtype, "__mf_value");
504 mf_elem = create_tmp_var (mf_cache_structptr_type, "__mf_elem");
505 mf_base = create_tmp_var (mf_uintptr_type, "__mf_base");
507 /* Build: __mf_value = <address expression>. */
508 t = build (MODIFY_EXPR, void_type_node, mf_value, unshare_expr (addr));
509 SET_EXPR_LOCUS (t, locus);
510 gimplify_to_stmt_list (&t);
511 head = tsi_start (t);
512 tsi = tsi_last (t);
514 /* Build: __mf_base = (uintptr_t)__mf_value. */
515 t = build (MODIFY_EXPR, void_type_node, mf_base,
516 build1 (NOP_EXPR, mf_uintptr_type, mf_value));
517 SET_EXPR_LOCUS (t, locus);
518 gimplify_to_stmt_list (&t);
519 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
521 /* Build: __mf_elem = &__mf_lookup_cache [(__mf_base >> __mf_shift)
522 & __mf_mask]. */
523 t = build (RSHIFT_EXPR, mf_uintptr_type, mf_base,
524 (flag_mudflap_threads ? mf_cache_shift_decl : mf_cache_shift_decl_l));
525 t = build (BIT_AND_EXPR, mf_uintptr_type, t,
526 (flag_mudflap_threads ? mf_cache_mask_decl : mf_cache_mask_decl_l));
527 t = build (ARRAY_REF,
528 TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
529 mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
530 t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
531 t = build (MODIFY_EXPR, void_type_node, mf_elem, t);
532 SET_EXPR_LOCUS (t, locus);
533 gimplify_to_stmt_list (&t);
534 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
536 /* Quick validity check.
538 if (__mf_elem->low > __mf_base
539 || (__mf_elem_high < __mf_base + sizeof(T) - 1))
541 __mf_check ();
542 ... and only if single-threaded:
543 __mf_lookup_shift_1 = f...;
544 __mf_lookup_mask_l = ...;
547 It is expected that this body of code is rarely executed so we mark
548 the edge to the THEN clause of the conditional jump as unlikely. */
550 /* Construct t <-- '__mf_elem->low > __mf_base'. */
551 t = build (COMPONENT_REF, mf_uintptr_type,
552 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
553 TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
554 t = build (GT_EXPR, boolean_type_node, t, mf_base);
556 /* Construct '__mf_elem->high < __mf_base + sizeof(T) - 1'.
558 First build:
559 1) u <-- '__mf_elem->high'
560 2) v <-- '__mf_base + sizeof (T) - 1'.
562 Then build 'u <-- (u < v). */
565 u = build (COMPONENT_REF, mf_uintptr_type,
566 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
567 TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
569 v = convert (mf_uintptr_type,
570 size_binop (MINUS_EXPR, size, size_one_node));
571 v = fold (build (PLUS_EXPR, mf_uintptr_type, mf_base, v));
573 u = build (LT_EXPR, boolean_type_node, u, v);
575 /* Build the composed conditional: t <-- 't || u'. Then store the
576 result of the evaluation of 't' in a temporary variable which we
577 can use as the condition for the conditional jump. */
578 t = build (TRUTH_OR_EXPR, boolean_type_node, t, u);
579 cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
580 t = build (MODIFY_EXPR, boolean_type_node, cond, t);
581 gimplify_to_stmt_list (&t);
582 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
584 /* Build the conditional jump. 'cond' is just a temporary so we can
585 simply build a void COND_EXPR. We do need labels in both arms though. */
586 t = build (COND_EXPR, void_type_node, cond,
587 build (GOTO_EXPR, void_type_node, tree_block_label (then_bb)),
588 build (GOTO_EXPR, void_type_node, tree_block_label (join_bb)));
589 SET_EXPR_LOCUS (t, locus);
590 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
592 /* At this point, after so much hard work, we have only constructed
593 the conditional jump,
595 if (__mf_elem->low > __mf_base
596 || (__mf_elem_high < __mf_base + sizeof(T) - 1))
598 The lowered GIMPLE tree representing this code is in the statement
599 list starting at 'head'.
601 We can insert this now in the current basic block, ie. the one that
602 the statement we're instrumenting was originally in. */
603 bsi = bsi_last (cond_bb);
604 for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
605 bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
607 /* Now build up the body of the cache-miss handling:
609 __mf_check();
610 refresh *_l vars.
612 This is the body of the conditional. */
614 u = tree_cons (NULL_TREE,
615 mf_file_function_line_tree (locus == NULL ? UNKNOWN_LOCATION
616 : *locus),
617 NULL_TREE);
618 u = tree_cons (NULL_TREE, dirflag, u);
619 u = tree_cons (NULL_TREE, size, u);
620 u = tree_cons (NULL_TREE, mf_value, u);
621 t = build_function_call_expr (mf_check_fndecl, u);
622 gimplify_to_stmt_list (&t);
623 head = tsi_start (t);
624 tsi = tsi_last (t);
626 if (! flag_mudflap_threads)
628 t = build (MODIFY_EXPR, void_type_node,
629 mf_cache_shift_decl_l, mf_cache_shift_decl);
630 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
632 t = build (MODIFY_EXPR, void_type_node,
633 mf_cache_mask_decl_l, mf_cache_mask_decl);
634 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
637 /* Insert the check code in the THEN block. */
638 bsi = bsi_start (then_bb);
639 for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
640 bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
642 *instr_bsi = bsi_start (join_bb);
643 bsi_next (instr_bsi);
646 static void
647 mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
648 location_t *locus, tree dirflag)
650 tree type, ptr_type, addr, size, t;
652 /* Don't instrument read operations. */
653 if (dirflag == integer_zero_node && flag_mudflap_ignore_reads)
654 return;
656 t = *tp;
657 type = TREE_TYPE (t);
658 size = TYPE_SIZE_UNIT (type);
660 switch (TREE_CODE (t))
662 case ARRAY_REF:
664 /* Omit checking if we can statically determine that the access is
665 valid. For non-addressable local arrays this is not optional,
666 since we won't have called __mf_register for the object. */
667 tree op0, op1;
669 op0 = TREE_OPERAND (t, 0);
670 op1 = TREE_OPERAND (t, 1);
671 while (TREE_CODE (op1) == INTEGER_CST)
673 tree dom = TYPE_DOMAIN (TREE_TYPE (op0));
675 /* Test for index in range. Break if not. */
676 if (!dom
677 || (! TYPE_MIN_VALUE (dom)
678 || ! really_constant_p (TYPE_MIN_VALUE (dom)))
679 || (! TYPE_MAX_VALUE (dom)
680 || ! really_constant_p (TYPE_MAX_VALUE (dom)))
681 || (tree_int_cst_lt (op1, TYPE_MIN_VALUE (dom))
682 || tree_int_cst_lt (TYPE_MAX_VALUE (dom), op1)))
683 break;
685 /* If we're looking at a non-external VAR_DECL, then the
686 access must be ok. */
687 if (TREE_CODE (op0) == VAR_DECL && !DECL_EXTERNAL (op0))
688 return;
690 /* Only continue if we're still looking at an array. */
691 if (TREE_CODE (op0) != ARRAY_REF)
692 break;
694 op1 = TREE_OPERAND (op0, 1);
695 op0 = TREE_OPERAND (op0, 0);
698 /* If we got here, we couldn't statically the check. */
699 ptr_type = build_pointer_type (type);
700 addr = build1 (ADDR_EXPR, ptr_type, t);
702 break;
704 case INDIRECT_REF:
705 addr = TREE_OPERAND (t, 0);
706 ptr_type = TREE_TYPE (addr);
707 break;
709 case ARRAY_RANGE_REF:
710 warning ("mudflap checking not yet implemented for ARRAY_RANGE_REF");
711 return;
713 case COMPONENT_REF:
715 tree field;
717 /* If we're not dereferencing something, then the access
718 must be ok. */
719 if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
720 return;
722 field = TREE_OPERAND (t, 1);
724 /* If we're looking at a bit field, then we can't take its address
725 with ADDR_EXPR -- lang_hooks.mark_addressable will error. Do
726 things the hard way with PLUS. */
727 if (DECL_BIT_FIELD_TYPE (field))
729 if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST)
730 size = DECL_SIZE_UNIT (field);
732 addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
733 addr = fold_convert (ptr_type_node, addr);
734 addr = fold (build (PLUS_EXPR, ptr_type_node,
735 addr, fold_convert (ptr_type_node,
736 byte_position (field))));
738 else
740 ptr_type = build_pointer_type (type);
741 addr = build1 (ADDR_EXPR, ptr_type, t);
744 break;
746 case BIT_FIELD_REF:
748 tree ofs, rem, bpu;
750 /* If we're not dereferencing something, then the access
751 must be ok. */
752 if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
753 return;
755 bpu = bitsize_int (BITS_PER_UNIT);
756 ofs = convert (bitsizetype, TREE_OPERAND (t, 2));
757 rem = size_binop (TRUNC_MOD_EXPR, ofs, bpu);
758 ofs = size_binop (TRUNC_DIV_EXPR, ofs, bpu);
760 size = convert (bitsizetype, TREE_OPERAND (t, 1));
761 size = size_binop (PLUS_EXPR, size, rem);
762 size = size_binop (CEIL_DIV_EXPR, size, bpu);
763 size = convert (sizetype, size);
765 addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
766 addr = convert (ptr_type_node, addr);
767 addr = fold (build (PLUS_EXPR, ptr_type_node, addr, ofs));
769 break;
771 default:
772 return;
775 mf_build_check_statement_for (addr, size, iter, locus, dirflag);
778 static void
779 mf_xform_derefs (void)
781 basic_block bb, next;
782 block_stmt_iterator i;
783 int saved_last_basic_block = last_basic_block;
785 bb = ENTRY_BLOCK_PTR ->next_bb;
788 next = bb->next_bb;
789 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
791 tree s = bsi_stmt (i);
793 /* Only a few GIMPLE statements can reference memory. */
794 switch (TREE_CODE (s))
796 case MODIFY_EXPR:
797 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
798 integer_one_node);
799 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 1), EXPR_LOCUS (s),
800 integer_zero_node);
801 break;
803 case RETURN_EXPR:
804 if (TREE_OPERAND (s, 0) != NULL_TREE)
806 if (TREE_CODE (TREE_OPERAND (s, 0)) == MODIFY_EXPR)
807 mf_xform_derefs_1 (&i, &TREE_OPERAND (TREE_OPERAND (s, 0), 1),
808 EXPR_LOCUS (s), integer_zero_node);
809 else
810 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
811 integer_zero_node);
813 break;
815 default:
819 bb = next;
821 while (bb && bb->index <= saved_last_basic_block);
824 /* ------------------------------------------------------------------------ */
825 /* ADDR_EXPR transforms. Perform the declaration-related mudflap tree
826 transforms on the current function.
828 This is the first part of the mudflap instrumentation. It works on
829 high-level GIMPLE because after lowering, all variables are moved out
830 of their BIND_EXPR binding context, and we lose liveness information
831 for the declarations we wish to instrument. */
833 static void
834 execute_mudflap_function_decls (void)
836 if (mf_marked_p (current_function_decl))
837 return;
839 push_gimplify_context ();
841 mf_xform_decls (DECL_SAVED_TREE (current_function_decl),
842 DECL_ARGUMENTS (current_function_decl));
844 pop_gimplify_context (NULL);
847 /* This struct is passed between mf_xform_decls to store state needed
848 during the traversal searching for objects that have their
849 addresses taken. */
850 struct mf_xform_decls_data
852 tree param_decls;
856 /* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of
857 _DECLs if appropriate. Arrange to call the __mf_register function
858 now, and the __mf_unregister function later for each. */
859 static void
860 mx_register_decls (tree decl, tree *stmt_list)
862 tree finally_stmts = NULL_TREE;
863 tree_stmt_iterator initially_stmts = tsi_start (*stmt_list);
865 while (decl != NULL_TREE)
867 /* Eligible decl? */
868 if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
869 /* It must be a non-external, automatic variable. */
870 && ! DECL_EXTERNAL (decl)
871 && ! TREE_STATIC (decl)
872 /* The decl must have its address taken. */
873 && TREE_ADDRESSABLE (decl)
874 /* The type of the variable must be complete. */
875 && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
876 /* Don't process the same decl twice. */
877 && ! mf_marked_p (decl))
879 tree size = NULL_TREE, variable_name;
880 tree unregister_fncall, unregister_fncall_params;
881 tree register_fncall, register_fncall_params;
883 if (DECL_DEFER_OUTPUT (decl))
885 /* Oh no ... it's probably a variable-length array (VLA).
886 The size and address cannot be computed by merely
887 looking at the DECL. See gimplify_decl_stmt for the
888 method by which VLA declarations turn into calls to
889 BUILT_IN_STACK_ALLOC. We assume that multiple
890 VLAs declared later in the same block get allocation
891 code later than the others. */
892 tree stack_alloc_call = NULL_TREE;
894 while(! tsi_end_p (initially_stmts))
896 tree t = tsi_stmt (initially_stmts);
898 tree call = NULL_TREE;
899 if (TREE_CODE (t) == CALL_EXPR)
900 call = t;
901 else if (TREE_CODE (t) == MODIFY_EXPR &&
902 TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR)
903 call = TREE_OPERAND (t, 1);
904 else if (TREE_CODE (t) == TRY_FINALLY_EXPR)
906 /* We hope that this is the try/finally block sometimes
907 constructed by gimplify_bind_expr() for a BIND_EXPR
908 that contains VLAs. This very naive recursion
909 appears to be sufficient. */
910 initially_stmts = tsi_start (TREE_OPERAND (t, 0));
913 if (call != NULL_TREE)
915 if (TREE_CODE (TREE_OPERAND(call, 0)) == ADDR_EXPR &&
916 TREE_OPERAND (TREE_OPERAND (call, 0), 0) ==
917 implicit_built_in_decls [BUILT_IN_STACK_ALLOC])
919 tree stack_alloc_args = TREE_OPERAND (call, 1);
920 tree stack_alloc_op1 = TREE_VALUE (stack_alloc_args);
921 tree stack_alloc_op2 = TREE_VALUE (TREE_CHAIN (stack_alloc_args));
923 if (TREE_CODE (stack_alloc_op1) == ADDR_EXPR &&
924 TREE_OPERAND (stack_alloc_op1, 0) == decl)
926 /* Got it! */
927 size = stack_alloc_op2;
928 stack_alloc_call = call;
929 /* Advance iterator to point past this allocation call. */
930 tsi_next (&initially_stmts);
931 break;
936 tsi_next (&initially_stmts);
939 if (stack_alloc_call == NULL_TREE)
941 warning ("mudflap cannot handle variable-sized declaration `%s'",
942 IDENTIFIER_POINTER (DECL_NAME (decl)));
943 break;
946 else
948 size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
951 /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
952 unregister_fncall_params =
953 tree_cons (NULL_TREE,
954 convert (ptr_type_node,
955 mf_mark (build1 (ADDR_EXPR,
956 build_pointer_type (TREE_TYPE (decl)),
957 decl))),
958 tree_cons (NULL_TREE,
959 size,
960 tree_cons (NULL_TREE,
961 build_int_2 (3, 0), /* __MF_TYPE_STACK */
962 NULL_TREE)));
963 /* __mf_unregister (...) */
964 unregister_fncall = build_function_call_expr (mf_unregister_fndecl,
965 unregister_fncall_params);
967 /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, "name") */
968 variable_name = mf_varname_tree (decl);
969 register_fncall_params =
970 tree_cons (NULL_TREE,
971 convert (ptr_type_node,
972 mf_mark (build1 (ADDR_EXPR,
973 build_pointer_type (TREE_TYPE (decl)),
974 decl))),
975 tree_cons (NULL_TREE,
976 size,
977 tree_cons (NULL_TREE,
978 build_int_2 (3, 0), /* __MF_TYPE_STACK */
979 tree_cons (NULL_TREE,
980 variable_name,
981 NULL_TREE))));
983 /* __mf_register (...) */
984 register_fncall = build_function_call_expr (mf_register_fndecl,
985 register_fncall_params);
987 /* Accumulate the two calls. */
988 /* ??? Set EXPR_LOCATION. */
989 gimplify_stmt (&register_fncall);
990 gimplify_stmt (&unregister_fncall);
992 /* Add the __mf_register call at the current appending point. */
993 if (tsi_end_p (initially_stmts))
994 internal_error ("mudflap ran off end of BIND_EXPR body");
995 tsi_link_before (&initially_stmts, register_fncall, TSI_SAME_STMT);
997 /* Accumulate the FINALLY piece. */
998 append_to_statement_list (unregister_fncall, &finally_stmts);
1000 mf_mark (decl);
1003 decl = TREE_CHAIN (decl);
1006 /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
1007 if (finally_stmts != NULL_TREE)
1009 tree t = build (TRY_FINALLY_EXPR, void_type_node,
1010 *stmt_list, finally_stmts);
1011 *stmt_list = NULL;
1012 append_to_statement_list (t, stmt_list);
1017 /* Process every variable mentioned in BIND_EXPRs. */
1018 static tree
1019 mx_xfn_xform_decls (tree *t, int *continue_p, void *data)
1021 struct mf_xform_decls_data* d = (struct mf_xform_decls_data*) data;
1023 if (*t == NULL_TREE || *t == error_mark_node)
1025 *continue_p = 0;
1026 return NULL_TREE;
1029 *continue_p = 1;
1031 switch (TREE_CODE (*t))
1033 case BIND_EXPR:
1035 /* Process function parameters now (but only once). */
1036 mx_register_decls (d->param_decls, &BIND_EXPR_BODY (*t));
1037 d->param_decls = NULL_TREE;
1039 mx_register_decls (BIND_EXPR_VARS (*t), &BIND_EXPR_BODY (*t));
1041 break;
1043 default:
1044 break;
1047 return NULL;
1050 /* Perform the object lifetime tracking mudflap transform on the given function
1051 tree. The tree is mutated in place, with possibly copied subtree nodes.
1053 For every auto variable declared, if its address is ever taken
1054 within the function, then supply its lifetime to the mudflap
1055 runtime with the __mf_register and __mf_unregister calls.
1058 static void
1059 mf_xform_decls (tree fnbody, tree fnparams)
1061 struct mf_xform_decls_data d;
1062 d.param_decls = fnparams;
1063 walk_tree_without_duplicates (&fnbody, mx_xfn_xform_decls, &d);
1067 /* ------------------------------------------------------------------------ */
1068 /* Externally visible mudflap functions. */
1071 /* Mark and return the given tree node to prevent further mudflap
1072 transforms. */
1073 static GTY ((param_is (union tree_node))) htab_t marked_trees = NULL;
1075 tree
1076 mf_mark (tree t)
1078 void **slot;
1080 if (marked_trees == NULL)
1081 marked_trees = htab_create_ggc (31, htab_hash_pointer, htab_eq_pointer, NULL);
1083 slot = htab_find_slot (marked_trees, t, INSERT);
1084 *slot = t;
1085 return t;
1089 mf_marked_p (tree t)
1091 void *entry;
1093 if (marked_trees == NULL)
1094 return 0;
1096 entry = htab_find (marked_trees, t);
1097 return (entry != NULL);
1100 /* Remember given node as a static of some kind: global data,
1101 function-scope static, or an anonymous constant. Its assembler
1102 label is given. */
1104 /* A list of globals whose incomplete declarations we encountered.
1105 Instead of emitting the __mf_register call for them here, it's
1106 delayed until program finish time. If they're still incomplete by
1107 then, warnings are emitted. */
1109 static GTY (()) varray_type deferred_static_decls;
1111 /* A list of statements for calling __mf_register() at startup time. */
1112 static GTY (()) tree enqueued_call_stmt_chain;
1114 static void
1115 mudflap_register_call (tree obj, tree object_size, tree varname)
1117 tree arg, args, call_stmt;
1119 args = tree_cons (NULL_TREE, varname, NULL_TREE);
1121 arg = build_int_2 (4, 0); /* __MF_TYPE_STATIC */
1122 args = tree_cons (NULL_TREE, arg, args);
1124 arg = convert (size_type_node, object_size);
1125 args = tree_cons (NULL_TREE, arg, args);
1127 arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj);
1128 arg = convert (ptr_type_node, arg);
1129 args = tree_cons (NULL_TREE, arg, args);
1131 call_stmt = build_function_call_expr (mf_register_fndecl, args);
1133 append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
1136 void
1137 mudflap_enqueue_decl (tree obj)
1139 if (mf_marked_p (obj))
1140 return;
1142 /* We don't need to process variable decls that are internally
1143 generated extern. If we did, we'd end up with warnings for them
1144 during mudflap_finish_file (). That would confuse the user,
1145 since the text would refer to variables that don't show up in the
1146 user's source code. */
1147 if (DECL_P (obj) && DECL_EXTERNAL (obj) && DECL_ARTIFICIAL (obj))
1148 return;
1150 if (COMPLETE_TYPE_P (TREE_TYPE (obj)))
1152 tree object_size;
1154 mf_mark (obj);
1156 object_size = size_in_bytes (TREE_TYPE (obj));
1158 if (dump_file)
1160 fprintf (dump_file, "enqueue_decl obj=`");
1161 print_generic_expr (dump_file, obj, dump_flags);
1162 fprintf (dump_file, "' size=");
1163 print_generic_expr (dump_file, object_size, dump_flags);
1164 fprintf (dump_file, "\n");
1167 /* NB: the above condition doesn't require TREE_USED or
1168 TREE_ADDRESSABLE. That's because this object may be a global
1169 only used from other compilation units. XXX: Maybe static
1170 objects could require those attributes being set. */
1172 mudflap_register_call (obj, object_size, mf_varname_tree (obj));
1174 else
1176 size_t i;
1178 if (! deferred_static_decls)
1179 VARRAY_TREE_INIT (deferred_static_decls, 10, "deferred static list");
1181 /* Ugh, linear search... */
1182 for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
1183 if (VARRAY_TREE (deferred_static_decls, i) == obj)
1185 warning ("mudflap cannot track lifetime of `%s'",
1186 IDENTIFIER_POINTER (DECL_NAME (obj)));
1187 return;
1190 VARRAY_PUSH_TREE (deferred_static_decls, obj);
1194 void
1195 mudflap_enqueue_constant (tree obj)
1197 tree object_size, varname;
1199 if (mf_marked_p (obj))
1200 return;
1202 if (TREE_CODE (obj) == STRING_CST)
1203 object_size = build_int_2 (TREE_STRING_LENGTH (obj), 0);
1204 else
1205 object_size = size_in_bytes (TREE_TYPE (obj));
1207 if (dump_file)
1209 fprintf (dump_file, "enqueue_constant obj=`");
1210 print_generic_expr (dump_file, obj, dump_flags);
1211 fprintf (dump_file, "' size=");
1212 print_generic_expr (dump_file, object_size, dump_flags);
1213 fprintf (dump_file, "\n");
1216 if (TREE_CODE (obj) == STRING_CST)
1217 varname = mf_build_string ("string literal");
1218 else
1219 varname = mf_build_string ("constant");
1221 mudflap_register_call (obj, object_size, varname);
1225 /* Emit any file-wide instrumentation. */
1226 void
1227 mudflap_finish_file (void)
1229 /* Try to give the deferred objects one final try. */
1230 if (deferred_static_decls)
1232 size_t i;
1234 for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
1236 tree obj = VARRAY_TREE (deferred_static_decls, i);
1238 /* Call enqueue_decl again on the same object it has previously
1239 put into the table. (It won't modify the table this time, so
1240 infinite iteration is not a problem.) */
1241 mudflap_enqueue_decl (obj);
1244 VARRAY_CLEAR (deferred_static_decls);
1247 if (enqueued_call_stmt_chain)
1249 cgraph_build_static_cdtor ('I', enqueued_call_stmt_chain);
1250 enqueued_call_stmt_chain = 0;
1255 static bool
1256 gate_mudflap (void)
1258 return flag_mudflap != 0;
1261 struct tree_opt_pass pass_mudflap_1 =
1263 "mudflap1", /* name */
1264 gate_mudflap, /* gate */
1265 execute_mudflap_function_decls, /* execute */
1266 NULL, /* sub */
1267 NULL, /* next */
1268 0, /* static_pass_number */
1269 0, /* tv_id */
1270 PROP_gimple_any, /* properties_required */
1271 0, /* properties_provided */
1272 0, /* properties_destroyed */
1273 0, /* todo_flags_start */
1274 TODO_dump_func /* todo_flags_finish */
1277 struct tree_opt_pass pass_mudflap_2 =
1279 "mudflap2", /* name */
1280 gate_mudflap, /* gate */
1281 execute_mudflap_function_ops, /* execute */
1282 NULL, /* sub */
1283 NULL, /* next */
1284 0, /* static_pass_number */
1285 0, /* tv_id */
1286 PROP_gimple_leh, /* properties_required */
1287 0, /* properties_provided */
1288 0, /* properties_destroyed */
1289 0, /* todo_flags_start */
1290 TODO_verify_flow | TODO_verify_stmts
1291 | TODO_dump_func /* todo_flags_finish */
1294 #include "gt-tree-mudflap.h"