[dev.ssa] cmd/compile/internal/ssa: implement ODOT

Implement ODOT.  Similar to ArrayIndex, StructSelect selects a field
out of a larger Value.

We may need more ways to rewrite StructSelect, but StructSelect/Load
is the typical way it is used.

Change-Id: Ida7b8aab3298f4754eaf9fee733974cf8736e45d
Reviewed-on: https://go-review.googlesource.com/12265
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index 3ad21a6..2ba1ddb 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -226,6 +226,11 @@
 	return s.curBlock.NewValue1A(s.peekLine(), op, t, aux, arg)
 }
 
+// newValue1I adds a new value with one argument and an auxint value to the current block.
+func (s *state) newValue1I(op ssa.Op, t ssa.Type, aux int64, arg *ssa.Value) *ssa.Value {
+	return s.curBlock.NewValue1I(s.peekLine(), op, t, aux, arg)
+}
+
 // newValue2 adds a new value with two arguments to the current block.
 func (s *state) newValue2(op ssa.Op, t ssa.Type, arg0, arg1 *ssa.Value) *ssa.Value {
 	return s.curBlock.NewValue2(s.peekLine(), op, t, arg0, arg1)
@@ -556,6 +561,10 @@
 		s.nilCheck(p)
 		return s.newValue2(ssa.OpLoad, n.Type, p, s.mem())
 
+	case ODOT:
+		v := s.expr(n.Left)
+		return s.newValue1I(ssa.OpStructSelect, n.Type, n.Xoffset, v)
+
 	case ODOTPTR:
 		p := s.expr(n.Left)
 		s.nilCheck(p)