aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkhr@golang.org <khr@golang.org>2026-02-21 10:07:54 -0800
committerGopher Robot <gobot@golang.org>2026-04-07 04:16:40 -0700
commita415314c0bdec971ecd503471c804ec0208c6a2b (patch)
tree26e8582c46e0ba71be16de9b4a5fe7d837a18cdf
parente93b26688c0c25efa78b3948a58c5309307025a2 (diff)
downloadgo-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.go23
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