aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorJunyang Shao <shaojunyang@google.com>2026-03-12 20:56:24 +0000
committerJunyang Shao <shaojunyang@google.com>2026-03-13 09:03:37 -0700
commit9ce4f3876e89a43dbd8508cb2762a2e4644dfe84 (patch)
treef32bc2a886fd45d2062bd29138146092beebfb99 /src/cmd
parentb3ee07636a1fe4ba5129705fd4692b442cf6b6f0 (diff)
downloadgo-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.go42
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: