cmd/5g, cmd/6g, cmd/8g: flush return parameters in case of panic.

Fixes #4066.

R=rsc, minux.ma
CC=golang-dev
https://golang.org/cl/7040044
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c
index 5f7ed2e..584ffc2 100644
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -1075,8 +1075,12 @@
 		default:
 			// Work around for issue 1304:
 			// flush modified globals before each instruction.
-			for(z=0; z<BITS; z++)
+			for(z=0; z<BITS; z++) {
 				cal.b[z] |= externs.b[z];
+				// issue 4066: flush modified return variables in case of panic
+				if(hasdefer)
+					cal.b[z] |= ovar.b[z];
+			}
 			break;
 		}
 		for(z=0; z<BITS; z++) {
diff --git a/src/cmd/6g/reg.c b/src/cmd/6g/reg.c
index 8d15bf9..9c9b74d 100644
--- a/src/cmd/6g/reg.c
+++ b/src/cmd/6g/reg.c
@@ -1121,8 +1121,12 @@
 		default:
 			// Work around for issue 1304:
 			// flush modified globals before each instruction.
-			for(z=0; z<BITS; z++)
+			for(z=0; z<BITS; z++) {
 				cal.b[z] |= externs.b[z];
+				// issue 4066: flush modified return variables in case of panic
+				if(hasdefer)
+					cal.b[z] |= ovar.b[z];
+			}
 			break;
 		}
 		for(z=0; z<BITS; z++) {
diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c
index 80230bc..7b8b39e 100644
--- a/src/cmd/8g/reg.c
+++ b/src/cmd/8g/reg.c
@@ -1048,8 +1048,12 @@
 		default:
 			// Work around for issue 1304:
 			// flush modified globals before each instruction.
-			for(z=0; z<BITS; z++)
+			for(z=0; z<BITS; z++) {
 				cal.b[z] |= externs.b[z];
+				// issue 4066: flush modified return variables in case of panic
+				if(hasdefer)
+					cal.b[z] |= ovar.b[z];
+			}
 			break;
 		}
 		for(z=0; z<BITS; z++) {
diff --git a/test/fixedbugs/issue4066.go b/test/fixedbugs/issue4066.go
new file mode 100644
index 0000000..19cfe66
--- /dev/null
+++ b/test/fixedbugs/issue4066.go
@@ -0,0 +1,37 @@
+// run
+
+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 4066: return values not being spilled eagerly enough
+
+package main
+
+func main() {
+	n := foo()
+	if n != 2 {
+		println(n)
+		panic("wrong return value")
+	}
+}
+
+type terr struct{}
+
+func foo() (val int) {
+	val = 0
+	defer func() {
+		if x := recover(); x != nil {
+			_ = x.(terr)
+		}
+	}()
+	for {
+		val = 2
+		foo1()
+	}
+	panic("unreachable")
+}
+
+func foo1() {
+	panic(terr{})
+}