diff options
author | Keith Randall <khr@golang.org> | 2016-03-09 19:27:57 -0800 |
---|---|---|
committer | Keith Randall <khr@golang.org> | 2016-03-10 22:33:49 +0000 |
commit | ddc6b64444c3914621b3b1ff019e02b5aabdc20c (patch) | |
tree | dd192ae64f4abcb0bcc694702f7f5e680578c67e /src/cmd/compile/internal/ssa/check.go | |
parent | 9c8f549abbc339fce83f96d80500ab9160a4c84d (diff) | |
download | go-ddc6b64444c3914621b3b1ff019e02b5aabdc20c.tar.gz go-ddc6b64444c3914621b3b1ff019e02b5aabdc20c.zip |
cmd/compile: fix defer/deferreturn
Make sure we do any just-before-return cleanup on all paths out of a
function, including when recovering. Each exit path should include
deferreturn (if there are any defers) and then the exit
code (e.g. copying heap-escaping return values back to the stack).
Introduce a Defer SSA block type which has two outgoing edges - one the
fallthrough edge (the defer was queued successfully) and one which
immediately returns (the defer had a successful recover() call and
normal execution should resume at the return point).
Fixes #14725
Change-Id: Iad035c9fd25ef8b7a74dafbd7461cf04833d981f
Reviewed-on: https://go-review.googlesource.com/20486
Reviewed-by: David Chase <drchase@google.com>
Diffstat (limited to 'src/cmd/compile/internal/ssa/check.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/check.go | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/check.go b/src/cmd/compile/internal/ssa/check.go index 7243cdc310..83aae3af33 100644 --- a/src/cmd/compile/internal/ssa/check.go +++ b/src/cmd/compile/internal/ssa/check.go @@ -125,6 +125,16 @@ func checkFunc(f *Func) { if !b.Control.Type.IsMemory() { f.Fatalf("call block %s has non-memory control value %s", b, b.Control.LongString()) } + case BlockDefer: + if len(b.Succs) != 2 { + f.Fatalf("defer block %s len(Succs)==%d, want 2", b, len(b.Succs)) + } + if b.Control == nil { + f.Fatalf("defer block %s has no control value", b) + } + if !b.Control.Type.IsMemory() { + f.Fatalf("defer block %s has non-memory control value %s", b, b.Control.LongString()) + } case BlockCheck: if len(b.Succs) != 1 { f.Fatalf("check block %s len(Succs)==%d, want 1", b, len(b.Succs)) |