On Sat, Nov 03, 2012 at 10:05:35AM -0700, Wei Mi wrote:
> --- gcc/sanitizer.def (revision 0)
> +++ gcc/sanitizer.def (revision 0)
> @@ -0,0 +1,31 @@
> +DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_WRITE_16, "__tsan_write16",
> + BT_FN_VOID_PTR, ATTR_NOTHROW_LEAF_LIST)
> +
> +
> +
Please remove the trailing whitespace.
> +/* Builtin used by the implementation of libsanitizer. These
> + functions are mapped to the actual implementation of the
> + libasan and libtsan library. */
> +#undef DEF_SANITIZER_BUILTIN
> +#define DEF_SANITIZER_BUILTIN(ENUM, NAME, TYPE, ATTRS) \
> + DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE, \
> + true, true, true, ATTRS, true, flag_tsan)
That should be eventually flag_asan || flag_tsan, as sanitizer.def
should be also for asan builtins, or it must be DEF_TSAN_BUILTIN/tsan.def.
> +static tree
> +get_memory_access_decl (bool is_write, unsigned size)
> +{
> + enum built_in_function fcode;
> +
> + if (size <= 1)
> + fcode = is_write ? BUILT_IN_TSAN_WRITE_1 :
> + BUILT_IN_TSAN_READ_1;
Formatting, : should be below ?.
> +
> + return builtin_decl_implicit(fcode);
Space before (. Several times in the code.
Also, as is the tsan builtins will be defined only for
C/C++ family FEs, so either something needs to be done
for other FEs, or perhaps the pass should just error out
if say the BUILT_IN_TSAN_INIT isn't defined.
> +static tree
> +is_vptr_store (gimple stmt, tree expr, int is_write)
is_write should be bool,
> +{
> + if (is_write == 1
and this just is_write
> +static bool
> +is_load_of_const_p (tree expr, int is_write)
> +{
> + if (is_write)
> + return false;
Again.
> + /* The var does not live in memory -> no possibility of races. */
> + || (tcode == VAR_DECL
> + && !TREE_ADDRESSABLE (expr)
> + && TREE_STATIC (expr) == 0)
Please use && !is_global_var (expr) here instead.
> + /* TODO: handle other cases
> + (FIELD_DECL, MEM_REF, ARRAY_RANGE_REF, TARGET_MEM_REF, ADDR_EXPR). */
The comment is obsolete, MEM_REF is handled.
> + if (tcode != ARRAY_REF
> + && tcode != VAR_DECL
> + && tcode != COMPONENT_REF
> + && tcode != INDIRECT_REF
> + && tcode != MEM_REF)
> + return false;
> +
> + stmt = gsi_stmt (gsi);
> + loc = gimple_location (stmt);
> + rhs = is_vptr_store (stmt, expr, is_write);
> +#ifdef DEBUG
> + if (rhs == NULL)
> + gcc_assert (is_gimple_addressable (expr));
> +#endif
That should be
gcc_checking_assert (rhs != NULL || is_gimple_addressable (expr));
if you want to check it in checking versions only.
> + size = int_size_in_bytes(expr_type);
Missing space.
> + g = gimple_build_call(
> + get_memory_access_decl(is_write, size),
> + 1, expr_ptr);
And the formatting here is completely wrong.
> + }
> + else
> + g = gimple_build_call(
> + builtin_decl_implicit(BUILT_IN_TSAN_VPTR_UPDATE),
> + 1, expr_ptr);
> + gimple_set_location (g, loc);
> + /* Instrumentation for assignment of a function result
> + must be inserted after the call. Instrumentation for
> + reads of function arguments must be inserted before the call.
> + That's because the call can contain synchronization. */
> + if (is_gimple_call (stmt) && is_write)
> + {
> + int flags = gimple_call_flags (stmt);
> + /* If the call can throw, it must be the last stmt in
> + * a basicblock, so the instrumented stmts need to be
> + * inserted on a successor edge. */
Please avoid *'s at the beginning of comment continuation lines.
Use is_ctrl_altering_stmt (stmt) to check whether the call must
be the last stmt in a block or not.
And, don't expect there is a single_succ_edge, there could be
no edge at all (e.g. noreturn call), or there could be multiple
edges.
> + stmt = gsi_stmt (gsi);
> + if (is_gimple_call (stmt) &&
> + (gimple_call_fndecl(stmt) !=
Again, missing spaces, && and != belong on next lines.
> + if (gimple_assign_single_p (stmt))
Not gimple_assign_load_p instead?
> +static bool
> +instrument_memory_accesses (void)
> +{
> + basic_block bb;
> + gimple_stmt_iterator gsi;
> + bool fentry_exit_instrument = false;
> +
> + FOR_EACH_BB (bb)
> + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
> + fentry_exit_instrument = instrument_gimple (gsi) ||
> fentry_exit_instrument;
Line too long. Just do
fentry_exit_instrument |= instrument_gimple (gsi); ?
> + return fentry_exit_instrument;
> +}
> +
> +/* Instruments function entry. */
> +
> +static void
> +instrument_func_entry (void)
> +{
> + basic_block entry_bb;
> + edge entry_edge;
> + gimple_stmt_iterator gsi;
> + tree ret_addr;
> + gimple g;
> +
> + entry_bb = ENTRY_BLOCK_PTR;
> + entry_edge = single_succ_edge (entry_bb);
> + entry_bb = split_edge (entry_edge);
> + gsi = gsi_start_bb (entry_bb);
Why? Just add the stmts to gsi_after_labels of
single_succ (ENTRY_BLOCK_PTR) ?
> +
> + g = gimple_build_call(
> + builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS),
> + 1, integer_zero_node);
Wrong formatting.
> + ret_addr = create_tmp_var (ptr_type_node, "ret_addr");
You don't need to create a decl for that, just
ret_addr = make_ssa_name (ptr_type_node, NULL);
> +static unsigned
> +tsan_pass (void)
> +{
> + struct gimplify_ctx gctx;
> +
> + push_gimplify_context (&gctx);
Why?
> + GIMPLE_PASS,
> + "tsan0", /* name */
> + tsan_gate_O0, /* gate */
> + tsan_pass, /* execute */
> + NULL, /* sub */
The above is clearly badly formatted, /* execute */ comment
is not aligned with others. Please just use tabs instead
of spaces.
> + TODO_verify_all | TODO_update_ssa
Ideally you shouldn't need TODO_update_ssa.
> + | TODO_update_address_taken /* todo_flags_finish */
And why this?
> + Copyright (C) 2011 Free Software Foundation, Inc.
We have 2012 now, so 2011, 2012.
Jakub