compiler: make sure variables captured by defer closure live

Local variables captured by the deferred closure need to be live
until the function finishes, especially when the deferred
function runs. In Function::build, for function that has a defer,
we wrap the function body in a try block. So the backend sees
the local variables only live in the try block, without knowing
that they are needed also in the finally block where we invoke
the deferred function. Fix this by creating top-level
declarations for non-escaping address-taken locals when there
is a defer.

An example of miscompilation without this CL:

func F(fn func()) {
	didPanic := true
	defer func() {
		println(didPanic)
	}()
	fn()
	didPanic = false
}

With escape analysis turned on, at optimization level -O1 or -O2,
the store "didPanic = false" is elided by the backend's
optimizer, presumably because it thinks "didPanic" is not live
after the store, so the store is useless.

Change-Id: I6bcd49e6f5e2d1b1093aff301b9e95eaa0fac231
Reviewed-on: https://go-review.googlesource.com/86241
Reviewed-by: Ian Lance Taylor <iant@golang.org>
1 file changed