aboutsummaryrefslogtreecommitdiff
path: root/gcc/tsan.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2015-01-05 22:47:51 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2015-01-05 22:47:51 +0100
commitfca4adf2095dfcd453ab32250984d85ff66bbd32 (patch)
tree71684c10bc82a08750e567f3a2526c6817160a6b /gcc/tsan.c
parente534110031564716a1e495a38bf8d893b23a5993 (diff)
downloadgcc-fca4adf2095dfcd453ab32250984d85ff66bbd32.zip
gcc-fca4adf2095dfcd453ab32250984d85ff66bbd32.tar.gz
gcc-fca4adf2095dfcd453ab32250984d85ff66bbd32.tar.bz2
re PR sanitizer/64265 (r217669 broke tsan)
PR sanitizer/64265 * gimplify.c (gimplify_function_tree): Add TSAN_FUNC_EXIT internal call as cleanup of the whole body. * internal-fn.def (TSAN_FUNC_EXIT): New internal call. * tsan.c (replace_func_exit): New function. (instrument_func_exit): Moved earlier. (instrument_memory_accesses): Adjust TSAN_FUNC_EXIT internal calls. Call instrument_func_exit if no TSAN_FUNC_EXIT internal calls have been found. (tsan_pass): Don't call instrument_func_exit. * internal-fn.c (expand_TSAN_FUNC_EXIT): New function. * tree-inline.c (copy_bb): Drop TSAN_FUNC_EXIT internal calls during inlining. From-SVN: r219202
Diffstat (limited to 'gcc/tsan.c')
-rw-r--r--gcc/tsan.c105
1 files changed, 71 insertions, 34 deletions
diff --git a/gcc/tsan.c b/gcc/tsan.c
index 1bc146f..567a421 100644
--- a/gcc/tsan.c
+++ b/gcc/tsan.c
@@ -704,6 +704,47 @@ instrument_gimple (gimple_stmt_iterator *gsi)
return instrumented;
}
+/* Replace TSAN_FUNC_EXIT internal call with function exit tsan builtin. */
+
+static void
+replace_func_exit (gimple stmt)
+{
+ tree builtin_decl = builtin_decl_implicit (BUILT_IN_TSAN_FUNC_EXIT);
+ gimple g = gimple_build_call (builtin_decl, 0);
+ gimple_set_location (g, cfun->function_end_locus);
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+ gsi_replace (&gsi, g, true);
+}
+
+/* Instrument function exit. Used when TSAN_FUNC_EXIT does not exist. */
+
+static void
+instrument_func_exit (void)
+{
+ location_t loc;
+ basic_block exit_bb;
+ gimple_stmt_iterator gsi;
+ gimple stmt, g;
+ tree builtin_decl;
+ edge e;
+ edge_iterator ei;
+
+ /* Find all function exits. */
+ exit_bb = EXIT_BLOCK_PTR_FOR_FN (cfun);
+ FOR_EACH_EDGE (e, ei, exit_bb->preds)
+ {
+ gsi = gsi_last_bb (e->src);
+ stmt = gsi_stmt (gsi);
+ gcc_assert (gimple_code (stmt) == GIMPLE_RETURN
+ || gimple_call_builtin_p (stmt, BUILT_IN_RETURN));
+ loc = gimple_location (stmt);
+ builtin_decl = builtin_decl_implicit (BUILT_IN_TSAN_FUNC_EXIT);
+ g = gimple_build_call (builtin_decl, 0);
+ gimple_set_location (g, loc);
+ gsi_insert_before (&gsi, g, GSI_SAME_STMT);
+ }
+}
+
/* Instruments all interesting memory accesses in the current function.
Return true if func entry/exit should be instrumented. */
@@ -713,10 +754,38 @@ instrument_memory_accesses (void)
basic_block bb;
gimple_stmt_iterator gsi;
bool fentry_exit_instrument = false;
+ bool func_exit_seen = false;
+ auto_vec<gimple> tsan_func_exits;
FOR_EACH_BB_FN (bb, cfun)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- fentry_exit_instrument |= instrument_gimple (&gsi);
+ {
+ gimple stmt = gsi_stmt (gsi);
+ if (is_gimple_call (stmt)
+ && gimple_call_internal_p (stmt)
+ && gimple_call_internal_fn (stmt) == IFN_TSAN_FUNC_EXIT)
+ {
+ if (fentry_exit_instrument)
+ replace_func_exit (stmt);
+ else
+ tsan_func_exits.safe_push (stmt);
+ func_exit_seen = true;
+ }
+ else
+ fentry_exit_instrument |= instrument_gimple (&gsi);
+ }
+ unsigned int i;
+ gimple stmt;
+ FOR_EACH_VEC_ELT (tsan_func_exits, i, stmt)
+ if (fentry_exit_instrument)
+ replace_func_exit (stmt);
+ else
+ {
+ gsi = gsi_for_stmt (stmt);
+ gsi_remove (&gsi, true);
+ }
+ if (fentry_exit_instrument && !func_exit_seen)
+ instrument_func_exit ();
return fentry_exit_instrument;
}
@@ -745,35 +814,6 @@ instrument_func_entry (void)
gsi_insert_seq_on_edge_immediate (e, seq);
}
-/* Instruments function exits. */
-
-static void
-instrument_func_exit (void)
-{
- location_t loc;
- basic_block exit_bb;
- gimple_stmt_iterator gsi;
- gimple stmt, g;
- tree builtin_decl;
- edge e;
- edge_iterator ei;
-
- /* Find all function exits. */
- exit_bb = EXIT_BLOCK_PTR_FOR_FN (cfun);
- FOR_EACH_EDGE (e, ei, exit_bb->preds)
- {
- gsi = gsi_last_bb (e->src);
- stmt = gsi_stmt (gsi);
- gcc_assert (gimple_code (stmt) == GIMPLE_RETURN
- || gimple_call_builtin_p (stmt, BUILT_IN_RETURN));
- loc = gimple_location (stmt);
- builtin_decl = builtin_decl_implicit (BUILT_IN_TSAN_FUNC_EXIT);
- g = gimple_build_call (builtin_decl, 0);
- gimple_set_location (g, loc);
- gsi_insert_before (&gsi, g, GSI_SAME_STMT);
- }
-}
-
/* ThreadSanitizer instrumentation pass. */
static unsigned
@@ -781,10 +821,7 @@ tsan_pass (void)
{
initialize_sanitizer_builtins ();
if (instrument_memory_accesses ())
- {
- instrument_func_entry ();
- instrument_func_exit ();
- }
+ instrument_func_entry ();
return 0;
}