diff options
| author | khr@golang.org <khr@golang.org> | 2026-02-21 10:07:54 -0800 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2026-04-07 04:16:40 -0700 |
| commit | a415314c0bdec971ecd503471c804ec0208c6a2b (patch) | |
| tree | 26e8582c46e0ba71be16de9b4a5fe7d837a18cdf | |
| parent | e93b26688c0c25efa78b3948a58c5309307025a2 (diff) | |
| download | go-a415314c0bdec971ecd503471c804ec0208c6a2b.tar.xz | |
cmd/compile: ensure result selects are in the block of a call
Without this CL, when compiling test/range4.go:func9, we get:
b1:
v1 = StaticLECall <runtime.deferrangefunc>
mem = SelectN [1] v1
Defer v1 -> b2 b3
b2:
v2 = SelectN [0] v1
That select in b2 should really live in b1. This doesn't cause a bug
as far as I can tell, but it makes a check fail when when checkEnabled
is set in the compiler.
Change-Id: I8fe928fa8c376b81131ec712fc69d5fd39a1d4bb
Reviewed-on: https://go-review.googlesource.com/c/go/+/747740
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
| -rw-r--r-- | src/cmd/compile/internal/ssagen/ssa.go | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go index 6eb8b4f7d0..952bd1b71c 100644 --- a/src/cmd/compile/internal/ssagen/ssa.go +++ b/src/cmd/compile/internal/ssagen/ssa.go @@ -5162,6 +5162,19 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool, deferExt s.vars[memVar] = s.newValue1A(ssa.OpVarLive, types.TypeMem, v, s.mem()) } + // Build result value (before we might end the defer block, below). + var result *ssa.Value + if len(res) == 0 || k != callNormal { + result = nil + } else { + fp := res[0] + if returnResultAddr { + result = s.resultAddrOfCall(call, 0, fp.Type) + } else { + result = s.newValue1I(ssa.OpSelectN, fp.Type, 0, call) + } + } + // Finish block for defers if k == callDefer || k == callDeferStack || isCallDeferRangeFunc { b := s.endBlock() @@ -5181,15 +5194,7 @@ func (s *state) call(n *ir.CallExpr, k callKind, returnResultAddr bool, deferExt s.startBlock(bNext) } - if len(res) == 0 || k != callNormal { - // call has no return value. Continue with the next statement. - return nil - } - fp := res[0] - if returnResultAddr { - return s.resultAddrOfCall(call, 0, fp.Type) - } - return s.newValue1I(ssa.OpSelectN, fp.Type, 0, call) + return result } // maybeNilCheckClosure checks if a nil check of a closure is needed in some |
