diff options
| author | Junyang Shao <shaojunyang@google.com> | 2026-03-12 20:56:24 +0000 |
|---|---|---|
| committer | Junyang Shao <shaojunyang@google.com> | 2026-03-13 09:03:37 -0700 |
| commit | 9ce4f3876e89a43dbd8508cb2762a2e4644dfe84 (patch) | |
| tree | f32bc2a886fd45d2062bd29138146092beebfb99 /src/cmd | |
| parent | b3ee07636a1fe4ba5129705fd4692b442cf6b6f0 (diff) | |
| download | go-9ce4f3876e89a43dbd8508cb2762a2e4644dfe84.tar.xz | |
cmd/compile: keep blank nodes alive in b.loop
The current bloop pass implementation skips blank nodes silently. This
CL makes it aware of that and keep them alive in temps.
Fixes #77654.
Change-Id: Iaffa5194ba1f0fe8d7c80a4c8e5c9a65a47bf534
Reviewed-on: https://go-review.googlesource.com/c/go/+/754920
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/cmd')
| -rw-r--r-- | src/cmd/compile/internal/bloop/bloop.go | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/src/cmd/compile/internal/bloop/bloop.go b/src/cmd/compile/internal/bloop/bloop.go index 8af29b7237..d5f001abf0 100644 --- a/src/cmd/compile/internal/bloop/bloop.go +++ b/src/cmd/compile/internal/bloop/bloop.go @@ -216,11 +216,49 @@ func preserveCallArgs(curFn *ir.Func, call *ir.CallExpr) ir.Node { func preserveStmt(curFn *ir.Func, stmt ir.Node) ir.Node { switch n := stmt.(type) { case *ir.AssignStmt: + // If the left hand side is blank, we need to assign it to a temp + // so that it can be kept alive. + if ir.IsBlank(n.X) { + tmp := typecheck.TempAt(n.Pos(), curFn, n.Y.Type()) + n.X = tmp + n.Def = true + n.PtrInit().Append(typecheck.Stmt(ir.NewDecl(n.Pos(), ir.ODCL, tmp))) + stmt = typecheck.AssignExpr(n) + n = stmt.(*ir.AssignStmt) + } return keepAliveAt(getKeepAliveNodes(n.Pos(), n.X), n) case *ir.AssignListStmt: var ns ir.Nodes - for _, lhs := range n.Lhs { - ns = append(ns, getKeepAliveNodes(n.Pos(), lhs)...) + hasBlank := false + for i, lhs := range n.Lhs { + if ir.IsBlank(lhs) { + // If the left hand side has blanks, we need to assign them to temps + // so that they can be kept alive. + var typ *types.Type + // AssignListStmt can have tuple or a list of expressions on the right hand side. + if len(n.Rhs) == 1 && n.Rhs[0].Type() != nil && + n.Rhs[0].Type().IsTuple() && + len(n.Lhs) == n.Rhs[0].Type().NumFields() { + typ = n.Rhs[0].Type().Field(i).Type + } else if len(n.Rhs) == len(n.Lhs) { + typ = n.Rhs[i].Type() + } else { + // Unrecognized shapes, skip? + base.WarnfAt(n.Pos(), "unrecognized shape for assign list stmt for blank assignment") + continue + } + tmp := typecheck.TempAt(n.Pos(), curFn, typ) + n.Lhs[i] = tmp + n.PtrInit().Append(typecheck.Stmt(ir.NewDecl(n.Pos(), ir.ODCL, tmp))) + hasBlank = true + } + ns = append(ns, getKeepAliveNodes(n.Pos(), n.Lhs[i])...) + } + if hasBlank { + // blank nodes are rewritten to temps, we need to typecheck the node again. + n.Def = true + stmt = typecheck.AssignExpr(n) + n = stmt.(*ir.AssignListStmt) } return keepAliveAt(ns, n) case *ir.AssignOpStmt: |
