]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.ssa] cmd/compile/internal/ssa: implement ODOT
authorKeith Randall <khr@golang.org>
Thu, 16 Jul 2015 04:33:49 +0000 (21:33 -0700)
committerKeith Randall <khr@golang.org>
Thu, 16 Jul 2015 05:43:36 +0000 (05:43 +0000)
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>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/ssa/gen/generic.rules
src/cmd/compile/internal/ssa/gen/genericOps.go
src/cmd/compile/internal/ssa/opGen.go
src/cmd/compile/internal/ssa/rewritegeneric.go

index 3ad21a6193b360958c2e507184e225e710708756..2ba1ddbb44aa41347b7267d10d6abfe69fec0069 100644 (file)
@@ -226,6 +226,11 @@ func (s *state) newValue1A(op ssa.Op, t ssa.Type, aux interface{}, arg *ssa.Valu
        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 @@ func (s *state) expr(n *Node) *ssa.Value {
                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)
index 9f11a60a6bd4cf4bdf30fc0ee297e41a8ae2f72f..a906ec6a5c38445fe5899343638c64007a577d01 100644 (file)
@@ -34,6 +34,7 @@
 // Note: bounds check has already been done
 (ArrayIndex (Load ptr mem) idx) -> (Load (PtrIndex <v.Type.PtrTo()> ptr idx) mem)
 (PtrIndex <t> ptr idx) -> (Add ptr (Mul <config.Uintptr> idx (Const <config.Uintptr> [t.Elem().Size()])))
+(StructSelect [idx] (Load ptr mem)) -> (Load (OffPtr <v.Type.PtrTo()> [idx] ptr) mem)
 
 // big-object moves
 // TODO: fix size
index 9155e00859d8019a2cb05e7efd08f76c201b2a6c..0af7df17757f6117bf4bbd2af3699cb821308ca5 100644 (file)
@@ -71,9 +71,10 @@ var genericOps = []opData{
        {name: "IsInBounds"}, // 0 <= arg0 < arg1
 
        // Indexing operations
-       {name: "ArrayIndex"}, // arg0=array, arg1=index.  Returns a[i]
-       {name: "PtrIndex"},   // arg0=ptr, arg1=index. Computes ptr+sizeof(*v.type)*index, where index is extended to ptrwidth type
-       {name: "OffPtr"},     // arg0 + auxint (arg0 and result are pointers)
+       {name: "ArrayIndex"},   // arg0=array, arg1=index.  Returns a[i]
+       {name: "PtrIndex"},     // arg0=ptr, arg1=index. Computes ptr+sizeof(*v.type)*index, where index is extended to ptrwidth type
+       {name: "OffPtr"},       // arg0 + auxint (arg0 and result are pointers)
+       {name: "StructSelect"}, // arg0=struct, auxint=field offset.  Returns field at that offset (size=size of result type)
 
        // Slices
        {name: "SliceMake"}, // arg0=ptr, arg1=len, arg2=cap
index 494f4ecf402946438f5c0c2e3035a40e8e4ea6b8..74d30e1df552622a06dddcfe791bd897f108604d 100644 (file)
@@ -146,6 +146,7 @@ const (
        OpArrayIndex
        OpPtrIndex
        OpOffPtr
+       OpStructSelect
        OpSliceMake
        OpSlicePtr
        OpSliceLen
@@ -1232,6 +1233,15 @@ var opcodeTable = [...]opInfo{
                },
                generic: true,
        },
+       {
+               name: "StructSelect",
+               reg: regInfo{
+                       inputs:   []regMask{},
+                       clobbers: 0,
+                       outputs:  []regMask{},
+               },
+               generic: true,
+       },
        {
                name: "SliceMake",
                reg: regInfo{
index 78cb2c8ebb9d198660eab2d7ed0a2d861cd967ad..ca523ee19b030440153546c223d4c78ba5c58455 100644 (file)
@@ -383,6 +383,32 @@ func rewriteValuegeneric(v *Value, config *Config) bool {
                }
                goto end061edc5d85c73ad909089af2556d9380
        end061edc5d85c73ad909089af2556d9380:
+               ;
+       case OpStructSelect:
+               // match: (StructSelect [idx] (Load ptr mem))
+               // cond:
+               // result: (Load (OffPtr <v.Type.PtrTo()> [idx] ptr) mem)
+               {
+                       idx := v.AuxInt
+                       if v.Args[0].Op != OpLoad {
+                               goto end16fdb45e1dd08feb36e3cc3fb5ed8935
+                       }
+                       ptr := v.Args[0].Args[0]
+                       mem := v.Args[0].Args[1]
+                       v.Op = OpLoad
+                       v.AuxInt = 0
+                       v.Aux = nil
+                       v.resetArgs()
+                       v0 := v.Block.NewValue0(v.Line, OpOffPtr, TypeInvalid)
+                       v0.Type = v.Type.PtrTo()
+                       v0.AuxInt = idx
+                       v0.AddArg(ptr)
+                       v.AddArg(v0)
+                       v.AddArg(mem)
+                       return true
+               }
+               goto end16fdb45e1dd08feb36e3cc3fb5ed8935
+       end16fdb45e1dd08feb36e3cc3fb5ed8935:
        }
        return false
 }