aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/walk
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-06-22 20:33:00 -0700
committerMatthew Dempsky <mdempsky@google.com>2021-06-23 04:46:36 +0000
commite59a19ccebe87b84e69625d0b83df6d0fe2499db (patch)
treed6a722723db2fbb63172c977d34722c2933204dd /src/cmd/compile/internal/walk
parent493e177639140d83807ae72b6ea840ce025416ce (diff)
downloadgo-e59a19ccebe87b84e69625d0b83df6d0fe2499db.tar.gz
go-e59a19ccebe87b84e69625d0b83df6d0fe2499db.zip
[dev.typeparams] cmd/compile: simplify walkGoDefer
order already takes care of wrapping all go/defer function calls, so there's no need for walk to duplicate that logic: it's never going to be used. Change-Id: I54e545404e52ab8f9d60151d1bd2aff4b9bd8b72 Reviewed-on: https://go-review.googlesource.com/c/go/+/330270 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com> Trust: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/walk')
-rw-r--r--src/cmd/compile/internal/walk/stmt.go128
1 files changed, 16 insertions, 112 deletions
diff --git a/src/cmd/compile/internal/walk/stmt.go b/src/cmd/compile/internal/walk/stmt.go
index 0bf76680c4..e1ac652364 100644
--- a/src/cmd/compile/internal/walk/stmt.go
+++ b/src/cmd/compile/internal/walk/stmt.go
@@ -7,7 +7,6 @@ package walk
import (
"cmd/compile/internal/base"
"cmd/compile/internal/ir"
- "cmd/compile/internal/typecheck"
)
// The result of walkStmt MUST be assigned back to n, e.g.
@@ -187,33 +186,26 @@ func walkFor(n *ir.ForStmt) ir.Node {
return n
}
+// validGoDeferCall reports whether call is a valid call to appear in
+// a go or defer statement; that is, whether it's a regular function
+// call without arguments or results.
+func validGoDeferCall(call ir.Node) bool {
+ if call, ok := call.(*ir.CallExpr); ok && call.Op() == ir.OCALLFUNC && len(call.KeepAlive) == 0 {
+ sig := call.X.Type()
+ return sig.NumParams()+sig.NumResults() == 0
+ }
+ return false
+}
+
// walkGoDefer walks an OGO or ODEFER node.
func walkGoDefer(n *ir.GoDeferStmt) ir.Node {
- var init ir.Nodes
- switch call := n.Call; call.Op() {
- case ir.OPRINT, ir.OPRINTN:
- call := call.(*ir.CallExpr)
- n.Call = wrapCall(call, &init)
-
- case ir.ODELETE:
- call := call.(*ir.CallExpr)
- n.Call = wrapCall(call, &init)
-
- case ir.OCOPY:
- call := call.(*ir.BinaryExpr)
- n.Call = walkCopy(call, &init, true)
+ if !validGoDeferCall(n.Call) {
+ base.FatalfAt(n.Pos(), "invalid %v call: %v", n.Op(), n.Call)
+ }
- case ir.OCALLFUNC, ir.OCALLMETH, ir.OCALLINTER:
- call := call.(*ir.CallExpr)
- if len(call.KeepAlive) > 0 {
- n.Call = wrapCall(call, &init)
- } else {
- n.Call = walkExpr(call, &init)
- }
+ var init ir.Nodes
+ n.Call = walkExpr(n.Call, &init)
- default:
- n.Call = walkExpr(call, &init)
- }
if len(init) > 0 {
init.Append(n)
return ir.NewBlockStmt(n.Pos(), init)
@@ -229,94 +221,6 @@ func walkIf(n *ir.IfStmt) ir.Node {
return n
}
-// Rewrite
-// go builtin(x, y, z)
-// into
-// go func(a1, a2, a3) {
-// builtin(a1, a2, a3)
-// }(x, y, z)
-// for print, println, and delete.
-//
-// Rewrite
-// go f(x, y, uintptr(unsafe.Pointer(z)))
-// into
-// go func(a1, a2, a3) {
-// f(a1, a2, uintptr(a3))
-// }(x, y, unsafe.Pointer(z))
-// for function contains unsafe-uintptr arguments.
-
-var wrapCall_prgen int
-
-// The result of wrapCall MUST be assigned back to n, e.g.
-// n.Left = wrapCall(n.Left, init)
-func wrapCall(n *ir.CallExpr, init *ir.Nodes) ir.Node {
- if len(n.Init()) != 0 {
- walkStmtList(n.Init())
- init.Append(ir.TakeInit(n)...)
- }
-
- isBuiltinCall := n.Op() != ir.OCALLFUNC && n.Op() != ir.OCALLMETH && n.Op() != ir.OCALLINTER
-
- // Turn f(a, b, []T{c, d, e}...) back into f(a, b, c, d, e).
- if !isBuiltinCall && n.IsDDD {
- undoVariadic(n)
- }
-
- wrapArgs := n.Args
- // If there's a receiver argument, it needs to be passed through the wrapper too.
- if n.Op() == ir.OCALLMETH || n.Op() == ir.OCALLINTER {
- recv := n.X.(*ir.SelectorExpr).X
- wrapArgs = append([]ir.Node{recv}, wrapArgs...)
- }
-
- // origArgs keeps track of what argument is uintptr-unsafe/unsafe-uintptr conversion.
- origArgs := make([]ir.Node, len(wrapArgs))
- var funcArgs []*ir.Field
- for i, arg := range wrapArgs {
- s := typecheck.LookupNum("a", i)
- if !isBuiltinCall && arg.Op() == ir.OCONVNOP && arg.Type().IsUintptr() && arg.(*ir.ConvExpr).X.Type().IsUnsafePtr() {
- origArgs[i] = arg
- arg = arg.(*ir.ConvExpr).X
- wrapArgs[i] = arg
- }
- funcArgs = append(funcArgs, ir.NewField(base.Pos, s, nil, arg.Type()))
- }
- t := ir.NewFuncType(base.Pos, nil, funcArgs, nil)
-
- wrapCall_prgen++
- sym := typecheck.LookupNum("wrap·", wrapCall_prgen)
- fn := typecheck.DeclFunc(sym, t)
-
- args := ir.ParamNames(t.Type())
- for i, origArg := range origArgs {
- if origArg == nil {
- continue
- }
- args[i] = ir.NewConvExpr(base.Pos, origArg.Op(), origArg.Type(), args[i])
- }
- if n.Op() == ir.OCALLMETH || n.Op() == ir.OCALLINTER {
- // Move wrapped receiver argument back to its appropriate place.
- recv := typecheck.Expr(args[0])
- n.X.(*ir.SelectorExpr).X = recv
- args = args[1:]
- }
- call := ir.NewCallExpr(base.Pos, n.Op(), n.X, args)
- if !isBuiltinCall {
- call.SetOp(ir.OCALL)
- call.IsDDD = n.IsDDD
- }
- fn.Body = []ir.Node{call}
-
- typecheck.FinishFuncBody()
-
- typecheck.Func(fn)
- typecheck.Stmts(fn.Body)
- typecheck.Target.Decls = append(typecheck.Target.Decls, fn)
-
- call = ir.NewCallExpr(base.Pos, ir.OCALL, fn.Nname, wrapArgs)
- return walkExpr(typecheck.Stmt(call), init)
-}
-
// undoVariadic turns a call to a variadic function of the form
//
// f(a, b, []T{c, d, e}...)