* config/arm/symbian.h (STARTFILE_SPEC): Remove crt*.o.
[official-gcc.git] / gcc / tree-mudflap.c
bloba61a7ad935c32ad3bcb3145b5d83caf724c756cd
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) = build_array_type
80 (char_type_node, build_index_type (build_int_cst (NULL_TREE, len)));
81 TREE_CONSTANT (result) = 1;
82 TREE_INVARIANT (result) = 1;
83 TREE_READONLY (result) = 1;
84 TREE_STATIC (result) = 1;
86 result = build1 (ADDR_EXPR, build_pointer_type (char_type_node), result);
88 return mf_mark (result);
91 /* Create a properly typed STRING_CST node that describes the given
92 declaration. It will be used as an argument for __mf_register().
93 Try to construct a helpful string, including file/function/variable
94 name. */
96 static tree
97 mf_varname_tree (tree decl)
99 static pretty_printer buf_rec;
100 static int initialized = 0;
101 pretty_printer *buf = & buf_rec;
102 const char *buf_contents;
103 tree result;
105 gcc_assert (decl);
107 if (!initialized)
109 pp_construct (buf, /* prefix */ NULL, /* line-width */ 0);
110 initialized = 1;
112 pp_clear_output_area (buf);
114 /* Add FILENAME[:LINENUMBER[:COLUMNNUMBER]]. */
116 expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (decl));
117 const char *sourcefile;
118 unsigned sourceline = xloc.line;
119 unsigned sourcecolumn = 0;
120 #ifdef USE_MAPPED_LOCATION
121 sourcecolumn = xloc.column;
122 #endif
123 sourcefile = xloc.file;
124 if (sourcefile == NULL && current_function_decl != NULL_TREE)
125 sourcefile = DECL_SOURCE_FILE (current_function_decl);
126 if (sourcefile == NULL)
127 sourcefile = "<unknown file>";
129 pp_string (buf, sourcefile);
131 if (sourceline != 0)
133 pp_string (buf, ":");
134 pp_decimal_int (buf, sourceline);
136 if (sourcecolumn != 0)
138 pp_string (buf, ":");
139 pp_decimal_int (buf, sourcecolumn);
144 if (current_function_decl != NULL_TREE)
146 /* Add (FUNCTION) */
147 pp_string (buf, " (");
149 const char *funcname = NULL;
150 if (DECL_NAME (current_function_decl))
151 funcname = lang_hooks.decl_printable_name (current_function_decl, 1);
152 if (funcname == NULL)
153 funcname = "anonymous fn";
155 pp_string (buf, funcname);
157 pp_string (buf, ") ");
159 else
160 pp_string (buf, " ");
162 /* Add <variable-declaration>, possibly demangled. */
164 const char *declname = NULL;
166 if (strcmp ("GNU C++", lang_hooks.name) == 0 &&
167 DECL_NAME (decl) != NULL)
169 /* The gcc/cp decl_printable_name hook doesn't do as good a job as
170 the libiberty demangler. */
171 declname = cplus_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)),
172 DMGL_AUTO | DMGL_VERBOSE);
175 if (declname == NULL)
176 declname = lang_hooks.decl_printable_name (decl, 3);
178 if (declname == NULL)
179 declname = "<unnamed variable>";
181 pp_string (buf, declname);
184 /* Return the lot as a new STRING_CST. */
185 buf_contents = pp_base_formatted_text (buf);
186 result = mf_build_string (buf_contents);
187 pp_clear_output_area (buf);
189 return result;
193 /* And another friend, for producing a simpler message. */
195 static tree
196 mf_file_function_line_tree (location_t location)
198 expanded_location xloc = expand_location (location);
199 const char *file = NULL, *colon, *line, *op, *name, *cp;
200 char linecolbuf[30]; /* Enough for two decimal numbers plus a colon. */
201 char *string;
202 tree result;
204 /* Add FILENAME[:LINENUMBER[:COLUMNNUMBER]]. */
205 file = xloc.file;
206 if (file == NULL && current_function_decl != NULL_TREE)
207 file = DECL_SOURCE_FILE (current_function_decl);
208 if (file == NULL)
209 file = "<unknown file>";
211 if (xloc.line > 0)
213 #ifdef USE_MAPPED_LOCATION
214 if (xloc.column > 0)
215 sprintf (linecolbuf, "%d:%d", xloc.line, xloc.column);
216 else
217 #endif
218 sprintf (linecolbuf, "%d", xloc.line);
219 colon = ":";
220 line = linecolbuf;
222 else
223 colon = line = "";
225 /* Add (FUNCTION). */
226 name = lang_hooks.decl_printable_name (current_function_decl, 1);
227 if (name)
229 op = " (";
230 cp = ")";
232 else
233 op = name = cp = "";
235 string = concat (file, colon, line, op, name, cp, NULL);
236 result = mf_build_string (string);
237 free (string);
239 return result;
243 /* global tree nodes */
245 /* Global tree objects for global variables and functions exported by
246 mudflap runtime library. mf_init_extern_trees must be called
247 before using these. */
249 /* uintptr_t (usually "unsigned long") */
250 static GTY (()) tree mf_uintptr_type;
252 /* struct __mf_cache { uintptr_t low; uintptr_t high; }; */
253 static GTY (()) tree mf_cache_struct_type;
255 /* struct __mf_cache * const */
256 static GTY (()) tree mf_cache_structptr_type;
258 /* extern struct __mf_cache __mf_lookup_cache []; */
259 static GTY (()) tree mf_cache_array_decl;
261 /* extern unsigned char __mf_lc_shift; */
262 static GTY (()) tree mf_cache_shift_decl;
264 /* extern uintptr_t __mf_lc_mask; */
265 static GTY (()) tree mf_cache_mask_decl;
267 /* Their function-scope local shadows, used in single-threaded mode only. */
269 /* auto const unsigned char __mf_lc_shift_l; */
270 static GTY (()) tree mf_cache_shift_decl_l;
272 /* auto const uintptr_t __mf_lc_mask_l; */
273 static GTY (()) tree mf_cache_mask_decl_l;
275 /* extern void __mf_check (void *ptr, size_t sz, int type, const char *); */
276 static GTY (()) tree mf_check_fndecl;
278 /* extern void __mf_register (void *ptr, size_t sz, int type, const char *); */
279 static GTY (()) tree mf_register_fndecl;
281 /* extern void __mf_unregister (void *ptr, size_t sz, int type); */
282 static GTY (()) tree mf_unregister_fndecl;
284 /* extern void __mf_init (); */
285 static GTY (()) tree mf_init_fndecl;
287 /* extern int __mf_set_options (const char*); */
288 static GTY (()) tree mf_set_options_fndecl;
291 /* Helper for mudflap_init: construct a decl with the given category,
292 name, and type, mark it an external reference, and pushdecl it. */
293 static inline tree
294 mf_make_builtin (enum tree_code category, const char *name, tree type)
296 tree decl = mf_mark (build_decl (category, get_identifier (name), type));
297 TREE_PUBLIC (decl) = 1;
298 DECL_EXTERNAL (decl) = 1;
299 lang_hooks.decls.pushdecl (decl);
300 return decl;
303 /* Helper for mudflap_init: construct a tree corresponding to the type
304 struct __mf_cache { uintptr_t low; uintptr_t high; };
305 where uintptr_t is the FIELD_TYPE argument. */
306 static inline tree
307 mf_make_mf_cache_struct_type (tree field_type)
309 /* There is, abominably, no language-independent way to construct a
310 RECORD_TYPE. So we have to call the basic type construction
311 primitives by hand. */
312 tree fieldlo = build_decl (FIELD_DECL, get_identifier ("low"), field_type);
313 tree fieldhi = build_decl (FIELD_DECL, get_identifier ("high"), field_type);
315 tree struct_type = make_node (RECORD_TYPE);
316 DECL_CONTEXT (fieldlo) = struct_type;
317 DECL_CONTEXT (fieldhi) = struct_type;
318 TREE_CHAIN (fieldlo) = fieldhi;
319 TYPE_FIELDS (struct_type) = fieldlo;
320 TYPE_NAME (struct_type) = get_identifier ("__mf_cache");
321 layout_type (struct_type);
323 return struct_type;
326 #define build_function_type_0(rtype) \
327 build_function_type (rtype, void_list_node)
328 #define build_function_type_1(rtype, arg1) \
329 build_function_type (rtype, tree_cons (0, arg1, void_list_node))
330 #define build_function_type_3(rtype, arg1, arg2, arg3) \
331 build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2, \
332 tree_cons (0, arg3, void_list_node))))
333 #define build_function_type_4(rtype, arg1, arg2, arg3, arg4) \
334 build_function_type (rtype, tree_cons (0, arg1, tree_cons (0, arg2, \
335 tree_cons (0, arg3, tree_cons (0, arg4, \
336 void_list_node)))))
338 /* Initialize the global tree nodes that correspond to mf-runtime.h
339 declarations. */
340 void
341 mudflap_init (void)
343 static bool done = false;
344 tree mf_const_string_type;
345 tree mf_cache_array_type;
346 tree mf_check_register_fntype;
347 tree mf_unregister_fntype;
348 tree mf_init_fntype;
349 tree mf_set_options_fntype;
351 if (done)
352 return;
353 done = true;
355 mf_uintptr_type = lang_hooks.types.type_for_mode (ptr_mode,
356 /*unsignedp=*/true);
357 mf_const_string_type
358 = build_pointer_type (build_qualified_type
359 (char_type_node, TYPE_QUAL_CONST));
361 mf_cache_struct_type = mf_make_mf_cache_struct_type (mf_uintptr_type);
362 mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type);
363 mf_cache_array_type = build_array_type (mf_cache_struct_type, 0);
364 mf_check_register_fntype =
365 build_function_type_4 (void_type_node, ptr_type_node, size_type_node,
366 integer_type_node, mf_const_string_type);
367 mf_unregister_fntype =
368 build_function_type_3 (void_type_node, ptr_type_node, size_type_node,
369 integer_type_node);
370 mf_init_fntype =
371 build_function_type_0 (void_type_node);
372 mf_set_options_fntype =
373 build_function_type_1 (integer_type_node, mf_const_string_type);
375 mf_cache_array_decl = mf_make_builtin (VAR_DECL, "__mf_lookup_cache",
376 mf_cache_array_type);
377 mf_cache_shift_decl = mf_make_builtin (VAR_DECL, "__mf_lc_shift",
378 unsigned_char_type_node);
379 mf_cache_mask_decl = mf_make_builtin (VAR_DECL, "__mf_lc_mask",
380 mf_uintptr_type);
381 mf_check_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_check",
382 mf_check_register_fntype);
383 mf_register_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_register",
384 mf_check_register_fntype);
385 mf_unregister_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_unregister",
386 mf_unregister_fntype);
387 mf_init_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_init",
388 mf_init_fntype);
389 mf_set_options_fndecl = mf_make_builtin (FUNCTION_DECL, "__mf_set_options",
390 mf_set_options_fntype);
392 #undef build_function_type_4
393 #undef build_function_type_3
394 #undef build_function_type_1
395 #undef build_function_type_0
398 /* ------------------------------------------------------------------------ */
399 /* Memory reference transforms. Perform the mudflap indirection-related
400 tree transforms on the current function.
402 This is the second part of the mudflap instrumentation. It works on
403 low-level GIMPLE using the CFG, because we want to run this pass after
404 tree optimizations have been performed, but we have to preserve the CFG
405 for expansion from trees to RTL. */
407 static void
408 execute_mudflap_function_ops (void)
410 if (mf_marked_p (current_function_decl))
411 return;
413 push_gimplify_context ();
415 /* In multithreaded mode, don't cache the lookup cache parameters. */
416 if (! flag_mudflap_threads)
417 mf_decl_cache_locals ();
419 mf_xform_derefs ();
421 if (! flag_mudflap_threads)
422 mf_decl_clear_locals ();
424 pop_gimplify_context (NULL);
427 /* Create and initialize local shadow variables for the lookup cache
428 globals. Put their decls in the *_l globals for use by
429 mf_build_check_statement_for. */
431 static void
432 mf_decl_cache_locals (void)
434 tree t, shift_init_stmts, mask_init_stmts;
435 tree_stmt_iterator tsi;
437 /* Build the cache vars. */
438 mf_cache_shift_decl_l
439 = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_shift_decl),
440 "__mf_lookup_shift_l"));
442 mf_cache_mask_decl_l
443 = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_mask_decl),
444 "__mf_lookup_mask_l"));
446 /* Build initialization nodes for the cache vars. We just load the
447 globals into the cache variables. */
448 t = build (MODIFY_EXPR, TREE_TYPE (mf_cache_shift_decl_l),
449 mf_cache_shift_decl_l, mf_cache_shift_decl);
450 SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
451 gimplify_to_stmt_list (&t);
452 shift_init_stmts = t;
454 t = build (MODIFY_EXPR, TREE_TYPE (mf_cache_mask_decl_l),
455 mf_cache_mask_decl_l, mf_cache_mask_decl);
456 SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
457 gimplify_to_stmt_list (&t);
458 mask_init_stmts = t;
460 /* Anticipating multiple entry points, we insert the cache vars
461 initializers in each successor of the ENTRY_BLOCK_PTR. */
462 for (tsi = tsi_start (shift_init_stmts);
463 ! tsi_end_p (tsi);
464 tsi_next (&tsi))
465 insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
467 for (tsi = tsi_start (mask_init_stmts);
468 ! tsi_end_p (tsi);
469 tsi_next (&tsi))
470 insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
471 bsi_commit_edge_inserts (NULL);
475 static void
476 mf_decl_clear_locals (void)
478 /* Unset local shadows. */
479 mf_cache_shift_decl_l = NULL_TREE;
480 mf_cache_mask_decl_l = NULL_TREE;
483 static void
484 mf_build_check_statement_for (tree addr, tree size,
485 block_stmt_iterator *instr_bsi,
486 location_t *locus, tree dirflag)
488 tree_stmt_iterator head, tsi;
489 tree ptrtype = TREE_TYPE (addr);
490 block_stmt_iterator bsi;
491 basic_block cond_bb, then_bb, join_bb;
492 edge e;
493 tree cond, t, u, v, l1, l2;
494 tree mf_value;
495 tree mf_base;
496 tree mf_elem;
498 /* We first need to split the current basic block, and start altering
499 the CFG. This allows us to insert the statements we're about to
500 construct into the right basic blocks. The label l1 is the label
501 of the block for the THEN clause of the conditional jump we're
502 about to construct, and l2 is the ELSE clause, which is just the
503 continuation of the old statement stream. */
504 l1 = create_artificial_label ();
505 l2 = create_artificial_label ();
506 cond_bb = bb_for_stmt (bsi_stmt (*instr_bsi));
507 bsi = *instr_bsi;
508 bsi_prev (&bsi);
509 if (! bsi_end_p (bsi))
511 /* We're processing a statement in the middle of the block, so
512 we need to split the block. This creates a new block and a new
513 fallthrough edge. */
514 e = split_block (cond_bb, bsi_stmt (bsi));
515 cond_bb = e->src;
516 join_bb = e->dest;
518 else
520 /* We're processing the first statement in the block, so we need
521 to split the incoming edge. This also creates a new block
522 and a new fallthrough edge. */
523 join_bb = cond_bb;
524 cond_bb = split_edge (find_edge (join_bb->prev_bb, join_bb));
527 /* A recap at this point: join_bb is the basic block at whose head
528 is the gimple statement for which this check expression is being
529 built. cond_bb is the (possibly new, synthetic) basic block the
530 end of which will contain the cache-lookup code, and a
531 conditional that jumps to the cache-miss code or, much more
532 likely, over to join_bb. */
534 /* Create the bb that contains the cache-miss fallback block (mf_check). */
535 then_bb = create_empty_bb (cond_bb);
536 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
537 make_single_succ_edge (then_bb, join_bb, EDGE_FALLTHRU);
539 /* We expect that the conditional jump we will construct will not
540 be taken very often as it basically is an exception condition. */
541 predict_edge_def (EDGE_PRED (then_bb, 0), PRED_MUDFLAP, NOT_TAKEN);
543 /* Mark the pseudo-fallthrough edge from cond_bb to join_bb. */
544 e = find_edge (cond_bb, join_bb);
545 e->flags = EDGE_FALSE_VALUE;
546 predict_edge_def (e, PRED_MUDFLAP, TAKEN);
548 /* Update dominance info. Note that bb_join's data was
549 updated by split_block. */
550 if (dom_computed[CDI_DOMINATORS] >= DOM_CONS_OK)
552 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
553 set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb);
556 /* Build our local variables. */
557 mf_value = create_tmp_var (ptrtype, "__mf_value");
558 mf_elem = create_tmp_var (mf_cache_structptr_type, "__mf_elem");
559 mf_base = create_tmp_var (mf_uintptr_type, "__mf_base");
561 /* Build: __mf_value = <address expression>. */
562 t = build (MODIFY_EXPR, void_type_node, mf_value, unshare_expr (addr));
563 SET_EXPR_LOCUS (t, locus);
564 gimplify_to_stmt_list (&t);
565 head = tsi_start (t);
566 tsi = tsi_last (t);
568 /* Build: __mf_base = (uintptr_t)__mf_value. */
569 t = build (MODIFY_EXPR, void_type_node, mf_base,
570 build1 (NOP_EXPR, mf_uintptr_type, mf_value));
571 SET_EXPR_LOCUS (t, locus);
572 gimplify_to_stmt_list (&t);
573 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
575 /* Build: __mf_elem = &__mf_lookup_cache [(__mf_base >> __mf_shift)
576 & __mf_mask]. */
577 t = build (RSHIFT_EXPR, mf_uintptr_type, mf_base,
578 (flag_mudflap_threads ? mf_cache_shift_decl : mf_cache_shift_decl_l));
579 t = build (BIT_AND_EXPR, mf_uintptr_type, t,
580 (flag_mudflap_threads ? mf_cache_mask_decl : mf_cache_mask_decl_l));
581 t = build (ARRAY_REF,
582 TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
583 mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
584 t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
585 t = build (MODIFY_EXPR, void_type_node, mf_elem, t);
586 SET_EXPR_LOCUS (t, locus);
587 gimplify_to_stmt_list (&t);
588 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
590 /* Quick validity check.
592 if (__mf_elem->low > __mf_base
593 || (__mf_elem_high < __mf_base + sizeof(T) - 1))
595 __mf_check ();
596 ... and only if single-threaded:
597 __mf_lookup_shift_1 = f...;
598 __mf_lookup_mask_l = ...;
601 It is expected that this body of code is rarely executed so we mark
602 the edge to the THEN clause of the conditional jump as unlikely. */
604 /* Construct t <-- '__mf_elem->low > __mf_base'. */
605 t = build (COMPONENT_REF, mf_uintptr_type,
606 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
607 TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
608 t = build (GT_EXPR, boolean_type_node, t, mf_base);
610 /* Construct '__mf_elem->high < __mf_base + sizeof(T) - 1'.
612 First build:
613 1) u <-- '__mf_elem->high'
614 2) v <-- '__mf_base + sizeof (T) - 1'.
616 Then build 'u <-- (u < v). */
619 u = build (COMPONENT_REF, mf_uintptr_type,
620 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
621 TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
623 v = convert (mf_uintptr_type,
624 size_binop (MINUS_EXPR, size, size_one_node));
625 v = fold (build (PLUS_EXPR, mf_uintptr_type, mf_base, v));
627 u = build (LT_EXPR, boolean_type_node, u, v);
629 /* Build the composed conditional: t <-- 't || u'. Then store the
630 result of the evaluation of 't' in a temporary variable which we
631 can use as the condition for the conditional jump. */
632 t = build (TRUTH_OR_EXPR, boolean_type_node, t, u);
633 cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
634 t = build (MODIFY_EXPR, boolean_type_node, cond, t);
635 gimplify_to_stmt_list (&t);
636 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
638 /* Build the conditional jump. 'cond' is just a temporary so we can
639 simply build a void COND_EXPR. We do need labels in both arms though. */
640 t = build (COND_EXPR, void_type_node, cond,
641 build (GOTO_EXPR, void_type_node, tree_block_label (then_bb)),
642 build (GOTO_EXPR, void_type_node, tree_block_label (join_bb)));
643 SET_EXPR_LOCUS (t, locus);
644 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
646 /* At this point, after so much hard work, we have only constructed
647 the conditional jump,
649 if (__mf_elem->low > __mf_base
650 || (__mf_elem_high < __mf_base + sizeof(T) - 1))
652 The lowered GIMPLE tree representing this code is in the statement
653 list starting at 'head'.
655 We can insert this now in the current basic block, i.e. the one that
656 the statement we're instrumenting was originally in. */
657 bsi = bsi_last (cond_bb);
658 for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
659 bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
661 /* Now build up the body of the cache-miss handling:
663 __mf_check();
664 refresh *_l vars.
666 This is the body of the conditional. */
668 u = tree_cons (NULL_TREE,
669 mf_file_function_line_tree (locus == NULL ? UNKNOWN_LOCATION
670 : *locus),
671 NULL_TREE);
672 u = tree_cons (NULL_TREE, dirflag, u);
673 u = tree_cons (NULL_TREE, size, u);
674 u = tree_cons (NULL_TREE, mf_value, u);
675 t = build_function_call_expr (mf_check_fndecl, u);
676 gimplify_to_stmt_list (&t);
677 head = tsi_start (t);
678 tsi = tsi_last (t);
680 if (! flag_mudflap_threads)
682 t = build (MODIFY_EXPR, void_type_node,
683 mf_cache_shift_decl_l, mf_cache_shift_decl);
684 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
686 t = build (MODIFY_EXPR, void_type_node,
687 mf_cache_mask_decl_l, mf_cache_mask_decl);
688 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
691 /* Insert the check code in the THEN block. */
692 bsi = bsi_start (then_bb);
693 for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
694 bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
696 *instr_bsi = bsi_start (join_bb);
697 bsi_next (instr_bsi);
700 static void
701 mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
702 location_t *locus, tree dirflag)
704 tree type, ptr_type, addr, size, t;
706 /* Don't instrument read operations. */
707 if (dirflag == integer_zero_node && flag_mudflap_ignore_reads)
708 return;
710 /* Don't instrument marked nodes. */
711 if (mf_marked_p (*tp))
712 return;
714 t = *tp;
715 type = TREE_TYPE (t);
716 size = TYPE_SIZE_UNIT (type);
718 switch (TREE_CODE (t))
720 case ARRAY_REF:
722 /* Omit checking if we can statically determine that the access is
723 valid. For non-addressable local arrays this is not optional,
724 since we won't have called __mf_register for the object. */
725 tree op0, op1;
727 op0 = TREE_OPERAND (t, 0);
728 op1 = TREE_OPERAND (t, 1);
729 while (TREE_CODE (op1) == INTEGER_CST)
731 tree dom = TYPE_DOMAIN (TREE_TYPE (op0));
733 /* Test for index in range. Break if not. */
734 if (!dom
735 || (! TYPE_MIN_VALUE (dom)
736 || ! really_constant_p (TYPE_MIN_VALUE (dom)))
737 || (! TYPE_MAX_VALUE (dom)
738 || ! really_constant_p (TYPE_MAX_VALUE (dom)))
739 || (tree_int_cst_lt (op1, TYPE_MIN_VALUE (dom))
740 || tree_int_cst_lt (TYPE_MAX_VALUE (dom), op1)))
741 break;
743 /* If we're looking at a non-external VAR_DECL, then the
744 access must be ok. */
745 if (TREE_CODE (op0) == VAR_DECL && !DECL_EXTERNAL (op0))
746 return;
748 /* Only continue if we're still looking at an array. */
749 if (TREE_CODE (op0) != ARRAY_REF)
750 break;
752 op1 = TREE_OPERAND (op0, 1);
753 op0 = TREE_OPERAND (op0, 0);
756 /* If we got here, we couldn't statically the check. */
757 ptr_type = build_pointer_type (type);
758 addr = build1 (ADDR_EXPR, ptr_type, t);
760 break;
762 case INDIRECT_REF:
763 addr = TREE_OPERAND (t, 0);
764 ptr_type = TREE_TYPE (addr);
765 break;
767 case ARRAY_RANGE_REF:
768 warning ("mudflap checking not yet implemented for ARRAY_RANGE_REF");
769 return;
771 case COMPONENT_REF:
773 tree field;
775 /* If we're not dereferencing something, then the access
776 must be ok. */
777 if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
778 return;
780 field = TREE_OPERAND (t, 1);
782 /* If we're looking at a bit field, then we can't take its address
783 with ADDR_EXPR -- lang_hooks.mark_addressable will error. Do
784 things the hard way with PLUS. */
785 if (DECL_BIT_FIELD_TYPE (field))
787 if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST)
788 size = DECL_SIZE_UNIT (field);
790 addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
791 addr = fold_convert (ptr_type_node, addr);
792 addr = fold (build (PLUS_EXPR, ptr_type_node,
793 addr, fold_convert (ptr_type_node,
794 byte_position (field))));
796 else
798 ptr_type = build_pointer_type (type);
799 addr = build1 (ADDR_EXPR, ptr_type, t);
802 break;
804 case BIT_FIELD_REF:
806 tree ofs, rem, bpu;
808 /* If we're not dereferencing something, then the access
809 must be ok. */
810 if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
811 return;
813 bpu = bitsize_int (BITS_PER_UNIT);
814 ofs = convert (bitsizetype, TREE_OPERAND (t, 2));
815 rem = size_binop (TRUNC_MOD_EXPR, ofs, bpu);
816 ofs = size_binop (TRUNC_DIV_EXPR, ofs, bpu);
818 size = convert (bitsizetype, TREE_OPERAND (t, 1));
819 size = size_binop (PLUS_EXPR, size, rem);
820 size = size_binop (CEIL_DIV_EXPR, size, bpu);
821 size = convert (sizetype, size);
823 addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
824 addr = convert (ptr_type_node, addr);
825 addr = fold (build (PLUS_EXPR, ptr_type_node, addr, ofs));
827 break;
829 default:
830 return;
833 mf_build_check_statement_for (addr, size, iter, locus, dirflag);
836 static void
837 mf_xform_derefs (void)
839 basic_block bb, next;
840 block_stmt_iterator i;
841 int saved_last_basic_block = last_basic_block;
843 bb = ENTRY_BLOCK_PTR ->next_bb;
846 next = bb->next_bb;
847 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
849 tree s = bsi_stmt (i);
851 /* Only a few GIMPLE statements can reference memory. */
852 switch (TREE_CODE (s))
854 case MODIFY_EXPR:
855 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
856 integer_one_node);
857 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 1), EXPR_LOCUS (s),
858 integer_zero_node);
859 break;
861 case RETURN_EXPR:
862 if (TREE_OPERAND (s, 0) != NULL_TREE)
864 if (TREE_CODE (TREE_OPERAND (s, 0)) == MODIFY_EXPR)
865 mf_xform_derefs_1 (&i, &TREE_OPERAND (TREE_OPERAND (s, 0), 1),
866 EXPR_LOCUS (s), integer_zero_node);
867 else
868 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
869 integer_zero_node);
871 break;
873 default:
877 bb = next;
879 while (bb && bb->index <= saved_last_basic_block);
882 /* ------------------------------------------------------------------------ */
883 /* ADDR_EXPR transforms. Perform the declaration-related mudflap tree
884 transforms on the current function.
886 This is the first part of the mudflap instrumentation. It works on
887 high-level GIMPLE because after lowering, all variables are moved out
888 of their BIND_EXPR binding context, and we lose liveness information
889 for the declarations we wish to instrument. */
891 static void
892 execute_mudflap_function_decls (void)
894 if (mf_marked_p (current_function_decl))
895 return;
897 push_gimplify_context ();
899 mf_xform_decls (DECL_SAVED_TREE (current_function_decl),
900 DECL_ARGUMENTS (current_function_decl));
902 pop_gimplify_context (NULL);
905 /* This struct is passed between mf_xform_decls to store state needed
906 during the traversal searching for objects that have their
907 addresses taken. */
908 struct mf_xform_decls_data
910 tree param_decls;
914 /* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of
915 _DECLs if appropriate. Arrange to call the __mf_register function
916 now, and the __mf_unregister function later for each. */
917 static void
918 mx_register_decls (tree decl, tree *stmt_list)
920 tree finally_stmts = NULL_TREE;
921 tree_stmt_iterator initially_stmts = tsi_start (*stmt_list);
923 while (decl != NULL_TREE)
925 /* Eligible decl? */
926 if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
927 /* It must be a non-external, automatic variable. */
928 && ! DECL_EXTERNAL (decl)
929 && ! TREE_STATIC (decl)
930 /* The decl must have its address taken. */
931 && TREE_ADDRESSABLE (decl)
932 /* The type of the variable must be complete. */
933 && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
934 /* The decl hasn't been decomposed somehow. */
935 && DECL_VALUE_EXPR (decl) == NULL
936 /* Don't process the same decl twice. */
937 && ! mf_marked_p (decl))
939 tree size = NULL_TREE, variable_name;
940 tree unregister_fncall, unregister_fncall_params;
941 tree register_fncall, register_fncall_params;
943 size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
945 /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
946 unregister_fncall_params =
947 tree_cons (NULL_TREE,
948 convert (ptr_type_node,
949 mf_mark (build1 (ADDR_EXPR,
950 build_pointer_type (TREE_TYPE (decl)),
951 decl))),
952 tree_cons (NULL_TREE,
953 size,
954 tree_cons (NULL_TREE,
955 /* __MF_TYPE_STACK */
956 build_int_cst (NULL_TREE, 3),
957 NULL_TREE)));
958 /* __mf_unregister (...) */
959 unregister_fncall = build_function_call_expr (mf_unregister_fndecl,
960 unregister_fncall_params);
962 /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, "name") */
963 variable_name = mf_varname_tree (decl);
964 register_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)),
969 decl))),
970 tree_cons (NULL_TREE,
971 size,
972 tree_cons (NULL_TREE,
973 /* __MF_TYPE_STACK */
974 build_int_cst (NULL_TREE, 3),
975 tree_cons (NULL_TREE,
976 variable_name,
977 NULL_TREE))));
979 /* __mf_register (...) */
980 register_fncall = build_function_call_expr (mf_register_fndecl,
981 register_fncall_params);
983 /* Accumulate the two calls. */
984 /* ??? Set EXPR_LOCATION. */
985 gimplify_stmt (&register_fncall);
986 gimplify_stmt (&unregister_fncall);
988 /* Add the __mf_register call at the current appending point. */
989 if (tsi_end_p (initially_stmts))
990 internal_error ("mudflap ran off end of BIND_EXPR body");
991 tsi_link_before (&initially_stmts, register_fncall, TSI_SAME_STMT);
993 /* Accumulate the FINALLY piece. */
994 append_to_statement_list (unregister_fncall, &finally_stmts);
996 mf_mark (decl);
999 decl = TREE_CHAIN (decl);
1002 /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
1003 if (finally_stmts != NULL_TREE)
1005 tree t = build (TRY_FINALLY_EXPR, void_type_node,
1006 *stmt_list, finally_stmts);
1007 *stmt_list = NULL;
1008 append_to_statement_list (t, stmt_list);
1013 /* Process every variable mentioned in BIND_EXPRs. */
1014 static tree
1015 mx_xfn_xform_decls (tree *t, int *continue_p, void *data)
1017 struct mf_xform_decls_data* d = (struct mf_xform_decls_data*) data;
1019 if (*t == NULL_TREE || *t == error_mark_node)
1021 *continue_p = 0;
1022 return NULL_TREE;
1025 *continue_p = 1;
1027 switch (TREE_CODE (*t))
1029 case BIND_EXPR:
1031 /* Process function parameters now (but only once). */
1032 mx_register_decls (d->param_decls, &BIND_EXPR_BODY (*t));
1033 d->param_decls = NULL_TREE;
1035 mx_register_decls (BIND_EXPR_VARS (*t), &BIND_EXPR_BODY (*t));
1037 break;
1039 default:
1040 break;
1043 return NULL;
1046 /* Perform the object lifetime tracking mudflap transform on the given function
1047 tree. The tree is mutated in place, with possibly copied subtree nodes.
1049 For every auto variable declared, if its address is ever taken
1050 within the function, then supply its lifetime to the mudflap
1051 runtime with the __mf_register and __mf_unregister calls.
1054 static void
1055 mf_xform_decls (tree fnbody, tree fnparams)
1057 struct mf_xform_decls_data d;
1058 d.param_decls = fnparams;
1059 walk_tree_without_duplicates (&fnbody, mx_xfn_xform_decls, &d);
1063 /* ------------------------------------------------------------------------ */
1064 /* Externally visible mudflap functions. */
1067 /* Mark and return the given tree node to prevent further mudflap
1068 transforms. */
1069 static GTY ((param_is (union tree_node))) htab_t marked_trees = NULL;
1071 tree
1072 mf_mark (tree t)
1074 void **slot;
1076 if (marked_trees == NULL)
1077 marked_trees = htab_create_ggc (31, htab_hash_pointer, htab_eq_pointer, NULL);
1079 slot = htab_find_slot (marked_trees, t, INSERT);
1080 *slot = t;
1081 return t;
1085 mf_marked_p (tree t)
1087 void *entry;
1089 if (marked_trees == NULL)
1090 return 0;
1092 entry = htab_find (marked_trees, t);
1093 return (entry != NULL);
1096 /* Remember given node as a static of some kind: global data,
1097 function-scope static, or an anonymous constant. Its assembler
1098 label is given. */
1100 /* A list of globals whose incomplete declarations we encountered.
1101 Instead of emitting the __mf_register call for them here, it's
1102 delayed until program finish time. If they're still incomplete by
1103 then, warnings are emitted. */
1105 static GTY (()) varray_type deferred_static_decls;
1107 /* A list of statements for calling __mf_register() at startup time. */
1108 static GTY (()) tree enqueued_call_stmt_chain;
1110 static void
1111 mudflap_register_call (tree obj, tree object_size, tree varname)
1113 tree arg, args, call_stmt;
1115 args = tree_cons (NULL_TREE, varname, NULL_TREE);
1117 arg = build_int_cst (NULL_TREE, 4); /* __MF_TYPE_STATIC */
1118 args = tree_cons (NULL_TREE, arg, args);
1120 arg = convert (size_type_node, object_size);
1121 args = tree_cons (NULL_TREE, arg, args);
1123 arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj);
1124 arg = convert (ptr_type_node, arg);
1125 args = tree_cons (NULL_TREE, arg, args);
1127 call_stmt = build_function_call_expr (mf_register_fndecl, args);
1129 append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
1132 void
1133 mudflap_enqueue_decl (tree obj)
1135 if (mf_marked_p (obj))
1136 return;
1138 /* We don't need to process variable decls that are internally
1139 generated extern. If we did, we'd end up with warnings for them
1140 during mudflap_finish_file (). That would confuse the user,
1141 since the text would refer to variables that don't show up in the
1142 user's source code. */
1143 if (DECL_P (obj) && DECL_EXTERNAL (obj) && DECL_ARTIFICIAL (obj))
1144 return;
1146 if (COMPLETE_TYPE_P (TREE_TYPE (obj)))
1148 tree object_size;
1150 mf_mark (obj);
1152 object_size = size_in_bytes (TREE_TYPE (obj));
1154 if (dump_file)
1156 fprintf (dump_file, "enqueue_decl obj=`");
1157 print_generic_expr (dump_file, obj, dump_flags);
1158 fprintf (dump_file, "' size=");
1159 print_generic_expr (dump_file, object_size, dump_flags);
1160 fprintf (dump_file, "\n");
1163 /* NB: the above condition doesn't require TREE_USED or
1164 TREE_ADDRESSABLE. That's because this object may be a global
1165 only used from other compilation units. XXX: Maybe static
1166 objects could require those attributes being set. */
1168 mudflap_register_call (obj, object_size, mf_varname_tree (obj));
1170 else
1172 size_t i;
1174 if (! deferred_static_decls)
1175 VARRAY_TREE_INIT (deferred_static_decls, 10, "deferred static list");
1177 /* Ugh, linear search... */
1178 for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
1179 if (VARRAY_TREE (deferred_static_decls, i) == obj)
1181 warning ("mudflap cannot track lifetime of %qs",
1182 IDENTIFIER_POINTER (DECL_NAME (obj)));
1183 return;
1186 VARRAY_PUSH_TREE (deferred_static_decls, obj);
1190 void
1191 mudflap_enqueue_constant (tree obj)
1193 tree object_size, varname;
1195 if (mf_marked_p (obj))
1196 return;
1198 if (TREE_CODE (obj) == STRING_CST)
1199 object_size = build_int_cst (NULL_TREE, TREE_STRING_LENGTH (obj));
1200 else
1201 object_size = size_in_bytes (TREE_TYPE (obj));
1203 if (dump_file)
1205 fprintf (dump_file, "enqueue_constant obj=`");
1206 print_generic_expr (dump_file, obj, dump_flags);
1207 fprintf (dump_file, "' size=");
1208 print_generic_expr (dump_file, object_size, dump_flags);
1209 fprintf (dump_file, "\n");
1212 if (TREE_CODE (obj) == STRING_CST)
1213 varname = mf_build_string ("string literal");
1214 else
1215 varname = mf_build_string ("constant");
1217 mudflap_register_call (obj, object_size, varname);
1221 /* Emit any file-wide instrumentation. */
1222 void
1223 mudflap_finish_file (void)
1225 tree ctor_statements = NULL_TREE;
1227 /* Try to give the deferred objects one final try. */
1228 if (deferred_static_decls)
1230 size_t i;
1232 for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
1234 tree obj = VARRAY_TREE (deferred_static_decls, i);
1236 /* Call enqueue_decl again on the same object it has previously
1237 put into the table. (It won't modify the table this time, so
1238 infinite iteration is not a problem.) */
1239 mudflap_enqueue_decl (obj);
1242 VARRAY_CLEAR (deferred_static_decls);
1245 /* Insert a call to __mf_init. */
1247 tree call2_stmt = build_function_call_expr (mf_init_fndecl, NULL_TREE);
1248 append_to_statement_list (call2_stmt, &ctor_statements);
1251 /* If appropriate, call __mf_set_options to pass along read-ignore mode. */
1252 if (flag_mudflap_ignore_reads)
1254 tree arg = tree_cons (NULL_TREE,
1255 mf_build_string ("-ignore-reads"), NULL_TREE);
1256 tree call_stmt = build_function_call_expr (mf_set_options_fndecl, arg);
1257 append_to_statement_list (call_stmt, &ctor_statements);
1260 /* Append all the enqueued registration calls. */
1261 if (enqueued_call_stmt_chain)
1263 append_to_statement_list (enqueued_call_stmt_chain, &ctor_statements);
1264 enqueued_call_stmt_chain = NULL_TREE;
1267 cgraph_build_static_cdtor ('I', ctor_statements,
1268 MAX_RESERVED_INIT_PRIORITY-1);
1272 static bool
1273 gate_mudflap (void)
1275 return flag_mudflap != 0;
1278 struct tree_opt_pass pass_mudflap_1 =
1280 "mudflap1", /* name */
1281 gate_mudflap, /* gate */
1282 execute_mudflap_function_decls, /* execute */
1283 NULL, /* sub */
1284 NULL, /* next */
1285 0, /* static_pass_number */
1286 0, /* tv_id */
1287 PROP_gimple_any, /* properties_required */
1288 0, /* properties_provided */
1289 0, /* properties_destroyed */
1290 0, /* todo_flags_start */
1291 TODO_dump_func, /* todo_flags_finish */
1292 0 /* letter */
1295 struct tree_opt_pass pass_mudflap_2 =
1297 "mudflap2", /* name */
1298 gate_mudflap, /* gate */
1299 execute_mudflap_function_ops, /* execute */
1300 NULL, /* sub */
1301 NULL, /* next */
1302 0, /* static_pass_number */
1303 0, /* tv_id */
1304 PROP_gimple_leh, /* properties_required */
1305 0, /* properties_provided */
1306 0, /* properties_destroyed */
1307 0, /* todo_flags_start */
1308 TODO_verify_flow | TODO_verify_stmts
1309 | TODO_dump_func, /* todo_flags_finish */
1310 0 /* letter */
1313 #include "gt-tree-mudflap.h"