2015-01-05 Jakub Jelinek <jakub@redhat.com>
+ 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.
+
PR sanitizer/64344
* ubsan.h (ubsan_instrument_float_cast): Add ARG argument.
* ubsan.c (ubsan_instrument_float_cast): Add ARG argument, pass
seq = NULL;
gimple_seq_add_stmt (&seq, new_bind);
gimple_set_body (fndecl, seq);
+ bind = new_bind;
+ }
+
+ if (flag_sanitize & SANITIZE_THREAD)
+ {
+ gcall *call = gimple_build_call_internal (IFN_TSAN_FUNC_EXIT, 0);
+ gimple tf = gimple_build_try (seq, call, GIMPLE_TRY_FINALLY);
+ gbind *new_bind = gimple_build_bind (NULL, tf, gimple_bind_block (bind));
+ /* Clear the block for BIND, since it is no longer directly inside
+ the function, but within a try block. */
+ gimple_bind_set_block (bind, NULL);
+ /* Replace the current function body with the body
+ wrapped in the try/finally TF. */
+ seq = NULL;
+ gimple_seq_add_stmt (&seq, new_bind);
+ gimple_set_body (fndecl, seq);
}
DECL_SAVED_TREE (fndecl) = NULL_TREE;
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. */
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;
}
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
{
initialize_sanitizer_builtins ();
if (instrument_memory_accesses ())
- {
- instrument_func_entry ();
- instrument_func_exit ();
- }
+ instrument_func_entry ();
return 0;
}