aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa/check.go
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2016-03-09 19:27:57 -0800
committerKeith Randall <khr@golang.org>2016-03-10 22:33:49 +0000
commitddc6b64444c3914621b3b1ff019e02b5aabdc20c (patch)
treedd192ae64f4abcb0bcc694702f7f5e680578c67e /src/cmd/compile/internal/ssa/check.go
parent9c8f549abbc339fce83f96d80500ab9160a4c84d (diff)
downloadgo-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.go10
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))