aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile')
-rw-r--r--src/cmd/compile/internal/gc/builtin.go1
-rw-r--r--src/cmd/compile/internal/gc/builtin/runtime.go1
-rw-r--r--src/cmd/compile/internal/gc/racewalk.go14
-rw-r--r--src/cmd/compile/internal/gc/ssa.go47
-rw-r--r--src/cmd/compile/internal/ssa/schedule.go2
-rw-r--r--src/cmd/compile/internal/ssa/tighten.go3
6 files changed, 38 insertions, 30 deletions
diff --git a/src/cmd/compile/internal/gc/builtin.go b/src/cmd/compile/internal/gc/builtin.go
index 0e5fe2ab60..66f66a7690 100644
--- a/src/cmd/compile/internal/gc/builtin.go
+++ b/src/cmd/compile/internal/gc/builtin.go
@@ -151,6 +151,7 @@ const runtimeimport = "" +
"func @\"\".uint64tofloat64 (? uint64) (? float64)\n" +
"func @\"\".complex128div (@\"\".num·2 complex128, @\"\".den·3 complex128) (@\"\".quo·1 complex128)\n" +
"func @\"\".racefuncenter (? uintptr)\n" +
+ "func @\"\".racefuncenterfp (? *int32)\n" +
"func @\"\".racefuncexit ()\n" +
"func @\"\".raceread (? uintptr)\n" +
"func @\"\".racewrite (? uintptr)\n" +
diff --git a/src/cmd/compile/internal/gc/builtin/runtime.go b/src/cmd/compile/internal/gc/builtin/runtime.go
index f8487de45b..43c35ca850 100644
--- a/src/cmd/compile/internal/gc/builtin/runtime.go
+++ b/src/cmd/compile/internal/gc/builtin/runtime.go
@@ -189,6 +189,7 @@ func complex128div(num complex128, den complex128) (quo complex128)
// race detection
func racefuncenter(uintptr)
+func racefuncenterfp(*int32)
func racefuncexit()
func raceread(uintptr)
func racewrite(uintptr)
diff --git a/src/cmd/compile/internal/gc/racewalk.go b/src/cmd/compile/internal/gc/racewalk.go
index 9301d87d2e..852ae98ec1 100644
--- a/src/cmd/compile/internal/gc/racewalk.go
+++ b/src/cmd/compile/internal/gc/racewalk.go
@@ -11,7 +11,7 @@ import (
// The racewalk pass modifies the code tree for the function as follows:
//
-// 1. It inserts a call to racefuncenter at the beginning of each function.
+// 1. It inserts a call to racefuncenterfp at the beginning of each function.
// 2. It inserts a call to racefuncexit at the end of each function.
// 3. It inserts a call to raceread before each memory read.
// 4. It inserts a call to racewrite before each memory write.
@@ -26,7 +26,7 @@ import (
// at best instrumentation would cause infinite recursion.
var omit_pkgs = []string{"runtime", "runtime/race"}
-// Only insert racefuncenter/racefuncexit into the following packages.
+// Only insert racefuncenterfp/racefuncexit into the following packages.
// Memory accesses in the packages are either uninteresting or will cause false positives.
var noinst_pkgs = []string{"sync", "sync/atomic"}
@@ -64,15 +64,7 @@ func racewalk(fn *Node) {
racewalklist(fn.Func.Exit, nil)
}
- // nodpc is the PC of the caller as extracted by
- // getcallerpc. We use -widthptr(FP) for x86.
- // BUG: this will not work on arm.
- nodpc := Nod(OXXX, nil, nil)
-
- *nodpc = *nodfp
- nodpc.Type = Types[TUINTPTR]
- nodpc.Xoffset = int64(-Widthptr)
- nd := mkcall("racefuncenter", nil, nil, nodpc)
+ nd := mkcall("racefuncenterfp", nil, nil, Nod(OADDR, nodfp, nil))
fn.Func.Enter = concat(list1(nd), fn.Func.Enter)
nd = mkcall("racefuncexit", nil, nil)
fn.Func.Exit = list(fn.Func.Exit, nd)
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index b568c58fba..312d494f5d 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -1250,7 +1250,7 @@ func (s *state) expr(n *Node) *ssa.Value {
aux := &ssa.ExternSymbol{n.Type, n.Left.Sym}
return s.entryNewValue1A(ssa.OpAddr, n.Type, aux, s.sb)
case OPARAM:
- addr := s.addr(n)
+ addr := s.addr(n, false)
return s.newValue2(ssa.OpLoad, n.Left.Type, addr, s.mem())
case ONAME:
if n.Class == PFUNC {
@@ -1262,10 +1262,10 @@ func (s *state) expr(n *Node) *ssa.Value {
if canSSA(n) {
return s.variable(n, n.Type)
}
- addr := s.addr(n)
+ addr := s.addr(n, false)
return s.newValue2(ssa.OpLoad, n.Type, addr, s.mem())
case OCLOSUREVAR:
- addr := s.addr(n)
+ addr := s.addr(n, false)
return s.newValue2(ssa.OpLoad, n.Type, addr, s.mem())
case OLITERAL:
switch n.Val().Ctype() {
@@ -1376,8 +1376,10 @@ func (s *state) expr(n *Node) *ssa.Value {
}
if flag_race != 0 {
- s.Unimplementedf("questionable CONVNOP from race detector %v -> %v\n", from, to)
- return nil
+ // These appear to be fine, but they fail the
+ // integer constraint below, so okay them here.
+ // Sample non-integer conversion: map[string]string -> *uint8
+ return v
}
if etypesign(from.Etype) == 0 {
@@ -1716,7 +1718,7 @@ func (s *state) expr(n *Node) *ssa.Value {
return s.expr(n.Left)
case OADDR:
- return s.addr(n.Left)
+ return s.addr(n.Left, n.Bounded)
case OINDREG:
if int(n.Reg) != Thearch.REGSP {
@@ -1733,7 +1735,7 @@ func (s *state) expr(n *Node) *ssa.Value {
case ODOT:
// TODO: fix when we can SSA struct types.
- p := s.addr(n)
+ p := s.addr(n, false)
return s.newValue2(ssa.OpLoad, n.Type, p, s.mem())
case ODOTPTR:
@@ -1757,11 +1759,11 @@ func (s *state) expr(n *Node) *ssa.Value {
ptr = s.newValue2(ssa.OpAddPtr, ptrtyp, ptr, i)
return s.newValue2(ssa.OpLoad, Types[TUINT8], ptr, s.mem())
case n.Left.Type.IsSlice():
- p := s.addr(n)
+ p := s.addr(n, false)
return s.newValue2(ssa.OpLoad, n.Left.Type.Type, p, s.mem())
case n.Left.Type.IsArray():
// TODO: fix when we can SSA arrays of length 1.
- p := s.addr(n)
+ p := s.addr(n, false)
return s.newValue2(ssa.OpLoad, n.Left.Type.Type, p, s.mem())
default:
s.Fatalf("bad type for index %v", n.Left.Type)
@@ -1927,7 +1929,7 @@ func (s *state) expr(n *Node) *ssa.Value {
args = append(args, s.expr(l.N))
store = append(store, true)
} else {
- args = append(args, s.addr(l.N))
+ args = append(args, s.addr(l.N, false))
store = append(store, false)
}
}
@@ -1970,7 +1972,7 @@ func (s *state) assign(left *Node, right *ssa.Value, wb bool) {
// right == nil means use the zero value of the assigned type.
if !canSSA(left) {
// if we can't ssa this memory, treat it as just zeroing out the backing memory
- addr := s.addr(left)
+ addr := s.addr(left, false)
if left.Op == ONAME {
s.vars[&memVar] = s.newValue1A(ssa.OpVarDef, ssa.TypeMem, left, s.mem())
}
@@ -1985,7 +1987,7 @@ func (s *state) assign(left *Node, right *ssa.Value, wb bool) {
return
}
// not ssa-able. Treat as a store.
- addr := s.addr(left)
+ addr := s.addr(left, false)
if left.Op == ONAME {
s.vars[&memVar] = s.newValue1A(ssa.OpVarDef, ssa.TypeMem, left, s.mem())
}
@@ -2187,7 +2189,9 @@ func etypesign(e uint8) int8 {
// addr converts the address of the expression n to SSA, adds it to s and returns the SSA result.
// The value that the returned Value represents is guaranteed to be non-nil.
-func (s *state) addr(n *Node) *ssa.Value {
+// If bounded is true then this address does not require a nil check for its operand
+// even if that would otherwise be implied.
+func (s *state) addr(n *Node, bounded bool) *ssa.Value {
switch n.Op {
case ONAME:
switch n.Class {
@@ -2250,7 +2254,7 @@ func (s *state) addr(n *Node) *ssa.Value {
p := s.newValue1(ssa.OpSlicePtr, Ptrto(n.Left.Type.Type), a)
return s.newValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Type), p, i)
} else { // array
- a := s.addr(n.Left)
+ a := s.addr(n.Left, bounded)
i := s.expr(n.Right)
i = s.extendIndex(i)
len := s.constInt(Types[TINT], n.Left.Type.Bound)
@@ -2261,14 +2265,18 @@ func (s *state) addr(n *Node) *ssa.Value {
}
case OIND:
p := s.expr(n.Left)
- s.nilCheck(p)
+ if !bounded {
+ s.nilCheck(p)
+ }
return p
case ODOT:
- p := s.addr(n.Left)
+ p := s.addr(n.Left, bounded)
return s.newValue2(ssa.OpAddPtr, p.Type, p, s.constIntPtr(Types[TUINTPTR], n.Xoffset))
case ODOTPTR:
p := s.expr(n.Left)
- s.nilCheck(p)
+ if !bounded {
+ s.nilCheck(p)
+ }
return s.newValue2(ssa.OpAddPtr, p.Type, p, s.constIntPtr(Types[TUINTPTR], n.Xoffset))
case OCLOSUREVAR:
return s.newValue2(ssa.OpAddPtr, Ptrto(n.Type),
@@ -2285,6 +2293,11 @@ func (s *state) addr(n *Node) *ssa.Value {
original_p.Xoffset = n.Xoffset
aux := &ssa.ArgSymbol{Typ: n.Type, Node: &original_p}
return s.entryNewValue1A(ssa.OpAddr, Ptrto(n.Type), aux, s.sp)
+ case OCONVNOP:
+ addr := s.addr(n.Left, bounded)
+ to := Ptrto(n.Type)
+ return s.newValue1(ssa.OpCopy, to, addr) // ensure that addr has the right type
+
default:
s.Unimplementedf("unhandled addr %v", Oconv(int(n.Op), 0))
return nil
diff --git a/src/cmd/compile/internal/ssa/schedule.go b/src/cmd/compile/internal/ssa/schedule.go
index 949de31afc..dd0a42a5dd 100644
--- a/src/cmd/compile/internal/ssa/schedule.go
+++ b/src/cmd/compile/internal/ssa/schedule.go
@@ -86,7 +86,7 @@ func schedule(f *Func) {
// in the entry block where there are no phi functions, so there is no
// conflict or ambiguity here.
if b != f.Entry {
- f.Fatalf("LoweredGetClosurePtr appeared outside of entry block.")
+ f.Fatalf("LoweredGetClosurePtr appeared outside of entry block, b=%s", b.String())
}
score[v.ID] = ScorePhi
case v.Op == OpPhi:
diff --git a/src/cmd/compile/internal/ssa/tighten.go b/src/cmd/compile/internal/ssa/tighten.go
index a43218095e..05c349cc17 100644
--- a/src/cmd/compile/internal/ssa/tighten.go
+++ b/src/cmd/compile/internal/ssa/tighten.go
@@ -54,7 +54,8 @@ func tighten(f *Func) {
for _, b := range f.Blocks {
for i := 0; i < len(b.Values); i++ {
v := b.Values[i]
- if v.Op == OpPhi {
+ if v.Op == OpPhi || v.Op == OpGetClosurePtr {
+ // GetClosurePtr must stay in entry block
continue
}
if uses[v.ID] == 1 && !phi[v.ID] && home[v.ID] != b && len(v.Args) < 2 {