cmd/compile: emit assignments after calls in the right order

Fixes a bug where assignments that should come after a call
were instead being issued before the call.

Fixes #17596
Fixes #17618

Change-Id: Ic9ae4c34ae38fc4ccd0604b65345b05896a2c295
Reviewed-on: https://go-review.googlesource.com/32226
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 9d21484..27cbf91 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -819,12 +819,13 @@
 			n.Rlist.Set1(r)
 			break
 		}
+		init.Append(r)
 
-		ll := ascompatet(n.Op, n.List, r.Type, 0, init)
+		ll := ascompatet(n.Op, n.List, r.Type)
 		for i, n := range ll {
 			ll[i] = applywritebarrier(n)
 		}
-		n = liststmt(append([]*Node{r}, ll...))
+		n = liststmt(ll)
 
 	// x, y = <-c
 	// orderstmt made sure x is addressable.
@@ -1848,10 +1849,10 @@
 // check assign type list to
 // a expression list. called in
 //	expr-list = func()
-func ascompatet(op Op, nl Nodes, nr *Type, fp int, init *Nodes) []*Node {
+func ascompatet(op Op, nl Nodes, nr *Type) []*Node {
 	r, saver := iterFields(nr)
 
-	var nn, mm []*Node
+	var nn, mm Nodes
 	var ullmanOverflow bool
 	var i int
 	for i = 0; i < nl.Len(); i++ {
@@ -1871,20 +1872,20 @@
 			tmp := temp(r.Type)
 			tmp = typecheck(tmp, Erv)
 			a := nod(OAS, l, tmp)
-			a = convas(a, init)
-			mm = append(mm, a)
+			a = convas(a, &mm)
+			mm.Append(a)
 			l = tmp
 		}
 
-		a := nod(OAS, l, nodarg(r, fp))
-		a = convas(a, init)
+		a := nod(OAS, l, nodarg(r, 0))
+		a = convas(a, &nn)
 		ullmancalc(a)
 		if a.Ullman >= UINF {
 			Dump("ascompatet ucount", a)
 			ullmanOverflow = true
 		}
 
-		nn = append(nn, a)
+		nn.Append(a)
 		r = saver.Next()
 	}
 
@@ -1895,7 +1896,7 @@
 	if ullmanOverflow {
 		Fatalf("ascompatet: too many function calls evaluating parameters")
 	}
-	return append(nn, mm...)
+	return append(nn.Slice(), mm.Slice()...)
 }
 
 // package all the arguments that match a ... T parameter into a []T.
diff --git a/test/fixedbugs/issue17596.go b/test/fixedbugs/issue17596.go
new file mode 100644
index 0000000..7398292
--- /dev/null
+++ b/test/fixedbugs/issue17596.go
@@ -0,0 +1,19 @@
+// compile
+
+// Copyright 2016 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.
+
+package foo
+
+type T interface {
+	foo()
+}
+
+func f() (T, int)
+
+func g(v interface{}) (interface{}, int) {
+	var x int
+	v, x = f()
+	return v, x
+}