diff options
author | Matthew Dempsky <mdempsky@google.com> | 2021-06-22 13:44:18 -0700 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2021-06-23 16:47:41 +0000 |
commit | 574ec1c6457c7779cd20db873fef2e2ed7e31ff1 (patch) | |
tree | 4e6ee46c1d7e1c27ae438c534441f3e5d442df10 /src/cmd/compile/internal/walk | |
parent | 9be8303df9e3aa5f4ea1879e82a3edbf54b78dbf (diff) | |
download | go-574ec1c6457c7779cd20db873fef2e2ed7e31ff1.tar.gz go-574ec1c6457c7779cd20db873fef2e2ed7e31ff1.zip |
[dev.typeparams] cmd/compile: desugar ORECOVER into ORECOVERFP
Currently ORECOVER is a single operation that both (1) calculates
the (logical) caller frame pointer and (2) calls runtime.gorecover.
This is normally fine, but it's inconvenient for regabi, which wants
to wrap "defer recover()" into "defer func() { recover() }" and
needs (1) and (2) to happen at different times.
The current solution is to apply walkRecover early to split it into
the two steps, but calling it during order is a minor layering
violation. It works well today because the order and walk phases are
closely related anyway and walkRecover is relatively simple, but it
won't work for go/defer wrapping earlier into the frontend.
This CL adds a new, lower-level ORECOVERFP primitive, which represents
just part (2); and OGETCALLER{PC,SP} primitives, which provide a way
to compute (1) in the frontend too.
OGETCALLERPC isn't needed/used today, but it seems worth including for
completeness. Maybe it will be useful at some point for intrinsifying
runtime.getcaller{pc,sp}, like we already do for runtime.getg.
Change-Id: Iaa8ae51e09306c45c147b6759a5b7c24dcc317ca
Reviewed-on: https://go-review.googlesource.com/c/go/+/330192
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Diffstat (limited to 'src/cmd/compile/internal/walk')
-rw-r--r-- | src/cmd/compile/internal/walk/builtin.go | 13 | ||||
-rw-r--r-- | src/cmd/compile/internal/walk/expr.go | 6 | ||||
-rw-r--r-- | src/cmd/compile/internal/walk/order.go | 13 | ||||
-rw-r--r-- | src/cmd/compile/internal/walk/stmt.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/walk/walk.go | 2 |
5 files changed, 11 insertions, 25 deletions
diff --git a/src/cmd/compile/internal/walk/builtin.go b/src/cmd/compile/internal/walk/builtin.go index be0f4c5208..135eaee6bc 100644 --- a/src/cmd/compile/internal/walk/builtin.go +++ b/src/cmd/compile/internal/walk/builtin.go @@ -641,16 +641,9 @@ func walkPrint(nn *ir.CallExpr, init *ir.Nodes) ir.Node { return walkStmt(typecheck.Stmt(r)) } -// walkRecover walks an ORECOVER node. -func walkRecover(nn *ir.CallExpr, init *ir.Nodes) ir.Node { - // Call gorecover with the FP of this frame. - // FP is equal to caller's SP plus FixedFrameSize(). - var fp ir.Node = mkcall("getcallersp", types.Types[types.TUINTPTR], init) - if off := base.Ctxt.FixedFrameSize(); off != 0 { - fp = ir.NewBinaryExpr(fp.Pos(), ir.OADD, fp, ir.NewInt(off)) - } - fp = ir.NewConvExpr(fp.Pos(), ir.OCONVNOP, types.NewPtr(types.Types[types.TINT32]), fp) - return mkcall("gorecover", nn.Type(), init, fp) +// walkRecover walks an ORECOVERFP node. +func walkRecoverFP(nn *ir.CallExpr, init *ir.Nodes) ir.Node { + return mkcall("gorecover", nn.Type(), init, walkExpr(nn.Args[0], init)) } func walkUnsafeSlice(n *ir.BinaryExpr, init *ir.Nodes) ir.Node { diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index 2fb907710b..070954be27 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -82,7 +82,7 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node { base.Fatalf("walkExpr: switch 1 unknown op %+v", n.Op()) panic("unreachable") - case ir.ONONAME, ir.OGETG: + case ir.OGETG, ir.OGETCALLERPC, ir.OGETCALLERSP: return n case ir.OTYPE, ir.ONAME, ir.OLITERAL, ir.ONIL, ir.OLINKSYMOFFSET: @@ -161,8 +161,8 @@ func walkExpr1(n ir.Node, init *ir.Nodes) ir.Node { n := n.(*ir.UnaryExpr) return mkcall("gopanic", nil, init, n.X) - case ir.ORECOVER: - return walkRecover(n.(*ir.CallExpr), init) + case ir.ORECOVERFP: + return walkRecoverFP(n.(*ir.CallExpr), init) case ir.OCFUNC: return n diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 75657cd3e4..ff8e95b330 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -777,10 +777,10 @@ func (o *orderState) stmt(n ir.Node) { o.out = append(o.out, n) o.cleanTemp(t) - case ir.OPRINT, ir.OPRINTN, ir.ORECOVER: + case ir.OPRINT, ir.OPRINTN, ir.ORECOVERFP: n := n.(*ir.CallExpr) t := o.markTemp() - o.exprList(n.Args) + o.call(n) o.out = append(o.out, n) o.cleanTemp(t) @@ -790,13 +790,6 @@ func (o *orderState) stmt(n ir.Node) { t := o.markTemp() o.init(n.Call) o.call(n.Call) - if n.Call.Op() == ir.ORECOVER { - // Special handling of "defer recover()". We need to evaluate the FP - // argument before wrapping. - var init ir.Nodes - n.Call = walkRecover(n.Call.(*ir.CallExpr), &init) - o.stmtList(init) - } o.wrapGoDefer(n) o.out = append(o.out, n) o.cleanTemp(t) @@ -1270,7 +1263,7 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node { ir.OMAKESLICECOPY, ir.ONEW, ir.OREAL, - ir.ORECOVER, + ir.ORECOVERFP, ir.OSTR2BYTES, ir.OSTR2BYTESTMP, ir.OSTR2RUNES: diff --git a/src/cmd/compile/internal/walk/stmt.go b/src/cmd/compile/internal/walk/stmt.go index 2352719da3..bcc0a3e517 100644 --- a/src/cmd/compile/internal/walk/stmt.go +++ b/src/cmd/compile/internal/walk/stmt.go @@ -49,7 +49,7 @@ func walkStmt(n ir.Node) ir.Node { ir.OPRINT, ir.OPRINTN, ir.OPANIC, - ir.ORECOVER, + ir.ORECOVERFP, ir.OGETG: if n.Typecheck() == 0 { base.Fatalf("missing typecheck: %+v", n) diff --git a/src/cmd/compile/internal/walk/walk.go b/src/cmd/compile/internal/walk/walk.go index 26da6e3145..6e992a91b8 100644 --- a/src/cmd/compile/internal/walk/walk.go +++ b/src/cmd/compile/internal/walk/walk.go @@ -343,7 +343,7 @@ func mayCall(n ir.Node) bool { ir.OCAP, ir.OIMAG, ir.OLEN, ir.OREAL, ir.OCONVNOP, ir.ODOT, ir.OCFUNC, ir.OIDATA, ir.OITAB, ir.OSPTR, - ir.OBYTES2STRTMP, ir.OGETG, ir.OSLICEHEADER: + ir.OBYTES2STRTMP, ir.OGETG, ir.OGETCALLERPC, ir.OGETCALLERSP, ir.OSLICEHEADER: // ok: operations that don't require function calls. // Expand as needed. } |