]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: factor shared code from geneq and genhash
authorJosh Bleecher Snyder <josharian@gmail.com>
Sun, 21 Feb 2016 23:49:52 +0000 (15:49 -0800)
committerJosh Bleecher Snyder <josharian@gmail.com>
Fri, 26 Feb 2016 22:17:31 +0000 (22:17 +0000)
Passes toolstash -cmp.

Change-Id: Ifae69e5ba673f01da3dfc1fd30cdc51873481623
Reviewed-on: https://go-review.googlesource.com/19840
Reviewed-by: David Crawshaw <crawshaw@golang.org>
src/cmd/compile/internal/gc/subr.go

index 896fa868fe5a59afa977f1e19b61151b14c36edf..5428066f4f765bc9a3e50100e0a9b6ed4b5fbc68 100644 (file)
@@ -2507,35 +2507,20 @@ func genhash(sym *Sym, t *Type) {
 
                fn.Nbody = list(fn.Nbody, n)
 
-               // Walk the struct using memhash for runs of AMEM
+       // Walk the struct using memhash for runs of AMEM
        // and calling specific hash functions for the others.
        case TSTRUCT:
-               var first *Type
-
-               offend := int64(0)
-               var size int64
                var call *Node
                var nx *Node
                var na *Node
                var hashel *Node
-               for t1 := t.Type; ; t1 = t1.Down {
-                       if t1 != nil && algtype1(t1.Type, nil) == AMEM && !isblanksym(t1.Sym) {
-                               offend = t1.Width + t1.Type.Width
-                               if first == nil {
-                                       first = t1
-                               }
 
-                               // If it's a memory field but it's padded, stop here.
-                               if ispaddedfield(t1, t.Width) {
-                                       t1 = t1.Down
-                               } else {
-                                       continue
-                               }
-                       }
+               for t1 := t.Type; ; t1 = t1.Down {
+                       first, size, next := memrun(t, t1)
+                       t1 = next
 
                        // Run memhash for fields up to this one.
                        if first != nil {
-                               size = offend - first.Width // first->width is offset
                                hashel = hashmem(first.Type)
 
                                // h = hashel(&p.first, size, h)
@@ -2548,8 +2533,6 @@ func genhash(sym *Sym, t *Type) {
                                call.List = list(call.List, nh)
                                call.List = list(call.List, Nodintconst(size))
                                fn.Nbody = list(fn.Nbody, Nod(OAS, nh, call))
-
-                               first = nil
                        }
 
                        if t1 == nil {
@@ -2745,25 +2728,11 @@ func geneq(sym *Sym, t *Type) {
        // and calling specific equality tests for the others.
        // Skip blank-named fields.
        case TSTRUCT:
-               var first *Type
-
                var conjuncts []*Node
-               offend := int64(0)
-               var size int64
-               for t1 := t.Type; ; t1 = t1.Down {
-                       if t1 != nil && algtype1(t1.Type, nil) == AMEM && !isblanksym(t1.Sym) {
-                               offend = t1.Width + t1.Type.Width
-                               if first == nil {
-                                       first = t1
-                               }
 
-                               // If it's a memory field but it's padded, stop here.
-                               if ispaddedfield(t1, t.Width) {
-                                       t1 = t1.Down
-                               } else {
-                                       continue
-                               }
-                       }
+               for t1 := t.Type; ; t1 = t1.Down {
+                       first, size, next := memrun(t, t1)
+                       t1 = next
 
                        // Run memequal for fields up to this one.
                        // TODO(rsc): All the calls to newname are wrong for
@@ -2779,11 +2748,8 @@ func geneq(sym *Sym, t *Type) {
                                        }
                                } else {
                                        // More than two fields: use memequal.
-                                       size = offend - first.Width // first->width is offset
                                        conjuncts = append(conjuncts, eqmem(np, nq, newname(first.Sym), size))
                                }
-
-                               first = nil
                        }
 
                        if t1 == nil {
@@ -2846,6 +2812,35 @@ func geneq(sym *Sym, t *Type) {
        Disable_checknil--
 }
 
+// memrun finds runs of struct fields for which memory-only algs are appropriate.
+// t is the parent struct type, and field is the field at which to start.
+// first is the first field in the memory run.
+// size is the length in bytes of the memory included in the run.
+// next is the next field after the memory run.
+func memrun(t *Type, field *Type) (first *Type, size int64, next *Type) {
+       var offend int64
+       for {
+               if field == nil || algtype1(field.Type, nil) != AMEM || isblanksym(field.Sym) {
+                       break
+               }
+               offend = field.Width + field.Type.Width
+               if first == nil {
+                       first = field
+               }
+
+               // If it's a memory field but it's padded, stop here.
+               if ispaddedfield(field, t.Width) {
+                       field = field.Down
+                       break
+               }
+               field = field.Down
+       }
+       if first != nil {
+               size = offend - first.Width // first.Width is offset
+       }
+       return first, size, field
+}
+
 func ifacelookdot(s *Sym, t *Type, followptr *bool, ignorecase int) *Type {
        *followptr = false