* target.h (struct gcc_target): Add new field to struct cxx: import_export_class.
[official-gcc.git] / gcc / tree-mudflap.c
blobdbb994d679ad981476cf16b71bcdfd7006131b0e
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"
48 /* Internal function decls */
50 /* Helpers. */
51 static tree mf_build_string (const char *string);
52 static tree mf_varname_tree (tree);
53 static tree mf_file_function_line_tree (location_t);
55 /* Initialization of all the mf-runtime.h extern decls. */
56 static void mf_init_extern_trees (void);
58 /* Indirection-related instrumentation. */
59 static void mf_decl_cache_locals (void);
60 static void mf_decl_clear_locals (void);
61 static void mf_xform_derefs (void);
62 static void execute_mudflap_function_ops (void);
64 /* Addressable variables instrumentation. */
65 static void mf_xform_decls (tree, tree);
66 static tree mx_xfn_xform_decls (tree *, int *, void *);
67 static void mx_register_decls (tree, tree *);
68 static void execute_mudflap_function_decls (void);
71 /* ------------------------------------------------------------------------ */
72 /* Some generally helpful functions for mudflap instrumentation. */
74 /* Build a reference to a literal string. */
75 static tree
76 mf_build_string (const char *string)
78 size_t len = strlen (string);
79 tree result = mf_mark (build_string (len + 1, string));
81 TREE_TYPE (result)
82 = build_array_type (char_type_node,
83 build_index_type (build_int_2 (len, 0)));
84 TREE_CONSTANT (result) = 1;
85 TREE_INVARIANT (result) = 1;
86 TREE_READONLY (result) = 1;
87 TREE_STATIC (result) = 1;
89 result = build1 (ADDR_EXPR, build_pointer_type (char_type_node), result);
91 return mf_mark (result);
94 /* Create a properly typed STRING_CST node that describes the given
95 declaration. It will be used as an argument for __mf_register().
96 Try to construct a helpful string, including file/function/variable
97 name. */
99 static tree
100 mf_varname_tree (tree decl)
102 static pretty_printer buf_rec;
103 static int initialized = 0;
104 pretty_printer *buf = & buf_rec;
105 const char *buf_contents;
106 tree result;
108 if (decl == NULL_TREE)
109 abort ();
111 if (!initialized)
113 pp_construct (buf, /* prefix */ NULL, /* line-width */ 0);
114 initialized = 1;
116 pp_clear_output_area (buf);
118 /* Add FILENAME[:LINENUMBER]. */
120 expanded_location xloc = expand_location (DECL_SOURCE_LOCATION (decl));
121 const char *sourcefile;
122 unsigned sourceline = xloc.line;
124 sourcefile = xloc.file;
125 if (sourcefile == NULL && current_function_decl != NULL_TREE)
126 sourcefile = DECL_SOURCE_FILE (current_function_decl);
127 if (sourcefile == NULL)
128 sourcefile = "<unknown file>";
130 pp_string (buf, sourcefile);
132 if (sourceline != 0)
134 pp_string (buf, ":");
135 pp_decimal_int (buf, sourceline);
139 if (current_function_decl != NULL_TREE)
141 /* Add (FUNCTION): */
142 pp_string (buf, " (");
144 const char *funcname = NULL;
145 if (DECL_NAME (current_function_decl))
146 funcname = lang_hooks.decl_printable_name (current_function_decl, 1);
147 if (funcname == NULL)
148 funcname = "anonymous fn";
150 pp_string (buf, funcname);
152 pp_string (buf, ") ");
154 else
155 pp_string (buf, " ");
157 /* Add <variable-declaration>, possibly demangled. */
159 const char *declname = NULL;
161 if (strcmp ("GNU C++", lang_hooks.name) == 0 &&
162 DECL_NAME (decl) != NULL)
164 /* The gcc/cp decl_printable_name hook doesn't do as good a job as
165 the libiberty demangler. */
166 declname = cplus_demangle (IDENTIFIER_POINTER (DECL_NAME (decl)),
167 DMGL_AUTO | DMGL_VERBOSE);
170 if (declname == NULL)
171 declname = lang_hooks.decl_printable_name (decl, 3);
173 if (declname == NULL)
174 declname = "<unnamed variable>";
176 pp_string (buf, declname);
179 /* Return the lot as a new STRING_CST. */
180 buf_contents = pp_base_formatted_text (buf);
181 result = mf_build_string (buf_contents);
182 pp_clear_output_area (buf);
184 return result;
188 /* And another friend, for producing a simpler message. */
190 static tree
191 mf_file_function_line_tree (location_t location)
193 expanded_location xloc = expand_location (location);
194 const char *file = NULL, *colon, *line, *op, *name, *cp;
195 char linebuf[18];
196 char *string;
197 tree result;
199 /* Add FILENAME[:LINENUMBER]. */
200 if (xloc.file == NULL && current_function_decl != NULL_TREE)
201 xloc.file = DECL_SOURCE_FILE (current_function_decl);
202 if (xloc.file == NULL)
203 xloc.file = "<unknown file>";
205 if (xloc.line > 0)
207 sprintf (linebuf, "%d", xloc.line);
208 colon = ":";
209 line = linebuf;
211 else
212 colon = line = "";
214 /* Add (FUNCTION). */
215 name = lang_hooks.decl_printable_name (current_function_decl, 1);
216 if (name)
218 op = " (";
219 cp = ")";
221 else
222 op = name = cp = "";
224 string = concat (file, colon, line, op, name, cp, NULL);
225 result = mf_build_string (string);
226 free (string);
228 return result;
232 /* global tree nodes */
234 /* Global tree objects for global variables and functions exported by
235 mudflap runtime library. mf_init_extern_trees must be called
236 before using these. */
238 /* uintptr_t (usually "unsigned long") */
239 static GTY (()) tree mf_uintptr_type;
241 /* struct __mf_cache { uintptr_t low; uintptr_t high; }; */
242 static GTY (()) tree mf_cache_struct_type;
244 /* struct __mf_cache * const */
245 static GTY (()) tree mf_cache_structptr_type;
247 /* extern struct __mf_cache __mf_lookup_cache []; */
248 static GTY (()) tree mf_cache_array_decl;
250 /* extern const unsigned char __mf_lc_shift; */
251 static GTY (()) tree mf_cache_shift_decl;
253 /* extern const uintptr_t __mf_lc_mask; */
254 static GTY (()) tree mf_cache_mask_decl;
256 /* Their function-scope local shadows, used in single-threaded mode only. */
258 /* auto const unsigned char __mf_lc_shift_l; */
259 static GTY (()) tree mf_cache_shift_decl_l;
261 /* auto const uintptr_t __mf_lc_mask_l; */
262 static GTY (()) tree mf_cache_mask_decl_l;
264 /* extern void __mf_check (void *ptr, size_t sz, int type, const char *); */
265 static GTY (()) tree mf_check_fndecl;
267 /* extern void __mf_register (void *ptr, size_t sz, int type, const char *); */
268 static GTY (()) tree mf_register_fndecl;
270 /* extern void __mf_unregister (void *ptr, size_t sz); */
271 static GTY (()) tree mf_unregister_fndecl;
274 /* Initialize the global tree nodes that correspond to mf-runtime.h
275 declarations. */
276 static void
277 mf_init_extern_trees (void)
279 static bool done = false;
281 if (done)
282 return;
283 done = true;
285 mf_uintptr_type = TREE_TYPE (mflang_lookup_decl ("uintptr_t"));
286 mf_cache_array_decl = mf_mark (mflang_lookup_decl ("__mf_lookup_cache"));
287 mf_cache_struct_type = TREE_TYPE (TREE_TYPE (mf_cache_array_decl));
288 mf_cache_structptr_type = build_pointer_type (mf_cache_struct_type);
289 mf_cache_shift_decl = mf_mark (mflang_lookup_decl ("__mf_lc_shift"));
290 mf_cache_mask_decl = mf_mark (mflang_lookup_decl ("__mf_lc_mask"));
291 mf_check_fndecl = mflang_lookup_decl ("__mf_check");
292 mf_register_fndecl = mflang_lookup_decl ("__mf_register");
293 mf_unregister_fndecl = mflang_lookup_decl ("__mf_unregister");
297 /* ------------------------------------------------------------------------ */
298 /* Memory reference transforms. Perform the mudflap indirection-related
299 tree transforms on the current function.
301 This is the second part of the mudflap instrumentation. It works on
302 low-level GIMPLE using the CFG, because we want to run this pass after
303 tree optimizations have been performed, but we have to preserve the CFG
304 for expansion from trees to RTL. */
306 static void
307 execute_mudflap_function_ops (void)
309 if (mf_marked_p (current_function_decl))
310 return;
312 push_gimplify_context ();
314 /* In multithreaded mode, don't cache the lookup cache parameters. */
315 if (! flag_mudflap_threads)
316 mf_decl_cache_locals ();
318 mf_xform_derefs ();
320 if (! flag_mudflap_threads)
321 mf_decl_clear_locals ();
323 pop_gimplify_context (NULL);
326 /* Create and initialize local shadow variables for the lookup cache
327 globals. Put their decls in the *_l globals for use by
328 mf_build_check_statement_for. */
330 static void
331 mf_decl_cache_locals (void)
333 tree t, shift_init_stmts, mask_init_stmts;
334 tree_stmt_iterator tsi;
336 /* Build the cache vars. */
337 mf_cache_shift_decl_l
338 = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_shift_decl),
339 "__mf_lookup_shift_l"));
341 mf_cache_mask_decl_l
342 = mf_mark (create_tmp_var (TREE_TYPE (mf_cache_mask_decl),
343 "__mf_lookup_mask_l"));
345 /* Build initialization nodes for the cache vars. We just load the
346 globals into the cache variables. */
347 t = build (MODIFY_EXPR, TREE_TYPE (mf_cache_shift_decl_l),
348 mf_cache_shift_decl_l, mf_cache_shift_decl);
349 SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
350 gimplify_to_stmt_list (&t);
351 shift_init_stmts = t;
353 t = build (MODIFY_EXPR, TREE_TYPE (mf_cache_mask_decl_l),
354 mf_cache_mask_decl_l, mf_cache_mask_decl);
355 SET_EXPR_LOCATION (t, DECL_SOURCE_LOCATION (current_function_decl));
356 gimplify_to_stmt_list (&t);
357 mask_init_stmts = t;
359 /* Anticipating multiple entry points, we insert the cache vars
360 initializers in each successor of the ENTRY_BLOCK_PTR. */
361 for (tsi = tsi_start (shift_init_stmts);
362 ! tsi_end_p (tsi);
363 tsi_next (&tsi))
364 insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
366 for (tsi = tsi_start (mask_init_stmts);
367 ! tsi_end_p (tsi);
368 tsi_next (&tsi))
369 insert_edge_copies (tsi_stmt (tsi), ENTRY_BLOCK_PTR);
370 bsi_commit_edge_inserts (NULL);
374 static void
375 mf_decl_clear_locals (void)
377 /* Unset local shadows. */
378 mf_cache_shift_decl_l = NULL_TREE;
379 mf_cache_mask_decl_l = NULL_TREE;
382 static void
383 mf_build_check_statement_for (tree addr, tree size,
384 block_stmt_iterator *instr_bsi,
385 location_t *locus, tree dirflag)
387 tree_stmt_iterator head, tsi;
388 tree ptrtype = TREE_TYPE (addr);
389 block_stmt_iterator bsi;
390 basic_block cond_bb, then_bb, join_bb;
391 edge e;
392 tree cond, t, u, v, l1, l2;
393 tree mf_value;
394 tree mf_base;
395 tree mf_elem;
397 /* We first need to split the current basic block, and start altering
398 the CFG. This allows us to insert the statements we're about to
399 construct into the right basic blocks. The label l1 is the label
400 of the block for the THEN clause of the conditional jump we're
401 about to construct, and l2 is the ELSE clause, which is just the
402 continuation of the old statement stream. */
403 l1 = create_artificial_label ();
404 l2 = create_artificial_label ();
405 cond_bb = bb_for_stmt (bsi_stmt (*instr_bsi));
406 bsi = *instr_bsi;
407 bsi_prev (&bsi);
408 if (! bsi_end_p (bsi))
410 e = split_block (cond_bb, bsi_stmt (bsi));
411 cond_bb = e->src;
412 join_bb = e->dest;
414 else
416 join_bb = cond_bb;
417 cond_bb = create_empty_bb (join_bb->prev_bb);
418 e = make_edge (cond_bb, join_bb, 0);
420 e->flags = EDGE_FALSE_VALUE;
421 then_bb = create_empty_bb (cond_bb);
422 make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE);
423 make_edge (then_bb, join_bb, EDGE_FALLTHRU);
425 /* We expect that the conditional jump we will construct will not
426 be taken very often as it basically is an exception condition. */
427 predict_edge_def (then_bb->pred, PRED_MUDFLAP, NOT_TAKEN);
429 /* Update dominance info. Note that bb_join's data was
430 updated by split_block. */
431 if (dom_computed[CDI_DOMINATORS] >= DOM_CONS_OK)
433 set_immediate_dominator (CDI_DOMINATORS, then_bb, cond_bb);
434 set_immediate_dominator (CDI_DOMINATORS, join_bb, cond_bb);
437 /* Build our local variables. */
438 mf_value = create_tmp_var (ptrtype, "__mf_value");
439 mf_elem = create_tmp_var (mf_cache_structptr_type, "__mf_elem");
440 mf_base = create_tmp_var (mf_uintptr_type, "__mf_base");
442 /* Build: __mf_value = <address expression>. */
443 t = build (MODIFY_EXPR, void_type_node, mf_value, unshare_expr (addr));
444 SET_EXPR_LOCUS (t, locus);
445 gimplify_to_stmt_list (&t);
446 head = tsi_start (t);
447 tsi = tsi_last (t);
449 /* Build: __mf_base = (uintptr_t)__mf_value. */
450 t = build (MODIFY_EXPR, void_type_node, mf_base,
451 build1 (NOP_EXPR, mf_uintptr_type, mf_value));
452 SET_EXPR_LOCUS (t, locus);
453 gimplify_to_stmt_list (&t);
454 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
456 /* Build: __mf_elem = &__mf_lookup_cache [(__mf_base >> __mf_shift)
457 & __mf_mask]. */
458 t = build (RSHIFT_EXPR, mf_uintptr_type, mf_base,
459 (flag_mudflap_threads ? mf_cache_shift_decl : mf_cache_shift_decl_l));
460 t = build (BIT_AND_EXPR, mf_uintptr_type, t,
461 (flag_mudflap_threads ? mf_cache_mask_decl : mf_cache_mask_decl_l));
462 t = build (ARRAY_REF,
463 TREE_TYPE (TREE_TYPE (mf_cache_array_decl)),
464 mf_cache_array_decl, t, NULL_TREE, NULL_TREE);
465 t = build1 (ADDR_EXPR, mf_cache_structptr_type, t);
466 t = build (MODIFY_EXPR, void_type_node, mf_elem, t);
467 SET_EXPR_LOCUS (t, locus);
468 gimplify_to_stmt_list (&t);
469 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
471 /* Quick validity check.
473 if (__mf_elem->low > __mf_base
474 || (__mf_elem_high < __mf_base + sizeof(T) - 1))
476 __mf_check ();
477 ... and only if single-threaded:
478 __mf_lookup_shift_1 = f...;
479 __mf_lookup_mask_l = ...;
482 It is expected that this body of code is rarely executed so we mark
483 the edge to the THEN clause of the conditional jump as unlikely. */
485 /* Construct t <-- '__mf_elem->low > __mf_base'. */
486 t = build (COMPONENT_REF, mf_uintptr_type,
487 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
488 TYPE_FIELDS (mf_cache_struct_type), NULL_TREE);
489 t = build (GT_EXPR, boolean_type_node, t, mf_base);
491 /* Construct '__mf_elem->high < __mf_base + sizeof(T) - 1'.
493 First build:
494 1) u <-- '__mf_elem->high'
495 2) v <-- '__mf_base + sizeof (T) - 1'.
497 Then build 'u <-- (u < v). */
500 u = build (COMPONENT_REF, mf_uintptr_type,
501 build1 (INDIRECT_REF, mf_cache_struct_type, mf_elem),
502 TREE_CHAIN (TYPE_FIELDS (mf_cache_struct_type)), NULL_TREE);
504 v = convert (mf_uintptr_type,
505 size_binop (MINUS_EXPR, size, size_one_node));
506 v = fold (build (PLUS_EXPR, mf_uintptr_type, mf_base, v));
508 u = build (LT_EXPR, boolean_type_node, u, v);
510 /* Build the composed conditional: t <-- 't || u'. Then store the
511 result of the evaluation of 't' in a temporary variable which we
512 can use as the condition for the conditional jump. */
513 t = build (TRUTH_OR_EXPR, boolean_type_node, t, u);
514 cond = create_tmp_var (boolean_type_node, "__mf_unlikely_cond");
515 t = build (MODIFY_EXPR, boolean_type_node, cond, t);
516 gimplify_to_stmt_list (&t);
517 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
519 /* Build the conditional jump. 'cond' is just a temporary so we can
520 simply build a void COND_EXPR. We do need labels in both arms though. */
521 t = build (COND_EXPR, void_type_node, cond,
522 build (GOTO_EXPR, void_type_node, tree_block_label (then_bb)),
523 build (GOTO_EXPR, void_type_node, tree_block_label (join_bb)));
524 SET_EXPR_LOCUS (t, locus);
525 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
527 /* At this point, after so much hard work, we have only constructed
528 the conditional jump,
530 if (__mf_elem->low > __mf_base
531 || (__mf_elem_high < __mf_base + sizeof(T) - 1))
533 The lowered GIMPLE tree representing this code is in the statement
534 list starting at 'head'.
536 We can insert this now in the current basic block, ie. the one that
537 the statement we're instrumenting was originally in. */
538 bsi = bsi_last (cond_bb);
539 for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
540 bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
542 /* Now build up the body of the cache-miss handling:
544 __mf_check();
545 refresh *_l vars.
547 This is the body of the conditional. */
549 u = tree_cons (NULL_TREE,
550 mf_file_function_line_tree (locus == NULL ? UNKNOWN_LOCATION
551 : *locus),
552 NULL_TREE);
553 u = tree_cons (NULL_TREE, dirflag, u);
554 u = tree_cons (NULL_TREE, size, u);
555 u = tree_cons (NULL_TREE, mf_value, u);
556 t = build_function_call_expr (mf_check_fndecl, u);
557 gimplify_to_stmt_list (&t);
558 head = tsi_start (t);
559 tsi = tsi_last (t);
561 if (! flag_mudflap_threads)
563 t = build (MODIFY_EXPR, void_type_node,
564 mf_cache_shift_decl_l, mf_cache_shift_decl);
565 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
567 t = build (MODIFY_EXPR, void_type_node,
568 mf_cache_mask_decl_l, mf_cache_mask_decl);
569 tsi_link_after (&tsi, t, TSI_CONTINUE_LINKING);
572 /* Insert the check code in the THEN block. */
573 bsi = bsi_start (then_bb);
574 for (tsi = head; ! tsi_end_p (tsi); tsi_next (&tsi))
575 bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_CONTINUE_LINKING);
577 *instr_bsi = bsi_start (join_bb);
578 bsi_next (instr_bsi);
581 static void
582 mf_xform_derefs_1 (block_stmt_iterator *iter, tree *tp,
583 location_t *locus, tree dirflag)
585 tree type, ptr_type, addr, size, t;
587 /* Don't instrument read operations. */
588 if (dirflag == integer_zero_node && flag_mudflap_ignore_reads)
589 return;
591 t = *tp;
592 type = TREE_TYPE (t);
593 size = TYPE_SIZE_UNIT (type);
595 switch (TREE_CODE (t))
597 case ARRAY_REF:
599 /* Omit checking if we can statically determine that the access is
600 valid. For non-addressable local arrays this is not optional,
601 since we won't have called __mf_register for the object. */
602 tree op0, op1;
604 op0 = TREE_OPERAND (t, 0);
605 op1 = TREE_OPERAND (t, 1);
606 while (TREE_CODE (op1) == INTEGER_CST)
608 tree dom = TYPE_DOMAIN (TREE_TYPE (op0));
610 /* Test for index in range. Break if not. */
611 if (!dom
612 || (! TYPE_MIN_VALUE (dom)
613 || ! really_constant_p (TYPE_MIN_VALUE (dom)))
614 || (! TYPE_MAX_VALUE (dom)
615 || ! really_constant_p (TYPE_MAX_VALUE (dom)))
616 || (tree_int_cst_lt (op1, TYPE_MIN_VALUE (dom))
617 || tree_int_cst_lt (TYPE_MAX_VALUE (dom), op1)))
618 break;
620 /* If we're looking at a non-external VAR_DECL, then the
621 access must be ok. */
622 if (TREE_CODE (op0) == VAR_DECL && !DECL_EXTERNAL (op0))
623 return;
625 /* Only continue if we're still looking at an array. */
626 if (TREE_CODE (op0) != ARRAY_REF)
627 break;
629 op1 = TREE_OPERAND (op0, 1);
630 op0 = TREE_OPERAND (op0, 0);
633 /* If we got here, we couldn't statically the check. */
634 ptr_type = build_pointer_type (type);
635 addr = build1 (ADDR_EXPR, ptr_type, t);
637 break;
639 case INDIRECT_REF:
640 addr = TREE_OPERAND (t, 0);
641 ptr_type = TREE_TYPE (addr);
642 break;
644 case ARRAY_RANGE_REF:
645 warning ("mudflap checking not yet implemented for ARRAY_RANGE_REF");
646 return;
648 case COMPONENT_REF:
650 tree field;
652 /* If we're not dereferencing something, then the access
653 must be ok. */
654 if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
655 return;
657 field = TREE_OPERAND (t, 1);
659 /* If we're looking at a bit field, then we can't take its address
660 with ADDR_EXPR -- lang_hooks.mark_addressable will error. Do
661 things the hard way with PLUS. */
662 if (DECL_BIT_FIELD_TYPE (field))
664 if (TREE_CODE (DECL_SIZE_UNIT (field)) == INTEGER_CST)
665 size = DECL_SIZE_UNIT (field);
667 addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
668 addr = fold_convert (ptr_type_node, addr);
669 addr = fold (build (PLUS_EXPR, ptr_type_node,
670 addr, fold_convert (ptr_type_node,
671 byte_position (field))));
673 else
675 ptr_type = build_pointer_type (type);
676 addr = build1 (ADDR_EXPR, ptr_type, t);
679 break;
681 case BIT_FIELD_REF:
683 tree ofs, rem, bpu;
685 /* If we're not dereferencing something, then the access
686 must be ok. */
687 if (TREE_CODE (TREE_OPERAND (t, 0)) != INDIRECT_REF)
688 return;
690 bpu = bitsize_int (BITS_PER_UNIT);
691 ofs = convert (bitsizetype, TREE_OPERAND (t, 2));
692 rem = size_binop (TRUNC_MOD_EXPR, ofs, bpu);
693 ofs = size_binop (TRUNC_DIV_EXPR, ofs, bpu);
695 size = convert (bitsizetype, TREE_OPERAND (t, 1));
696 size = size_binop (PLUS_EXPR, size, rem);
697 size = size_binop (CEIL_DIV_EXPR, size, bpu);
698 size = convert (sizetype, size);
700 addr = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
701 addr = convert (ptr_type_node, addr);
702 addr = fold (build (PLUS_EXPR, ptr_type_node, addr, ofs));
704 break;
706 default:
707 return;
710 mf_build_check_statement_for (addr, size, iter, locus, dirflag);
713 static void
714 mf_xform_derefs (void)
716 basic_block bb, next;
717 block_stmt_iterator i;
718 int saved_last_basic_block = last_basic_block;
720 bb = ENTRY_BLOCK_PTR ->next_bb;
723 next = bb->next_bb;
724 for (i = bsi_start (bb); !bsi_end_p (i); bsi_next (&i))
726 tree s = bsi_stmt (i);
728 /* Only a few GIMPLE statements can reference memory. */
729 switch (TREE_CODE (s))
731 case MODIFY_EXPR:
732 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
733 integer_one_node);
734 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 1), EXPR_LOCUS (s),
735 integer_zero_node);
736 break;
738 case RETURN_EXPR:
739 if (TREE_OPERAND (s, 0) != NULL_TREE)
741 if (TREE_CODE (TREE_OPERAND (s, 0)) == MODIFY_EXPR)
742 mf_xform_derefs_1 (&i, &TREE_OPERAND (TREE_OPERAND (s, 0), 1),
743 EXPR_LOCUS (s), integer_zero_node);
744 else
745 mf_xform_derefs_1 (&i, &TREE_OPERAND (s, 0), EXPR_LOCUS (s),
746 integer_zero_node);
748 break;
750 default:
754 bb = next;
756 while (bb && bb->index <= saved_last_basic_block);
759 /* ------------------------------------------------------------------------ */
760 /* ADDR_EXPR transforms. Perform the declaration-related mudflap tree
761 transforms on the current function.
763 This is the first part of the mudflap instrumentation. It works on
764 high-level GIMPLE because after lowering, all variables are moved out
765 of their BIND_EXPR binding context, and we lose liveness information
766 for the declarations we wish to instrument. */
768 static void
769 execute_mudflap_function_decls (void)
771 if (mf_marked_p (current_function_decl))
772 return;
774 push_gimplify_context ();
776 mf_init_extern_trees ();
777 mf_xform_decls (DECL_SAVED_TREE (current_function_decl),
778 DECL_ARGUMENTS (current_function_decl));
780 pop_gimplify_context (NULL);
783 /* This struct is passed between mf_xform_decls to store state needed
784 during the traversal searching for objects that have their
785 addresses taken. */
786 struct mf_xform_decls_data
788 tree param_decls;
792 /* Synthesize a CALL_EXPR and a TRY_FINALLY_EXPR, for this chain of
793 _DECLs if appropriate. Arrange to call the __mf_register function
794 now, and the __mf_unregister function later for each. */
795 static void
796 mx_register_decls (tree decl, tree *stmt_list)
798 tree finally_stmts = NULL_TREE;
799 tree_stmt_iterator initially_stmts = tsi_start (*stmt_list);
801 while (decl != NULL_TREE)
803 /* Eligible decl? */
804 if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
805 /* It must be a non-external, automatic variable. */
806 && ! DECL_EXTERNAL (decl)
807 && ! TREE_STATIC (decl)
808 /* The decl must have its address taken. */
809 && TREE_ADDRESSABLE (decl)
810 /* The type of the variable must be complete. */
811 && COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (decl))
812 /* Don't process the same decl twice. */
813 && ! mf_marked_p (decl))
815 tree size = NULL_TREE, variable_name;
816 tree unregister_fncall, unregister_fncall_params;
817 tree register_fncall, register_fncall_params;
819 if (DECL_DEFER_OUTPUT (decl))
821 /* Oh no ... it's probably a variable-length array (VLA).
822 The size and address cannot be computed by merely
823 looking at the DECL. See gimplify_decl_stmt for the
824 method by which VLA declarations turn into calls to
825 BUILT_IN_STACK_ALLOC. We assume that multiple
826 VLAs declared later in the same block get allocation
827 code later than the others. */
828 tree stack_alloc_call = NULL_TREE;
830 while(! tsi_end_p (initially_stmts))
832 tree t = tsi_stmt (initially_stmts);
834 tree call = NULL_TREE;
835 if (TREE_CODE (t) == CALL_EXPR)
836 call = t;
837 else if (TREE_CODE (t) == MODIFY_EXPR &&
838 TREE_CODE (TREE_OPERAND (t, 1)) == CALL_EXPR)
839 call = TREE_OPERAND (t, 1);
840 else if (TREE_CODE (t) == TRY_FINALLY_EXPR)
842 /* We hope that this is the try/finally block sometimes
843 constructed by gimplify_bind_expr() for a BIND_EXPR
844 that contains VLAs. This very naive recursion
845 appears to be sufficient. */
846 initially_stmts = tsi_start (TREE_OPERAND (t, 0));
849 if (call != NULL_TREE)
851 if (TREE_CODE (TREE_OPERAND(call, 0)) == ADDR_EXPR &&
852 TREE_OPERAND (TREE_OPERAND (call, 0), 0) ==
853 implicit_built_in_decls [BUILT_IN_STACK_ALLOC])
855 tree stack_alloc_args = TREE_OPERAND (call, 1);
856 tree stack_alloc_op1 = TREE_VALUE (stack_alloc_args);
857 tree stack_alloc_op2 = TREE_VALUE (TREE_CHAIN (stack_alloc_args));
859 if (TREE_CODE (stack_alloc_op1) == ADDR_EXPR &&
860 TREE_OPERAND (stack_alloc_op1, 0) == decl)
862 /* Got it! */
863 size = stack_alloc_op2;
864 stack_alloc_call = call;
865 /* Advance iterator to point past this allocation call. */
866 tsi_next (&initially_stmts);
867 break;
872 tsi_next (&initially_stmts);
875 if (stack_alloc_call == NULL_TREE)
877 warning ("mudflap cannot handle variable-sized declaration `%s'",
878 IDENTIFIER_POINTER (DECL_NAME (decl)));
879 break;
882 else
884 size = convert (size_type_node, TYPE_SIZE_UNIT (TREE_TYPE (decl)));
887 /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK) */
888 unregister_fncall_params =
889 tree_cons (NULL_TREE,
890 convert (ptr_type_node,
891 mf_mark (build1 (ADDR_EXPR,
892 build_pointer_type (TREE_TYPE (decl)),
893 decl))),
894 tree_cons (NULL_TREE,
895 size,
896 tree_cons (NULL_TREE,
897 build_int_2 (3, 0), /* __MF_TYPE_STACK */
898 NULL_TREE)));
899 /* __mf_unregister (...) */
900 unregister_fncall = build_function_call_expr (mf_unregister_fndecl,
901 unregister_fncall_params);
903 /* (& VARIABLE, sizeof (VARIABLE), __MF_TYPE_STACK, "name") */
904 variable_name = mf_varname_tree (decl);
905 register_fncall_params =
906 tree_cons (NULL_TREE,
907 convert (ptr_type_node,
908 mf_mark (build1 (ADDR_EXPR,
909 build_pointer_type (TREE_TYPE (decl)),
910 decl))),
911 tree_cons (NULL_TREE,
912 size,
913 tree_cons (NULL_TREE,
914 build_int_2 (3, 0), /* __MF_TYPE_STACK */
915 tree_cons (NULL_TREE,
916 variable_name,
917 NULL_TREE))));
919 /* __mf_register (...) */
920 register_fncall = build_function_call_expr (mf_register_fndecl,
921 register_fncall_params);
923 /* Accumulate the two calls. */
924 /* ??? Set EXPR_LOCATION. */
925 gimplify_stmt (&register_fncall);
926 gimplify_stmt (&unregister_fncall);
928 /* Add the __mf_register call at the current appending point. */
929 if (tsi_end_p (initially_stmts))
930 internal_error ("mudflap ran off end of BIND_EXPR body");
931 tsi_link_before (&initially_stmts, register_fncall, TSI_SAME_STMT);
933 /* Accumulate the FINALLY piece. */
934 append_to_statement_list (unregister_fncall, &finally_stmts);
936 mf_mark (decl);
939 decl = TREE_CHAIN (decl);
942 /* Actually, (initially_stmts!=NULL) <=> (finally_stmts!=NULL) */
943 if (finally_stmts != NULL_TREE)
945 tree t = build (TRY_FINALLY_EXPR, void_type_node,
946 *stmt_list, finally_stmts);
947 *stmt_list = NULL;
948 append_to_statement_list (t, stmt_list);
953 /* Process every variable mentioned in BIND_EXPRs. */
954 static tree
955 mx_xfn_xform_decls (tree *t, int *continue_p, void *data)
957 struct mf_xform_decls_data* d = (struct mf_xform_decls_data*) data;
959 if (*t == NULL_TREE || *t == error_mark_node)
961 *continue_p = 0;
962 return NULL_TREE;
965 *continue_p = 1;
967 switch (TREE_CODE (*t))
969 case BIND_EXPR:
971 /* Process function parameters now (but only once). */
972 mx_register_decls (d->param_decls, &BIND_EXPR_BODY (*t));
973 d->param_decls = NULL_TREE;
975 mx_register_decls (BIND_EXPR_VARS (*t), &BIND_EXPR_BODY (*t));
977 break;
979 default:
980 break;
983 return NULL;
986 /* Perform the object lifetime tracking mudflap transform on the given function
987 tree. The tree is mutated in place, with possibly copied subtree nodes.
989 For every auto variable declared, if its address is ever taken
990 within the function, then supply its lifetime to the mudflap
991 runtime with the __mf_register and __mf_unregister calls.
994 static void
995 mf_xform_decls (tree fnbody, tree fnparams)
997 struct mf_xform_decls_data d;
998 d.param_decls = fnparams;
999 walk_tree_without_duplicates (&fnbody, mx_xfn_xform_decls, &d);
1003 /* ------------------------------------------------------------------------ */
1004 /* Externally visible mudflap functions. */
1007 /* Mark and return the given tree node to prevent further mudflap
1008 transforms. */
1009 static GTY ((param_is (union tree_node))) htab_t marked_trees = NULL;
1011 tree
1012 mf_mark (tree t)
1014 void **slot;
1016 if (marked_trees == NULL)
1017 marked_trees = htab_create_ggc (31, htab_hash_pointer, htab_eq_pointer, NULL);
1019 slot = htab_find_slot (marked_trees, t, INSERT);
1020 *slot = t;
1021 return t;
1025 mf_marked_p (tree t)
1027 void *entry;
1029 if (marked_trees == NULL)
1030 return 0;
1032 entry = htab_find (marked_trees, t);
1033 return (entry != NULL);
1036 /* Remember given node as a static of some kind: global data,
1037 function-scope static, or an anonymous constant. Its assembler
1038 label is given. */
1040 /* A list of globals whose incomplete declarations we encountered.
1041 Instead of emitting the __mf_register call for them here, it's
1042 delayed until program finish time. If they're still incomplete by
1043 then, warnings are emitted. */
1045 static GTY (()) varray_type deferred_static_decls;
1047 /* A list of statements for calling __mf_register() at startup time. */
1048 static GTY (()) tree enqueued_call_stmt_chain;
1050 static void
1051 mudflap_register_call (tree obj, tree object_size, tree varname)
1053 tree arg, args, call_stmt;
1055 args = tree_cons (NULL_TREE, varname, NULL_TREE);
1057 arg = build_int_2 (4, 0); /* __MF_TYPE_STATIC */
1058 args = tree_cons (NULL_TREE, arg, args);
1060 arg = convert (size_type_node, object_size);
1061 args = tree_cons (NULL_TREE, arg, args);
1063 arg = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (obj)), obj);
1064 arg = convert (ptr_type_node, arg);
1065 args = tree_cons (NULL_TREE, arg, args);
1067 mf_init_extern_trees ();
1068 call_stmt = build_function_call_expr (mf_register_fndecl, args);
1070 append_to_statement_list (call_stmt, &enqueued_call_stmt_chain);
1073 void
1074 mudflap_enqueue_decl (tree obj)
1076 if (mf_marked_p (obj))
1077 return;
1079 /* We don't need to process variable decls that are internally
1080 generated extern. If we did, we'd end up with warnings for them
1081 during mudflap_finish_file (). That would confuse the user,
1082 since the text would refer to variables that don't show up in the
1083 user's source code. */
1084 if (DECL_P (obj) && DECL_EXTERNAL (obj) && DECL_ARTIFICIAL (obj))
1085 return;
1087 if (COMPLETE_TYPE_P (TREE_TYPE (obj)))
1089 tree object_size;
1091 mf_mark (obj);
1093 object_size = size_in_bytes (TREE_TYPE (obj));
1095 if (dump_file)
1097 fprintf (dump_file, "enqueue_decl obj=`");
1098 print_generic_expr (dump_file, obj, dump_flags);
1099 fprintf (dump_file, "' size=");
1100 print_generic_expr (dump_file, object_size, dump_flags);
1101 fprintf (dump_file, "\n");
1104 /* NB: the above condition doesn't require TREE_USED or
1105 TREE_ADDRESSABLE. That's because this object may be a global
1106 only used from other compilation units. XXX: Maybe static
1107 objects could require those attributes being set. */
1109 mudflap_register_call (obj, object_size, mf_varname_tree (obj));
1111 else
1113 size_t i;
1115 if (! deferred_static_decls)
1116 VARRAY_TREE_INIT (deferred_static_decls, 10, "deferred static list");
1118 /* Ugh, linear search... */
1119 for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
1120 if (VARRAY_TREE (deferred_static_decls, i) == obj)
1122 warning ("mudflap cannot track lifetime of `%s'",
1123 IDENTIFIER_POINTER (DECL_NAME (obj)));
1124 return;
1127 VARRAY_PUSH_TREE (deferred_static_decls, obj);
1131 void
1132 mudflap_enqueue_constant (tree obj)
1134 tree object_size, varname;
1136 if (mf_marked_p (obj))
1137 return;
1139 if (TREE_CODE (obj) == STRING_CST)
1140 object_size = build_int_2 (TREE_STRING_LENGTH (obj), 0);
1141 else
1142 object_size = size_in_bytes (TREE_TYPE (obj));
1144 if (dump_file)
1146 fprintf (dump_file, "enqueue_constant obj=`");
1147 print_generic_expr (dump_file, obj, dump_flags);
1148 fprintf (dump_file, "' size=");
1149 print_generic_expr (dump_file, object_size, dump_flags);
1150 fprintf (dump_file, "\n");
1153 if (TREE_CODE (obj) == STRING_CST)
1154 varname = mf_build_string ("string literal");
1155 else
1156 varname = mf_build_string ("constant");
1158 mudflap_register_call (obj, object_size, varname);
1162 /* Emit any file-wide instrumentation. */
1163 void
1164 mudflap_finish_file (void)
1166 /* Try to give the deferred objects one final try. */
1167 if (deferred_static_decls)
1169 size_t i;
1171 for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_static_decls); i++)
1173 tree obj = VARRAY_TREE (deferred_static_decls, i);
1175 /* Call enqueue_decl again on the same object it has previously
1176 put into the table. (It won't modify the table this time, so
1177 infinite iteration is not a problem.) */
1178 mudflap_enqueue_decl (obj);
1181 VARRAY_CLEAR (deferred_static_decls);
1184 mflang_flush_calls (enqueued_call_stmt_chain);
1188 static bool
1189 gate_mudflap (void)
1191 return flag_mudflap != 0;
1194 struct tree_opt_pass pass_mudflap_1 =
1196 "mudflap1", /* name */
1197 gate_mudflap, /* gate */
1198 execute_mudflap_function_decls, /* execute */
1199 NULL, /* sub */
1200 NULL, /* next */
1201 0, /* static_pass_number */
1202 0, /* tv_id */
1203 PROP_gimple_any, /* properties_required */
1204 0, /* properties_provided */
1205 0, /* properties_destroyed */
1206 0, /* todo_flags_start */
1207 TODO_dump_func /* todo_flags_finish */
1210 struct tree_opt_pass pass_mudflap_2 =
1212 "mudflap2", /* name */
1213 gate_mudflap, /* gate */
1214 execute_mudflap_function_ops, /* execute */
1215 NULL, /* sub */
1216 NULL, /* next */
1217 0, /* static_pass_number */
1218 0, /* tv_id */
1219 PROP_gimple_leh, /* properties_required */
1220 0, /* properties_provided */
1221 0, /* properties_destroyed */
1222 0, /* todo_flags_start */
1223 TODO_verify_flow | TODO_verify_stmts
1224 | TODO_dump_func /* todo_flags_finish */
1227 #include "gt-tree-mudflap.h"