[dev.ssa] cmd/compile: implement OCALLMETH

This mimics the way the old backend
compiles OCALLMETH.

Change-Id: I635c8e7a48c8b5619bd837f78fa6eeba83a57b2f
Reviewed-on: https://go-review.googlesource.com/12549
Reviewed-by: Keith Randall <khr@golang.org>
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 32d42d8..4de0518 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -940,13 +940,30 @@
 			return s.constInt(s.config.Int, n.Left.Type.Bound)
 		}
 
-	case OCALLFUNC:
-		static := n.Left.Op == ONAME && n.Left.Class == PFUNC
+	case OCALLFUNC, OCALLMETH:
+		left := n.Left
+		static := left.Op == ONAME && left.Class == PFUNC
+
+		if n.Op == OCALLMETH {
+			// Rewrite to an OCALLFUNC: (p.f)(...) becomes (f)(p, ...)
+			// Take care not to modify the original AST.
+			if left.Op != ODOTMETH {
+				Fatal("OCALLMETH: n.Left not an ODOTMETH: %v", left)
+			}
+
+			newLeft := *left.Right
+			newLeft.Type = left.Type
+			if newLeft.Op == ONAME {
+				newLeft.Class = PFUNC
+			}
+			left = &newLeft
+			static = true
+		}
 
 		// evaluate closure
 		var closure *ssa.Value
 		if !static {
-			closure = s.expr(n.Left)
+			closure = s.expr(left)
 		}
 
 		// run all argument assignments
@@ -955,13 +972,13 @@
 		bNext := s.f.NewBlock(ssa.BlockPlain)
 		var call *ssa.Value
 		if static {
-			call = s.newValue1A(ssa.OpStaticCall, ssa.TypeMem, n.Left.Sym, s.mem())
+			call = s.newValue1A(ssa.OpStaticCall, ssa.TypeMem, left.Sym, s.mem())
 		} else {
 			entry := s.newValue2(ssa.OpLoad, s.config.Uintptr, closure, s.mem())
 			call = s.newValue3(ssa.OpClosureCall, ssa.TypeMem, entry, closure, s.mem())
 		}
-		dowidth(n.Left.Type)
-		call.AuxInt = n.Left.Type.Argwid // call operations carry the argsize of the callee along with them
+		dowidth(left.Type)
+		call.AuxInt = left.Type.Argwid // call operations carry the argsize of the callee along with them
 		b := s.endBlock()
 		b.Kind = ssa.BlockCall
 		b.Control = call
@@ -971,7 +988,7 @@
 		// read result from stack at the start of the fallthrough block
 		s.startBlock(bNext)
 		var titer Iter
-		fp := Structfirst(&titer, Getoutarg(n.Left.Type))
+		fp := Structfirst(&titer, Getoutarg(left.Type))
 		if fp == nil {
 			// CALLFUNC has no return value. Continue with the next statement.
 			return nil