void callGoStackCheck(void);
 void callPanic(void);
 void callCgoAllocate(void);
+int callGoReturnVal(void);
+int returnAfterGrow(void);
+int returnAfterGrowFromGo(void);
 */
 import "C"
 
        C.callCgoAllocate() // crashes or exits on failure
 }
 
+// Test that C code can return a value if it calls a Go function that
+// causes a stack copy.
+func testReturnAfterGrow(t *testing.T) {
+       // Use a new goroutine so that we get a small stack.
+       c := make(chan int)
+       go func() {
+               c <- int(C.returnAfterGrow())
+       }()
+       if got, want := <-c, 123456; got != want {
+               t.Errorf("got %d want %d", got, want)
+       }
+}
+
+// Test that we can return a value from Go->C->Go if the Go code
+// causes a stack copy.
+func testReturnAfterGrowFromGo(t *testing.T) {
+       // Use a new goroutine so that we get a small stack.
+       c := make(chan int)
+       go func() {
+               c <- int(C.returnAfterGrowFromGo())
+       }()
+       if got, want := <-c, 129*128/2; got != want {
+               t.Errorf("got %d want %d", got, want)
+       }
+}
+
+//export goReturnVal
+func goReturnVal() (r C.int) {
+       // Force a stack copy.
+       var f func(int) int
+       f = func(i int) int {
+               var buf [256]byte
+               use(buf[:])
+               if i == 0 {
+                       return 0
+               }
+               return i + f(i-1)
+       }
+       r = C.int(f(128))
+       return
+}
+
 func testCallbackStack(t *testing.T) {
        // Make cgo call and callback with different amount of stack stack available.
        // We do not do any explicit checks, just ensure that it does not crash.
 
 // so that they can use cgo (import "C").
 // These wrappers are here for gotest to find.
 
-func TestAlign(t *testing.T)               { testAlign(t) }
-func TestConst(t *testing.T)               { testConst(t) }
-func TestEnum(t *testing.T)                { testEnum(t) }
-func TestAtol(t *testing.T)                { testAtol(t) }
-func TestErrno(t *testing.T)               { testErrno(t) }
-func TestMultipleAssign(t *testing.T)      { testMultipleAssign(t) }
-func TestUnsignedInt(t *testing.T)         { testUnsignedInt(t) }
-func TestCallback(t *testing.T)            { testCallback(t) }
-func TestCallbackGC(t *testing.T)          { testCallbackGC(t) }
-func TestCallbackPanic(t *testing.T)       { testCallbackPanic(t) }
-func TestCallbackPanicLoop(t *testing.T)   { testCallbackPanicLoop(t) }
-func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) }
-func TestPanicFromC(t *testing.T)          { testPanicFromC(t) }
-func TestAllocateFromC(t *testing.T)       { testAllocateFromC(t) }
-func TestZeroArgCallback(t *testing.T)     { testZeroArgCallback(t) }
-func TestBlocking(t *testing.T)            { testBlocking(t) }
-func Test1328(t *testing.T)                { test1328(t) }
-func TestParallelSleep(t *testing.T)       { testParallelSleep(t) }
-func TestSetEnv(t *testing.T)              { testSetEnv(t) }
-func TestHelpers(t *testing.T)             { testHelpers(t) }
-func TestLibgcc(t *testing.T)              { testLibgcc(t) }
-func Test1635(t *testing.T)                { test1635(t) }
-func TestPrintf(t *testing.T)              { testPrintf(t) }
-func Test4029(t *testing.T)                { test4029(t) }
-func TestBoolAlign(t *testing.T)           { testBoolAlign(t) }
-func Test3729(t *testing.T)                { test3729(t) }
-func Test3775(t *testing.T)                { test3775(t) }
-func TestCthread(t *testing.T)             { testCthread(t) }
-func TestCallbackCallers(t *testing.T)     { testCallbackCallers(t) }
-func Test5227(t *testing.T)                { test5227(t) }
-func TestCflags(t *testing.T)              { testCflags(t) }
-func Test5337(t *testing.T)                { test5337(t) }
-func Test5548(t *testing.T)                { test5548(t) }
-func Test5603(t *testing.T)                { test5603(t) }
-func Test6833(t *testing.T)                { test6833(t) }
-func Test3250(t *testing.T)                { test3250(t) }
-func TestCallbackStack(t *testing.T)       { testCallbackStack(t) }
-func TestFpVar(t *testing.T)               { testFpVar(t) }
-func Test4339(t *testing.T)                { test4339(t) }
-func Test6390(t *testing.T)                { test6390(t) }
-func Test5986(t *testing.T)                { test5986(t) }
-func Test7665(t *testing.T)                { test7665(t) }
-func TestNaming(t *testing.T)              { testNaming(t) }
-func Test7560(t *testing.T)                { test7560(t) }
-func Test5242(t *testing.T)                { test5242(t) }
-func Test8092(t *testing.T)                { test8092(t) }
-func Test7978(t *testing.T)                { test7978(t) }
-func Test8694(t *testing.T)                { test8694(t) }
+func TestAlign(t *testing.T)                 { testAlign(t) }
+func TestConst(t *testing.T)                 { testConst(t) }
+func TestEnum(t *testing.T)                  { testEnum(t) }
+func TestAtol(t *testing.T)                  { testAtol(t) }
+func TestErrno(t *testing.T)                 { testErrno(t) }
+func TestMultipleAssign(t *testing.T)        { testMultipleAssign(t) }
+func TestUnsignedInt(t *testing.T)           { testUnsignedInt(t) }
+func TestCallback(t *testing.T)              { testCallback(t) }
+func TestCallbackGC(t *testing.T)            { testCallbackGC(t) }
+func TestCallbackPanic(t *testing.T)         { testCallbackPanic(t) }
+func TestCallbackPanicLoop(t *testing.T)     { testCallbackPanicLoop(t) }
+func TestCallbackPanicLocked(t *testing.T)   { testCallbackPanicLocked(t) }
+func TestPanicFromC(t *testing.T)            { testPanicFromC(t) }
+func TestAllocateFromC(t *testing.T)         { testAllocateFromC(t) }
+func TestZeroArgCallback(t *testing.T)       { testZeroArgCallback(t) }
+func TestBlocking(t *testing.T)              { testBlocking(t) }
+func Test1328(t *testing.T)                  { test1328(t) }
+func TestParallelSleep(t *testing.T)         { testParallelSleep(t) }
+func TestSetEnv(t *testing.T)                { testSetEnv(t) }
+func TestHelpers(t *testing.T)               { testHelpers(t) }
+func TestLibgcc(t *testing.T)                { testLibgcc(t) }
+func Test1635(t *testing.T)                  { test1635(t) }
+func TestPrintf(t *testing.T)                { testPrintf(t) }
+func Test4029(t *testing.T)                  { test4029(t) }
+func TestBoolAlign(t *testing.T)             { testBoolAlign(t) }
+func Test3729(t *testing.T)                  { test3729(t) }
+func Test3775(t *testing.T)                  { test3775(t) }
+func TestCthread(t *testing.T)               { testCthread(t) }
+func TestCallbackCallers(t *testing.T)       { testCallbackCallers(t) }
+func Test5227(t *testing.T)                  { test5227(t) }
+func TestCflags(t *testing.T)                { testCflags(t) }
+func Test5337(t *testing.T)                  { test5337(t) }
+func Test5548(t *testing.T)                  { test5548(t) }
+func Test5603(t *testing.T)                  { test5603(t) }
+func Test6833(t *testing.T)                  { test6833(t) }
+func Test3250(t *testing.T)                  { test3250(t) }
+func TestCallbackStack(t *testing.T)         { testCallbackStack(t) }
+func TestFpVar(t *testing.T)                 { testFpVar(t) }
+func Test4339(t *testing.T)                  { test4339(t) }
+func Test6390(t *testing.T)                  { test6390(t) }
+func Test5986(t *testing.T)                  { test5986(t) }
+func Test7665(t *testing.T)                  { test7665(t) }
+func TestNaming(t *testing.T)                { testNaming(t) }
+func Test7560(t *testing.T)                  { test7560(t) }
+func Test5242(t *testing.T)                  { test5242(t) }
+func Test8092(t *testing.T)                  { test8092(t) }
+func Test7978(t *testing.T)                  { test7978(t) }
+func Test8694(t *testing.T)                  { test8694(t) }
+func TestReturnAfterGrow(t *testing.T)       { testReturnAfterGrow(t) }
+func TestReturnAfterGrowFromGo(t *testing.T) { testReturnAfterGrowFromGo(t) }
 
 func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }
 
        fmt.Fprintf(fm, "int main() { return 0; }\n")
        if *importRuntimeCgo {
                fmt.Fprintf(fm, "void crosscall2(void(*fn)(void*, int), void *a, int c) { }\n")
+               fmt.Fprintf(fm, "char* cgo_topofstack(void) { return (char*)0; }\n")
        } else {
                // If we're not importing runtime/cgo, we *are* runtime/cgo,
                // which provides crosscall2.  We just need a prototype.
        // Use packed attribute to force no padding in this struct in case
        // gcc has different packing requirements.
        fmt.Fprintf(fgcc, "\t%s %v *a = v;\n", ctype, p.packedAttribute())
+       if n.FuncType.Result != nil {
+               // Save the stack top for use below.
+               fmt.Fprintf(fgcc, "\tchar *stktop = cgo_topofstack();\n")
+       }
        fmt.Fprintf(fgcc, "\t")
        if t := n.FuncType.Result; t != nil {
-               fmt.Fprintf(fgcc, "a->r = ")
+               fmt.Fprintf(fgcc, "__typeof__(a->r) r = ")
                if c := t.C.String(); c[len(c)-1] == '*' {
                        fmt.Fprint(fgcc, "(__typeof__(a->r)) ")
                }
                fmt.Fprintf(fgcc, "a->p%d", i)
        }
        fmt.Fprintf(fgcc, ");\n")
+       if n.FuncType.Result != nil {
+               // The cgo call may have caused a stack copy (via a callback).
+               // Adjust the return value pointer appropriately.
+               fmt.Fprintf(fgcc, "\ta = (void*)((char*)a + (cgo_topofstack() - stktop));\n")
+               // Save the return value.
+               fmt.Fprintf(fgcc, "\ta->r = r;\n")
+       }
        if n.AddError {
                fmt.Fprintf(fgcc, "\treturn errno;\n")
        }
 __cgo_size_assert(float, 4)
 __cgo_size_assert(double, 8)
 
+extern char* cgo_topofstack(void);
+
 #include <errno.h>
 #include <string.h>
 `