// Copyright 2012 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package gc import ( "cmd/compile/internal/types" "cmd/internal/src" "cmd/internal/sys" ) // The racewalk pass is currently handled in three parts. // // First, for flag_race, it inserts calls to racefuncenter and // racefuncexit at the start and end (respectively) of each // function. This is handled below. // // Second, during buildssa, it inserts appropriate instrumentation // calls immediately before each memory load or store. This is handled // by the (*state).instrument method in ssa.go, so here we just set // the Func.InstrumentBody flag as needed. For background on why this // is done during SSA construction rather than a separate SSA pass, // see issue #19054. // // Third we remove calls to racefuncenter and racefuncexit, for leaf // functions without instrumented operations. This is done as part of // ssa opt pass via special rule. // TODO(dvyukov): do not instrument initialization as writes: // a := make([]int, 10) // Do not instrument the following packages at all, // at best instrumentation would cause infinite recursion. var omit_pkgs = []string{ "runtime/internal/atomic", "runtime/internal/sys", "runtime/internal/math", "runtime", "runtime/race", "runtime/msan", "internal/cpu", } // Only insert racefuncenterfp/racefuncexit into the following packages. // Memory accesses in the packages are either uninteresting or will cause false positives. var norace_inst_pkgs = []string{"sync", "sync/atomic"} func ispkgin(pkgs []string) bool { if myimportpath != "" { for _, p := range pkgs { if myimportpath == p { return true } } } return false } func instrument(fn *Node) { if fn.Func.Pragma&Norace != 0 { return } if !flag_race || !ispkgin(norace_inst_pkgs) { fn.Func.SetInstrumentBody(true) } if flag_race { lno := lineno lineno = src.NoXPos if thearch.LinkArch.Arch.Family != sys.AMD64 { fn.Func.Enter.Prepend(mkcall("racefuncenterfp", nil, nil)) fn.Func.Exit.Append(mkcall("racefuncexit", nil, nil)) } else { // nodpc is the PC of the caller as extracted by // getcallerpc. We use -widthptr(FP) for x86. // This only works for amd64. This will not // work on arm or others that might support // race in the future. nodpc := nodfp.copy() nodpc.Type = types.Types[TUINTPTR] nodpc.Xoffset = int64(-Widthptr) fn.Func.Dcl = append(fn.Func.Dcl, nodpc) fn.Func.Enter.Prepend(mkcall("racefuncenter", nil, nil, nodpc)) fn.Func.Exit.Append(mkcall("racefuncexit", nil, nil)) } lineno = lno } }