aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/walk/race.go
blob: 20becf9be93d64d3bc89cdcc6adfaa6fe702820a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 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 walk

import (
	"cmd/compile/internal/base"
	"cmd/compile/internal/ir"
	"cmd/compile/internal/ssagen"
	"cmd/compile/internal/typecheck"
	"cmd/compile/internal/types"
	"cmd/internal/src"
	"cmd/internal/sys"
)

func instrument(fn *ir.Func) {
	if fn.Pragma&ir.Norace != 0 || (fn.Linksym() != nil && fn.Linksym().ABIWrapper()) {
		return
	}

	if !base.Flag.Race || !base.Compiling(base.NoRacePkgs) {
		fn.SetInstrumentBody(true)
	}

	if base.Flag.Race {
		lno := base.Pos
		base.Pos = src.NoXPos

		if ssagen.Arch.LinkArch.Arch.Family != sys.AMD64 {
			fn.Enter.Prepend(mkcall("racefuncenterfp", nil, nil))
			fn.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 := ir.NewNameAt(src.NoXPos, typecheck.Lookup(".fp"))
			nodpc.Class_ = ir.PPARAM
			nodpc.SetUsed(true)
			nodpc.SetType(types.Types[types.TUINTPTR])
			nodpc.SetFrameOffset(int64(-types.PtrSize))
			fn.Dcl = append(fn.Dcl, nodpc)
			fn.Enter.Prepend(mkcall("racefuncenter", nil, nil, nodpc))
			fn.Exit.Append(mkcall("racefuncexit", nil, nil))
		}
		base.Pos = lno
	}
}