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 }