Merge aosp-toolchain/gcc/gcc-4_9 changes.
[official-gcc.git] / gcc-4_6 / gcc / tree-tsan.c
blob44cf5385569befc467f07060a511a8442f55d4ab
1 /* ThreadSanitizer, a data race detector.
2 Copyright (C) 2011 Free Software Foundation, Inc.
3 Contributed by Dmitry Vyukov <dvyukov@google.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tree.h"
25 #include "intl.h"
26 #include "tm.h"
27 #include "basic-block.h"
28 #include "gimple.h"
29 #include "function.h"
30 #include "tree-flow.h"
31 #include "tree-pass.h"
32 #include "tree-tsan.h"
33 #include "tree-iterator.h"
34 #include "cfghooks.h"
35 #include "langhooks.h"
36 #include "output.h"
37 #include "options.h"
38 #include "target.h"
39 #include "cgraph.h"
40 #include "diagnostic.h"
42 /* ThreadSanitizer is a data race detector for C/C++ programs.
43 http://code.google.com/p/data-race-test/wiki/ThreadSanitizer
45 The tool consists of two parts:
46 instrumentation module (this file) and a run-time library.
47 The instrumentation module maintains shadow call stacks
48 and intercepts interesting memory accesses.
49 The instrumentation is enabled with -ftsan flag.
51 Instrumentation for shadow stack maintenance is as follows:
52 void somefunc ()
54 __tsan_shadow_stack [-1] = __builtin_return_address (0);
55 __tsan_shadow_stack++;
56 // function body
57 __tsan_shadow_stack--;
60 Interception for memory access interception is as follows:
61 *addr = 1;
62 __tsan_handle_mop (addr, flags);
63 where flags are (is_sblock | (is_store << 1) | ((sizeof (*addr) - 1) << 2).
64 is_sblock is used merely for optimization purposes and can always
65 be set to 1, see comments in instrument_mops function.
67 Ignore files can be used to selectively non instrument some functions.
68 Ignore file is specified with -ftsan-ignore=filename flag.
69 There are 3 types of ignores: (1) do not instrument memory accesses
70 in the function, (2) do not create sblocks in the function
71 and (3) recursively ignore memory accesses in the function.
72 That last ignore type requires additional instrumentation of the form:
73 void somefunc ()
75 __tsan_thread_ignore++;
76 // function body
77 __tsan_thread_ignore--;
80 The run-time library provides __tsan_handle_mop function,
81 definitions of __tsan_shadow_stack and __tsan_thread_ignore variables,
82 and intercepts synchronization related functions. */
84 #define TSAN_IGNORE "__tsan_thread_ignore"
85 #define TSAN_STACK "__tsan_shadow_stack"
86 #define TSAN_MOP "__tsan_handle_mop"
87 #define TSAN_INIT "__tsan_init"
88 #define TSAN_PERFIX "__tsan_"
89 #define MAX_MOP_BYTES 16
90 #define SBLOCK_SIZE 5
92 enum tsan_ignore_type
94 tsan_ignore_none = 1 << 0, /* Do not ignore. */
95 tsan_ignore_func = 1 << 1, /* Completely ignore the whole func. */
96 tsan_ignore_mop = 1 << 2, /* Do not instrument accesses. */
97 tsan_ignore_rec = 1 << 3, /* Do not instrument accesses recursively. */
98 tsan_ignore_hist = 1 << 4 /* Do not create superblocks. */
101 /* Info associated with each basic block.
102 Used to determine super-blocks (see instrument_mops ()). */
104 struct bb_data
106 int is_visited;
107 int has_sb;
108 const char *sb_file;
109 int sb_line_min;
110 int sb_line_max;
113 /* Memory access descriptor. */
115 struct mop_desc
117 int is_call;
118 int is_store;
119 gimple_stmt_iterator gsi;
120 tree expr;
123 /* Descriptor of an ignore file entry. */
125 struct tsan_ignore_desc
127 struct tsan_ignore_desc *next;
128 enum tsan_ignore_type type;
129 char *name;
132 /* Number of instrumented memory accesses in the current function. */
134 static int func_mops;
136 /* Number of function calls in the current function. */
138 static int func_calls;
140 /* Ignore status for the current function (see tsan_ignore_type). */
142 static enum tsan_ignore_type func_ignore;
144 static int ignore_init = 0;
145 static struct tsan_ignore_desc *ignore_head;
147 typedef struct mop_desc mop_desc;
148 DEF_VEC_O (mop_desc);
149 DEF_VEC_ALLOC_O (mop_desc, heap);
150 static VEC (mop_desc, heap) *mop_list;
152 /* Returns a definition of a runtime variable with type TYPE and name NAME. */
154 static tree
155 build_var_decl (tree type, const char *name)
157 tree id;
158 tree decl;
159 varpool_node_ptr var;
161 /* Check if a user has defined it for testing. */
162 id = get_identifier (name);
163 var = varpool_node_for_asm (id);
164 if (var != NULL)
166 decl = var->decl;
167 gcc_assert (TREE_CODE (decl) == VAR_DECL);
168 return decl;
171 decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, id, type);
172 TREE_STATIC (decl) = 1;
173 TREE_PUBLIC (decl) = 1;
174 DECL_EXTERNAL (decl) = 1;
175 if (targetm.have_tls)
176 DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
177 TREE_USED (decl) = 1;
178 TREE_THIS_VOLATILE (decl) = 1;
179 SET_DECL_ASSEMBLER_NAME (decl, id);
180 return decl;
183 /* Builds the following decl
184 extern __thread void **__tsan_shadow_stack; */
186 static tree
187 get_shadow_stack_decl (void)
189 static tree decl;
191 if (decl == NULL)
192 decl = build_var_decl (build_pointer_type (ptr_type_node), TSAN_STACK);
193 return decl;
196 /* Builds the following decl
197 extern __thread int __tsan_thread_ignore; */
199 static tree
200 get_thread_ignore_decl (void)
202 static tree decl;
204 if (decl == NULL)
205 decl = build_var_decl (integer_type_node, TSAN_IGNORE);
206 return decl;
209 /* Returns a definition of a runtime function with type TYPE and name NAME. */
211 static tree
212 build_func_decl (tree type, const char *name)
214 tree id;
215 cgraph_node_ptr func;
216 tree decl;
218 /* Check if a user has defined it for testing. */
219 id = get_identifier (name);
220 func = cgraph_node_for_asm (id);
221 if (func != NULL)
223 decl = func->decl;
224 gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
225 return decl;
228 decl = build_fn_decl (name, type);
229 TREE_NOTHROW (decl) = 1;
230 DECL_ATTRIBUTES (decl) = tree_cons (get_identifier ("leaf"),
231 NULL, DECL_ATTRIBUTES (decl));
232 DECL_ASSEMBLER_NAME (decl);
233 return decl;
236 /* Builds the following decl
237 void __tsan_handle_mop (void *addr, unsigned flags); */
239 static tree
240 get_handle_mop_decl (void)
242 tree typ;
243 static tree decl;
245 if (decl != NULL)
246 return decl;
248 typ = build_function_type_list (void_type_node, ptr_type_node,
249 integer_type_node , NULL_TREE);
250 decl = build_func_decl (typ, TSAN_MOP);
251 return decl;
254 /* Builds the following decl
255 void __tsan_init (void); */
257 static tree
258 get_init_decl (void)
260 tree typ;
261 static tree decl;
263 if (decl != NULL)
264 return decl;
266 typ = build_function_type_list (void_type_node, NULL_TREE);
267 decl = build_func_decl (typ, TSAN_INIT);
268 return decl;
271 /* Adds new ignore definition to the global list.
272 TYPE is the ignore type (see tsan_ignore_type).
273 NAME is the ignore pattern (e.g. "std*string*insert"). */
275 static void
276 ignore_append (enum tsan_ignore_type type, char *name)
278 struct tsan_ignore_desc *desc;
280 desc = XCNEW (struct tsan_ignore_desc);
281 desc->type = type;
282 desc->name = xstrdup (name);
283 desc->next = ignore_head;
284 ignore_head = desc;
287 /* Checks as to whether identifier STR matches template TEMPL.
288 Templates can only contain '*', e.g. 'std*string*insert'.
289 Templates implicitly start and end with '*'
290 since they are matched against mangled names.
291 Returns non-zero if STR is matched against TEMPL. */
293 static bool
294 ignore_match (char *templ, const char *str)
296 char *tpos;
297 const char *spos;
299 while (templ && templ [0])
301 if (templ [0] == '*')
303 templ++;
304 continue;
306 if (str [0] == 0)
307 return false;
308 tpos = strchr (templ, '*');
309 if (tpos != NULL)
310 tpos [0] = 0;
311 spos = strstr (str, templ);
312 str = spos + strlen (templ);
313 templ = tpos;
314 if (tpos != NULL)
315 tpos [0] = '*';
316 if (spos == NULL)
317 return false;
319 return true;
322 /* Loads ignore definitions from the file specified by -ftsan-ignore=filename.
323 The result is stored in the global ignore_head list.
324 Ignore files have the following format:
326 # This is a comment - ignored
328 # The below line says to not instrument memory accesses
329 # in all functions that match 'std*string*insert'
330 fun:std*string*insert
332 # The below line says to not instrument memory accesses
333 # in the function called 'foobar' *and* in all functions
334 # that it calls recursively
335 fun_r:foobar
337 # The below line says to not create superblocks
338 # in the function called 'barbaz'
339 fun_hist:barbaz
341 # Ignore all functions in the source file
342 src:atomic.c
344 # Everything else is uninteresting for us (e.g. obj:)
347 static void
348 ignore_load (void)
350 FILE *f;
351 char *line;
352 size_t linesz;
353 ssize_t sz;
354 char buf [PATH_MAX];
356 if (flag_tsan_ignore == NULL || flag_tsan_ignore [0] == 0)
357 return;
359 f = fopen (flag_tsan_ignore, "r");
360 if (f == NULL)
362 /* Try to open it relative to main_input_filename. */
363 strncpy (buf, main_input_filename, sizeof (buf));
364 buf [sizeof (buf) - 1] = 0;
365 line = strrchr (buf, '/');
366 if (line != NULL)
368 line++;
369 strncpy (line, flag_tsan_ignore, sizeof (buf) - (line - buf));
370 buf [sizeof (buf) - 1] = 0;
371 f = fopen (buf, "r");
374 if (f == NULL)
376 fatal_error ("failed to open ignore file '%s'\n", flag_tsan_ignore);
377 return;
380 line = 0;
381 linesz = 0;
382 while ((sz = getline (&line, &linesz, f)) != -1)
384 if (sz == 0)
385 continue;
386 /* Strip line terminator. */
387 if (line [sz - 1] == '\r' || line [sz - 1] == '\n')
388 line [sz - 1] = 0;
389 if (strncmp (line, "src:", sizeof ("src:") - 1) == 0)
390 ignore_append (tsan_ignore_func, line + sizeof ("src:") - 1);
391 else if (strncmp (line, "fun:", sizeof ("fun:") - 1) == 0)
392 ignore_append (tsan_ignore_mop, line + sizeof ("fun:") - 1);
393 else if (strncmp (line, "fun_r:", sizeof ("fun_r:") - 1) == 0)
394 ignore_append (tsan_ignore_rec, line + sizeof ("fun_r:") - 1);
395 else if (strncmp (line, "fun_hist:", sizeof ("fun_hist:") - 1) == 0)
396 ignore_append (tsan_ignore_hist, line + sizeof ("fun_hist:") - 1);
397 /* Other lines are not interesting. */
400 free (line);
401 fclose (f);
404 /* Returns ignore status for the current function. */
406 static enum tsan_ignore_type
407 tsan_ignore (void)
409 const char *func_name;
410 const char *src_name;
411 struct tsan_ignore_desc *desc;
413 if (ignore_init == 0)
415 ignore_load ();
416 ignore_init = 1;
419 /* Must be some artificial thunk function. */
420 if (DECL_ARTIFICIAL (cfun->decl) && DECL_IGNORED_P (cfun->decl))
421 return tsan_ignore_func;
423 src_name = expand_location (cfun->function_start_locus).file;
424 if (src_name == NULL)
425 src_name = "";
427 func_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (cfun->decl));
428 /* Ignore all functions starting with __tsan_ - intended for testing. */
429 if (strncmp (func_name, TSAN_PERFIX, sizeof (TSAN_PERFIX) - 1) == 0)
430 return tsan_ignore_func;
432 /* Ignore global ctors. */
433 if (strncmp (func_name, "_GLOBAL", sizeof ("_GLOBAL") - 1) == 0)
434 return tsan_ignore_func;
436 for (desc = ignore_head; desc; desc = desc->next)
438 if (desc->type == tsan_ignore_func)
440 if (ignore_match (desc->name, src_name))
441 return desc->type;
443 else if (ignore_match (desc->name, func_name))
444 return desc->type;
446 return tsan_ignore_none;
449 /* Builds either (__tsan_shadow_stack += 1) or (__tsan_shadow_stack -= 1)
450 expression depending on DO_DEC parameter. Appends the result to SEQ. */
452 static void
453 build_stack_op (gimple_seq *seq, bool do_dec)
455 tree op_size;
456 double_int op_size_cst;
457 unsigned long long size_val;
458 unsigned long long size_valhi;
459 tree op_expr;
460 gimple assign;
461 tree sstack_decl;
462 gimple_seq s;
464 op_size = TYPE_SIZE (ptr_type_node);
465 op_size_cst = tree_to_double_int (op_size);
466 size_val = op_size_cst.low / BITS_PER_UNIT;
467 size_valhi = 0;
468 if (do_dec)
470 size_val = -size_val;
471 size_valhi = -1;
473 op_size = build_int_cst_wide (sizetype, size_val, size_valhi);
474 sstack_decl = get_shadow_stack_decl ();
475 op_expr = build2 (POINTER_PLUS_EXPR, ptr_type_node, sstack_decl, op_size);
477 s = NULL;
478 op_expr = force_gimple_operand (op_expr, &s, true, NULL_TREE);
479 gimple_seq_add_seq (seq, s);
481 assign = gimple_build_assign (sstack_decl, op_expr);
482 gimple_seq_add_stmt (seq, assign);
485 /* Builds either (__tsan_thread_ignore += 1) or (__tsan_thread_ignore -= 1)
486 expression depending on OP parameter. Stores the result in SEQ. */
488 static void
489 build_rec_ignore_op (gimple_seq *seq, enum tree_code op)
491 tree rec_expr;
492 gimple_seq rec_inc;
493 gimple rec_assign;
494 tree ignore_decl;
496 ignore_decl = get_thread_ignore_decl ();
497 rec_expr = build2 (op, integer_type_node, ignore_decl, integer_one_node);
498 rec_inc = NULL;
499 rec_expr = force_gimple_operand (rec_expr, &rec_inc, true, NULL_TREE);
500 gimple_seq_add_seq (seq, rec_inc);
501 rec_assign = gimple_build_assign (ignore_decl, rec_expr);
502 gimple_seq_add_stmt (seq, rec_assign);
505 /* Build the following gimple sequence:
506 __tsan_shadow_stack [-1] = __builtin_return_address (0);
507 Stores the result in SEQ. */
509 static void
510 build_stack_assign (gimple_seq *seq)
512 tree pc_addr;
513 tree op_size;
514 tree op_expr;
515 tree stack_op;
516 tree retaddr_decl;
517 tree assign;
519 retaddr_decl = implicit_built_in_decls [BUILT_IN_RETURN_ADDRESS];
520 pc_addr = build_call_expr (retaddr_decl, 1, integer_zero_node);
521 op_size = build_int_cst_wide (sizetype, -(POINTER_SIZE / BITS_PER_UNIT), -1);
522 op_expr = build2 (POINTER_PLUS_EXPR, ptr_type_node,
523 get_shadow_stack_decl (), op_size);
524 stack_op = build1 (INDIRECT_REF, ptr_type_node, op_expr);
525 assign = build2 (MODIFY_EXPR, ptr_type_node, stack_op, pc_addr);
526 force_gimple_operand (assign, seq, true, NULL_TREE);
529 /* Builds the following gimple sequence:
530 __tsan_handle_mop (&EXPR,
531 (IS_SBLOCK | (IS_STORE << 1) | ((sizeof (EXPR) - 1) << 2);
532 The result is stored in GSEQ. */
534 static void
535 instr_mop (tree expr, int is_store, int is_sblock, gimple_seq *gseq)
537 tree addr_expr;
538 tree expr_type;
539 unsigned size;
540 unsigned flags;
541 tree flags_expr;
542 tree call_expr;
544 gcc_assert (gseq != 0 && *gseq == 0);
545 gcc_assert (is_gimple_addressable (expr));
547 addr_expr = build_addr (unshare_expr (expr), current_function_decl);
548 expr_type = TREE_TYPE (expr);
549 while (TREE_CODE (expr_type) == ARRAY_TYPE)
550 expr_type = TREE_TYPE (expr_type);
551 size = TREE_INT_CST_LOW (TYPE_SIZE (expr_type));
552 size = size / BITS_PER_UNIT;
553 if (size > MAX_MOP_BYTES)
554 size = MAX_MOP_BYTES;
555 size -= 1;
556 flags = ((!!is_sblock << 0) + (!!is_store << 1) + (size << 2));
557 flags_expr = build_int_cst (unsigned_type_node, flags);
558 call_expr = build_call_expr (get_handle_mop_decl (),
559 2, addr_expr, flags_expr);
560 force_gimple_operand (call_expr, gseq, true, 0);
563 /* Builds the following gimple sequence:
564 int is_store = (EXPR != RHS); // The temp is not actually introduced.
565 __tsan_handle_mop (&EXPR,
566 (IS_SBLOCK | (IS_STORE << 1) | ((sizeof (EXPR) - 1) << 2);
567 The result is stored in GSEQ. */
569 static void
570 instr_vptr_store (tree expr, tree rhs, int is_sblock, gimple_seq *gseq)
572 tree expr_ptr;
573 tree addr_expr;
574 tree expr_type;
575 unsigned size;
576 unsigned flags;
577 tree flags_expr;
578 gimple_seq flags_seq;
579 gimple collect;
580 tree is_store_expr;
582 expr_ptr = build_addr (unshare_expr (expr), current_function_decl);
583 addr_expr = force_gimple_operand (expr_ptr, gseq, true, NULL_TREE);
584 expr_type = TREE_TYPE (expr);
585 while (TREE_CODE (expr_type) == ARRAY_TYPE)
586 expr_type = TREE_TYPE (expr_type);
587 size = TREE_INT_CST_LOW (TYPE_SIZE (expr_type));
588 size = size / BITS_PER_UNIT;
589 if (size > MAX_MOP_BYTES)
590 size = MAX_MOP_BYTES;
591 size -= 1;
592 flags = ((!!is_sblock << 0) + (size << 2));
593 flags_expr = build_int_cst (unsigned_type_node, flags);
594 is_store_expr = build2 (NE_EXPR, unsigned_type_node,
595 build1 (VIEW_CONVERT_EXPR, size_type_node, expr),
596 build1 (VIEW_CONVERT_EXPR, size_type_node, rhs));
597 is_store_expr = build2 (LSHIFT_EXPR, unsigned_type_node,
598 is_store_expr, integer_one_node);
599 flags_expr = build2 (BIT_IOR_EXPR, unsigned_type_node,
600 is_store_expr, flags_expr);
601 flags_seq = 0;
602 flags_expr = force_gimple_operand (flags_expr, &flags_seq, true, NULL_TREE);
603 gimple_seq_add_seq (gseq, flags_seq);
604 collect = gimple_build_call (
605 get_handle_mop_decl (), 2, addr_expr, flags_expr);
606 gimple_seq_add_stmt (gseq, collect);
609 /* Returns true if function entry and exit need to be instrumented. */
611 static bool
612 is_func_instrumentation_required (void)
614 if (func_calls == 0 && func_mops == 0)
615 return false;
616 if (func_ignore != tsan_ignore_rec)
617 return true;
618 if (func_ignore == tsan_ignore_rec && func_calls != 0)
619 return true;
620 return false;
623 /* Returns gimple seq that needs to be inserted at function entry. */
625 static gimple_seq
626 build_func_entry_instr (void)
628 gimple_seq gs;
630 gs = NULL;
631 gcc_assert (is_func_instrumentation_required ());
632 if (func_ignore != tsan_ignore_rec)
634 build_stack_assign (&gs);
635 build_stack_op (&gs, false);
637 else
638 build_rec_ignore_op (&gs, PLUS_EXPR);
639 return gs;
642 /* Returns gimple seq that needs to be inserted before function exit. */
644 static gimple_seq
645 build_func_exit_instr (void)
647 gimple_seq gs;
649 gs = NULL;
650 gcc_assert (is_func_instrumentation_required ());
651 if (func_ignore != tsan_ignore_rec)
652 build_stack_op (&gs, true);
653 else
654 build_rec_ignore_op (&gs, MINUS_EXPR);
655 return gs;
658 /* Sets location LOC for all gimples in the SEQ. */
660 static void
661 set_location (gimple_seq seq, location_t loc)
663 gimple_seq_node n;
665 for (n = gimple_seq_first (seq); n != NULL; n = n->next)
666 gimple_set_location (n->stmt, loc);
669 /* Check as to whether EXPR refers to a store to vptr. */
671 static tree
672 is_vptr_store (gimple stmt, tree expr, int is_store)
674 if (is_store == 1
675 && gimple_assign_single_p (stmt)
676 && TREE_CODE (expr) == COMPONENT_REF)
678 tree field = TREE_OPERAND (expr, 1);
679 if (TREE_CODE (field) == FIELD_DECL
680 && DECL_VIRTUAL_P (field))
681 return gimple_assign_rhs1 (stmt);
683 return NULL;
686 /* Checks as to whether EXPR refers to constant var/field/param.
687 Don't bother to instrument them. */
689 static bool
690 is_load_of_const (tree expr, int is_store)
692 if (is_store)
693 return false;
694 if (TREE_CODE (expr) == COMPONENT_REF)
695 expr = TREE_OPERAND (expr, 1);
696 if (TREE_CODE (expr) == VAR_DECL
697 || TREE_CODE (expr) == PARM_DECL
698 || TREE_CODE (expr) == FIELD_DECL)
700 if (TREE_READONLY (expr))
701 return true;
703 return false;
706 /* Checks as to whether EXPR needs to be instrumented,
707 if so puts it into the MOP_LIST.
708 GSI is the iterator from which EXPR was extracted.
709 IS_STORE says as to whether EXPR refers to a memory store
710 or a memory load. */
712 static void
713 handle_expr (gimple_stmt_iterator gsi, tree expr, int is_store,
714 VEC (mop_desc, heap) **mop_list)
716 enum tree_code tcode;
717 struct mop_desc mop;
718 unsigned fld_off;
719 unsigned fld_size;
720 tree base;
722 base = get_base_address (expr);
723 if (base == NULL_TREE
724 || TREE_CODE (base) == SSA_NAME
725 || TREE_CODE (base) == STRING_CST)
726 return;
728 tcode = TREE_CODE (expr);
730 /* Below are things we do not instrument
731 (no possibility of races or not implemented yet). */
732 if ((func_ignore & (tsan_ignore_mop | tsan_ignore_rec))
733 /* Compiler-emitted artificial variables. */
734 || (DECL_P (expr) && DECL_ARTIFICIAL (expr))
735 /* The var does not live in memory -> no possibility of races. */
736 || (tcode == VAR_DECL
737 && TREE_ADDRESSABLE (expr) == 0
738 && DECL_EXTERNAL (expr) == 0)
739 /* TODO (dvyukov): not implemented. */
740 || TREE_CODE (TREE_TYPE (expr)) == RECORD_TYPE
741 /* TODO (dvyukov): not implemented. */
742 || tcode == CONSTRUCTOR
743 /* TODO (dvyukov): not implemented. */
744 || tcode == PARM_DECL
745 /* Load of a const variable/parameter/field. */
746 || is_load_of_const (expr, is_store))
747 return;
749 if (tcode == COMPONENT_REF)
751 tree field = TREE_OPERAND (expr, 1);
752 if (TREE_CODE (field) == FIELD_DECL)
754 fld_off = TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
755 fld_size = TREE_INT_CST_LOW (DECL_SIZE (field));
756 if (((fld_off % BITS_PER_UNIT) != 0)
757 || ((fld_size % BITS_PER_UNIT) != 0))
759 /* As of now it crashes compilation.
760 TODO (dvyukov): handle bit-fields as if touching
761 the whole field. */
762 return;
767 /* TODO (dvyukov): handle other cases
768 (FIELD_DECL, MEM_REF, ARRAY_RANGE_REF, TARGET_MEM_REF, ADDR_EXPR). */
769 if (tcode != ARRAY_REF
770 && tcode != VAR_DECL
771 && tcode != COMPONENT_REF
772 && tcode != INDIRECT_REF
773 && tcode != MEM_REF)
774 return;
776 mop.is_call = 0;
777 mop.gsi = gsi;
778 mop.expr = expr;
779 mop.is_store = is_store;
780 VEC_safe_push (mop_desc, heap, *mop_list, &mop);
783 /* Collects all interesting memory accesses from the gimple pointed to by GSI
784 into MOP_LIST. */
786 static void
787 handle_gimple (gimple_stmt_iterator gsi, VEC (mop_desc, heap) **mop_list)
789 unsigned i;
790 struct mop_desc mop;
791 gimple stmt;
792 enum gimple_code gcode;
793 tree rhs;
794 tree lhs;
796 stmt = gsi_stmt (gsi);
797 gcode = gimple_code (stmt);
798 gcc_assert (gcode < LAST_AND_UNUSED_GIMPLE_CODE);
800 switch (gcode)
802 case GIMPLE_CALL:
804 func_calls += 1;
805 memset (&mop, 0, sizeof (mop));
806 mop.is_call = 1;
807 VEC_safe_push (mop_desc, heap, *mop_list, &mop);
808 break;
811 case GIMPLE_ASSIGN:
813 /* Handle assignment lhs as store. */
814 lhs = gimple_assign_lhs (stmt);
815 handle_expr (gsi, lhs, 1, mop_list);
817 /* Handle operands as loads. */
818 for (i = 1; i < gimple_num_ops (stmt); i++)
820 rhs = gimple_op (stmt, i);
821 handle_expr (gsi, rhs, 0, mop_list);
823 break;
826 default:
827 break;
831 /* Instruments single basic block BB.
832 BBD is the sblock info associated with the block. */
834 static void
835 instrument_bblock (struct bb_data *bbd, basic_block bb)
837 int ix;
838 int is_sblock;
839 gimple_stmt_iterator gsi;
840 struct mop_desc *mop;
841 gimple stmt;
842 location_t loc;
843 expanded_location eloc;
844 gimple_seq instr_seq;
845 tree rhs;
847 /* Iterate over all gimples and collect interesting mops into mop_list. */
848 VEC_free (mop_desc, heap, mop_list);
849 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
851 handle_gimple (gsi, &mop_list);
854 mop = 0;
855 for (ix = 0; VEC_iterate (mop_desc, mop_list, ix, mop); ix += 1)
857 if (mop->is_call != 0)
859 /* After a function call we must start a brand new sblock,
860 because the function can contain synchronization. */
861 bbd->has_sb = 0;
862 continue;
865 func_mops += 1;
866 stmt = gsi_stmt (mop->gsi);
867 loc = gimple_location (stmt);
868 eloc = expand_location (loc);
870 /* Check as to whether we may not set sblock flag for the access. */
871 is_sblock = (bbd->has_sb == 0
872 || !(eloc.file != 0
873 && bbd->sb_file != 0
874 && strcmp (eloc.file, bbd->sb_file) == 0
875 && eloc.line >= bbd->sb_line_min
876 && eloc.line <= bbd->sb_line_max));
878 if (func_ignore == tsan_ignore_hist)
879 is_sblock = 0;
881 if (is_sblock)
883 /* Start new sblock with new source info. */
884 bbd->has_sb = 1;
885 bbd->sb_file = eloc.file;
886 bbd->sb_line_min = eloc.line;
887 bbd->sb_line_max = eloc.line + SBLOCK_SIZE;
890 instr_seq = 0;
891 rhs = is_vptr_store (stmt, mop->expr, mop->is_store);
892 if (rhs == NULL)
893 instr_mop (mop->expr, mop->is_store, is_sblock, &instr_seq);
894 else
895 instr_vptr_store (mop->expr, rhs, is_sblock, &instr_seq);
896 gcc_assert (instr_seq != 0);
897 set_location (instr_seq, loc);
898 /* Instrumentation for assignment of a function result
899 must be inserted after the call. Instrumentation for
900 reads of function arguments must be inserted before the call.
901 That's because the call can contain synchronization. */
902 if (is_gimple_call (stmt) && mop->is_store == 1)
903 gsi_insert_seq_after (&mop->gsi, instr_seq, GSI_NEW_STMT);
904 else
905 gsi_insert_seq_before (&mop->gsi, instr_seq, GSI_SAME_STMT);
909 /* Instruments all interesting memory accesses in the current function. */
911 static void
912 instrument_mops (void)
914 basic_block bb;
915 int *blocks_inverted;
916 struct bb_data *bb_data;
917 struct bb_data *pred;
918 struct bb_data *bbd;
919 edge e;
920 edge_iterator ei;
921 int sb_line_min, sb_line_max;
922 int cnt, i;
924 /* The function does basic block traversal in reverse top sort order
925 of the inverted CFG. Such order is required to properly mark super-blocks.
926 The idea behind super-blocks is as follows.
927 If several memory accesses happen within SBLOCK_SIZE source code lines
928 from each other, then we only mark the first access as SBLOCK.
929 This allows the runtime library to memorize a stack trace
930 only for the first access and do not memorize for others.
931 This significantly reduces memory consumption in exchange for slightly
932 imprecise stack traces for previous accesses. */
934 blocks_inverted = XNEWVEC (int, last_basic_block + NUM_FIXED_BLOCKS);
935 bb_data = XCNEWVEC (struct bb_data, last_basic_block + NUM_FIXED_BLOCKS);
936 cnt = inverted_post_order_compute (blocks_inverted);
937 for (i = 0; i < cnt; i++)
939 bb = BASIC_BLOCK (blocks_inverted [i]);
940 bbd = &bb_data [bb->index];
941 /* Iterate over all predecessors and merge their sblock info. */
942 FOR_EACH_EDGE (e, ei, bb->preds)
944 pred = &bb_data [e->src->index];
945 if (!pred->is_visited || !pred->has_sb || pred == bbd)
947 /* If there is a not visited predecessor,
948 or a predecessor with no active sblock info,
949 or a self-loop, then we will have to start
950 a brand new sblock on next memory access. */
951 bbd->has_sb = 0;
952 break;
954 else if (bbd->has_sb == 0)
956 /* If it's a first predecessor, just copy the info. */
957 bbd->has_sb = 1;
958 bbd->sb_file = pred->sb_file;
959 bbd->sb_line_min = pred->sb_line_min;
960 bbd->sb_line_max = pred->sb_line_max;
962 else
964 /* Otherwise, find the interception
965 between two sblock descriptors. */
966 bbd->has_sb = 0;
967 if (bbd->sb_file != 0 && pred->sb_file != 0
968 && strcmp (bbd->sb_file, pred->sb_file) == 0)
970 sb_line_min = MAX (bbd->sb_line_min, pred->sb_line_min);
971 sb_line_max = MIN (bbd->sb_line_max, pred->sb_line_max);
972 if (sb_line_min <= sb_line_max)
974 bbd->has_sb = 1;
975 bbd->sb_line_min = sb_line_min;
976 bbd->sb_line_max = sb_line_max;
979 /* No interception, have to start new sblock. */
980 if (bbd->has_sb == 0)
981 break;
985 instrument_bblock (bbd, bb);
986 bbd->is_visited = 1;
989 free (blocks_inverted);
990 free (bb_data);
993 /* Instruments function entry. */
995 static void
996 instrument_func_entry (void)
998 gimple_seq seq;
999 basic_block entry_bb;
1000 edge entry_edge;
1001 gimple_stmt_iterator gsi;
1003 /* Insert new BB before the first BB. */
1004 seq = build_func_entry_instr ();
1005 gcc_assert (seq != NULL);
1006 entry_bb = ENTRY_BLOCK_PTR;
1007 entry_edge = single_succ_edge (entry_bb);
1008 set_location (seq, cfun->function_start_locus);
1009 entry_bb = split_edge (entry_edge);
1010 gsi = gsi_start_bb (entry_bb);
1011 gsi_insert_seq_after (&gsi, seq, GSI_NEW_STMT);
1014 /* Instruments function exits. */
1016 static void
1017 instrument_func_exit (void)
1019 location_t loc;
1020 gimple_seq seq;
1021 basic_block exit_bb;
1022 gimple_stmt_iterator gsi;
1023 gimple stmt;
1024 edge e;
1025 edge_iterator ei;
1027 /* Find all function exits. */
1028 exit_bb = EXIT_BLOCK_PTR;
1029 FOR_EACH_EDGE (e, ei, exit_bb->preds)
1031 gsi = gsi_last_bb (e->src);
1032 stmt = gsi_stmt (gsi);
1033 gcc_assert (gimple_code (stmt) == GIMPLE_RETURN);
1034 loc = gimple_location (stmt);
1035 seq = build_func_exit_instr ();
1036 gcc_assert (seq != NULL);
1037 set_location (seq, loc);
1038 gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
1042 /* ThreadSanitizer instrumentation pass. */
1044 static unsigned
1045 tsan_pass (void)
1047 struct gimplify_ctx gctx;
1049 func_ignore = tsan_ignore ();
1050 if (func_ignore == tsan_ignore_func)
1051 return 0;
1053 func_calls = 0;
1054 func_mops = 0;
1056 push_gimplify_context (&gctx);
1058 instrument_mops ();
1060 if (is_func_instrumentation_required ())
1062 instrument_func_entry ();
1063 instrument_func_exit ();
1066 pop_gimplify_context (NULL);
1068 return 0;
1071 /* The pass's gate. */
1073 static bool
1074 tsan_gate (void)
1076 return flag_tsan != 0;
1079 /* Inserts __tsan_init () into the list of CTORs. */
1081 void tsan_finish_file (void)
1083 tree ctor_statements;
1085 ctor_statements = NULL_TREE;
1086 append_to_statement_list (build_call_expr (get_init_decl (), 0),
1087 &ctor_statements);
1088 cgraph_build_static_cdtor ('I', ctor_statements,
1089 MAX_RESERVED_INIT_PRIORITY - 1);
1092 /* The pass descriptor. */
1094 struct gimple_opt_pass pass_tsan = {{
1095 GIMPLE_PASS,
1096 "tsan", /* name */
1097 tsan_gate, /* gate */
1098 tsan_pass, /* execute */
1099 NULL, /* sub */
1100 NULL, /* next */
1101 0, /* static_pass_number */
1102 TV_NONE, /* tv_id */
1103 PROP_ssa | PROP_cfg, /* properties_required */
1104 0, /* properties_provided */
1105 0, /* properties_destroyed */
1106 0, /* todo_flags_start */
1107 TODO_dump_cgraph | TODO_dump_func | TODO_verify_all
1108 | TODO_update_ssa | TODO_update_address_taken /* todo_flags_finish */