aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/compile/internal/ssagen/ssa.go3
-rw-r--r--src/cmd/compile/internal/typecheck/_builtin/coverage.go1
-rw-r--r--src/cmd/compile/internal/typecheck/_builtin/runtime.go4
-rw-r--r--src/cmd/compile/internal/typecheck/builtin.go267
-rw-r--r--src/cmd/compile/internal/walk/builtin.go17
-rw-r--r--src/runtime/chan.go13
6 files changed, 163 insertions, 142 deletions
diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go
index 68b1547048..05919b9924 100644
--- a/src/cmd/compile/internal/ssagen/ssa.go
+++ b/src/cmd/compile/internal/ssagen/ssa.go
@@ -6349,6 +6349,9 @@ func (s *state) referenceTypeBuiltin(n *ir.UnaryExpr, x *ssa.Value) *ssa.Value {
if !n.X.Type().IsMap() && !n.X.Type().IsChan() {
s.Fatalf("node must be a map or a channel")
}
+ if n.X.Type().IsChan() && n.Op() == ir.OLEN {
+ s.Fatalf("cannot inline len(chan)") // must use runtime.chanlen now
+ }
// if n == nil {
// return 0
// } else {
diff --git a/src/cmd/compile/internal/typecheck/_builtin/coverage.go b/src/cmd/compile/internal/typecheck/_builtin/coverage.go
index 02226356bc..f5c9e24991 100644
--- a/src/cmd/compile/internal/typecheck/_builtin/coverage.go
+++ b/src/cmd/compile/internal/typecheck/_builtin/coverage.go
@@ -3,6 +3,7 @@
// license that can be found in the LICENSE file.
// NOTE: If you change this file you must run "go generate"
+// in cmd/compile/internal/typecheck
// to update builtin.go. This is not done automatically
// to avoid depending on having a working compiler binary.
diff --git a/src/cmd/compile/internal/typecheck/_builtin/runtime.go b/src/cmd/compile/internal/typecheck/_builtin/runtime.go
index 421152967c..1ae9fe21d9 100644
--- a/src/cmd/compile/internal/typecheck/_builtin/runtime.go
+++ b/src/cmd/compile/internal/typecheck/_builtin/runtime.go
@@ -3,6 +3,7 @@
// license that can be found in the LICENSE file.
// NOTE: If you change this file you must run "go generate"
+// in cmd/compile/internal/typecheck
// to update builtin.go. This is not done automatically
// to avoid depending on having a working compiler binary.
@@ -158,7 +159,8 @@ func makechan(chanType *byte, size int) (hchan chan any)
func chanrecv1(hchan <-chan any, elem *any)
func chanrecv2(hchan <-chan any, elem *any) bool
func chansend1(hchan chan<- any, elem *any)
-func closechan(hchan any)
+func closechan(hchan chan<- any)
+func chanlen(hchan any) int
var writeBarrier struct {
enabled bool
diff --git a/src/cmd/compile/internal/typecheck/builtin.go b/src/cmd/compile/internal/typecheck/builtin.go
index 09f60c68c0..975eff3f50 100644
--- a/src/cmd/compile/internal/typecheck/builtin.go
+++ b/src/cmd/compile/internal/typecheck/builtin.go
@@ -136,106 +136,107 @@ var runtimeDecls = [...]struct {
{"chanrecv1", funcTag, 100},
{"chanrecv2", funcTag, 101},
{"chansend1", funcTag, 103},
- {"closechan", funcTag, 30},
- {"writeBarrier", varTag, 105},
- {"typedmemmove", funcTag, 106},
- {"typedmemclr", funcTag, 107},
- {"typedslicecopy", funcTag, 108},
- {"selectnbsend", funcTag, 109},
- {"selectnbrecv", funcTag, 110},
- {"selectsetpc", funcTag, 111},
- {"selectgo", funcTag, 112},
+ {"closechan", funcTag, 104},
+ {"chanlen", funcTag, 105},
+ {"writeBarrier", varTag, 107},
+ {"typedmemmove", funcTag, 108},
+ {"typedmemclr", funcTag, 109},
+ {"typedslicecopy", funcTag, 110},
+ {"selectnbsend", funcTag, 111},
+ {"selectnbrecv", funcTag, 112},
+ {"selectsetpc", funcTag, 113},
+ {"selectgo", funcTag, 114},
{"block", funcTag, 9},
- {"makeslice", funcTag, 113},
- {"makeslice64", funcTag, 114},
- {"makeslicecopy", funcTag, 115},
- {"growslice", funcTag, 117},
- {"unsafeslicecheckptr", funcTag, 118},
+ {"makeslice", funcTag, 115},
+ {"makeslice64", funcTag, 116},
+ {"makeslicecopy", funcTag, 117},
+ {"growslice", funcTag, 119},
+ {"unsafeslicecheckptr", funcTag, 120},
{"panicunsafeslicelen", funcTag, 9},
{"panicunsafeslicenilptr", funcTag, 9},
- {"unsafestringcheckptr", funcTag, 119},
+ {"unsafestringcheckptr", funcTag, 121},
{"panicunsafestringlen", funcTag, 9},
{"panicunsafestringnilptr", funcTag, 9},
- {"memmove", funcTag, 120},
- {"memclrNoHeapPointers", funcTag, 121},
- {"memclrHasPointers", funcTag, 121},
- {"memequal", funcTag, 122},
- {"memequal0", funcTag, 123},
- {"memequal8", funcTag, 123},
- {"memequal16", funcTag, 123},
- {"memequal32", funcTag, 123},
- {"memequal64", funcTag, 123},
- {"memequal128", funcTag, 123},
- {"f32equal", funcTag, 124},
- {"f64equal", funcTag, 124},
- {"c64equal", funcTag, 124},
- {"c128equal", funcTag, 124},
- {"strequal", funcTag, 124},
- {"interequal", funcTag, 124},
- {"nilinterequal", funcTag, 124},
- {"memhash", funcTag, 125},
- {"memhash0", funcTag, 126},
- {"memhash8", funcTag, 126},
- {"memhash16", funcTag, 126},
- {"memhash32", funcTag, 126},
- {"memhash64", funcTag, 126},
- {"memhash128", funcTag, 126},
- {"f32hash", funcTag, 127},
- {"f64hash", funcTag, 127},
- {"c64hash", funcTag, 127},
- {"c128hash", funcTag, 127},
- {"strhash", funcTag, 127},
- {"interhash", funcTag, 127},
- {"nilinterhash", funcTag, 127},
- {"int64div", funcTag, 128},
- {"uint64div", funcTag, 129},
- {"int64mod", funcTag, 128},
- {"uint64mod", funcTag, 129},
- {"float64toint64", funcTag, 130},
- {"float64touint64", funcTag, 131},
- {"float64touint32", funcTag, 132},
- {"int64tofloat64", funcTag, 133},
- {"int64tofloat32", funcTag, 135},
- {"uint64tofloat64", funcTag, 136},
- {"uint64tofloat32", funcTag, 137},
- {"uint32tofloat64", funcTag, 138},
- {"complex128div", funcTag, 139},
- {"getcallerpc", funcTag, 140},
- {"getcallersp", funcTag, 140},
+ {"memmove", funcTag, 122},
+ {"memclrNoHeapPointers", funcTag, 123},
+ {"memclrHasPointers", funcTag, 123},
+ {"memequal", funcTag, 124},
+ {"memequal0", funcTag, 125},
+ {"memequal8", funcTag, 125},
+ {"memequal16", funcTag, 125},
+ {"memequal32", funcTag, 125},
+ {"memequal64", funcTag, 125},
+ {"memequal128", funcTag, 125},
+ {"f32equal", funcTag, 126},
+ {"f64equal", funcTag, 126},
+ {"c64equal", funcTag, 126},
+ {"c128equal", funcTag, 126},
+ {"strequal", funcTag, 126},
+ {"interequal", funcTag, 126},
+ {"nilinterequal", funcTag, 126},
+ {"memhash", funcTag, 127},
+ {"memhash0", funcTag, 128},
+ {"memhash8", funcTag, 128},
+ {"memhash16", funcTag, 128},
+ {"memhash32", funcTag, 128},
+ {"memhash64", funcTag, 128},
+ {"memhash128", funcTag, 128},
+ {"f32hash", funcTag, 129},
+ {"f64hash", funcTag, 129},
+ {"c64hash", funcTag, 129},
+ {"c128hash", funcTag, 129},
+ {"strhash", funcTag, 129},
+ {"interhash", funcTag, 129},
+ {"nilinterhash", funcTag, 129},
+ {"int64div", funcTag, 130},
+ {"uint64div", funcTag, 131},
+ {"int64mod", funcTag, 130},
+ {"uint64mod", funcTag, 131},
+ {"float64toint64", funcTag, 132},
+ {"float64touint64", funcTag, 133},
+ {"float64touint32", funcTag, 134},
+ {"int64tofloat64", funcTag, 135},
+ {"int64tofloat32", funcTag, 137},
+ {"uint64tofloat64", funcTag, 138},
+ {"uint64tofloat32", funcTag, 139},
+ {"uint32tofloat64", funcTag, 140},
+ {"complex128div", funcTag, 141},
+ {"getcallerpc", funcTag, 142},
+ {"getcallersp", funcTag, 142},
{"racefuncenter", funcTag, 31},
{"racefuncexit", funcTag, 9},
{"raceread", funcTag, 31},
{"racewrite", funcTag, 31},
- {"racereadrange", funcTag, 141},
- {"racewriterange", funcTag, 141},
- {"msanread", funcTag, 141},
- {"msanwrite", funcTag, 141},
- {"msanmove", funcTag, 142},
- {"asanread", funcTag, 141},
- {"asanwrite", funcTag, 141},
- {"checkptrAlignment", funcTag, 143},
- {"checkptrArithmetic", funcTag, 145},
- {"libfuzzerTraceCmp1", funcTag, 146},
- {"libfuzzerTraceCmp2", funcTag, 147},
- {"libfuzzerTraceCmp4", funcTag, 148},
- {"libfuzzerTraceCmp8", funcTag, 149},
- {"libfuzzerTraceConstCmp1", funcTag, 146},
- {"libfuzzerTraceConstCmp2", funcTag, 147},
- {"libfuzzerTraceConstCmp4", funcTag, 148},
- {"libfuzzerTraceConstCmp8", funcTag, 149},
- {"libfuzzerHookStrCmp", funcTag, 150},
- {"libfuzzerHookEqualFold", funcTag, 150},
- {"addCovMeta", funcTag, 152},
+ {"racereadrange", funcTag, 143},
+ {"racewriterange", funcTag, 143},
+ {"msanread", funcTag, 143},
+ {"msanwrite", funcTag, 143},
+ {"msanmove", funcTag, 144},
+ {"asanread", funcTag, 143},
+ {"asanwrite", funcTag, 143},
+ {"checkptrAlignment", funcTag, 145},
+ {"checkptrArithmetic", funcTag, 147},
+ {"libfuzzerTraceCmp1", funcTag, 148},
+ {"libfuzzerTraceCmp2", funcTag, 149},
+ {"libfuzzerTraceCmp4", funcTag, 150},
+ {"libfuzzerTraceCmp8", funcTag, 151},
+ {"libfuzzerTraceConstCmp1", funcTag, 148},
+ {"libfuzzerTraceConstCmp2", funcTag, 149},
+ {"libfuzzerTraceConstCmp4", funcTag, 150},
+ {"libfuzzerTraceConstCmp8", funcTag, 151},
+ {"libfuzzerHookStrCmp", funcTag, 152},
+ {"libfuzzerHookEqualFold", funcTag, 152},
+ {"addCovMeta", funcTag, 154},
{"x86HasPOPCNT", varTag, 6},
{"x86HasSSE41", varTag, 6},
{"x86HasFMA", varTag, 6},
{"armHasVFPv4", varTag, 6},
{"arm64HasATOMICS", varTag, 6},
- {"asanregisterglobals", funcTag, 121},
+ {"asanregisterglobals", funcTag, 123},
}
func runtimeTypes() []*types.Type {
- var typs [153]*types.Type
+ var typs [155]*types.Type
typs[0] = types.ByteType
typs[1] = types.NewPtr(typs[0])
typs[2] = types.Types[types.TANY]
@@ -340,55 +341,57 @@ func runtimeTypes() []*types.Type {
typs[101] = newSig(params(typs[99], typs[3]), params(typs[6]))
typs[102] = types.NewChan(typs[2], types.Csend)
typs[103] = newSig(params(typs[102], typs[3]), nil)
- typs[104] = types.NewArray(typs[0], 3)
- typs[105] = types.NewStruct([]*types.Field{types.NewField(src.NoXPos, Lookup("enabled"), typs[6]), types.NewField(src.NoXPos, Lookup("pad"), typs[104]), types.NewField(src.NoXPos, Lookup("cgo"), typs[6]), types.NewField(src.NoXPos, Lookup("alignme"), typs[24])})
- typs[106] = newSig(params(typs[1], typs[3], typs[3]), nil)
- typs[107] = newSig(params(typs[1], typs[3]), nil)
- typs[108] = newSig(params(typs[1], typs[3], typs[15], typs[3], typs[15]), params(typs[15]))
- typs[109] = newSig(params(typs[102], typs[3]), params(typs[6]))
- typs[110] = newSig(params(typs[3], typs[99]), params(typs[6], typs[6]))
- typs[111] = newSig(params(typs[71]), nil)
- typs[112] = newSig(params(typs[1], typs[1], typs[71], typs[15], typs[15], typs[6]), params(typs[15], typs[6]))
- typs[113] = newSig(params(typs[1], typs[15], typs[15]), params(typs[7]))
- typs[114] = newSig(params(typs[1], typs[22], typs[22]), params(typs[7]))
- typs[115] = newSig(params(typs[1], typs[15], typs[15], typs[7]), params(typs[7]))
- typs[116] = types.NewSlice(typs[2])
- typs[117] = newSig(params(typs[3], typs[15], typs[15], typs[15], typs[1]), params(typs[116]))
- typs[118] = newSig(params(typs[1], typs[7], typs[22]), nil)
- typs[119] = newSig(params(typs[7], typs[22]), nil)
- typs[120] = newSig(params(typs[3], typs[3], typs[5]), nil)
- typs[121] = newSig(params(typs[7], typs[5]), nil)
- typs[122] = newSig(params(typs[3], typs[3], typs[5]), params(typs[6]))
- typs[123] = newSig(params(typs[3], typs[3]), params(typs[6]))
- typs[124] = newSig(params(typs[7], typs[7]), params(typs[6]))
- typs[125] = newSig(params(typs[3], typs[5], typs[5]), params(typs[5]))
- typs[126] = newSig(params(typs[7], typs[5]), params(typs[5]))
- typs[127] = newSig(params(typs[3], typs[5]), params(typs[5]))
- typs[128] = newSig(params(typs[22], typs[22]), params(typs[22]))
- typs[129] = newSig(params(typs[24], typs[24]), params(typs[24]))
- typs[130] = newSig(params(typs[20]), params(typs[22]))
- typs[131] = newSig(params(typs[20]), params(typs[24]))
- typs[132] = newSig(params(typs[20]), params(typs[60]))
- typs[133] = newSig(params(typs[22]), params(typs[20]))
- typs[134] = types.Types[types.TFLOAT32]
- typs[135] = newSig(params(typs[22]), params(typs[134]))
- typs[136] = newSig(params(typs[24]), params(typs[20]))
- typs[137] = newSig(params(typs[24]), params(typs[134]))
- typs[138] = newSig(params(typs[60]), params(typs[20]))
- typs[139] = newSig(params(typs[26], typs[26]), params(typs[26]))
- typs[140] = newSig(nil, params(typs[5]))
- typs[141] = newSig(params(typs[5], typs[5]), nil)
- typs[142] = newSig(params(typs[5], typs[5], typs[5]), nil)
- typs[143] = newSig(params(typs[7], typs[1], typs[5]), nil)
- typs[144] = types.NewSlice(typs[7])
- typs[145] = newSig(params(typs[7], typs[144]), nil)
- typs[146] = newSig(params(typs[64], typs[64], typs[17]), nil)
- typs[147] = newSig(params(typs[58], typs[58], typs[17]), nil)
- typs[148] = newSig(params(typs[60], typs[60], typs[17]), nil)
- typs[149] = newSig(params(typs[24], typs[24], typs[17]), nil)
- typs[150] = newSig(params(typs[28], typs[28], typs[17]), nil)
- typs[151] = types.NewArray(typs[0], 16)
- typs[152] = newSig(params(typs[7], typs[60], typs[151], typs[28], typs[15], typs[64], typs[64]), params(typs[60]))
+ typs[104] = newSig(params(typs[102]), nil)
+ typs[105] = newSig(params(typs[2]), params(typs[15]))
+ typs[106] = types.NewArray(typs[0], 3)
+ typs[107] = types.NewStruct([]*types.Field{types.NewField(src.NoXPos, Lookup("enabled"), typs[6]), types.NewField(src.NoXPos, Lookup("pad"), typs[106]), types.NewField(src.NoXPos, Lookup("cgo"), typs[6]), types.NewField(src.NoXPos, Lookup("alignme"), typs[24])})
+ typs[108] = newSig(params(typs[1], typs[3], typs[3]), nil)
+ typs[109] = newSig(params(typs[1], typs[3]), nil)
+ typs[110] = newSig(params(typs[1], typs[3], typs[15], typs[3], typs[15]), params(typs[15]))
+ typs[111] = newSig(params(typs[102], typs[3]), params(typs[6]))
+ typs[112] = newSig(params(typs[3], typs[99]), params(typs[6], typs[6]))
+ typs[113] = newSig(params(typs[71]), nil)
+ typs[114] = newSig(params(typs[1], typs[1], typs[71], typs[15], typs[15], typs[6]), params(typs[15], typs[6]))
+ typs[115] = newSig(params(typs[1], typs[15], typs[15]), params(typs[7]))
+ typs[116] = newSig(params(typs[1], typs[22], typs[22]), params(typs[7]))
+ typs[117] = newSig(params(typs[1], typs[15], typs[15], typs[7]), params(typs[7]))
+ typs[118] = types.NewSlice(typs[2])
+ typs[119] = newSig(params(typs[3], typs[15], typs[15], typs[15], typs[1]), params(typs[118]))
+ typs[120] = newSig(params(typs[1], typs[7], typs[22]), nil)
+ typs[121] = newSig(params(typs[7], typs[22]), nil)
+ typs[122] = newSig(params(typs[3], typs[3], typs[5]), nil)
+ typs[123] = newSig(params(typs[7], typs[5]), nil)
+ typs[124] = newSig(params(typs[3], typs[3], typs[5]), params(typs[6]))
+ typs[125] = newSig(params(typs[3], typs[3]), params(typs[6]))
+ typs[126] = newSig(params(typs[7], typs[7]), params(typs[6]))
+ typs[127] = newSig(params(typs[3], typs[5], typs[5]), params(typs[5]))
+ typs[128] = newSig(params(typs[7], typs[5]), params(typs[5]))
+ typs[129] = newSig(params(typs[3], typs[5]), params(typs[5]))
+ typs[130] = newSig(params(typs[22], typs[22]), params(typs[22]))
+ typs[131] = newSig(params(typs[24], typs[24]), params(typs[24]))
+ typs[132] = newSig(params(typs[20]), params(typs[22]))
+ typs[133] = newSig(params(typs[20]), params(typs[24]))
+ typs[134] = newSig(params(typs[20]), params(typs[60]))
+ typs[135] = newSig(params(typs[22]), params(typs[20]))
+ typs[136] = types.Types[types.TFLOAT32]
+ typs[137] = newSig(params(typs[22]), params(typs[136]))
+ typs[138] = newSig(params(typs[24]), params(typs[20]))
+ typs[139] = newSig(params(typs[24]), params(typs[136]))
+ typs[140] = newSig(params(typs[60]), params(typs[20]))
+ typs[141] = newSig(params(typs[26], typs[26]), params(typs[26]))
+ typs[142] = newSig(nil, params(typs[5]))
+ typs[143] = newSig(params(typs[5], typs[5]), nil)
+ typs[144] = newSig(params(typs[5], typs[5], typs[5]), nil)
+ typs[145] = newSig(params(typs[7], typs[1], typs[5]), nil)
+ typs[146] = types.NewSlice(typs[7])
+ typs[147] = newSig(params(typs[7], typs[146]), nil)
+ typs[148] = newSig(params(typs[64], typs[64], typs[17]), nil)
+ typs[149] = newSig(params(typs[58], typs[58], typs[17]), nil)
+ typs[150] = newSig(params(typs[60], typs[60], typs[17]), nil)
+ typs[151] = newSig(params(typs[24], typs[24], typs[17]), nil)
+ typs[152] = newSig(params(typs[28], typs[28], typs[17]), nil)
+ typs[153] = types.NewArray(typs[0], 16)
+ typs[154] = newSig(params(typs[7], typs[60], typs[153], typs[28], typs[15], typs[64], typs[64]), params(typs[60]))
return typs[:]
}
diff --git a/src/cmd/compile/internal/walk/builtin.go b/src/cmd/compile/internal/walk/builtin.go
index 41fc0bf5dc..9a2c1353bb 100644
--- a/src/cmd/compile/internal/walk/builtin.go
+++ b/src/cmd/compile/internal/walk/builtin.go
@@ -153,9 +153,7 @@ func walkClear(n *ir.UnaryExpr) ir.Node {
// walkClose walks an OCLOSE node.
func walkClose(n *ir.UnaryExpr, init *ir.Nodes) ir.Node {
- // cannot use chanfn - closechan takes any, not chan any
- fn := typecheck.LookupRuntime("closechan", n.X.Type())
- return mkcall1(fn, nil, init, n.X)
+ return mkcall1(chanfn("closechan", 1, n.X.Type()), nil, init, n.X)
}
// Lower copy(a, b) to a memmove call or a runtime call.
@@ -263,6 +261,12 @@ func walkLenCap(n *ir.UnaryExpr, init *ir.Nodes) ir.Node {
_, len := backingArrayPtrLen(cheapExpr(conv.X, init))
return len
}
+ if isChanLen(n) {
+ // cannot use chanfn - closechan takes any, not chan any,
+ // because it accepts both send-only and recv-only channels.
+ fn := typecheck.LookupRuntime("chanlen", n.X.Type())
+ return mkcall1(fn, n.Type(), init, n.X)
+ }
n.X = walkExpr(n.X, init)
@@ -887,3 +891,10 @@ func isByteCount(n ir.Node) bool {
return base.Flag.N == 0 && !base.Flag.Cfg.Instrumenting && n.Op() == ir.OLEN &&
(n.(*ir.UnaryExpr).X.Op() == ir.OBYTES2STR || n.(*ir.UnaryExpr).X.Op() == ir.OBYTES2STRTMP)
}
+
+// isChanLen reports whether n is of the form len(c) for a channel c.
+// Note that this does not check for -n or instrumenting because this
+// is a correctness rewrite, not an optimization.
+func isChanLen(n ir.Node) bool {
+ return n.Op() == ir.OLEN && n.(*ir.UnaryExpr).X.Type().IsChan()
+}
diff --git a/src/runtime/chan.go b/src/runtime/chan.go
index ff9e2a9155..c48b85f576 100644
--- a/src/runtime/chan.go
+++ b/src/runtime/chan.go
@@ -724,20 +724,21 @@ func reflect_chanrecv(c *hchan, nb bool, elem unsafe.Pointer) (selected bool, re
return chanrecv(c, elem, !nb)
}
-//go:linkname reflect_chanlen reflect.chanlen
-func reflect_chanlen(c *hchan) int {
+func chanlen(c *hchan) int {
if c == nil {
return 0
}
return int(c.qcount)
}
+//go:linkname reflect_chanlen reflect.chanlen
+func reflect_chanlen(c *hchan) int {
+ return chanlen(c)
+}
+
//go:linkname reflectlite_chanlen internal/reflectlite.chanlen
func reflectlite_chanlen(c *hchan) int {
- if c == nil {
- return 0
- }
- return int(c.qcount)
+ return chanlen(c)
}
//go:linkname reflect_chancap reflect.chancap