go/ssa: export Defer.DeferStack field
Fixes golang/go#66601
Change-Id: I371541d470eb0d40abe9cf73f93d7718c700774d
Reviewed-on: https://go-review.googlesource.com/c/tools/+/590975
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/go/ssa/builder.go b/go/ssa/builder.go
index 8b7a814..7486681 100644
--- a/go/ssa/builder.go
+++ b/go/ssa/builder.go
@@ -2684,7 +2684,7 @@
// The "intrinsics" new/make/len/cap are forbidden here.
// panic is treated like an ordinary function call.
deferstack := emitLoad(fn, fn.lookup(fn.deferstack, false))
- v := Defer{pos: s.Defer, _DeferStack: deferstack}
+ v := Defer{pos: s.Defer, DeferStack: deferstack}
b.setCall(fn, s.Call, &v.Call)
fn.emit(&v)
diff --git a/go/ssa/interp/interp.go b/go/ssa/interp/interp.go
index acd0cca..3ba78fb 100644
--- a/go/ssa/interp/interp.go
+++ b/go/ssa/interp/interp.go
@@ -264,7 +264,7 @@
case *ssa.Defer:
fn, args := prepareCall(fr, &instr.Call)
defers := &fr.defers
- if into := fr.get(deferStack(instr)); into != nil {
+ if into := fr.get(instr.DeferStack); into != nil {
defers = into.(**deferred)
}
*defers = &deferred{
@@ -723,8 +723,3 @@
}
return
}
-
-// TODO(taking): Hack while proposal #66601 is being finalized.
-//
-//go:linkname deferStack golang.org/x/tools/go/ssa.deferStack
-func deferStack(i *ssa.Defer) ssa.Value
diff --git a/go/ssa/lift.go b/go/ssa/lift.go
index 49e148d..aada3dc 100644
--- a/go/ssa/lift.go
+++ b/go/ssa/lift.go
@@ -176,8 +176,12 @@
// While we're here, we also eliminate 'rundefers'
// instructions and ssa:deferstack() in functions that contain no
- // 'defer' instructions. Eliminate ssa:deferstack() if it does not
- // escape.
+ // 'defer' instructions. For now, we also eliminate
+ // 's = ssa:deferstack()' calls if s doesn't escape, replacing s
+ // with nil in Defer{DeferStack: s}. This has the same meaning,
+ // but allows eliminating the intrinsic function `ssa:deferstack()`
+ // (unless it is needed due to range-over-func instances). This gives
+ // ssa users more time to support range-over-func.
usesDefer := false
deferstackAlloc, deferstackCall := deferstackPreamble(fn)
eliminateDeferStack := deferstackAlloc != nil && !deferstackAlloc.Heap
@@ -205,12 +209,12 @@
case *Defer:
usesDefer = true
if eliminateDeferStack {
- // Clear _DeferStack and remove references to loads
- if instr._DeferStack != nil {
- if refs := instr._DeferStack.Referrers(); refs != nil {
+ // Clear DeferStack and remove references to loads
+ if instr.DeferStack != nil {
+ if refs := instr.DeferStack.Referrers(); refs != nil {
*refs = removeInstr(*refs, instr)
}
- instr._DeferStack = nil
+ instr.DeferStack = nil
}
}
case *RunDefers:
diff --git a/go/ssa/print.go b/go/ssa/print.go
index 40c0686..c890d7e 100644
--- a/go/ssa/print.go
+++ b/go/ssa/print.go
@@ -356,8 +356,8 @@
func (s *Defer) String() string {
prefix := "defer "
- if s._DeferStack != nil {
- prefix += "[" + relName(s._DeferStack, s) + "] "
+ if s.DeferStack != nil {
+ prefix += "[" + relName(s.DeferStack, s) + "] "
}
c := printCall(&s.Call, prefix, s)
return c
diff --git a/go/ssa/ssa.go b/go/ssa/ssa.go
index 59474a9..2c44fe4 100644
--- a/go/ssa/ssa.go
+++ b/go/ssa/ssa.go
@@ -1255,10 +1255,10 @@
// The Defer instruction pushes the specified call onto a stack of
// functions to be called by a RunDefers instruction or by a panic.
//
-// If _DeferStack != nil, it indicates the defer list that the defer is
+// If DeferStack != nil, it indicates the defer list that the defer is
// added to. Defer list values come from the Builtin function
// ssa:deferstack. Calls to ssa:deferstack() produces the defer stack
-// of the current function frame. _DeferStack allows for deferring into an
+// of the current function frame. DeferStack allows for deferring into an
// alternative function stack than the current function.
//
// See CallCommon for generic function call documentation.
@@ -1272,11 +1272,9 @@
// defer invoke t5.Println(...t6)
type Defer struct {
anInstruction
- Call CallCommon
- _DeferStack Value // stack (from ssa:deferstack() intrinsic) onto which this function is pushed
- pos token.Pos
-
- // TODO: Exporting _DeferStack and possibly making _DeferStack != nil awaits proposal https://github.com/golang/go/issues/66601.
+ Call CallCommon
+ DeferStack Value // stack of deferred functions (from ssa:deferstack() intrinsic) onto which this function is pushed
+ pos token.Pos
}
// The Send instruction sends X on channel Chan.
@@ -1718,7 +1716,7 @@
}
func (s *Defer) Operands(rands []*Value) []*Value {
- return append(s.Call.Operands(rands), &s._DeferStack)
+ return append(s.Call.Operands(rands), &s.DeferStack)
}
func (v *ChangeInterface) Operands(rands []*Value) []*Value {
@@ -1869,7 +1867,3 @@
func (v *Function) Operands(rands []*Value) []*Value { return rands }
func (v *Global) Operands(rands []*Value) []*Value { return rands }
func (v *Parameter) Operands(rands []*Value) []*Value { return rands }
-
-// Exposed to interp using the linkname hack
-// TODO(taking): Remove some form of https://go.dev/issue/66601 is accepted.
-func deferStack(i *Defer) Value { return i._DeferStack }