From 5a5ab24689b63b3c156a17103265c439c1e86df7 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Wed, 6 Jan 2021 10:47:35 +0700 Subject: [PATCH] [dev.regabi] cmd/compile: do not rely on CallExpr.Rargs for detect already walked calls Currently, there's an awkward issue with walk pass. When walking the AST tree, the compiler generate code for runtime functions (using mkcall* variants), add/modify the AST tree and walk new generated tree again. This causes the double walking on some CallExpr, which is relying on checking Rargs to prevent that. But checking Rargs has its own issue as well. For functions that does not have arguments, this check is failed, and we still double walk the CallExpr node. This CL change the way that compiler detects double walking, by using separated field instead of relying on Rargs. In perfect world, we should make the compiler walks the AST tree just once, but it's not safe to do that at this moment. Passes toolstash -cmp. Change-Id: Ifdd1e0f98940ddb1f574af2da2ac7f005b5fcadd Reviewed-on: https://go-review.googlesource.com/c/go/+/283672 Trust: Cuong Manh Le Run-TryBot: Cuong Manh Le TryBot-Result: Go Bot Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/ir/mini.go | 4 ++++ src/cmd/compile/internal/walk/expr.go | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/internal/ir/mini.go b/src/cmd/compile/internal/ir/mini.go index 4dd9a8807aa..429f4ed360b 100644 --- a/src/cmd/compile/internal/ir/mini.go +++ b/src/cmd/compile/internal/ir/mini.go @@ -58,6 +58,7 @@ const ( miniTypecheckShift = 2 miniDiag = 1 << 4 miniHasCall = 1 << 5 // for miniStmt + miniWalked = 1 << 6 // to prevent/catch re-walking ) func (n *miniNode) Typecheck() uint8 { return n.bits.get2(miniTypecheckShift) } @@ -71,6 +72,9 @@ func (n *miniNode) SetTypecheck(x uint8) { func (n *miniNode) Diag() bool { return n.bits&miniDiag != 0 } func (n *miniNode) SetDiag(x bool) { n.bits.set(miniDiag, x) } +func (n *miniNode) Walked() bool { return n.bits&miniWalked != 0 } +func (n *miniNode) SetWalked(x bool) { n.bits.set(miniWalked, x) } + // Empty, immutable graph structure. func (n *miniNode) Init() Nodes { return Nodes{} } diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index 893a95f4031..449f8ea3ec0 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -497,9 +497,10 @@ func walkCall(n *ir.CallExpr, init *ir.Nodes) ir.Node { } func walkCall1(n *ir.CallExpr, init *ir.Nodes) { - if len(n.Rargs) != 0 { + if n.Walked() { return // already walked } + n.SetWalked(true) // If this is a method call t.M(...), // rewrite into a function call T.M(t, ...).