From 64bc656aed3ba7539a85f6b52f2aa933c9ce8130 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 30 Nov 2020 23:49:25 -0500 Subject: [PATCH] [dev.regabi] cmd/compile: use explicit block statements for init For statements like goto that don't need an init, use an explicit block statement instead of forcing them to have one. There is also one call to addinit that is being replaced with a block. That call is the source of much of my confusion regarding init statements: walkstmt calls addinit on a statement, whereas all the other uses of addinit are on expressions. After this CL, they're all expressions. Passes buildall w/ toolstash -cmp. Change-Id: Ifdef9d318c236dc1a7567f9e9ef4a6bedd3fe81f Reviewed-on: https://go-review.googlesource.com/c/go/+/274597 Trust: Russ Cox Run-TryBot: Russ Cox TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/gc/inl.go | 21 +++++++---------- src/cmd/compile/internal/gc/walk.go | 36 ++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 24 deletions(-) diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 89c9873c1d..fd8e9cfd46 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -527,8 +527,8 @@ func inlcalls(fn *ir.Func) { // Turn an OINLCALL into a statement. func inlconv2stmt(inlcall ir.Node) ir.Node { n := ir.NodAt(inlcall.Pos(), ir.OBLOCK, nil, nil) - n.SetList(inlcall.Body()) - n.SetInit(inlcall.Init()) + n.SetList(inlcall.Init()) + n.PtrList().AppendNodes(inlcall.PtrBody()) return n } @@ -543,7 +543,7 @@ func inlconv2expr(n ir.Node) ir.Node { // Turn the rlist (with the return values) of the OINLCALL in // n into an expression list lumping the ninit and body // containing the inlined statements on the first list element so -// order will be preserved Used in return, oas2func and call +// order will be preserved. Used in return, oas2func and call // statements. func inlconv2list(n ir.Node) []ir.Node { if n.Op() != ir.OINLCALL || n.Rlist().Len() == 0 { @@ -1330,9 +1330,7 @@ func (subst *inlsubst) node(n ir.Node) ir.Node { // dump("Return before substitution", n); case ir.ORETURN: - m := nodSym(ir.OGOTO, nil, subst.retlabel) - m.PtrInit().Set(subst.list(n.Init())) - + init := subst.list(n.Init()) if len(subst.retvars) != 0 && n.List().Len() != 0 { as := ir.Nod(ir.OAS2, nil, nil) @@ -1352,14 +1350,11 @@ func (subst *inlsubst) node(n ir.Node) ir.Node { } as = typecheck(as, ctxStmt) - m.PtrInit().Append(as) + init = append(init, as) } - - typecheckslice(m.Init().Slice(), ctxStmt) - m = typecheck(m, ctxStmt) - - // dump("Return after substitution", m); - return m + init = append(init, nodSym(ir.OGOTO, nil, subst.retlabel)) + typecheckslice(init, ctxStmt) + return ir.NewBlockStmt(base.Pos, init) case ir.OGOTO, ir.OLABEL: m := ir.Copy(n) diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go index 7e8ae22e4e..f439237936 100644 --- a/src/cmd/compile/internal/gc/walk.go +++ b/src/cmd/compile/internal/gc/walk.go @@ -147,16 +147,25 @@ func walkstmt(n ir.Node) ir.Node { if n.Typecheck() == 0 { base.Fatalf("missing typecheck: %+v", n) } - wascopy := n.Op() == ir.OCOPY init := n.Init() n.PtrInit().Set(nil) n = walkexpr(n, &init) - if wascopy && n.Op() == ir.ONAME { + if n.Op() == ir.ONAME { // copy rewrote to a statement list and a temp for the length. // Throw away the temp to avoid plain values as statements. - n = ir.NodAt(n.Pos(), ir.OBLOCK, nil, nil) + n = ir.NewBlockStmt(n.Pos(), init.Slice()) + init.Set(nil) + } + if init.Len() > 0 { + switch n.Op() { + case ir.OAS, ir.OAS2, ir.OBLOCK: + n.PtrInit().Prepend(init.Slice()...) + + default: + init.Append(n) + n = ir.NewBlockStmt(n.Pos(), init.Slice()) + } } - n = addinit(n, init.Slice()) // special case for a receive where we throw away // the value received. @@ -223,29 +232,34 @@ func walkstmt(n ir.Node) ir.Node { } fallthrough case ir.OGO: + var init ir.Nodes switch n.Left().Op() { case ir.OPRINT, ir.OPRINTN: - n.SetLeft(wrapCall(n.Left(), n.PtrInit())) + n.SetLeft(wrapCall(n.Left(), &init)) case ir.ODELETE: if mapfast(n.Left().List().First().Type()) == mapslow { - n.SetLeft(wrapCall(n.Left(), n.PtrInit())) + n.SetLeft(wrapCall(n.Left(), &init)) } else { - n.SetLeft(walkexpr(n.Left(), n.PtrInit())) + n.SetLeft(walkexpr(n.Left(), &init)) } case ir.OCOPY: - n.SetLeft(copyany(n.Left(), n.PtrInit(), true)) + n.SetLeft(copyany(n.Left(), &init, true)) case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER: if n.Left().Body().Len() > 0 { - n.SetLeft(wrapCall(n.Left(), n.PtrInit())) + n.SetLeft(wrapCall(n.Left(), &init)) } else { - n.SetLeft(walkexpr(n.Left(), n.PtrInit())) + n.SetLeft(walkexpr(n.Left(), &init)) } default: - n.SetLeft(walkexpr(n.Left(), n.PtrInit())) + n.SetLeft(walkexpr(n.Left(), &init)) + } + if init.Len() > 0 { + init.Append(n) + n = ir.NewBlockStmt(n.Pos(), init.Slice()) } case ir.OFOR, ir.OFORUNTIL: -- 2.48.1