go.tools/go/ssa: emit a recover block if the function's results are unnamed

It is easier for clients to recover from panics if the recover block
is always present. Otherwise, the client has to work around the lack
of a recover block by synthesizing a zero value return.

LGTM=adonovan
R=adonovan
CC=golang-codereviews
https://golang.org/cl/87210044
This commit is contained in:
Peter Collingbourne 2014-06-13 13:08:35 -04:00 committed by Alan Donovan
parent f0ff511183
commit ce1e99a260
3 changed files with 6 additions and 14 deletions

View File

@ -1895,14 +1895,9 @@ start:
b.setCall(fn, s.Call, &v.Call) b.setCall(fn, s.Call, &v.Call)
fn.emit(&v) fn.emit(&v)
// A deferred call can cause recovery from panic. // A deferred call can cause recovery from panic,
// If the panicking function has named results, // and control resumes at the Recover block.
// control resumes at the Recover block to load those
// locals (which may be mutated by the deferred call)
// and return them.
if fn.namedResults != nil {
createRecoverBlock(fn) createRecoverBlock(fn)
}
case *ast.ReturnStmt: case *ast.ReturnStmt:
var results []Value var results []Value

View File

@ -555,9 +555,6 @@ func runFrame(fr *frame) {
} }
fr.runDefers() fr.runDefers()
fr.block = fr.fn.Recover fr.block = fr.fn.Recover
if fr.block == nil {
fr.result = zero(fr.fn.Signature.Results())
}
}() }()
for { for {

View File

@ -273,9 +273,9 @@ type Node interface {
// To iterate over the blocks in dominance order, use DomPreorder(). // To iterate over the blocks in dominance order, use DomPreorder().
// //
// Recover is an optional second entry point to which control resumes // Recover is an optional second entry point to which control resumes
// after a recovered panic. The Recover block may contain only a load // after a recovered panic. The Recover block may contain only a return
// of the function's named return parameters followed by a return of // statement, preceded by a load of the function's named return
// the loaded values. // parameters, if any.
// //
// A nested function (Parent()!=nil) that refers to one or more // A nested function (Parent()!=nil) that refers to one or more
// lexically enclosing local variables ("free variables") has FreeVar // lexically enclosing local variables ("free variables") has FreeVar