aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder
diff options
context:
space:
mode:
authorDavid Chase <drchase@google.com>2024-01-26 17:49:33 -0500
committerDavid Chase <drchase@google.com>2024-05-21 21:08:03 +0000
commit5a9dabc2ba873f89a5de9ff53c8eab7c96d0c6b5 (patch)
tree0012a70f6ab947152eb5702dc102c4bd6275252c /src/cmd/compile/internal/noder
parent643865856c535a5a644201c602b18bd87b121c93 (diff)
downloadgo-5a9dabc2ba873f89a5de9ff53c8eab7c96d0c6b5.tar.xz
cmd/compile: for rangefunc, add checks and tests, fix panic interactions
Modify rangefunc #next protocol to make it more robust Extra-terrible nests of rangefunc iterators caused the prior implementation to misbehave non-locally (in outer loops). Add more rangefunc exit flag tests, parallel and tricky This tests the assertion that a rangefunc iterator running in parallel can trigger the race detector if any of the parallel goroutines attempts an early exit. It also verifies that if everything else is carefully written, that it does NOT trigger the race detector if all the parts run time completion. Another test tries to rerun a yield function within a loop, so that any per-line shared checking would be fooled. Added all the use-of-body/yield-function checking. These checks handle pathological cases that would cause rangefunc for loops to behave in surprising ways (compared to "regular" for loops). For example, a rangefunc iterator might defer-recover a panic thrown in the syntactic body of a loop; this notices the fault and panics with an explanation Modified closure naming to ID rangefunc bodies Add a "-range<N>" suffix to the name of any closure generated for a rangefunc loop body, as provided in Alessandro Arzilli's CL (which is merged into this one). Fix return values for panicky range functions This removes the delayed implementation of "return x" by ensuring that return values (in rangefunc-return-containing functions) always have names and translating the "return x" into "#rv1 = x" where #rv1 is the synthesized name of the first result. Updates #61405. Change-Id: I933299ecce04ceabcf1c0c2de8e610b2ecd1cfd8 Reviewed-on: https://go-review.googlesource.com/c/go/+/584596 Reviewed-by: Matthew Dempsky <mdempsky@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Tim King <taking@google.com>
Diffstat (limited to 'src/cmd/compile/internal/noder')
-rw-r--r--src/cmd/compile/internal/noder/irgen.go7
-rw-r--r--src/cmd/compile/internal/noder/reader.go12
-rw-r--r--src/cmd/compile/internal/noder/unified.go4
-rw-r--r--src/cmd/compile/internal/noder/writer.go17
4 files changed, 24 insertions, 16 deletions
diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go
index 4d51c6b446..a95fa03e17 100644
--- a/src/cmd/compile/internal/noder/irgen.go
+++ b/src/cmd/compile/internal/noder/irgen.go
@@ -22,7 +22,8 @@ var versionErrorRx = regexp.MustCompile(`requires go[0-9]+\.[0-9]+ or later`)
// checkFiles configures and runs the types2 checker on the given
// parsed source files and then returns the result.
-func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
+// The map result value indicates which closures are generated from the bodies of range function loops.
+func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info, map[*syntax.FuncLit]bool) {
if base.SyntaxErrors() != 0 {
base.ErrorExit()
}
@@ -150,9 +151,9 @@ func checkFiles(m posMap, noders []*noder) (*types2.Package, *types2.Info) {
// If we do the rewrite in the back end, like between typecheck and walk,
// then the new implicit closure will not have a unified IR inline body,
// and bodyReaderFor will fail.
- rangefunc.Rewrite(pkg, info, files)
+ rangeInfo := rangefunc.Rewrite(pkg, info, files)
- return pkg, info
+ return pkg, info, rangeInfo
}
// A cycleFinder detects anonymous interface cycles (go.dev/issue/56103).
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go
index a7feadaf6e..042d81bbcd 100644
--- a/src/cmd/compile/internal/noder/reader.go
+++ b/src/cmd/compile/internal/noder/reader.go
@@ -2704,7 +2704,7 @@ func (r *reader) syntheticClosure(origPos src.XPos, typ *types.Type, ifaceHack b
return false
}
- fn := r.inlClosureFunc(origPos, typ)
+ fn := r.inlClosureFunc(origPos, typ, ir.OCLOSURE)
fn.SetWrapper(true)
clo := fn.OClosure
@@ -3035,8 +3035,12 @@ func (r *reader) funcLit() ir.Node {
origPos := r.pos()
sig := r.signature(nil)
r.suppressInlPos--
+ why := ir.OCLOSURE
+ if r.Bool() {
+ why = ir.ORANGE
+ }
- fn := r.inlClosureFunc(origPos, sig)
+ fn := r.inlClosureFunc(origPos, sig, why)
fn.ClosureVars = make([]*ir.Name, 0, r.Len())
for len(fn.ClosureVars) < cap(fn.ClosureVars) {
@@ -3062,14 +3066,14 @@ func (r *reader) funcLit() ir.Node {
// inlClosureFunc constructs a new closure function, but correctly
// handles inlining.
-func (r *reader) inlClosureFunc(origPos src.XPos, sig *types.Type) *ir.Func {
+func (r *reader) inlClosureFunc(origPos src.XPos, sig *types.Type, why ir.Op) *ir.Func {
curfn := r.inlCaller
if curfn == nil {
curfn = r.curfn
}
// TODO(mdempsky): Remove hard-coding of typecheck.Target.
- return ir.NewClosureFunc(origPos, r.inlPos(origPos), ir.OCLOSURE, sig, curfn, typecheck.Target)
+ return ir.NewClosureFunc(origPos, r.inlPos(origPos), why, sig, curfn, typecheck.Target)
}
func (r *reader) exprList() []ir.Node {
diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go
index 2391b2f34d..a1a90cd6b5 100644
--- a/src/cmd/compile/internal/noder/unified.go
+++ b/src/cmd/compile/internal/noder/unified.go
@@ -304,9 +304,9 @@ func readBodies(target *ir.Package, duringInlining bool) {
// writes an export data package stub representing them,
// and returns the result.
func writePkgStub(m posMap, noders []*noder) string {
- pkg, info := checkFiles(m, noders)
+ pkg, info, otherInfo := checkFiles(m, noders)
- pw := newPkgWriter(m, pkg, info)
+ pw := newPkgWriter(m, pkg, info, otherInfo)
pw.collectDecls(noders)
diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go
index 13706f9dd2..9b33fb7c6d 100644
--- a/src/cmd/compile/internal/noder/writer.go
+++ b/src/cmd/compile/internal/noder/writer.go
@@ -63,9 +63,10 @@ import (
type pkgWriter struct {
pkgbits.PkgEncoder
- m posMap
- curpkg *types2.Package
- info *types2.Info
+ m posMap
+ curpkg *types2.Package
+ info *types2.Info
+ rangeFuncBodyClosures map[*syntax.FuncLit]bool // non-public information, e.g., which functions are closures range function bodies?
// Indices for previously written syntax and types2 things.
@@ -90,13 +91,14 @@ type pkgWriter struct {
// newPkgWriter returns an initialized pkgWriter for the specified
// package.
-func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info) *pkgWriter {
+func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info, otherInfo map[*syntax.FuncLit]bool) *pkgWriter {
return &pkgWriter{
PkgEncoder: pkgbits.NewPkgEncoder(base.Debug.SyncFrames),
- m: m,
- curpkg: pkg,
- info: info,
+ m: m,
+ curpkg: pkg,
+ info: info,
+ rangeFuncBodyClosures: otherInfo,
pkgsIdx: make(map[*types2.Package]pkgbits.Index),
objsIdx: make(map[types2.Object]pkgbits.Index),
@@ -2336,6 +2338,7 @@ func (w *writer) funcLit(expr *syntax.FuncLit) {
w.Sync(pkgbits.SyncFuncLit)
w.pos(expr)
w.signature(sig)
+ w.Bool(w.p.rangeFuncBodyClosures[expr])
w.Len(len(closureVars))
for _, cv := range closureVars {