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